Docker 기반 CI·CD 파이프라인 구축

CI/CD - GitLab으로 AWS Cloud로의 지속적인 배포 (CD) - (1) / AWS Elastic Container Service (ECS) / Task & Task definition

wy-family 2024. 12. 7. 21:03

GitLab pipeline 에서 make build, make push 까지 했었다. (make test 의 경우에는 그냥 스테이지만 넣었고 실질적인 test를 넣은 건 아니었다.)

ECR까지 docker image가 등록이 된 상태다. 지속적인 통합 과정, CI 과정은 끝이 난 것.

 

이제 make deploy,

그러니까 AWS Cloud로의 배포까지 추가해서 사용자들이 사용할 수 있도록 하면 된다.

CI 까지 만들었으니까 CD 를 만든다는 것.

 

1. GitLab을 이용해서 프로젝트를 만들고

2. Docker Image를 빌드해서 ECR에 Push 했고

3. 이제 인터넷 사용자가 서비스를 사용할 수 있도록 Docker Image를 배포해야 한다.

4. AWS ECS 를 이용해서 우리가 개발한 어플리케이션을 AWS Cloud에 배포하게 된다.

5. 이를 통해서 개발, 통합, 빌드, 배포의 기본적인 CI/CD 파이프라인 전체를 구성해보게 된다.


AWS ECS와 CI/CD 파이프라인

AWS ECS(Amazon Elastic Container Service)는 컨테이너 오케스트레이션 도구로, Docker 컨테이너를 사용한 애플리케이션을 배포, 관리, 확장하는 데 사용됩니다. 특히 AWS CLI, Docker, 그리고 GitLab과 함께 사용하면 자동화된 CI/CD 파이프라인을 구축할 수 있습니다.


AWS ECS의 주요 기능

  1. 컨테이너 오케스트레이션
    • Docker 컨테이너를 실행, 관리하며 여러 컨테이너를 클러스터 환경에서 조율합니다.
    • ECS 작업(Task) 및 서비스(Service)를 통해 컨테이너의 실행 방식을 정의합니다.
  2. 유연한 실행 환경
    • AWS Fargate: 서버리스 방식으로 컨테이너 실행.
    • Amazon EC2: 사용자가 관리하는 가상 서버 환경에서 실행.
  3. 확장성
    • ECS는 필요에 따라 자동으로 클러스터의 작업 수를 확장하거나 축소합니다.
  4. 통합 지원
    • Docker: 컨테이너 이미지 생성 및 배포.
    • AWS CLI: ECS 클러스터 및 작업 정의를 관리.
    • GitLab: CI/CD 파이프라인의 소스 제어 및 자동화 트리거.

AWS ECS 기반 CI/CD 파이프라인의 구조

아래는 GitLab, Docker, AWS ECS, AWS CLI를 사용해 CI/CD 파이프라인을 구성하는 구조입니다:

1. CI/CD 파이프라인 흐름

  1. 코드 작성 및 Push
    개발자는 애플리케이션 코드를 작성하고 GitLab의 리포지토리에 Push합니다.
  2. GitLab CI/CD 트리거
    GitLab CI/CD 파이프라인이 트리거되며, 다음 작업이 진행됩니다:
    • Docker 이미지를 빌드.
    • AWS Elastic Container Registry(ECR)에 이미지 푸시.
  3. AWS ECS에 배포
    GitLab의 파이프라인 스크립트를 통해 AWS CLI를 호출하여 ECS 서비스에 새 Docker 이미지를 배포합니다.

2. 파이프라인 구성의 주요 단계

  1. Docker 이미지 빌드 및 푸시
    • Dockerfile을 기반으로 애플리케이션의 이미지를 빌드합니다.
    • 이미지를 AWS ECR(Amazon Elastic Container Registry)에 푸시합니다.
     
  2. ECS 작업(Task) 및 서비스 배포
    • AWS CLI 명령어를 사용해 ECS 클러스터와 서비스가 새 이미지를 기반으로 업데이트되도록 트리거합니다.
    • ECS 서비스는 배포 중에 롤링 업데이트를 수행해 다운타임 없이 새 버전을 배포합니다.
  3. 자동 확장 및 모니터링
    • Amazon CloudWatch를 사용하여 애플리케이션 상태를 모니터링.
    • 필요한 경우 Auto Scaling을 통해 ECS 작업을 확장.

작업 구조의 세부 설명

  1. ECS 클러스터
    Docker 컨테이너를 실행하는 리소스의 논리적 그룹입니다. 클러스터는 Fargate(서버리스) 또는 EC2(가상 머신 기반) 환경에서 실행됩니다.
  2. 작업 정의(Task Definition)
    실행할 컨테이너의 구성 정보입니다. 예를 들어, 사용해야 할 Docker 이미지, CPU/메모리 할당량, 네트워크 설정 등이 포함됩니다.
  3. 서비스(Service)
    ECS 서비스는 특정 수의 작업(Task)을 유지하며 로드 밸런싱 및 자동 복구를 지원합니다.

