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 시킨 후 정상 적으로 배포 완료된 모습입니다.


Fargate 을 통해 배포된 Appilication을 배포하였고 본 글에서는 CodePipeline을 이용하여 기본적인 CI/CD 구성을 하였습니다.

추가로 지난 Fargate 게시글 내용중에 생성한 작업정의(HelloappTask), 서비스(HelloService), 콘테이너(HelloContainer) 이름들과 같이 각각의 이름이 다를 경우 CodePipeline에서 해당 Appilication을 찾지 못하는 에러가 발생할 수 있어 본 글에서는 모두 helloapp으로 통일 하였습니다.

전체적인 작업 요약

  • 파이프라인 구성 준비

    1. CodeCommit에 사용자가 접근 할 수 있게 IAM 권한 설정

    2. CodeCommit에 Repository 생성 

    3. 빌드 사양 파일 추가

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

    1. CodePipeline 기본설정

    2. Source 스테이지 구성 - CodeCommit 

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

    4. Deploy 스테이지 구성 - Fargate ECS 로 배포 구성

    5. CodeBuild에 Amazon ECR 권한 설정

작업 시작

파이프라인 구성 준비

1. CodeCommit에 사용자가 접근 할 수 있게 IAM 권한 설정 


AWS CodeCommit의 Repository에 연결하여 소스를 업데이트 하기 위해 1.7.9이상의 Git을 설치 후 소스 폴더를 로컬 저장소로 초기화 합니다.

user:~$ sudo apt-get install git

 

...(중략)...

 

user:~$ cd hello_app/

user:~/hello_app$ git init

/home/user/hello_app/.git/ 안의 빈 깃 저장소를 다시 초기화했습니다

user:~/hello_app$



CodeCommit에 엑세스 하기 위해 IAM 을 통해 설정할 IAM 사용자에게 AWSCodeCommitFullAccess  또는 포함하는 권한을 연결합니다.


작업 PC의 터미널에서 ssh-keygen을 입력하여 홈 디렉토리 및의 .ssh/ 디렉토리에 생성된 키 파일의 내용을 확인합니다.

user:~/hello_app$ ssh-keygen


Generating public/private rsa key pair.

Enter file in which to save the key (/home/user/.ssh/id_rsa): /home/user/.ssh/codecommit_rsa          # 키 파일이 저장될 폴더 명을 입력합니다.


Enter passphrase (empty for no passphrase): **********          # 패스워드 입력

Enter same passphrase again: **********          # 패스워드 재 입력


Your identification has been saved in /home/user/.ssh/codecommit_rsa.

Your public key has been saved in /home/user/.ssh/codecommit_rsa.pub.

The key fingerprint is:

45:63:d5:99:0e:99:73:50:5e:d4:b3:2d:86:4a:2c:14 user@demo-pc

The key's randomart image is:

+--[ RSA 2048]----+ | E.+.o*.++| | .o .=.=o.| | . .. *. +| | ..o . +..| | So . . . | | . | | | | | | | +-----------------+

user:~/hello_app$ cat ~/.ssh/codecommit_rsa.pub

ssh-rsa EXAMPLE-AfICCQD6m7oRw0uXOjANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCVVMxCzAJB

gNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6b24xFDASBgNVBAsTC0lBTSBDb2

5zb2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAdBgkqhkiG9w0BCQEWEG5vb25lQGFtYXpvbi5jb20wHhc

NMTEwNDI1MjA0NTIxWhcNMTIwNDI0MjA0NTIxWjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAw

DgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6b24xFDAS=EXAMPLE user@demo-pc



IAM 콘솔에서 앞에서 생성된 사용자를 선택 후 보안 자격 증명 탭을 선택한 다음 SSH 퍼블릭 키 업로드를 클릭, codecommit_rsa.pub 내용을 업데이트 합니다.




SSH 키를 업데이트 후 콘솔에 나타난 SSH 키 ID 를 저장합니다.



작업 PC에서 ~/.ssh/ 디렉토리에 config 파일을 생성 한 SSH 퍼블릭 키 설정을 추가 후 해당 파일의 권한을 변경합니다.

user:~/hello_app$ vim ~/.ssh/config

Host git-codecommit.*.amazonaws.com

  User APKABCDEFGH5EXAMPLE

  IdentityFile ~/.ssh/codecommit_rsa


user:~/hello_app$ chmod 600 ~/.ssh/config



터미널을 통해 접속이 잘 되는지 확인해 봅니다. 

user:~/hello_app$ ssh git-codecommit.ap-northeast-2.amazonaws.com

You have successfully authenticated over SSH. You can use Git to interact with AWS CodeCommit. Interactive shells are not supported.Connection to git-codecommit.ap-northeast-2.amazonaws.com closed by remote host.

Connection to git-codecommit.ap-northeast-2.amazonaws.com closed.



2. CodeCommit에 Repository 생성

AWS CodeCommit 콘솔로 이동, [시작하기] - [리포지토리 생성]을 클릭 합니다.  리포지토리 이름을 입력 후 [생성] 을 클릭합니다.



리포지토리를 생성하면 SSH와 HTTPS를 통한 연결방법이 표시 됩니다. 앞에서 SSH 통해 연결하는 단계를 수행하였기 때문에 URL만 복제를 하겠습니다.



작업 PC의 소스가 저장 및 git의 Local Repository 에서 해당 주소를 통해 remote 주소를 추가해줍니다.

user:~/hello_app$ git remote add origin ssh://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/helloapp

