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 콘솔에서 [변경 사항 릴리즈]를 통해 파이프라인을 다시 수행하면 다음과 같이 단계별 진행사항을 볼 수 있습니다.



+ Recent posts