결론

AWS ECS는 Docker 기반 컨테이너를 자동으로 오케스트레이션하는 강력한 도구이며, GitLab과 AWS CLI를 활용하면 효율적이고 자동화된 CI/CD 파이프라인을 구축할 수 있습니다. 이 구조는 애플리케이션의 안정적인 배포와 빠른 반복 개발을 가능하게 합니다.

 

* Amazon ECS

  • Kubernetes 같은 Container Orrchestration 서비스
  • Kubernetes 에 비해서 저렴하고 사용하기가 쉽다
  • serverless 로 구성하면 인스턴스를 구성/관리할 필요가 없다
  • AWS의 다른 서비스와 쉽게 연동
  • 운영, 모니터링, 스케일링의 완전 자동화

Amazon ECS의 작동 원리와 구조

**Amazon ECS(Amazon Elastic Container Service)**는 컨테이너화된 애플리케이션을 클러스터 기반으로 배포, 관리, 확장하는 서비스입니다. 이를 효과적으로 설명하기 위해 아래 키워드들을 사용해 구조를 풀어보겠습니다:


구성 요소와 역할

  1. Amazon ECR (Elastic Container Registry)
    • ECR은 Docker 이미지를 저장하고 관리하는 서비스입니다.
    • 예를 들어, Service-A Image, Service-B Image, Service-C Image, Service-D Image 같은 Docker 이미지를 저장합니다.
    • 각 이미지는 컨테이너화된 애플리케이션이나 서비스의 실행 가능한 스냅샷입니다.
    작업 흐름:
    개발자는 애플리케이션 코드를 컨테이너화하여 Amazon ECR에 이미지를 푸시(push)합니다.
  2. 클러스터(Cluster)
    • 클러스터는 컨테이너가 실행되는 리소스의 논리적 그룹입니다.
    • ECS 클러스터는 Service-A, Service-B 같은 서비스를 실행하며, 이들은 각각의 Docker 이미지를 기반으로 실행됩니다.
    예:
    • 클러스터 내에 여러 EC2 인스턴스나 Fargate 작업(Task)이 존재하여 다양한 서비스를 실행합니다.
  3. 서비스(Service)
    • ECS 서비스는 특정 컨테이너 작업(Task)을 실행하고 관리합니다.
    • 예를 들어, Service-A는 Service-A Image를 사용해 클러스터 내 컨테이너를 실행합니다.
    • 서비스는 지정된 수의 컨테이너를 유지하며, 작업이 실패하면 자동 복구를 수행합니다.
  4. 자동 확장(Auto Scaling)
    • ECS는 Auto Scaling 기능을 통해 서비스나 클러스터의 작업(Task) 수를 자동으로 확장하거나 축소합니다.
    • 예를 들어, Service-A가 트래픽 증가로 인해 부하를 받으면 추가 작업(Task)을 시작하여 서비스 용량을 확장합니다.
  5. ELB (Elastic Load Balancer)
    • ELB는 클러스터 내에서 실행 중인 컨테이너 간의 부하를 분산합니다.
    • 예를 들어, Service-B에서 3개의 작업(Task)이 실행 중이라면, ELB는 들어오는 요청을 각 작업으로 고르게 분산시켜 애플리케이션의 가용성을 높입니다.
  6. CloudWatch
    • Amazon CloudWatch는 ECS 클러스터와 서비스의 성능 및 상태를 모니터링합니다.
    • 예시:
      • Service-C의 CPU 사용량이 80%를 초과하면 경고를 생성.
      • 이를 기반으로 Auto Scaling을 트리거하거나 문제를 디버깅할 수 있습니다.

ECS 작업 흐름 예시

  1. 이미지 준비
    • 개발자가 Docker 이미지를 생성하고 이를 Amazon ECR에 업로드합니다.
    • 예:
      • Service-A Image → 웹 서버
      • Service-B Image → 데이터 처리 워커
      • Service-C Image → 데이터베이스 관리
      • Service-D Image → 백엔드 API
  2. 서비스와 클러스터 설정
    • ECS 클러스터를 생성하고 각 이미지를 기반으로 서비스를 설정합니다.
    • 예:
      • Service-A는 3개의 작업(Task)을 실행.
      • Service-B는 2개의 작업(Task)을 실행.
  3. 트래픽 처리
    • ELB가 들어오는 요청을 받아 클러스터 내의 Service-A 작업(Task)로 분산합니다.
    • 요청이 증가하면 CloudWatch가 이를 감지하고, Auto Scaling을 통해 작업(Task)을 추가 생성합니다.
  4. 모니터링 및 유지 관리
    • CloudWatch에서 CPU 사용량, 메모리 소비량 등의 지표를 모니터링합니다.
    • 비정상 상태의 작업(Task)은 ECS가 자동으로 재시작합니다.

