Fargate 및 CodePipeline을 통해 CI/CD 환경을 구성하였습니다. 이번 글에서는 Fargate Task 배포시에 기존에는 사용하던 Rolling Update 옵션에서 Blue/Green Deployments 옵션으로 배포하는 구성을 하였습니다.

Blue/Green Deployments?

Blue/Green Deployments는 무중단 배포의 한 방식으로 기존 버전과 새버전이 공존하는 Rolling Update와는 달리 아래 그림과 기존 버전과 새버전이 별도로 존재하는 배포 형태를 말합니다. Blue/Green Deployments의 이점은 Rolling Update 대비 두가지 버전이 공존하면서 생기는 문제가 발생하지 않으며, 배포후에도 기존 버전이 일정시간 유지를 할 수 있어 새로운 버전의 배포가 문제가 있을 경우 더 빠른 Roll-back이 가능합니다. 



전체적인 작업 요약

  • Fargate 서비스 재구성

    1. CodeDeploy 에서 사용할 IAM Role 설정

    2. 로드 밸런서 재생성

    3. BuildArtifacts files 작성

    4. Fargate 서비스 생성
  • AWS CodePipeline을 통해 파이프라인 구성

    1. CodePipeline 기본설정

    2. Source 스테이지 구성 - CodeCommit 

    3. Build 스테이지 구성 - CodeBuild 선택

    4. Deploy 스테이지 구성 - Fargate ECS(블루/그린)으로 배포 구성

작업 시작

Fargate 서비스 재구성

1. CodeDeploy 에서 사용할 IAM Role 설정

ECS 배포에 Blue/Green Deployments을 사용하는 경우는 CodeDeploy에서 배포를 처리하는 도중 ECS 및 로드 밸런서, CloudWatch등에 관하여 수정, 처리를 하기 때문에 특정 권한이 필요 합니다. 이를 위해서 IAM Role을 생성해 줍니다.


IAM 콘솔을 통해 ecsCodeDeployRole을 만들고 다음의 정책을 연결합니다.



2. 로드 밸런서 생성

지난글에서 생성했던 ECS Fargate 서비스는 배포 옵션이 Rolling Update로 설정되어 새로운 개정으로 업데이트를 하여도 배포버전을 바꿀 수는 없습니다. 그래서  Blue/Green Deployments 배포 옵션을 위해서는 기존의 서비스가 아닌 새로운 서비스를 생성해야 합니다.

새로운 서비스를 만드는 만큼 서비스에 사용되는 Application Load Balancer도 새로 생성합니다.


[1. 로드 밸런서 구성]에서 ALB 생성시 이름은 helloapp-alb로 생성합니다. 

[3. 보안 그룹 구성]에서 배포중에 테스트로 사용할 포트에 대한 anywhere (0.0.0.0/0)로 부터의 TCP port 8080 연결을 허용하는 보안 그룹을 생성 또는 기존 보안 그룹을 연결합니다.

[4. 라우팅 구성]에서 helloap-tg1과 같이 번호로 식별할 수 있는 이름과 타겟 대상은 IP Address로 설정한 타겟 그룹을 생성합니다. Fargate Blue/Green Deployments은 2개의 타겟 그룹을 이용하여 2가지 버전을 연결하기 때문입니다.

[6. 검토] 후에 [생성]을 클릭하여 로그밸런서를 생성합니다.


3. BuildArtifacts files 작성

지난 CodePipeline과 단순 ECS 배포에서는 Pipeline의 구성 할때 CodeBuild에서 SourceArtifacts를 참조하여 빌드를 하였지만 CodeDeploy에서는 별다른 Artifacts설정없이 빌드중에 생성한 imagedefinitions.json를 참조하여 Deploy가 되었다면 Blue/Green Deployments에서는 실제 Deploy에도 Artifacts 설정을 해야 합니다.
Artfacts 입력을 위해 소스 root 디렉토리에 taskdef.json, appspec.yml 파일을 생성 후 아래 내용을 입력 및 저장합니다. 추가로 기존  buildspec.yml 파일 역시 입력 받은 taskdef.json, appspec.yml을 다시 BuildArtifacts로 내보내기 위해 하단 artifacts 항목을 수정합니다. 