user:~/hello_app$ git remote

origin

user:~/hello_app$ 


3. 파이프라인 구성 준비 - 빌드 사양 파일 추가

Pipeline?

컴퓨터 과학에서 파이프라인(영어: pipeline)은 한 데이터 처리 단계의 출력이 다음 단계의 입력으로 이어지는 형태로 연결된 구조를 가리킨다. 이렇게 연결된 데이터 처리 단계는 한 여러 단계가 서로 동시에, 또는 병렬적으로 수행될 수 있어 효율성의 향상을 꾀할 수 있다. 각 단계 사이의 입출력을 중계하기 위해 버퍼가 사용될 수 있다.

< 파이프라인 (컴퓨팅), 출처 : 위키 백과 >


CodePipeline은 위에서 정의한 파이프라인과 같이 CodeCommit -> CodeBuild -> CodeDeploy의 단계별 진행을 통해 파이프 라인을 구성하고 다음과 같은 순서로 진행됩니다.

  1. 개발자가 소스를 업데이트
  2. CloudWatch Event(권장사항)에서 이를 감지하여 CodeBuild로 전달
  3. CodeBuild는 CodeCommit의 결과물인 Source Artifact를 이용하여 빌드 진행
  4. 빌드 성공 시 이후 빌드의 결과물인 도커 이미지를 ECR에 등록
  5. CodeDelpoy는 CodeBuild의 결과물인 Build Artifact를 이용하여 배포 진행
  6. 배포 설정이 문제가 없으면 ECS Container는 ECR의 이미지를 통해 서비스 수행

앞에서는 1단계를 위한 CodeCommit에서 Remote Repository 생성 및 등록을 하였고 해당 소스를 업데이트 할 수 있는 환경을 구성하였고 실제 Pipeline 구성은 CodeBuild 이후의 설정이 주가 되겠습니다.

CodeBuild 수행을 위해서는 CodeCommit의 결과물인 Source Artifact가 필요하며 여기에는 필드에 필요한 소스 파일과 환경파일들로 다음과 같습니다.

hello.py, DockerFile, requirements.txt 3개 파일은 Local에서 빌드시에도 사용하는 파일이지만 buildspec.yml파일이 추가 되었습니다.

해당 파일은 Local 아닌 AWS에서 Build를 수행 하기 위해서는 실제 빌드에 수행되는 명령어와 환경변수등 빌드 사양을 정의하여 CodeBuild에 알려주기 위한 용도로 사용되며 소스 코드 root 디렉토리에 buildspec.yml을 생성 하여 아래 내용을 추가해 줍니다.

version: 0.2

phases:
pre_build:
commands:
- echo Logging in to Amazon ECR...
- aws --version
- $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
- REPOSITORY_URI=01234567890.dkr.ecr.ap-northeast-2.amazonaws.com/fargatedemo/helloapp
- COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
- IMAGE_TAG=${COMMIT_HASH:=latest}
build:
commands:
- echo Build started on `date`
- echo Building the Docker image...
- docker build -t $REPOSITORY_URI:latest .
- docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
post_build:
commands:
- echo Build completed on `date`
- echo Pushing the Docker images...
- docker push $REPOSITORY_URI:latest
- docker push $REPOSITORY_URI:$IMAGE_TAG
- echo Writing image definitions file...
- printf '[{"name":"helloapp","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
files:
- imagedefinitions.json


예제의 내용은 다음과 같습니다.

1. pre_build 단계에서는 다른 Fargate 예제에서 처럼 ECR에 로그인 후 이미지 별로 사용할 고유의 tag를 생성합니다.

2. build 단계에서는 DockerFile을 통해 실제 이미지를 빌드 후 pre_build에서 생성한 tag를 지정합니다.

3. post_build 단계에서는 고유의 tag와 latest tag의 2개의 tag와 함께 이미지를 ECR에 푸쉬 합니다.

    추가로 imagedefinitions.json을 결과물로 생성하여 CodeDeploy에서 이를 참조하여 ECS에 작업을 배포 합니다.


REPOSITORY_URI 값(012345678910.dkr.ecr.us-west-2.amazonaws.com/hello-world)을 해당 도커 이미지의 Amazon ECR 리포지토리 URI(이미지 태그 제외)로 바꿉니다. helloapp은 서비스에서 사용하는 작업 정의에서 도커 이미지를 참조하는 컨테이너 이름으로 바꿉니다.



buildspec.yml가 포함된 Local Repository를 Commit후 Remote로 푸쉬합니다.

user:~/hello_app$  git add .

user:~/hello_app$  git commit -m "first commit."

[master (최상위-커밋) d514011] first commit.

 4 files changed, 56 insertions(+)

 create mode 100644 Dockerfile

 create mode 100644 buildspec.yml

 create mode 100644 helloapp/hello.py

 create mode 100644 requirements.txt

user:~/hello_app$  

user:~/hello_app$  git push --set-upstream origin master

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

Delta compression using up to 8 threads.

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

오브젝트 쓰는 중: 100% (7/7), 1.21 KiB | 310.00 KiB/s, 완료.

Total 7 (delta 0), reused 0 (delta 0)

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

 * [new branch]      master -> master

'master' 브랜치가 리모트의 'master' 브랜치를 ('origin'에서) 따라가도록 설정되었습니다.




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

1. CodePipeline 기본설정

CodePipeline은 마법사에 따라 간단하게 진행 됩니다.

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



