본문 바로가기
aws

AWS CodePipeline으로 CI/CD 구축하기

by 초특급하품 2020. 5. 12.

CodePipeline을 사용하면 repository에 코드를 푸시했을 때 빌드, 테스트, 배포까지 CI/CD를 한 번에 관리할 수 있다.

 

예제 코드는 AWS fargate 사용법에서 만들었던 fargate 코드를 기반으로 한다.

code repository는 CodeCommit, 빌드는 CodeBuild, 배포는 Amazon ECS를 사용한다.

 

IAM

IAM -> Security credentials -> HTTPS Git credentials for AWS CodeCommit에서 credential을 생성한다.

 

 

CodeCommit

credential이 있으니 이제 CodeCommit에서 repository를 생성하고 git clone을 받을 수 있다. 위에서 받아온 자격 증명을 유지하기 위해 clone 하기 전에 git helper를 등록한다. 자격 증명이 invalid 되기 전까지 인증을 유지해준다.

$ git config --global credential.helper "!aws codecommit credential-helper $@"
$ git config --global credential.UseHttpPath true

$ git clone https://git-codecommit.{region_id}.amazonaws.com/v1/repos/{repository_name}

 

 

CodePipeline

CodePipeline으로 코드에 변화가 생겼을 때 빌드, 배포하는 과정을 정의한다.

Source

source proivider로 github이나 다른 서비스도 가능하다. 여기서는 위에서 생성한 CodeCommit의 repository를 설정한다. 

해당 repository의 branch에 변경이 일어났을 때 감지하는 방법으로는 aws가 권장하는 CloudWatch를 설정한다. 

Build

Jenkins로도 가능하지만 aws를 적극 활용하기 위해 AWS CodeBuild를 선택한다. 그리고 CodeBuild에 맞게 빌드 환경을 설정한다.

CodeBuild는 aws가 관리하는 인프라에서 빌드를 실행하기 때문에 권한이 필요하다. 생성된 IAM role의 policy를 보면 codebuild, s3, log 권한이 있다. 빌드한 결과물(여기선 imagedefinitions.json)을 s3로 업로드하고 deploy 단계에서 이 파일을 참조하는데, 이때 s3 권한이 필요하다.

 

빌드 스펙을 명시해야 한다. 기본으로 root directory에 buildspec.yml로 작성한다.

 

Deploy

ec2에 배포해야 하는 상황이라면, ec2에 CodeDeploy agent를 설치하고 appspec.yml을 작성해서 배포 환경을 구축해야 한다. 하지만 ECS Fargate는 Deploy provider로 지원이 되기 때문에 따로 이런 작업을 하지 않아도 된다. Amazon ECS를 선택한다. 

 

 

CodeBuild

이렇게 CodePipeline을 생성하면 CodeBuild 단계에서 에러가 발생한다.

Phase context status code: YAML_FILE_ERROR Message: YAML file does not exist

 

CodeBuild에서 요구하는 양식에 맞게 buildspec.yml 파일을 작성해야 한다.

version: 0.2

phases:
  install:
    runtime-versions:
      docker: 18
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - aws --version
      - $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
      - REPOSITORY_URI={account_id}.dkr.ecr.us-west-2.amazonaws.com/{repository_name}
      - 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":"{container_name}","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
    files: imagedefinitions.json

aws docs의 sample을 참조해서 buildspec.yml을 만들어 push 한다. 그러면 방금 생성한 CodePipeline이 다시 실행된다.

이번엔 다른 에러가 발생한다.

Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email). Reason: exit status 255

 

CodeBuild가 ECR에서 image를 가져올 때 권한이 없다. CodePipeline의 build 단계에서 생성된 build role에 AmazonEC2ContainerRegistryPowerUser 권한을 추가한다.

 

다시 pipeline을 재실행시켜보면 성공한다.

s3에 codepipeline-* 으로 생성된 버킷에 들어가 보면 BuildArtif 경로에 결과물이 생성되었다. buildspec.yml에서 artifiacts로 정의한 imagedefinitions.json 파일이다. 이 파일은 post_build 단계에서 만들었고 build 단계에서 태깅한 image uri와 container_name 정보가 들어있다.

 

수동으로 잘 돌아가는지 확인해 봤으니 CodeCommit부터 시작하는 전체 pipeline이 잘 동작하는지 메시지를 바꿔서 push 한다.

app.use(ctx => {
  ctx.body = 'Hello v2';
});

 

alb dns name으로 접속해보면 Hello v2가 출력된다.

 

 

Notify

pipeline의 과정에서 trigger를 추가해서 notification을 생성한다.

 

알람을 받기 원하는 trigger를 선택하고, 전달할 target으로 SNS 또는 Chatbot을 설정할 수 있다.

'aws' 카테고리의 다른 글

SAM으로 API Gateway - Lambda - DynamoDB 구성하기  (0) 2020.08.26
Serverless Application Model(SAM) 기본  (0) 2020.08.25
AWS fargate 사용법  (0) 2020.05.12
AWS X-Ray  (0) 2020.05.05
AWS API Gateway  (0) 2020.05.02

댓글