# taskdef.json
{
"executionRoleArn": "arn:aws:iam::01234567890:role/ecsTaskExecutionRole",
"containerDefinitions": [{
"name": "helloapp",
"image": "01234567890.dkr.ecr.ap-northeast-2.amazonaws.com/fargatedemo/helloapp",
"essential": true,
"portMappings": [{
"hostPort": 80,
"protocol": "tcp",
"containerPort": 80
}]
}],
"requiresCompatibilities": [
"FARGATE"
],
"networkMode": "awsvpc",
"cpu": "256",
"memory": "512",
"family": "helloapp"
}

# appspec.yml
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: "arn:aws:ecs:ap-northeast-2:01234567890:task-definition/helloapp"
LoadBalancerInfo:
ContainerName: "helloapp"
ContainerPort: 80

# buildspec.yml
...(중략)...
artifacts:
files:
- imagedefinitions.json
- taskdef.json
- appspec.yml
discard-paths: yes


수정 및 추가된 파일을 CodeCommit Repository에 업데이트 합니다.

user:~/hello_app$ git add .

user:~/hello_app$ git commit -m "add build artifacts files"

[master 6b109ae] add build artifacts files

 3 files changed, 45 insertions(+), 1 deletion(-)

 create mode 100644 appspec.yml

 create mode 100644 taskdef.json

user:~/hello_app$  

user:~/hello_app$ git push

오브젝트 개수 세는 중: 5, 완료.

Delta compression using up to 8 threads.

오브젝트 압축하는 중: 100% (5/5), 완료.

오브젝트 쓰는 중: 100% (5/5), 1.06 KiB | 544.00 KiB/s, 완료.

Total 5 (delta 1), reused 0 (delta 0)

To ssh://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/helloapp

   60e8b2b..6b109ae  master -> master


4. Fargate 서비스 생성

2번과 마찬가지로 Fargate 서비스도 새로 생성해야 합니다. 생성 단계는 다음과 같습니다.

  1. [클러스터] 에서 기존에 생성했던 클러스터를 선택 후, 상세페이지에서 서비스 탭의 [생성] 버튼을 클릭합니다.
  2. [단계 1: 서비스 구성]는 상단은 기존과 같이 입력합니다.
  3. [단계 1: 서비스 구성]의 하단 부분 Deployments 항목으로 이동,  [Develoymet type]을 [Blue/green deployments][Service role for CodeDeploy]에는 1번에서 생성한 IAM role을 선택 한 후 다음 단계로 진행합니다.
  4. [단계 2: 네트워크 구성]는 상단은 기존과 같이 입력합니다.
  5. [단계 2: 네트워크 구성] 하단의 [로드를 밸런싱할 컨테이너] 항목으로 이동, 현재 서비스에서 사용할 ALB인 helloapp-alb를 추가 후 리스터 포트 80 및 테스트 리스터 포트 8080을 입력하여 신규로 생성합니다.
  6. 하단의 [Additional configuration] 항목으로 이동, [Target group 1 name] [helloapp-tg1]을 선택하고 [Target group 2 name]에는 [helloapp-tg2]를 입력하여 신규 생성합니다.
  7. [단계 3: Auto Scaling (선택사항)] [단계 4: 서비스 검토]를 검토 후 [서비스 생성]을 클릭하면 서비스가 생성되고 기존의 단순 ECS 배포와는 다르게 CodeDeploy Application이 생성되었다는 메세지가 아래와 같이 하단에 추가되며 CodeDeploy에도 해당 Application이 자동으로 생성됩니다.



AWS CodePipeline을 통해 파이프라인 구성

1. CodePipeline 기본설정