[Step 1]에서 [파이프라인 이름]을 입력후 [다음]을 클릭합니다. Service role 및 Role name, 아티팩트 스토어는 기본 설정으로 유지 합니다.


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

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

변경 탐지 옵션은 소스 변경시 바로 업데이트 될 수 있도록 권장사항인 CloudWatch Event를 그대로 두면 됩니다.

추가로 소스 공급자가 CodeCommit과 같은 AWS 자원이 아닌 외부 자원인 GitHub이나 BitBucker등일 때는 Webhook 설정을 해야 합니다.


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 name은 기본 설정으로 유지합니다.


* Role name은 CodeBuild가 진행될 때 ECR의 도커 이미지를 기반으로 빌드 후 다시 업데이트 하기 때문에 해당 Role에 ECR 에 접근할 권한 업데이트가 필요 합니다.




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

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



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


4. Deploy 스테이지 구성 - Fargate ECS 로 배포 구성

[Step 4]에서 [배포 공급자] [Amazon ECS], [클러스터 이름], [서비스 이름]을 ECS에서 생성한 사용했던 클러스터 및 서비스 이름을 선택 후 [다음]을 클릭합니다.


5. CodeBuild에 Amazon ECR 권한 설정

[Step 5]에서 내용을 검토 후 하단의 [파이프라인 생성]을 클릭하면 파이프 라인이 생성되고 바로 파이프 라인이 실행 되지만 CodeBuild에서 언급한 것과 같이 권한이 부족하여 빌드 단계에서 실패하게 됩니다.


권한 부여를 위해 IAM 콘솔에서 CodeBuild에서 생성한 role인 [code-helloapp-service-role]에 아래와 같이 [AmazonEC2ContainerRegistryPowerUser] 정책을 부여 합니다.



권한 업데이트 후 CodePipeline 콘솔에서 [변경 사항 릴리즈]를 통해 파이프라인을 다시 수행하면 다음과 같이 단계별 진행사항을 볼 수 있습니다.



AWS ECS fargate를 사용한 Appilication 배포 - 2

지난 글에서는 Fargate를 통해 Appilication을 배포하였고 본 글에서는 Appilication이 도커 이미지 또는 작업이 업데이트 되는 경우와 기타 옵션들에 대해 좀 더 자세히 확인하도록 하겠습니다.


웹 어플리케이션 업데이트

지난 글에는 간단하게 웹에 접근했을 때 "Hello World!"를 출력하였는데 /welcome 으로 접근할때는 "Welcome!"을 출력하는 엄청난 기능을 추가하였습니다.
# hello.py
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
return "Hello World!"

@app.route("/welcome")
def hello():
return "Welcome!"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)



소스가 업데이트 되었으니 지난글에서와 같이 우선 ECR에 푸쉬 하도록 하겠습니다.

푸쉬 명령어 4개 중에 1번의 로그인 과정은 최초 로그인 후 12시간이 지속되니 로그인 세션이 남아있다면 생략 가능 합니다. 추가로 푸쉬전에 태깅을 할때 latest로 태깅을 하면 지난 푸쉬 이미지 Tag과 겹치니 버전과 같은 고유한 숫자, 문자등으로 식별할 수 있도록 구분하여 태깅합니다. 

이번 푸쉬 명령어에서는 최초에서 변경된 내용만 업데이트 되었습니다.


(venv) user:~/hello_app$ docker build -t fargatedemo/helloapp .

Sending build context to Docker daemon  67.66MB

Step 1/8 : FROM python:alpine

 ---> 1a8edcb29ce4

Step 2/8 : LABEL Name=flaskapp Version=0.0.1

 ---> Using cache

 ---> 840ae2afa937

...(중략)...

Successfully built 74b72d5f1369

Successfully tagged fargatedemo/helloapp:latest

(venv) user:~/hello_app$  

(venv) user:~/hello_app$ docker tag fargatedemo/helloapp:latest 111111111111.dkr.ecr.ap-northeast-2.amazonaws.com/fargatedemo/helloapp:revision3
(venv) user:~/hello_app$
(venv) user:~/hello_app$ docker push 111111111111.dkr.ecr.ap-northeast-2.amazonaws.com/fargatedemo/helloapp:revision3
The push refers to repository [111111111111.dkr.ecr.ap-northeast-2.amazonaws.com/fargatedemo/helloapp]
f2ea5f782ba9: Pushed 
767a8a839569: Pushed 
cb0f6e36ebca: Pushed 
7158e09cb118: Layer already exists 
8643e4accddc: Layer already exists 
43e8a7decf15: Layer already exists 
7484166a246c: Layer already exists 
1c862c0e1a30: Layer already exists 
7bff100f35cb: Layer already exists 
latest: digest: sha256:d192735e68903be86a6f9bc0c33c55c16c4d123640571b11da53c0c1220ccf54 size: 2200
(venv) user:~/hello_app$


푸쉬가 끝난 후 ECR에서 repository를 확인하면 다음과 같이 image가 추가 되어 있습니다.



새로운 이미지를 생성하였으니 작업정의도 업데이트가 필요 합니다. 업데이트를 하기 위하여 작업정의 항목에서 지난글에서 작성한 작업정의를 체크한 후 새 개정 생성을 클릭합니다.



지난글에서 작성하였던 작업정의 생성 화면과 거의 유사한 설정 화면이 나옵니다. 설정한 것들은 현재는 크게 바뀌지 않았고 소스 코드가 담긴 도커 이미지가 바뀌었으니 하단에 컨테이너 정의 항목으로 이동하여 해당 컨테이너를 클릭하여 설정화면이 나오면 이미지의 URL을 새로 업데이트 된 이미지의 URL로 변경합니다.



