반응형
Notice
Recent Posts
Recent Comments
Link
«   2025/12   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Archives
Today
Total
관리 메뉴

Devsecops로 발전하는 엔지니어

ECS Multi-container CI/CD 파이프라인 구축 삽질기: 실수에서 배운 교훈 본문

Devops

ECS Multi-container CI/CD 파이프라인 구축 삽질기: 실수에서 배운 교훈

cloud/devops/opensource 관심 많은 곰 2025. 9. 4. 08:24
반응형

내용 정리 목적

WordPress와 MySQL을 ECS에 Multi-container 구조로 배포하면서 겪은 다양한 시행착오를 정리합니다. 처음 도전하는 사람이라면 반드시 한 번쯤 마주칠 수 있는 이슈들이고, 반복하지 않기 위해 기록으로 남겨둡니다.

🔥 삽질 포인트와 해결 과정

  1. GitLab CI/CD Variables 실종 사건

문제 상황

.gitlab-ci.yml 파일을 이용하여 아래의 명령어가 실행이 되었으나,

aws ecs update-service --cluster $ECS_CLUSTER --service $ECS_SERVICE
ServiceNotFoundException:
-> 에러 발생

원인

  • GitLab의 CI/CD Variables인 ECS_CLUSTER, ECS_SERVICE가 누군가에 의해 삭제됨
  • GitLab Runner가 삭제되면서 같이 삭제되었다고 착각함 (실제로는 별개)
  • 빈 문자열이 변수로 전달되면서 ECS 서비스 탐색 실패

해결 방법

# GitLab → Settings → CI/CD → Variables 부분에 값 재등록 처리
ECS_CLUSTER = devops-test-cluster
ECS_SERVICE = devops-test-service
AWS_REGION = ap-northeast-2

교훈

  • 중요 변수는 반드시 문서화
  • Protected 설정은 protected 브랜치에서만 작동
  1. Multi-container 네트워킹 에러 무한 루프
{
  "containerDefinitions": [{
    "name": "wordpress-container",
    "environment": [{
      "name": "WORDPRESS_DB_HOST",
      "value": "localhost"  // ❌ 작동 안 함
    }]
  }]
}

원인

  • ECS의 bridge 네트워크 모드에서 컨테이너는 각자 고립된 네임스페이스를 가짐
  • localhost는 자기 자신만을 의미 하기 때문에 DB 연결 실패

해결 방법

{
  "containerDefinitions": [{
    "name": "wordpress-container",
    "links": ["mysql"],  // ✅ 컨테이너 연결
    "environment": [{
      "name": "WORDPRESS_DB_HOST",
      "value": "mysql:3306"  // ✅ 컨테이너 이름으로 접근
    }]
  }]
}

교훈

  • Docker 네트워크 모드별 특성은 반드시 이해 필요
  • bridge 모드에서는 links 옵션으로 컨테이너 연결
  • 컨테이너 이름으로 통신해야 한다는 점 유의

3. 컨테이너 이름 불일치 함정

문제 상황

The container devops-test-container does not exist in the task definition.

원인

# Terraform
container_definitions = jsonencode([{
  name = "devops-test-container"  // Terraform이 기대하는 이름
}])

// multi-container-task-def.json
{
  "name": "wordpress-container"  // 실제 설정된 이름
}

해결 방법

  • 모든 구성 요소에서 일관된 컨테이너 이름 사용
  • 불일치 시 ECS 서비스를 재생성

교훈

  • 네이밍 컨벤션은 프로젝트 초기에 통일
  • Terraform 코드와 JSON Task 정의 파일 간 일관성 유지 필수

ALB 헬스체크 무한 실패

문제상황

"State": "unhealthy",
"Reason": "Target.ResponseCodeMismatch",
"Description": "Health checks failed with these codes: [500]"

원인

  • WordPress가 DB 연결 실패 → / 경로에서 500 에러 발생
  • ALB 헬스체크 실패 → ECS가 Task를 계속 재시작 (무한 루프발생)
# Terraform
health_check {
  path                = "/wp-admin/install.php"  // 500도 정상으로 간주
  matcher             = "200,302,500"
  unhealthy_threshold = 10
  interval            = 60
}

교훈

  • 헬스체크 경로는 서비스 특성에 맞게 설정
  • 초기에 500 에러가 날 수 있음을 고려한 matcher 조정 필요

최종 아키텍쳐

Developer
   ↓
GitLab → GitLab CI/CD → Docker Build → ECR
                                ↓
                     ECS Task Definition Update
                                ↓
                  ECS Service (Multi-container)
                     ├── WordPress Container
                     └── MySQL Container
                                ↓
                            ALB → Users

💡 핵심 교훈 정리

✅ 변수 관리

  • GitLab CI/CD 변수는 정기적으로 백업
  • 팀 내 변수 Naming Rule, 삭제 금지 정책 수립

✅ 네트워킹

  • 컨테이너 간 통신 방식은 배포 전 docker-compose로 사전 테스트
  • localhost와 컨테이너 이름 차이 반드시 이해

✅ 일관성

  • 모든 이름(TF, JSON, ALB Target 등)은 표준 네이밍 컨벤션 따라야 함
  • Task Definition과 Terraform 코드 간 일관성 확보

✅ 디버깅

  • CloudWatch Logs, ECS Events, Target Group 상태 적극 확인
  • Task stopped, Service Events, ALB Health까지 모두 체크

✅ 점진적 구성

  • 단일 컨테이너 → 멀티컨테이너 → Production 구성 순서로 확장
  • 초기에는 구성 단순하게, 단계적으로 복잡도 추가ECS Multi-container CI/CD 파이프라인 구축 삽질기: 실수에서 배운 교훈들
반응형