CodePipeline은 설정은 대부분 지난글과 같고 CodeDeploy 항목만 다소 차이가 있습니다.

최초 CodePipeline 생성을 위해 콘솔을 열고 [시작하기] 페이지에서 [파이프라인 생성]을 클릭합니다.


[Step 1]에서 [파이프라인 이름]을 입력후 지난글에서 작성한 [Service role]을 선택 하고  [다음]을 클릭합니다.  아티팩트 스토어는 기본 설정으로 유지 합니다.


2. Source 스테이지 구성 - CodeCommit 선택 

[Step 2]에서 [소스 공급자]를 [AWS CodeCommit]을 선택, [리포지토리 이름]과 [브랜치 이름]을 각각 어플리케이션에 맞게 선택 후 [다음]을 클릭합니다.


3. Build 스테이지 구성 - CodeBuild 선택

[Step 3]에서 [빌드 공급자]를 [AWS CodeBuild]을 선택 후, 현재 생성된 빌드 프로젝트가 없기 때문에 [Create project]를 선택합니다.


[Create project]을 클릭하면 빌드 프로젝트를 생성하기 위해 CodeBuild 콘솔이 팝업창으로 뜨고 이 창을 통해 프로젝트를 생성합니다.

프로젝트 설정 항목에서 [Project name]에 빌드 프로젝트 이름을 입력합니다.


환경 설정에서 CodeBuild는 별도의 빌드서버를 계속 구동할 필요 없이 빌드가 수행 되는 순간에만 Instance가 가동되어 빌드가 진행되어 실제 Instance가 구동되는 시간만큼의 비용을 지불하게 됩니다. 이때 빌드가 진행될 환경에 대한 설정으로 환경에 맞게 [Operating system][Runtime][Runtime version], [Image version]을 설정하며 Service Role은 지난 글에서 작성한 Role을 다시 사용합니다.

* 지난글에서 작성한 Role을 사용하면 ECR에 대한 권한 설정이 되어 CodePipeline 최초 구성시에도 Build가 실패하지 않습니다.


빌드 사양 및 로그에 관한 설정은 Default로 두고 [Continue to CodePileline]을 클릭하면 다시 CodePipelline 설정 화면으로 이동합니다.

위에서 작성한 buildspec.yml 파일이 root에 없거나 파일이름이 틀린 경우 [Buildspec name] 따로 입력합니다.


CodePipeline의 Step 3의 [프로젝트 이름]에서 방금 생성한 프로젝트가 선택 된 것을 확인 후 [다음]을 클릭합니다.


4. Deploy 스테이지 구성 - Fargate ECS(블루/그린)으로 배포 구성

[Step 4]에서 [배포 공급자] [Amazon ECS(블루/그린)], 어플리케이션 이름, 배포그룹, 작업정의 파일 AppSpec 파일을 선택 후 [다음]을 클릭합니다.

Build 스테이지에서와 같이 takedef.json 파일과 appsepc.yml 파일의 경로나 이름이 틀린 경우 따로 입력합니다.


[Step 5]에서 내용을 검토 후 하단의 [파이프라인 생성]을 클릭하면 파이프 라인이 생성되고 바로 파이프 라인이 실행되며 Deploy에서 오랜 시간이 진행됩니다. 이때 세부정보를 클릭하면 배포 진행을 자세하게 볼 수 있습니다.



배포 작업 세부정보 하단을 보면 단계적으로 대체 작업이 정상적으로 시작되어 현재 모든 트래픽이 흐르고 있는 것을 확인할 수 있습니다.

그 이후에 기존 작업은 1시간 대기 후 기존 작업을 종료 하게 되어 있습니다. 상용 서비스인 경우는 QA를 수행하겠지만 현재는 Demo 용도인 만큼 수동으로 Terminate시키면 4단계 1시간 대기가 정상 종료 후 배포도 정상 완료됩니다.


수동 Terminate 시킨 후 정상 적으로 배포 완료된 모습입니다.


+ Recent posts