다음은 컨테이너 항목 창에서 업데이트를 클릭하여 나온 후 최하단의 생성 버튼을 눌러서 새 개정을 생성해 주면 다음과 같이 개정이 추가 됩니다.

추후에도 개정을 도커이미지 업데이트(소스 변화)에 따라 생성시 버젼별로 작업을 관리 할 수도 있고 서비스 업데이트 후 문제가 발생시 지난 버전의 작업으로 빠르게 롤백이 가능합니다.



새로운 작업정의를 바탕으로 서비스도 업데이트가 필요 합니다. 서비스 업데이트를 위해 클러스터 항목에서 지난글에서 작성한 서비스가 포함된 클러스터를 클릭하면 다음과 같이 클러스터에 대한 상세 정보가 표시 됩니다. 업데이트를 할 서비스를 체크 후 업데이트 합니다.



서비스 생성시 화면과 유사한 1단계 설정 화면이 표시되는데 Revision을 최신 버전으로 변경하고 새 배포 적용에 체크를 하고 다음 단계로 넘어갑니다.

추가로 2단계 네트워크 설정 및 3단계 오토스케일링도 변동이 없다면 4단계 검토 화면까지 넘어가서 서비스 업데이트를 적용합니다.



서비스가 업데이트 되면 Fargate는 작업 개수, 최소 정상 상태 백분율, 최대 백분율 배포를 수행합니다.

배포 중에 배포 화면은 다음과 같이 새로 배포된 작업정의 개정이 PRIMARY이지만 기존 작업도 실행하다 안정화 된 후 제외됩니다.



역시 작업탭에서도 Task2의 기존 작업 외에 Task 3이 프로비저닝 -> 펜딩 -> 런닝 상태로 진행 되어 정상 작동시 서비스를 인계 후 기존 작업은 추후에 중지 됩니다.



서비스 업데이트 후 추가로 한 /welcome 경로에 대한 서비스가 추가 되었습니다.


부록

배포 관련 옵션

지난 글에서 배포 관련 옵션인 작업 개수, 최소 정상 상태 백분율, 최대 백분율 배포에 대하여 간략하게 넘겼는데 다음과 같습니다.

작업 개수 - 사용자가 원하는 평상시 원하는 실제 서비스 작업 숫자

최소 정상 상태 백분율 - 작업 개수 대비 배포가 진행중 작업의 stuatus RUNNING의 필수 백분율

최대 백분율 - 작업 개수 대비 배포 진행되는중 PROVISIONING, RUNNING, PENDING 등의 모든 상태가 가능한 백분율


예를 들면 작업개수가 2 이고 최소가 50, 최대가 100이면 배포를 진행하기 위해 이미 실행중이던 작업 하나를 중단하는 상황이 발생 합니다.

최소와 최대의 비율에 따라 대략적으로 아래표와 같이 진행합니다.

결론은 클러스터 자원을 적게 하기 위해서는 1~2번 방법을 가용성을 위해서는 3~4번을 사용하면 되겠습니다.

다만 Fargate 특성상 초단위로 사용한 비용만 청구 되고 실제 4번 단계로 진행되어도 작업개수의 200%로 작업이 진행되는 10분 내외이기 때문에 최대 백분율은 default인 200%가 좋을듯 합니다.

 

 최소정상상태

 최대 백분율

 작업 분류

 배포전

 단계 1

 단계 2

 단계 3

 단계 4

50% 

 100%

 기존 작업

 2(success)

 1(success)

 1(success)

 

 

 배포 대상 작업

 

 

 1(success)

 1(success)

 2(success)

 50% 

150% 

 기존 작업

 2(success)

 2(success)

 1(success)

 

 

 배포 대상 작업

 

 1(pending)

 1(pending)

 1(success) 1(pending)

 2(success)

 100%

150% 

 기존 작업

 2(success)

 2(success)

 1(success) 

1(success)  

 

 배포 대상 작업

 

 1(pending)

 1(success) 1(pending)

 2(success)

 2(success)

 100%

 200%

 기존 작업

 2(success)

 2(success)

 2(success)

 

 

 배포 대상 작업

 

 2(pending)

 2(success)

 2(success)

 


스케일 업

AWS 컴퓨팅 자원들은 트래픽이 증가할 경우 AutoScaling을 통해 자동으로 Scale-Out 을 구현할 수 있습니다. Fargate는 Scale-Out은 물론 Scale-Up도 운영에 큰 부담이 가지 않게 적용 가능합니다. 개발용이나 초창기 어플리케이션은 최하 사양으로도 사용하다 규모나 사용성이 올라가면 손쉽게 Scale-Up을 할 수 있는 것입니다.

상단에서 작업했던 작업 정의에서 새 개정을 생성시 vCPU 및 메모리를 다시 설정할 수 있는데 아래 사진처럼 새 개정 생성을 만들고 새로운 개정을 통해 서비스를 재시작 하기만 하면 위에서 도커 이미지를 업데이트 한것과 같이 Fargate에서 자동으로 작업을 전환합니다.






AWS Fargate 소개

AWS Fargate는 AWS의 컨테이너 서비스인 ECS에 포함된 하나의 옵션으로 2017년 부터 시작된 서비스 이며 2018년 말경 한국리전에서도 사용할 수 있게 되었습니다.

