[AWS] CodePipeline을 이용한 ECS Rolling Update (With EC2)

Jeongtae Kim·2023년 3월 8일
0

AWS

목록 보기
4/13
post-thumbnail

컨테이너 관리 서비스인 ECS의 Service를 CodePipeline(CodeCommit, CodeBuild, CodeDeploy)을 활용해 Rolling Update 해보겠습니다.

0. ECS Service 생성

ECS Service 생성 링크

1. CodeCommit

CodePipeline에서 Source 역할을 맡는 CodeCommit Repository를 하나 먼저 생성합니다.
저는 'ecs-rolling-update' 라는 이름으로 생성하겠습니다.

2. Codebuild

CodeBuild Project 이름은 'ecs-codebuild' 라고 정하겠습니다.

Source로는 전에 생성한 CodeCommit Repository를 선택하고, 기본 브랜치인 master을 선택합니다.

Environment는 EC2 Instance Type으로 많이 사용하는 Amazon Linux 2(standard:3.0) 을 선택하고, 안에서 Docker image를 빌드할 것이기 때문에 Privileged 를 체크합니다. IAM Role은 'ecs-codebuild-iam-role' 이라는 이름으로 새로 만들겠습니다. 생성된 IAM Role에 Docker Image 빌드를 위해서 AmazonEC2ContainerRegistryPowerUser Policy를 붙이는 것이 좋습니다.

추가로, 로그 기록을 위해 Cloudwatch Log Group의 이름과 Stream의 이름을 지정해주고 생성합니다.

이제 buildspec.yml을 작성하겠습니다. CodeCommit Repository에 buildspec.yml, Dockerfile, main.go(Go Application)을 생성했습니다.

version: 0.2

phases:
  pre_build:
    commands:
      - ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
      - 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.ap-northeast-2.amazonaws.com
      - REPOSITORY_URI=(AWS_ACCOUNT_ID).dkr.ecr.ap-northeast-2.amazonaws.com/blue-web
      - IMAGE_TAG=$(date "+%Y-%m-%d.%H.%M.%S")
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...
      - docker build -t $REPOSITORY_URI:$IMAGE_TAG . --no-cache
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker images...
      - docker push $REPOSITORY_URI:$IMAGE_TAG
      - echo Writing image definitions file...
      - printf '[{"name":"ecs-container","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
  files: 
    - imagedefinitions.json
    - taskdef.json
    - appspec.yaml

Docker Image의 태그를 날짜로 설정하여 빌드 & 푸쉬하고 있습니다. (예 : 2023년 3월 7일 8시 53분 56초 -> 2023-03-07.20.53.56) Task Definition의 image를 최신 버전으로 바꿔야하기 때문에 imagedefinitions.json도 post_build에서 생성하겠습니다.

3. CodeDeploy

CodeDeploy 같은 경우 CodePipeline에서 생성할 것이기 때문에 CodeCommit Repository에 taskdef.jsonappspec.yml 을 생성합니다. taskdef.json은 task definition을 설정하는 파일입니다.

taskdef.json

{
    "executionRoleArn": "arn:aws:iam::(AWS_ACCOUNT_ID):role/ecsTaskExecutionRole",
    "containerDefinitions": [
        {
            "name": "ecs-container",
            "image": "(AWS_ACCOUNT_ID).dkr.ecr.ap-northeast-2.amazonaws.com/blue-web",
            "memory": 256,
            "essential": true,
            "portMappings": [
                {
                    "hostPort": 0,
                    "protocol": "tcp",
                    "containerPort": 80
                }
            ],
            "healthCheck": {
                "command": [
                    "CMD-SHELL",
                    "curl -f http://localhost/health || exit 1"
                ]
            }
        }
    ],
    "requiresCompatibilities": [
        "EC2"
    ],
    "networkMode": "bridge",
    "family": "ecs-task-definition"
}

appspec.yml

version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: <TASK_DEFINITION>
        LoadBalancerInfo:
          ContainerName: "ecs-container"
          ContainerPort: 80

원래 appspec.yml에 TaskDefinition의 arn을 넣어야 하는데 taskdef.json을 정의해주었으므로 '<TASK_DEFINITION>' 이라고 적습니다.

4. CodePipeline

CodePipeline의 이름은 'ecs-pipeline' 이라고 하고, Service Role은 새로 생성하겠습니다.

Source는 CodeCommit의 Repository와 Branch를 선택합니다. 나머지는 기본 설정으로 놔두겠습니다.

Build는 CodeBuild의 Project를 선택합니다.

Deploy Provider는 Amazon ECS를 선택하고 기존에 생성한 Cluster, Service를 선택하고, CodeBuild에서 Output으로 나오는 Image Definitions File의 이름을 적습니다.

이제 pipeline을 생성합니다.

Deploy까지 완료됐고, 무엇이 바뀌었는지 보겠습니다.

1. ECR Image가 업데이트 되었습니다.


2. Task들의 Revision이 업데이트 되었습니다.

마치도록 하겠습니다. 감사합니다.

profile
유용할지도 모른다.

0개의 댓글