티스토리 뷰
개요
AWS CodePipeline
은 아마존의 서버리스 매니지드 CD(지속적 배포) 상품이다. 이를 이용하여 인스턴스를 필요로 했던 기존의 Jenkins와 같은 CD 도구를 대체하여 서비 관리 유지 부담을 줄이고, 개발자는 온전히 비지니스 로직 구현에 집중할 수 있다.- 이번 글에서는 AWS CodePipeline 상품을 이용하여
Amazon ECS
에서 운영 중인 서비스에 대해 빌드 및 배포 파이프라인을 만드는 과정을 설명하고자 한다.
배포 시나리오
- 배포 대상 프로젝트는 Gradle 기반으로 제작된 Spring Boot 프로젝트이다.
- 프로젝트 루트에 빌드시 실행될 명령어 목록을 저장하는
buildspec.yml
파일이 존재한다. - 프로젝트 저장소는
GitHub Enterprise Cloud
에 위치하며, 배포 대상 브랜치는 master로 설정한다. Amazon ECR
에 Docker 이미지를 보관하는 리파지터리가 생성되어 있다. [관련 링크]Amazon ECS
에 해당 이미지를 기반으로 서비스가 생성되어 있다. [관련 링크]AWS CodePipeline
로 GitHub Enterprise Cloud에서 소스 코드를 내려 받아 Docker 이미지로 빌드하여 Amazon ECR에 푸시 후, Amazon ECS에 배포한다.
buildspec.yml 작성
- 파이프라인 생성에 앞서 가장 먼저 빌드 대상이 되는 프로젝트 루트에 buildspec.yml 파일을 작성해야 한다. (반드시 루트 경로와 파일명을 일치시킬 필요는 없다. 아래 빌드 프로젝트 생성 단계에서 커스터마이징이 가능하기 때문이다.)
- 파일이 존재하지 않거나 형식이 맞지 않을 경우 빌드시 DOWNLOAD_SOURCE 단계에서 YAML_FILE_ERROR가 발생한다.
version: 0.2
phases:
install:
runtime-versions:
java: corretto11
pre_build:
commands:
- REGION=ap-northeast-2
- REPOSITORY_URI=xxxxx.dkr.ecr.ap-northeast-2.amazonaws.com
- IMAGE_NAME=foobar
- IMAGE_TAG=latest
- COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
- BUILD_TAG=${COMMIT_HASH:=latest}
- CONTAINER_NAME=foobar
- echo Logging in to Amazon ECR...
- aws --version
- aws ecr get-login-password --region $REGION | docker login -u AWS --password-stdin $REPOSITORY_URI
build:
commands:
- echo Building the Docker image...
- chmod +x gradlew
- ./gradlew bootBuildImage --imageName=$IMAGE_NAME
- docker tag $REPOSITORY_URI/$IMAGE_NAME:$IMAGE_TAG $REPOSITORY_URI/$IMAGE_NAME:$BUILD_TAG
post_build:
commands:
- echo Pushing the Docker images...
- docker push $REPOSITORY_URI/$IMAGE_NAME:$IMAGE_TAG
- docker push $REPOSITORY_URI/$IMAGE_NAME:$BUILD_TAG
- printf '[{"name":"%s","imageUri":"%s"}]' $CONTAINER_NAME $REPOSITORY_URI/$IMAGE_NAME:$BUILD_TAG > imagedefinitions.json
- cat imagedefinitions.json
artifacts:
files:
- imagedefinitions.json
- buildspec.yml 파일은 런타임에 소스 코드를 내려 받은 후 빌드하는 시점에 실행될 명령어 목록을 정의한 파일이다.
pre_build
,build
,post_build
3단계에 걸쳐 실행될 명령어 목록을 작성해야 한다. artifacts
는 빌드의 결과로 생성된 파일 목록을 의미한다.imagedefinitions.json
에는 빌드 완료 후 배포 대상이 되는 컨테이너의 정보를 보관하는데, 이 정보를 기반으로 Amazon ECS 서비스에 소속된 작업 정의를 개정하고, 서비스를 업데이트하는 과정을 자동으로 진행한다.
파이프라인 생성
- 이제 파이프라인을 생성할 차례이다. 아래는 GitHub Enterprise Cloud에 프로젝트가 존재한다는 가정 하에 소스 코드 빌드 후 Amazon ECS의 서비스를 배포하는 예이다.
AWS CodePipeline 콘솔 접속
→ [파이프라인 생성] 클릭
# 파이프라인 설정
→ 파이프라인 이름: foobar (입력)
→ 서비스 역할: [새 서비스 역할] 선택
→ 역할 이름: AWSCodePipelineServiceRole-ap-northeast-2-foobar (입력)
→ [다음] 클릭
# 소스
→ 소스 공급자: [GitHub(버전 2)] 선택
→ 연결: [GitHub에 연결] 클릭
→ 연결 이름: foobar (입력)
→ [GitHub에 연결] 클릭
→ [새 앱 설치] 클릭
→ [연결] 클릭
→ 리포지토리 이름: some-company/foobar (선택)
→ 브랜치 이름: master (선택)
→ 출력 아티팩트 형식: [Codepipeline 기본값] 선택
→ [다음] 클릭
# 빌드
→ 빌드 공급자: [AWS CodeBuild]
→ 리전: [아시아 태평양 (서울)]
→ [프로젝트 생성] 클릭
# 빌드 > 프로젝트 생성 > 프로젝트 구성
→ 프로젝트 이름: foobar (입력)
# 빌드 > 프로젝트 생성 > 환경
→ 환경 이미지: [관리형 이미지] 선택
→ 운영 체제: [Amazon Linux 2] 선택
→ 런타임: [Standard] 선택
→ 이미지: [aws/codebuild/amazonlinux2-x86_64-standard:3.0] 선택
→ 이미지 버전: [이 런타임에 항상 최신 이미지 사용] 선택
→ 환경 유형: [Linux] 선택
→ [도커 이미지를 빌드하거나 빌드의 권한을 승력하려면 이 플래그를 활성화합니다.] 선택
→ 서비스 역할: [새 서비스 역할] 선택
→ 역할 이름: codebuild-foobar-service-role (입력)
# 빌드 > 프로젝트 생성 > Buildspec
→ 빌드 사양: [buildspec 파일 사용] 사용
→ buildspec 이름: buildspec (입력)
# 빌드 > 프로젝트 생성
→ [Code Pipeline으로 계속] 클릭
# 빌드
→ [다음] 클릭
# 배포
→ 배포 공급자: [Amazon ECS] 선택
→ 리전: [아시아 태평양 (서울) 선택)
→ 클러스터 이름: (생성한 클러스터 이름 선택)
→ 서비스 이름: (생성한 서비스 이름 선택)
→ 이미지 정의 파일: imagedefinitions.json (입력)
→ [다음] 클릭
# 검토
→ [파이프라인 생성] 클릭
- GitHub 연결시 앱을 설치할 계정은 빌드할 프로젝트의 계정명이 되어야 한다.
- Buildspec 이름에는 프로젝트 루트를 기준으로 미리 존재하는 파일명을 입력한다. 미입력시 프로젝트 루트에 buildspec.yml 파일이 존재하는 것으로 간주한다.
빌드 역할에 GitHub 풀링 권한 부여
- 앞서의 작업 후에 빌드 역할에 대해 GitHub 풀링 권한을 추가해야 한다. (권한 미부여시 authorization failed for primary source and source version 오류로 빌드가 실패한다.) [관련 링크]
AWS CodePipeline 콘솔 접속
→ [파이프라인] 클릭 → [파이프라인] 클릭
→ [foobar-prod] 클릭
→ Source 스테이지의 [i] 클릭 → [ConnectionArn] 값 복사 (ex: arn:aws:codestar-connections:us-east-2:115255558787:connection/687cad53-33d7-48bd-b558-ceed6ee1ce39)
→ [빌드] 클릭 → [프로젝트 빌드] 클릭
→ foobar-prod 클릭
# 빌드 프로젝트
→ [빌드 세부 정보] 클릭
→ [서비스 역할] → codebuild-foobar-prod-service-role 클릭
# IAM 콘솔 > 역할 > 요약
→ [정책 연결] 클릭
# 권한 연결
→ [정책 생성] 클릭
→ [JSON] 클릭 후 아래 내용 입력
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "codestar-connections:UseConnection",
"Resource": "{앞서 복사한 [ConnectionArn] 값 입력}"
}
]
}
→ [정책 검토] 클릭
# 정책 생성
→ 이름: [GitHubPullAccess] 입력
→ [정책 생성] 클릭
트러블슈팅: Submodules를 가진 프로젝트 빌드 오류 해결
- AWS CodePipeline은 현재 Submodules를 가진 프로젝트의 빌드를 자체적으로 지원하고 있지 않다. 서브모듈이 빠진 채로 빌드되기 때문에 빌드 단계에서 오류가 발생한다.
- 해결책은 서브모듈 부분에 대한 풀링을 직접 buildspec.yml에 명시하는 것이다. 꽤나 번거롭지만 확실한 해결책이다.
version: 0.2
env:
parameter-store:
GITHUB_SSH_KEY: GITHUB_SSH_KEY
phases:
install:
runtime-versions:
java: corretto11
commands:
- mkdir -p ~/.ssh
- echo "$GITHUB_SSH_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- eval "$(ssh-agent -s)"
- ssh-add ~/.ssh/id_rsa
- git config --global url."git@github.com:".insteadOf "https://github.com/"
- echo Pooling Git Submodules...
- git submodule init
- git submodule update --recursive
pre_build:
commands:
- REGION=ap-northeast-2
- REPOSITORY_URI=xxxxx.dkr.ecr.ap-northeast-2.amazonaws.com
- IMAGE_NAME=foobar
- IMAGE_TAG=latest
- DEPLOY_TAG=prod
- COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
- BUILD_TAG=${COMMIT_HASH:=prod}
- CONTAINER_NAME=foobar-prod
- echo Logging in to Amazon ECR...
- aws --version
- aws ecr get-login-password --region $REGION | docker login -u AWS --password-stdin $REPOSITORY_URI
build:
commands:
- echo Building the Docker image...
- chmod +x ./gradlew
- ./gradlew api:bootBuildImage --imageName=$IMAGE_NAME
- docker tag $IMAGE_NAME:$IMAGE_TAG $REPOSITORY_URI/$IMAGE_NAME:$DEPLOY_TAG
post_build:
commands:
- echo Pushing the Docker images...
- docker push $REPOSITORY_URI/$IMAGE_NAME:$DEPLOY_TAG
- printf '[{"name":"%s","imageUri":"%s"}]' $CONTAINER_NAME $REPOSITORY_URI/$IMAGE_NAME:$DEPLOY_TAG > imagedefinitions.json
- cat imagedefinitions.json
artifacts:
files:
- imagedefinitions.json
- 필요한 작업이 더 있다. 서브모듈 풀링을 SSH Key를 이용하기 때문에 해당 파이프라인에 종속되어 생성된 코드 빌드 역할에 AWS Parameter Store 접근 권한을 추가해야 한다. (권한 미부여시 AccessDeniedException 오류로 빌드가 실패한다.)
AWS CodePipeline 콘솔 접속
→ [빌드] 클릭 → [프로젝트 빌드] 클릭
→ foobar-prod 클릭
# 빌드 프로젝트
→ [빌드 세부 정보] 클릭
→ [서비스 역할] → codebuild-foobar-prod-service-role 클릭
# IAM 콘솔 > 역할 > 권한
→ [정책 연결] 클릭
# 권한 연결
→ [AmazonSSMReadOnlyAccess] 체크
→ [정책 연결] 클릭
참고 글
- 자습서: Amazon ECS 표준 배포 CodePipeline
- Test Reports with AWS CodeBuild
- Creating CI/CD Pipeline for AWS ECS - Part II
- AWS CodePipeline for Containerized Deployments Part 1
- AWS CodeBuild | AWS ECR | Build & Push SpringBoot Docker Image to ECR | ECS | JavaTechie
- How to auto deploying git repositories with submodules on AWS?
- Error: Permission denied (publickey)
댓글
공지사항
최근에 올라온 글
- Total
- 2,308,903
- Today
- 264
- Yesterday
- 687
링크
TAG
- JavaScript
- Kendo UI
- jQuery
- bootstrap
- Tomcat
- It
- 로드바이크
- 로드 바이크
- 구동계
- Spring Boot
- date
- timestamp
- 태그를 입력해 주세요.
- MySQL
- Spring MVC 3
- java
- 자전거
- CSS
- jsp
- Kendo UI Web Grid
- Docker
- jstl
- JAX-RS
- Eclipse
- spring
- chrome
- CentOS
- node.js
- 평속
- PC앱