기존의 ECS가 Amazon EC2 인스턴스 클러스터를 관리하고, 인스턴스 유형을 선택하고, 컨테이너의 일정을 관리하고, 클러스터 사용률을 최적화해야 했던 것과는 다르게 EC2 자원 관리를 AWS에 맡겨 서버의 프로비저닝이나 스케일링에 대해 걱정할 필요없이 컨테이너 및 어플리케이션에 집중할 수 있습니다. 추가로 네트워크, 보안 및 서비스 통신에 대한 완벽한 제어 기능을 제공하며 보안, 네트워킹, 액세스 제어, 개발자 툴링, 모니터링 및 로깅을 위해 AWS 서비스와 기본적으로 통합되어 있습니다.


서버를 관리하지 않는 것은  AWS의 다른 ServerLess 서비스인 Lambda와 비슷하여 컨테이너 버전의 ServerLess라고 할 수 있으며 성능이나 시간제한이 있었던 Lambda의 단점을 어느정도 채워줄 수 있는 옵션이 될 수 있습니다.


비용

아래는 AWS 홈페이지에 소개된 비용으로 1CPU 1GB 메모리 기준 시간당 약 0.051$의 요금으로 같은 스펙인 t2.micro 의 0.013$ 보다는 비싸편 입니다.

 
  • 아시아 태평양(서울)
요금
시간별 vCPU당0.04656 USD
시간별 GB당0.00511 USD

다만 지원 되는 구성이 다음와 같이 0.25개부터 가능하여 다소 절약은 가능합니다(그것보다 Fargate 덕분에 감소하는 인적 리소스로 인한 감소가 더 클것입니다.)

CPU
메모리 값
0.25vCPU0.5GB, 1GB, 2GB
0.5vCPU최소 1GB 및 최대 4GB(1GB씩 증가)
1vCPU최소 2GB 및 최대 8GB(1GB씩 증가)
2vCPU최소 4GB 및 최대 16GB(1GB씩 증가)
4vCPU최소 8GB 및 최대 30GB(1GB씩 증가)


작업환경 전 준비사항

1. 로컬 데스크탑 환경 - 본 글에서는 ubuntu 리눅스로 진행하지만 간단한 소스 코드에 AWS 콘솔위주이기 때문에 크게 상관 없습니다.

2. AWS 계정

3. 도커에 대한 기본 지식


작업 시작

IAM 계정 생성

AWS를 사용하며 작업중 aws cli를 사용을 위해 Access 키가 필요하여 필요한 IAM 계정을 생성합니다. 다만 aws cli는 간단하게 명령어 만으로 많은 작업을 수행할 수 있는 강력한 도구이기 때문에 막강한 권한을 가진 root 계정 또는 콘솔 로그인이 가능한 계정 보다는 해당 Appication에서 사용하는 특정 권한만을 허용한 계정을 사용하는 것이 보안에 좋습니다.


맨 처음 IAM 설정 권한을 가진 콘솔 계정으로 로그인하여 IAM을 검색, IAM 설정 페이지로 이동 후 user 생성을 위해 사용자 항목으로 이동을 합니다.


사용자 추가를 클릭하여 사용자 추가 화면으로 이동합니다.


1단계에서는 유저 이름 및 엑세스 유형을 입력합니다. 해당 IAM 계정은  Access Key를 필요로 하는 프로그래밍용 계정이므로 프로그래밍 방식 엑세를 선택 후 다음을 클릭합니다.



2단계는  권한 설정을 하는 페이지로 IAM과 ECS, ECR에 관해 깊은 이해가 있으면 필요한 권한만을 붙이는 것이 좋겠지만 현재 작업에서는 기존에 AWS에서 생성되는 작업으로 진항하겠습니다. 

정책 연결을 위해 기존 정책 직접 연결을 클릭 후 ECR 관련 작업을 위해 AmazonEC2ContainerRegistryFullAccess와 ECS 작업을 위해 AmazonEC2ContainerServiceFullAccess 정책을 각각 검색하여연결해 줍니다. 3단계는 해당 IAM에 Tag를 달아주기 위해 Key에 Name Value에 1단계에서 입력한 IAM롤의 이름을 입력하고 다음을 클릭합니다.

4단계에서는 1~3단계에서 작업한 내용을 확인 후 실제 생성을 위해 사용자 만들기를 클릭합니다.



5단계는 Access Key를 확인하는 단계로 ID와 비밀 키가를 확인하거나 CSV 파일로 다운받아 관리할 수 있습니다.

비밀 액세스 키 밑의 표시를 누르면 위와 같이 표시 되니 잘 관리해야 합니다. 계정의 Access Key는 본 페이지 외에서는 확인할 수 없고 분실할 경우에는 IAM 권한을 가진 계정으로 키를 다시 생성하여 다른 키를 사용해야 합니다.


2. 도커 이미지 생성 및 ECR에 등록

- aws cli 환경설정

우선  어플리케이션을 AWS에 push 하기 위해 먼저 aws cli 환경설정을 합니다. aws cli는 Python pip를 통해 설치하는데 시스템 전체에 영향을 주지 않기 위해 virtualenv를 설치합니다.

user:~$ sudo apt-get update -y

...(중략)...

user:~$ sudo apt-get install -y python-virtualenv

...(중략)...

user:~$ mkdir hello_app

user:~$ cd hello_app/

user:~/hello_app$ 

user:~/hello_app$ virtualenv -p python3 venv