ECS 구조 다이어그램 (설명)

  1. ECR
    • Docker 이미지를 저장 (Service-A Image, Service-B Image 등).
  2. 클러스터
    • 여러 서비스를 실행하는 컨테이너 작업(Task)의 집합.
    • 예:
      • Service-A는 클러스터 내에서 3개의 작업 실행.
      • Service-B는 2개의 작업 실행.
  3. ELB
    • 클라이언트의 요청을 클러스터 내 컨테이너로 라우팅.
  4. Auto Scaling
    • 클러스터 또는 서비스의 작업(Task) 수를 자동으로 조정.
  5. CloudWatch
    • 서비스 상태 및 성능을 실시간으로 모니터링.

결론

Amazon ECS는 ECR에서 저장된 Docker 이미지를 클러스터 내에서 서비스로 실행하며, ELB와 Auto Scaling을 통해 애플리케이션의 확장성과 안정성을 보장합니다. CloudWatch는 이를 실시간으로 모니터링하며, 문제 발생 시 빠른 복구 및 확장을 지원합니다.


아래는 Amazon ECS의 구조를 텍스트 기반으로 시각화한 예입니다. 키워드와 구성 요소의 관계를 계층적으로 보여줍니다.

Amazon ECS 구조

1. Amazon ECR
   ├── Service-A Image
   ├── Service-B Image
   ├── Service-C Image
   └── Service-D Image

2. ECS Cluster
   ├── Service-A
   │   ├── Task 1 (Docker Container: Service-A Image)
   │   ├── Task 2 (Docker Container: Service-A Image)
   │   └── Task 3 (Docker Container: Service-A Image)
   ├── Service-B
   │   ├── Task 1 (Docker Container: Service-B Image)
   │   └── Task 2 (Docker Container: Service-B Image)
   ├── Service-C
   │   └── Task 1 (Docker Container: Service-C Image)
   └── Service-D
       ├── Task 1 (Docker Container: Service-D Image)
       └── Task 2 (Docker Container: Service-D Image)

3. Elastic Load Balancer (ELB)
   ├── Routes traffic to Service-A Tasks
   └── Routes traffic to Service-D Tasks

4. Auto Scaling
   ├── Monitors Cluster or Service Metrics via CloudWatch
   ├── Scales up Service-A to 5 Tasks during high traffic
   └── Scales down Service-D to 1 Task during low traffic

5. CloudWatch
   ├── Logs metrics for CPU, Memory, and Task Health
   ├── Sends alerts when thresholds are breached
   └── Triggers Auto Scaling events

구조 설명

  1. Amazon ECR
    • 모든 Docker 이미지는 ECR에 저장되며, ECS 서비스가 이를 가져다 사용합니다.
  2. ECS Cluster
    • 클러스터는 여러 서비스로 구성되고, 각 서비스는 작업(Task)을 실행합니다.
    • 예를 들어, Service-A는 3개의 작업(Task)을 실행하며, 각 작업은 동일한 Docker 이미지를 사용합니다.
  3. Elastic Load Balancer (ELB)
    • 클라이언트의 요청을 클러스터 내 적절한 작업(Task)으로 라우팅합니다.
    • 예: Service-A의 3개 작업(Task)로 요청을 분산.
  4. Auto Scaling
    • 트래픽 증가 시 작업(Task) 수를 확장하고, 감소 시 축소합니다.
    • 예: CloudWatch의 CPU 사용량 경고에 따라 Service-A 작업(Task)을 3개에서 5개로 증가.
  5. CloudWatch
    • ECS의 성능과 상태를 모니터링하며, 경고 및 확장을 트리거합니다.

실제 동작 예시

  1. 클라이언트가 애플리케이션에 접속.
  2. ELB가 요청을 받아 Service-A의 작업(Task)으로 전달.
  3. 트래픽 증가로 인해 CloudWatch가 CPU 사용량 상승을 감지.
  4. Auto Scaling이 트리거되어 Service-A의 작업(Task)을 추가.
  5. 트래픽 감소 시 Auto Scaling이 작업(Task)을 축소.

Amazon ECS에서의 Task와 Task Definition

TaskTask Definition은 Amazon ECS의 핵심 개념으로, 컨테이너화된 애플리케이션을 실행하고 관리하는 데 중요한 역할을 합니다.


1. Task란?

