AWS에서 CodeBuild, CodeDeploy를 사용해서 CI/CD를 구축하는 과정에서 무엇이 어려웠는지, 시간이 걸렸는지 작성해보려고 한다. GitLab Self-managed와 AWS 서비스를 연동하면서 겪었던 시행착오와 해결 과정을 상세히 기록했다.
🎯 프로젝트 목표
- 소스: GitLab Self-managed (nginx 웹서버)
- 빌드: AWS CodeBuild (Docker 이미지 빌드 → ECR 푸시)
- 배포: AWS CodeDeploy (EC2 인스턴스에 컨테이너 배포)
- 트리거: main 브랜치 merge 시 자동 배포
📋 전체 아키텍처
GitLab (dev → main merge)
↓ Webhook
CodePipeline
↓
CodeBuild (Docker 빌드) → ECR
↓
CodeDeploy → EC2 (컨테이너 실행)
🚧 겪었던 주요 문제들과 해결 과정
1. GitLab Self-managed 연결
문제: VPC 설정 오류
처음에는 GitLab 서버의 실제 IP(xx.xx.xx.xxx)로 연결을 시도했지만 VPC 설정에서 계속 실패했다.
해결책: ngrok 터널 사용
# ngrok으로 HTTPS 터널 생성
ngrok http 80
# 생성된 URL: https://xxxx-xx-xx-xx-xxx.ngrok-free.app
핵심 포인트: AWS CodePipeline에서 GitLab Self-managed 연결 시 "No VPC" 옵션을 선택해야 한다. VPC 설정은 복잡하고 ngrok 같은 외부 터널에서는 작동하지 않는다.
Personal Access Token 생성
GitLab → User Settings → Access Tokens
- 이름: codepipeline-token
- 스코프: api (필수)
- 만료일: 1년
2. SSH 키 연결 문제
문제: Permission denied (publickey)
AWS EC2 PEM 키와 GitLab SSH 키가 매칭되지 않는 문제가 발생했다.
git@xx.xx.xx.xxx: Permission denied (publickey).
해결 과정:
- IP 주소 불일치 발견: xx.xx.xx.xxx → yy.yy.yy.yyy
- PEM 키에서 공개키 추출:
ssh-keygen -y -f my_key_pair.pem > my_key_pair.pub
- Git Bash 사용: Windows PowerShell의 SSH 에이전트 문제로 Git Bash로 전환
교훈: 초기 설정 시 IP 주소와 키 매칭을 정확히 확인해야 한다.
3. CodePipeline 생성
문제: buildspec.yml 명령어 길이 제한
처음에 "관리형" 빌드 공급자를 선택하고 인라인으로 buildspec 내용을 넣었는데 1000자 제한에 걸렸다.
1 validation error detected: Member must have length less than or equal to 1000
해결책: 파일 기반 buildspec 사용
- GitLab에 buildspec.yml 파일 생성
- "기타 빌드 공급자" → AWS CodeBuild 선택
- "buildspec 파일 사용" 옵션 선택
version: 0.2
env:
variables:
AWS_DEFAULT_REGION: ap-northeast-2
AWS_ACCOUNT_ID: xxxxxxxxxxxx
IMAGE_REPO_NAME: nginx-app
IMAGE_TAG: latest
phases:
pre_build:
commands:
- echo Logging in to Amazon ECR...
- aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
build:
commands:
- echo Building the Docker image...
- docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .
- docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
post_build:
commands:
- echo Pushing the Docker image...
- docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
- printf '[{"name":"nginx-container","imageUri":"%s"}]' $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG > imagedefinitions.json
artifacts:
files:
- imagedefinitions.json
- appspec.yml
4. 권한 지옥
이 부분이 가장 많은 시간을 잡아먹었다. AWS의 세분화된 권한 체계 때문에 여러 서비스 역할에 권한을 추가해야 했다.
문제 1: CodePipeline이 CodeBuild를 실행할 수 없음
User: AWSCodePipelineServiceRole-... is not authorized to perform: codebuild:StartBuild
문제 2: CodeBuild가 환경 변수를 읽을 수 없음
is not authorized to perform: ssm:GetParameters
문제 3: Parameter Store에 값이 없음
parameter does not exist: xxxxxxxxxxxx
해결책: 권한 대폭 완화
결국 테스트 환경이니까 다음과 같이 널널하게 권한을 부여했다:
1. CodePipeline 서비스 역할
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
2. CodeBuild 서비스 역할
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
3. 환경 변수 타입 변경 CodeBuild 환경 변수를 **"파라미터"**에서 **"텍스트"**로 변경했다. Parameter Store를 사용하지 않고 일반 텍스트로 설정하니 바로 해결되었다.
5. CodeDeploy 설정
애플리케이션 및 배포 그룹 생성
애플리케이션: nginx-app-deploy
배포 그룹: nginx-deployment-group
컴퓨팅 플랫폼: EC2/온프레미스
중요한 설정들:
- 서비스 역할: CodeDeploy 전용 서비스 역할 필요
- 태그 매칭: EC2 인스턴스의 Name 태그와 배포 그룹의 태그가 정확히 일치해야 함
- 로드 밸런서: 단순한 웹서버라면 비활성화
6. 브랜치 전략 설정
main 브랜치 생성
git checkout dev
git checkout -b main
git push -u origin main
워크플로우
# 개발
git checkout dev
# 코드 수정...
git commit -m "개발 완료"
git push origin dev
# 배포 (파이프라인 트리거)
git checkout main
git merge dev
git push origin main # 이 순간 자동 배포!
🎉 최종 성과
성공한 파이프라인 구조:
Source (GitLab) ✅ → Build (CodeBuild) ✅ → Deploy (CodeDeploy) ⏳
소요 시간 정리:
- GitLab 연결: 2시간 (VPC 이슈)
- SSH 키 설정: 1시간 (키 매칭 문제)
- 파이프라인 생성: 1시간 (buildspec 길이 제한)
- 권한 설정: 3시간 (다양한 권한 오류)
- CodeDeploy 설정: 45분
총 소요 시간: 약 8시간 (예상 1.5시간 → 실제 8시간)
💡 핵심 교훈들
1. 권한 관리의 복잡성
AWS의 세분화된 권한 체계는 보안상 좋지만, 개발 환경에서는 오히려 장애물이 될 수 있다. 테스트 단계에서는 광범위한 권한을 주고, 나중에 최소 권한으로 제한하는 것이 효율적이다.
2. 환경 변수 타입 선택의 중요성
CodeBuild에서 환경 변수 타입을 잘못 선택하면 SSM Parameter Store나 Secrets Manager와의 연동 문제가 발생한다. 단순한 설정값은 "텍스트" 타입이 가장 안전하다.
3. GitLab Self-managed의 네트워크 고려사항
VPC 설정 없이 ngrok 같은 터널을 사용하는 것이 초기 테스트에서는 더 간단하다. 프로덕션에서는 적절한 네트워크 설정을 고려해야 한다.
4. 태그 기반 배포의 정확성
CodeDeploy에서 EC2 인스턴스를 식별할 때 태그가 정확히 일치해야 한다. 대소문자, 공백 등 모든 것이 정확해야 한다.
5. 파일 기반 설정의 유연성
buildspec.yml이나 appspec.yml을 파일로 관리하는 것이 인라인보다 유지보수와 버전 관리 측면에서 훨씬 좋다.
🚀 다음 단계
현재 Build까지 성공했고, Deploy 단계가 진행 중이다. 다음에 해야 할 것들:
- EC2 인스턴스 준비
- CodeDeploy Agent 설치
- Docker 설치 및 권한 설정
- appspec.yml 최적화
- 컨테이너 생명주기 관리
- 롤백 전략 구현
- 모니터링 및 알림
- CloudWatch 로그 설정
- SNS 알림 구성
- 보안 강화
- 최소 권한 원칙 적용
- 환경 변수 암호화
🔚 마무리
AWS의 CodeBuild, CodeDeploy를 이용한 CI/CD 구축은 생각보다 복잡했다. 특히 권한 관리와 서비스 간 연동에서 많은 시간이 소요되었다. 하지만 한 번 설정이 완료되면 안정적이고 강력한 배포 파이프라인을 얻을 수 있다는 점에서 가치가 있다.
'AWS' 카테고리의 다른 글
| AWS 다중 계정 비용 관리 시스템 구축 (2) | 2025.07.03 |
|---|---|
| Amazon EKS 실습 환경 구축하기 (1) | 2025.06.24 |
| AWS ALB 이름 변경하려고 삭제하고 새로 만든 과정 (0) | 2025.05.27 |
| RDS, Aurora PostgreSQL 자동 시작/중지 스케줄링 SSM(System Manager)으로 구현 (0) | 2025.05.26 |
| AWS에서 dockerd 없이 containerd만으로 컨테이너 런타임 운영하기 (0) | 2025.05.16 |