Running virtualenv with interpreter /home/user/flaskapp/venv/bin/python3
Using real prefix '/usr'
New python executable in /home/user/hello_app/venv/bin/python3
Also creating executable in /home/user/hello_app/venv/bin/python
Installing setuptools, pkg_resources, pip, wheel...done.
user:~/hello_app$
user:~/hello_app$ source venv/bin/activate

(venv) user:~/hello_app$ 

Python 3.6.7



다음으로 awscli를 설치하고 기본 설정을 합니다. 설정은 아래와 같이 위에서 설정한 IAM 계정의 Access Key와 비밀키, 기본 리전과 기본 출력 형식을 지정합니다.


(venv) user:~/hello_app$ pip install awscli --upgrade

...(중략)...

(venv) user:~/hello_app$ aws configure

AWS Access Key ID [****************L2DQ]: AKIAIAI5N5YP57AOVZFA

AWS Secret Access Key [****************KEHt]: ssf+...(중략)...DDvp

Default region name [ap-northeast-2]: 

Default output format [json]: 



 -  Docker 이미지용 Application 작성

aws에 이미지를 올리고 컨테이너를 컨트롤할 준비가 되었으면 실제 aws에 올릴 이미지를 작성하겠습니다. 이미지를 생성하기 위해 위해 가장 간단한게 웹페이지에 "Hello World!"를 출력하는 프로그램을 아래와 같이 작성하였습니다. 해당 프로그램은 모든 소스로 부터 접근이 가능하며 80포트로 서비스 하도록 설정되었습니다.

# hello.py
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
return "Hello World!"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)


 - ECR에 repository 생성

다음으로 해당 프로그램을 실제 AWS Fargate로 서비스를 하기 위해 ECR에 등록 합니다. 

참고로 ECR은 Amazon Elastic Container Registry의 약자로 사용자가 Docker 컨테이너 이미지를 손쉽게 저장, 관리 및 배포할 수 있게 해주는 완전관리형 Docker 컨테이너 레지스트리입니다. 쉽게 얘기하면 Fargate를 포함한 아마존의 컨테이너 서비스에서 사용하기 위한 도커 이미지 저장소입니다.


ECR에 등록하기 위해서는 최초에는 AWS 콘솔에서 ECR을 검색한 후 repository를 작성합니다.


다음 구성화면에서 repository 이름을 작성하는데 콘솔에서 보여주는 것과 같이 네임스페이스/서비스 형식의 이름으로 작성할 수 있으며 대문자는 사용 불가능 합니다.


위의 AWS 콘솔에서는 "fargagedemo/helloapp"으로 repository를 작성하였고 aws cli 명령어는 다음과 같습니다.

(venv) user:~/hello_app$ aws ecr create-repository --repository-name fargatedemo/helloapp

{

    "repository": {

        "repositoryArn": "arn:aws:ecr:ap-northeast-2:111111111111:repository/fargatedemo/helloapp",

        "registryId": "111111111111",

        "repositoryName": "fargatedemo/helloapp",

        "repositoryUri": "111111111111.dkr.ecr.ap-northeast-2.amazonaws.com/fargatedemo/helloapp",

        "createdAt": 1547993101.0

    }

}

(venv) user:~/hello_app$ 


 - ECR에 repository에 Docker Image 올리기

repository 생성 후에 ECR 메인 페이지에서 해당 repository이름을 클릭하면 다음과 같이 repository에 포함된 이미지 리스트가 표시되며 최초 이미지 등록시 푸쉬 명력 보기를 통해 손쉽게 도커 이미지를 ECR에 올릴 수 있습니다.


푸쉬 명령은 다음과 같으며 AWS CLI를 통해 직접 명령어를 입력시 오탈자등으로 인해 잘못 입력되기 쉬운데 친절하게 붙여준 텍스트를 단계별로 수행만 하면 이미지가 저장됩니다.


Command 입력 결과는 다음과 같습니다. 로그인 수행 시 최초 명령의 결과값을 그대로 복사하여 다시 입력하면 로그인이 되고 그 이후에 순서대로 2. 빌드 -> 3. 태깅 -> 4. 푸쉬를 진행 합니다.

푸쉬는 모든 이미지가 Pushed가 되면 종료 된 것입니다.

(venv) user:~/hello_app$ (aws ecr get-login --no-include-email --region ap-northeast-2)

docker login -u AWS -p eyJwYXlsb2FkIjoiY1VkeE1sc3d2M1FLbEU0dHVtZzA3aVh0K0F1SWoySzFQZG1OYy9GYjYvYy9MYnR1bnVJNll1b2I1bX

...(중략)...

9uIjoiMiIsInR5cGUiOiJEQVRBX0tFWSIsImV4cGlyYXRpb24iOjE1NDgwMzcyNDh9 https://111111111111.dkr.ecr.ap-northeast-2.amazonaws.com

## 위 명력을 그대로 입력 ##

(venv) user:~/hello_app$ 

(venv) user:~/hello_app$ docker login -u AWS -p eyJwYXlsb2FkIjoiY1VkeE1sc3d2M1FLbEU0dHVtZzA3aVh0K0F1SWoySzFQZG1OYy9GYjYvYy9MYnR1bnVJNll1b2I1bX

...(중략)...

9uIjoiMiIsInR5cGUiOiJEQVRBX0tFWSIsImV4cGlyYXRpb24iOjE1NDgwMzcyNDh9 https://111111111111.dkr.ecr.ap-northeast-2.amazonaws.com


Login Succeeded