Task는 Amazon ECS에서 실행되는 컨테이너의 단위입니다.

  • Task는 Task Definition을 기반으로 실행됩니다.
  • 하나의 Task는 하나 이상의 컨테이너를 포함할 수 있습니다.
    예를 들어, 웹 서버 컨테이너로깅 컨테이너를 하나의 Task로 정의할 수 있습니다.
  • Task는 ECS 클러스터 내에서 실행되며, Fargate(서버리스) 또는 EC2 인스턴스를 기반으로 작동할 수 있습니다.

예시

  • "Task-A"는 Service-A에 의해 실행되는 단일 컨테이너 또는 여러 컨테이너를 포함하는 단위입니다.
  • "웹 애플리케이션" 작업을 담당하는 Task가 3개 실행 중이면, 동일한 컨테이너가 3개 복제되어 클러스터에서 작동 중임을 의미합니다.

2. Task Definition이란?

Task Definition은 ECS에서 Task를 정의하는 설정 파일입니다.

  • JSON 형식으로 작성되며, Task를 실행하기 위해 필요한 정보를 포함합니다.
  • Task Definition은 Amazon ECS가 Task를 생성하고 실행하는 방법을 알려주는 설명서 역할을 합니다.

3. Task Definition이 담고 있는 내용

Task Definition에는 다음과 같은 정보가 포함됩니다:

1) 컨테이너 정의(Container Definitions)

  • 컨테이너 이미지: 사용할 Docker 이미지의 위치(ECR, Docker Hub 등).
  • 메모리 및 CPU: 컨테이너에 할당할 자원 크기.
  • 네트워크 포트: 컨테이너가 수신 대기할 포트 정보.
  • 환경 변수: 컨테이너에 전달할 환경 변수.
  • 로깅: 컨테이너의 로그를 저장할 경로 및 설정.

예:

"containerDefinitions": [
  {
    "name": "web-app",
    "image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-web-app:latest",
    "cpu": 256,
    "memory": 512,
    "portMappings": [
      {
        "containerPort": 80,
        "hostPort": 80
      }
    ],
    "environment": [
      { "name": "ENV_VAR", "value": "production" }
    ],
    "logConfiguration": {
      "logDriver": "awslogs",
      "options": {
        "awslogs-group": "/ecs/my-web-app",
        "awslogs-region": "us-east-1",
        "awslogs-stream-prefix": "ecs"
      }
    }
  }
]

2) 네트워크 설정

  • VPC(Network Mode): bridge, awsvpc 같은 네트워크 모드.
  • Subnets 및 Security Groups: 컨테이너가 실행될 네트워크 위치.

3) Task의 실행 권한

  • AWS 리소스에 접근할 수 있는 IAM 역할 정의.

예:

"taskRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole"

4) Task-level 옵션

  • Task 전체의 메모리 및 CPU 제한.
  • 실행 타입: EC2 또는 Fargate.
  • 작업 개수: 몇 개의 복제본을 실행할 것인지 설정.

예:

"cpu": "1024",
"memory": "2048",
"requiresCompatibilities": ["FARGATE"]

4. Task와 Task Definition의 관계

  1. Task Definition 작성
    개발자는 Task Definition에 컨테이너 이미지와 관련 설정을 정의합니다.
  2. Task 실행
    ECS는 Task Definition을 읽어 Task를 생성하고 실행합니다.
    각 Task는 정의된 대로 컨테이너를 실행하며, ECS 클러스터 내에서 배포됩니다.
  3. Task의 동작
    실행된 Task는 ELB를 통해 요청을 처리하거나, Auto Scaling 설정에 따라 수가 조정됩니다.

Task와 Task Definition의 시각적 표현

Task Definition
└── Container Definitions
    ├── Container A (웹 서버 컨테이너)
    │   ├── 이미지: my-web-app:latest
    │   ├── 포트: 80
    │   └── CPU: 256 / 메모리: 512 MB
    └── Container B (로깅 컨테이너)
        ├── 이미지: logging-app:latest
        ├── 포트: 5000
        └── CPU: 128 / 메모리: 256 MB

Task (Task Definition 기반 실행)
└── 실행 중인 컨테이너:
    ├── 웹 서버 컨테이너 (A)
    └── 로깅 컨테이너 (B)

Cluster
└── 실행 중인 Task들:
    ├── Task 1
    ├── Task 2
    └── Task 3

요약

  • Task는 ECS 클러스터 내에서 실행되는 실제 작업 단위(컨테이너)입니다.
  • Task Definition은 Task 실행에 필요한 설정(컨테이너 정의, 네트워크, 리소스 등)을 담은 설명서입니다.
  • Task는 Task Definition을 기반으로 생성되며, ECS는 이를 자동으로 관리하고 확장할 수 있습니다.