(venv) user:~/hello_app$ docker build -t fargatedemo/helloapp .

Sending build context to Docker daemon  17.34MB

Step 1/8 : FROM python:alpine

 ---> 1a8edcb29ce4

Step 2/8 : LABEL Name=flaskapp Version=0.0.1

 ---> Using cache

 ---> 840ae2afa937

...(중략)...

Successfully built 74b72d5f1369

Successfully tagged fargatedemo/helloapp:latest

(venv) user:~/hello_app$  

(venv) user:~/hello_app$ docker tag fargatedemo/helloapp:latest 111111111111.dkr.ecr.ap-northeast-2.amazonaws.com/fargatedemo/helloapp:latest
(venv) user:~/hello_app$
(venv) user:~/hello_app$ docker push 111111111111.dkr.ecr.ap-northeast-2.amazonaws.com/fargatedemo/helloapp:latest
The push refers to repository [111111111111.dkr.ecr.ap-northeast-2.amazonaws.com/fargatedemo/helloapp]
55e63f5d5562: Pushed 
642a791f9fd2: Pushed 
76e39cec4c1f: Pushed 
7158e09cb118: Pushed 
8643e4accddc: Pushed 
43e8a7decf15: Pushed 
7484166a246c: Pushed 
1c862c0e1a30: Pushed 
7bff100f35cb: Pushed 
latest: digest: sha256:1b0130a147ac48795d9f14831cea3028ea7872b497ce64fb6bcebcd22c01256f size: 2200
(venv) user:~/hello_app$


3. 작업 정의

등록한 이미지를 바탕으로 작업을 정의 합니다. 작업(Task)은 같이 실행되는 한개 이상의 컨테이너의 집합체를 말합니다. 작업정의를 통해 하나 이상의 컨테이너 실행될때 컨테이너의 사용할 도커 이미지 사용할 CPU, 메모리, 네트워크 등을 설정할 수 있습니다.


 - 작업 정의 생성

작업 정의를 생성 하기 위해 작업 정의를 선택 후 새 작업 정의 생성을 눌러 작업 정의를 생성합니다.

다음으로 EC2 자원을 정의하지 않는 Fargate를 선택 후 다음단계로 진행합니다.


2단계에서 상단의 항목에서 필수 입력할 항목은 작업이름입니다.

그 외에 작업 역할은 해당 작업이 다른 AWS 서비스를 API를 통해 호출하여 사용할 경우 지정합니다. 예를 들면 RDS에 table을 수정한다면 RDS write권한을 가진 Role을 선택해 줍니다. 해당 예제에서는 없음을 선택하였습니다.

호환성 요구 사항 및 네트워크 모드는 1단계에서 FARGATE 선택시 선택 할 수 없는 옵션이 없이 Default값을 사용합니다.






하단 항목에서는 첫째로 작업이 실행되는 ECS 및 ECR 관련 권한을 가진 IAM Role을 선택하는데 안내와 같이 기본으로 제공되는 ecsTaskExecutionRole을 생성하여 사용합니다.

둘째로 작업 크기는 FARGATE에서만 필수 항목으로 EC2 유형을 선택한 경우는 Instance에 대해 제어하며 관리하기 vCPU 및 메모리에 관하여 이미 Instance에 할당된 자원 내에서 사용하겠지만 Instance를 관리하지 않는 FARGATE는 작업에 사용될 자원만 지정하여 지정된 자원만큼에 대해 비용을 지불하는 방식이기 때문입니다.

세번째는 컨테이너 추가를 클릭하여 도커 이미지를 통해 실제 작업에서 사용할 컨테이너를 구성합니다.

테이너는 1개 이상이 등록가능하지만 AWS에서는 기본적으론 개별적인 컨테이너 프로비저닝, 스캐일링을 할 수 있도록 개별적으로 작업 정의를 사용하길 권하고 있습니다. 그 예외의 경우는 다음과 같습니다.

 - 컨테이너가 공통 수명 주기를 공유하는 경우(즉 함께 시작하고 종료되어야 함).

 - 컨테이너가 동일한 기본 호스트에서 실행되어야 하는 경우(즉 로컬호스트 포트에서 한 컨테이너가 다른 컨테이너를 참조함)

 - 컨테이너가 리소스를 공유하길 원하는 경우.

 - 컨테이너가 데이터 볼륨을 공유하는 경우



 - 작업 정의에 컨테이너 추가

컨테이너 추가를 클릭하여 나타난 다음의 정보를 입력하고 추가를 클릭하면 컨테이너가 등록됩니다.

사용할 이미지는 사용할 이미지의 URL을 입력하는데 아래 첨부된 스샷과 같이 ECR에서 간단하게 복사하여 사용하면 됩니다.

프라이빗 레지스트리 인증은 개별적으로 사용중인 Docker Repository를 사용하는 경우 인증관련 옵션을 설정하는 항목으로 본 예제에서는 사용하지 않습니다.

포트 매핑은 컨테이너가 사용할 포트를 지정하는 것으로 따로 웹으로 별도의 서비스와 연동하지 않는 단순 작업은 지정하지 않아도 되며 본 예제의 코드에서는 80포트를 사용하기 때문에 80으로 지정합니다.




ECR에서 작업에 사용할 Repository 복사



컨테이너를 등록 후 등록된 컨테이너를 확인 후 생성을 클릭하여 작업정의를 생성합니다.


4. 클러스터 및 서비스 생성

ECR을 통해 도커 이미지를 등록했고 ECS에서 작업정의를 통해 작업정의를 작성했다면 다음은 실제로 작업들을 수행하기 위해 클러스터를 구성하고 서비스를 작성하는 단계입니다.
클러스터는 일반적으로 비슷한 역할 또는 기능을 수행하는 집단, 장치등을 묶어서 하나의 집단 장치처럼 작용하게 하는 것으로 IT에서는 주로 컴퓨팅 자원을 묶어서 사용하는데 많이 사용되어 집니다.
ECS에서의 클러스터 또한 리전별로 고유한 서비스 또는 작업들의 논리적인 묶음으로 다수의 서비스 및 작업들을 포함할 수 있습니다.

 - 클러스터 생성

클러스터를 생성하기 위해 클러스터 항목으로 이동하여 클러스터 생성을 클릭합니다.


EC2 자원을 사용하지 않기 때문에 네트워킹 전용을 선택 후 다음단계로 진행합니다.


클러스터 이름을 입력한 후 생성을 클릭합니다.

네트워킹에서 VPC 생성 옵션은 클러스터에서 사용할 신규 VPC를 생성할 때 사용하는 옵션으로 이미 VPC가 구성되어 있고 해당 VPC에서 어플리케이션을 서비스 할 경우 생략 하고 진행하면 되겠습니다.


 - 서비스 생성

클러스터를 생성 확인을 한 후 해당 클러스터를 클릭하면 해당 클러스터에 서비스를 작성 할 수 있습니다.

AWS ECS에서 서비스는 작업 정의에서 정의된 작업들을 실제로 운용 하는 말그대로 서비스 단위 라고 할 수 있습니다. 모놀리식 서비스라면 전체 어플리케이션의 서비스를 뜻하겠고 마이크로서비스 라면 각각의 모듈서비스 들이 될 수 있습니다..

클러스터 내에서는 각각의 서비스들은 작업 정의에서 정해진 작업들을 기반으로 네트워크 설정, 가용성 설정등을 하여 실제 서비스를 구현합니다.


서비스 생성을 위해서 클러스터 상세페이지에서 서비스 탭의 생성 버튼을 클릭합니다.


서비스 생성에서 1단계는 서비스 구성으로 다음과 같은 항목을 입력합니다.

시작 유형은 FARGATE를 선택, 작업 정의는 사용할 작업과 Revision을 선택합니다. Revision(개정)은 작업 정의에서 해당 작업에서 새로운 버전 업데이트 또는 작업의 설정이 변경할 경우 새로운 버전을 뜻합니다.

플랫폼 버전은 ECS에서 FARGATE를 선택한 경우 FARGATE의 플랫폼 버전을 뜻하며 최신으로 선택하였습니다.

클러스터는 기존에 구성한 클러스터중 포함될 클러스터를 선택합니다.

작업 개수 및 최소 정상 상태 백분율, 최대 백분율은 배포랑 가용성과 연관된 항목으로 자세한 내용은 다음 글에서 기재하도록 하고 현재는 작업 개수를 2개 적용하고 다음 단계를 눌러 단계 2로 넘어갑니다.





서비스 생성 2단계는 네트워크 구성입니다.

기존에 사용중인 VPC 및 서브넷을 입력해 줍니다. 가용성을 위해 서브넷은 2개 이상의 가용 영역을 선택하며 보안그룹은 적당히 inbound에 80을 열어주면 되겠습니다. 추가로 보안을 위해 서브넷은 Private 망을 선택하였으며 퍼블릭 IP는 할당하지 않게 설정하였습니다.



아래로 스크롤을 내리면 ELB 설정을 할 수 있습니다. 상태 검사 유예 기간은 ELB에서 상태 검사를 진행시 유예 기간을 설정하는 것으로 너무 수치가 낮을 경우 작업이 시작시간이 다소 걸리는 경우 장애로 판정을 하고 이로 인해 계속 작업이 재시작 되는 경우가 있을 수 있습니다. 

Load Balancing은 타겟 그룹은 설정되지 않은 미리 작성된 Application Load Balancing을 사용하였습니다.

Route 53을 통한 DNS 설정은 해당 글에서는 다루지 않을 것이기 때문에 체크를 해제한 후 다음단계로 진행합니다.





3단계에서는 오토 스케일링 설정을 합니다. 실제 서비스를 구성할 경우 가용성 및 확장성을 위해 활성화를 시켜주시면 되고 현재는 데모용이기 때문에 비활성으로 진행합니다. Default는 비활성입니다.

3단계에서 다음단계를 선택 후 4단계는 검토를 한 후 하단의 서비스 생성을 클릭하면 서비스가 생성 됩니다.



 - 서비스 확인

서비스가 완성되면 다음과 같이 서비스 상태가 PROVISIOING -> Pending -> RUNNING의 순서로 바뀌며 실행중인 개수와 대기중인 개수도 변동하게 됩니다. 또한 FARGATE는 로드 밸런스의 컨트롤 하에 사용자가 설정한 원하는 개수에 맞춰 정상 작업을 유지시켜 줍니다.  



미리 작성 했었던 Application Load Balancing의 DNS의 주소를 브라우저에 입력하면 다음과 같이 Hello World! 가 출력됩니다.




지금까지 AWS ECS fargate를 사용하여 Appilication을 최초로 배포 하였습니다. 다음글에서는 도커 이미지 또는 작업이 업데이트 되는 경우와 기타 옵션들에 대해 좀 더 자세히 확인하는 내용이 될 예정입니다.


+ Recent posts