잘못된 정보가 있다면, 꼭 댓글로 알려주세요(비로그인 익명도 가능).

여러분의 피드백이 저와 방문자 모두를 올바른 정보로 인도할 수 있습니다.

감사합니다. -현록

후원해주실 분은 여기로→

현록의 기록저장소

AWS CodeDeploy와 Github Action으로 자동 배포 설정 본문

Study/AWS

AWS CodeDeploy와 Github Action으로 자동 배포 설정

현록 2023. 2. 4. 16:46

[Workflow]

[준비사항]

[설정]

[확인]

 

 


[Workflow]

 

Workflow는 다음과 같다.

 

Github의 특정 branch에 코드 push

gradle이나 maven 등으로 build(test를 포함하고 있다면 수행)

빌드 결과물(jar, war, ...)과 배포 설정(appspec.yml) 등을 압축하여 AWS S3 버킷에 업로드

AWS CodeDeploy 서비스에 설정한 대로 배포 요청(배포 생성)

AWS EC2에서는 설치했던 AWS CodeDeploy Agent가

AWS S3 버킷에서 배포본을 받고 압축을 푼 후, 압축 파일 내부의 appspec.yml에 정의된대로 스크립트를 실행

(실행 중이던 기존 애플리케이션/서비스를 중지하고, 새 애플리케이션으로 교체 후 재실행)

 

 


 

[준비사항]

 

AWS IAM Role에서 AWS EC2가 AWS CodeDeployAgent를 사용하기 위한 역할(Role)을 생성한다.




 

 

AWS IAM Role에서 AWS CodeDeploy 서비스를 위한 역할(Role)을 생성한다.




 

 

AWS IAM User에서 Github Action이

S3에 압축파일을 업로드하고, AWS CodeDeploy 서비스에 배포 요청을 할 수 있는

권한을 부여한 사용자를 생성하고, 액세스 키(ID, SECRET)를 발급한다.


더보기


참고로 예시에서 사용하는 최소 정책은 다음과 같다.

(작성하려면 S3 버킷과 CodeDeploy 애플리케이션 및 배포 그룹 생성을 먼저 하고 리소스를 지정할 수 있다)

{

    "Version": "2012-10-17",

    "Statement": [

        {

            "Sid": "VisualEditor0",

            "Effect": "Allow",

            "Action": [

                "s3:PutObject",

                "codedeploy:CreateDeployment",

                "codedeploy:GetApplicationRevision",

                "codedeploy:RegisterApplicationRevision",

                "codedeploy:GetDeploymentConfig"

            ],

            "Resource": [

                "arn:aws:codedeploy:ap-northeast-2:1290????7149:deploymentconfig:CodeDeployDefault.OneAtATime",

                "arn:aws:codedeploy:ap-northeast-2:1290????7149:application:CODEDEPLOY애플리케이션이름",

                "arn:aws:codedeploy:ap-northeast-2:1290????7149:deploymentgroup:CODEDEPLOY애플리케이션이름/배포그룹이름",

                "arn:aws:s3:::S3버킷이름/디렉터리명.../파일명"

            ]

        }

    ]

}



IAM User가 생성된 것을 확인할 수 있다.


생성한 사용자를 선택하고, '보안 자격 증명' 탭으로 가서 '액세스 키 만들기'로 진입한다.


액세스 키보다 보안성이 높은 대체 권장 서비스를 권유하는 부분이다.

우리는 액세스 키를 사용해야하니 '기타'를 선택한다.


설명 태그는 선택 사항이다. 필요하면 사용한다.


 위의 알림대로 이 페이지를 벗어나면 다시는 비밀 액세스 키는 볼 수 없으니,

'.csv 파일 다운로드'를 통해 안전한 곳에 저장해둔다.



 

 

위의 액세스 키를 Github의 자동 배포를 수행하려는 Repository의 설정에서 Secrets에 저장해둔다.


더보기

Github에서 배포하려는 Repository의 설정 탭으로 가서,

Security > Secrets and variables > Actions 항목에서 secret 생성으로 진입한다.



발급받았던 액세스 키와 비밀 액세스 키 쌍을 각각 따로 저장한다.



 

 

AWS S3 서비스에서 S3 버킷을 생성한다.


더보기


버킷의 root(/) 디렉터리에 업로드할 것이 아니라면, '폴더 만들기'를 통해 원하는 위치 구조를 만들어둔다.




 

 

AWS EC2 서비스에서 EC2 인스턴스를 생성한다.


더보기

ㆍ위에서 생성했던 Role 중 AmazonEC2RoleForAWSCodeDeploy 정책이 연결된 Role을 선택해준다.

ㆍEC2가 생성되면 접속해서 AWS CodeDeploy agent를 설치해야하는데,

 사용자 데이터에 명령어들을 입력해두면 인스턴스 생성시 해당 명령어들을 수행해준다.

 

#!/bin/bash

  

sudo yum update -y

sudo yum install -y ruby

sudo yum install -y wget

  

/opt/codedeploy-agent/bin/codedeploy-agent stop

yum erase codedeploy-agent -y

  

cd /home/ec2-user

wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install

chmod +x ./install

sudo ./install auto

rm ./install

https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/codedeploy-agent-operations-install-linux.html

https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/resource-kit.html#resource-kit-bucket-names


만약 기존 사용 중인 EC2 인스턴스라면, 우클릭 메뉴에서 IAM Role을 수정할 수 있다.


기존에 아무 Role도 없었다면 생성했던 Role을 선택하면 되지만,

기존에 Role이 존재한다면 기존 Role에 AmazonEC2RoleForAWSCodeDeploy 정책을 추가하거나 합친 형태의 Role을 추가로 생성해야할 수 있다.

IAM Role을 수정했다면, 재부팅을 해야 올바르게 적용된다.


[ec2-user@ip-***-**-**-** ~]$ sudo service codedeploy-agent status

The AWS CodeDeploy agent is running as PID 3468

EC2 인스턴스로 접속하여 AWS CodeDeploy agent가 설치되어 실행 중인지 확인한다.

설치가 안됐다면 위의 사용자 데이터에 열거했던 명령어들을 입력해보고, 서비스 start로 실행하고 status로 확인한다.



 

 

AWS CodeDeploy 서비스에서 CodeDeploy 애플리케이션을 생성하고, 배포 그룹을 생성한다.


더보기


배포 그룹을 생성해야한다.



애플리케이션의 배포 그룹을 확인해보면 생성한 배포 그룹을 볼 수 있다.


참고로 배포 그룹을 선택해서 '배포 생성'을 하면 배포 이벤트를 생성할 수 있다.


자동 배포와는 관련 없이,

이미 S3 버킷에 업로드한 압축파일이나 Github의 Commit ID를 바탕으로 프로젝트를 내려받아 수행할 수 있는데,

이는 자동 배포 부분이 아니므로 여기서는 다루지 않겠다.

(직접 배포를 생성하더라도 EC2 대상들에 대해서는 일괄적으로 배포 스크립트를 수행하니,

CI/CD pipeline과는 관련 없지만 배포부터는 자동화라 각각 인스턴스에 수동으로 접속하여 수행할 때의 실수는 줄일 수 있다.)


 

 


[설정]

 

appspec.yml 파일을 git 프로젝트의 root(/) 디렉터리에 생성한다.

version0.0

  

oslinux

  

files:

  # - source:  /

  #   destination: /home/ec2-user/spring-simple-http-rest

  - source:  /build/libs

    destination/home/ec2-user/spring-simple-http-rest/build/libs

  - source:  /.aws/aws-codedeploy-scripts

    destination/home/ec2-user/spring-simple-http-rest/.aws/aws-codedeploy-scripts

  

file_exists_behaviorOVERWRITE

  

permissions:

  - object/

    pattern"**"

    ownerec2-user

    groupec2-user

  

hooks:

  AfterInstall:

    - location./.aws/aws-codedeploy-scripts/stop.sh

      timeout30

      runasec2-user

  ApplicationStart:

    - location./.aws/aws-codedeploy-scripts/start.sh

      timeout60

      runasec2-user

https://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file.html

ㆁ files 섹션

 ㆍsource: 압축파일 기준으로 압축을 풀 디렉터리/파일

 ㆍdestination: EC2 인스턴스 기준으로 설치가 될 디렉터리/파일

 ※ https://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-structure-files.html

ㆁhooks 섹션

 ㆍ배포 lifecycle의 각 event에 실행할 스크립트 파일을 설정할 수 있다.

 ㆍ이 스크립트 파일은 기존에 존재하든, 이번 배포 압축 파일에 포함되든 둘 다 가능하지만,

  기존에 존재하는 스크립트 파일이 아니라면 AfterInstall 이벤트부터 사용 가능하다.

  BeforeInstall에서는 압축을 풀기 전이라 해당 스크립트 파일을 찾지 못하고 이후 과정은 캔슬되어 전체 배포 과정을 실패로 마감한다.

 ※ https://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html

※ 이 appspec.yml은 압축 파일의 root(/)에 포함되어야 AWS CodeDeploy agent가 이를 토대로 작업들을 수행하지만,

 OS에 설치될 필요는 없는 파일이니, files 섹션에서 appspec.yml 자신은 빠져도 상관없다.

 

 


배포가 수행될 때 실행될 스크립트파일(*.sh)들을 git 프로젝트의 원하는 디렉터리에 작성한다.

예시에서 사용한 두 개의 스크립트 파일이다.

 

stop.sh

#sudo systemctl stop springserver

PID=$(ps -ef | grep -v grep | grep 'java -jar /home/ec2-user/spring-simple-http-rest/build/libs/simple-http-rest-1.0.0.war' | awk '{print $2}')

if [ -n "$PID] then

    kill -9 $PID

    sleep 10

fi

start.sh

#sudo systemctl start springserver

nohup java -jar /home/ec2-user/spring-simple-http-rest/build/libs/simple-http-rest-1.0.0.war 1>/dev/null 2>&1 &

 

 


appspec.yml스크립트들을 작성한 커밋들을 master branch에 push하고,

Github에서 repository로 들어가서 Github Action을 생성한다.

템플릿을 검색해서 수정해서 사용해도 되지만, 처음부터 기본판으로도 작성할 수 있다.

어차피 예시를 보여줄 것이니 이것으로 선택.

# This workflow uses actions that are not certified by GitHub.

# They are provided by a third-party and are governed by

# separate terms of service, privacy policy, and support

# documentation.

# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time

# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle

  

nameJava CI with Gradle and CD by AWS CodeDeploy

  

on:

  push:

    branches[ "main" ]

  pull_request:

    branches[ "main" ]

  

permissions:

  contentsread

  

jobs:

  ci-and-cd:

  

    runs-onubuntu-latest

  

    steps:

    - usesactions/checkout@v3

  

    - nameSet up JDK 17

      usesactions/setup-java@v3

      with:

        java-version'17'

        distribution'corretto'

  

    - nameRun chmod to make gradlew executable

      runchmod +x ./gradlew

  

    - nameBuild with Gradle

      usesgradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1

      with:

        argumentsbuild

  

    - nameMake zip File

      runzip -r ./build.zip ./build/libs/simple-http-rest-1.0.0.war ./appspec.yml ./.aws/aws-codedeploy-scripts

#      run: zip -r ./build.zip ./build/libs/*.war ./appspec.yml ./.aws/aws-codedeploy-scripts

  

    - nameConfigure AWS credentials

      usesaws-actions/configure-aws-credentials@v1

      with:

        aws-access-key-id: ${{ secrets.AWS_CD_ID }}

        aws-secret-access-key: ${{ secrets.AWS_CD_SECRET }}

        aws-regionap-northeast-2

  

    - nameUpload to S3

      runaws s3 cp --region ap-northeast-2 ./build.zip s3://s3-cd-blackdeer/spring-simple-http-rest/build.zip

  

    - nameAWS CodeDeploy

      run>

        aws deploy create-deployment

        --application-name test-spring-simple-rest

        --deployment-group-name cd-deploy-group-spring-simple-http-rest

        --deployment-config-name CodeDeployDefault.OneAtATime

        --s3-location bucket=s3-cd-blackdeer,bundleType=zip,key=spring-simple-http-rest/build.zip

'main' branch에 push나 pr이 완료되면,

gradle로 빌드 후,

빌드 파일(*.war)과 appspec.yml, 스크립트 파일들(*.sh)을 압축하고,

이 압축 파일을 AWS S3 버킷에 업로드 한 후,

AWS CodeDeploy 서비스에 배포를 요청한다.

https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle

https://docs.aws.amazon.com/cli/latest/reference/s3/cp.html

https://docs.aws.amazon.com/cli/latest/reference/deploy/create-deployment.html

 

AWS S3 버킷에 압축 파일 업로드와 AWS CodeDeploy 요청에

AWS Credential이 필요하며, 그래서 IAM User와 액세스 키를 발급했던 것이다.

Repository의 Secrets에 저장했던 ID와 SECRET을 여기에서 사용한다.

 

 


[확인]

 

Github Action을 작성한 커밋 이후로,

main branch에 push될 때마다 해당 작업이 수행될 것이다.

 

 

Repository의 Actions 탭에서

진행 상태와 결과 및 로그 등을 확인할 수 있다.

re-run도 가능하다.

 

 

S3 버킷의 지정한 경로에 압축 파일이 업로드된 것도 확인할 수 있다.

 

 

CodeDeploy의 애플리케이션이나 배포 그룹에서는 요청된 배포 내역을 확인할 수 있다.

각 배포 ID를 누르면 인스턴스별 진행 정도나 가장 최근 이벤트 등을 알 수 있다.

아래의 'View events'를 누르면 더 상세한 lifecycle 위치를 알 수 있다.

 

 

EC2 인스턴스에서는 해당 머신에 대해 더 자세한 로그를 뒤져볼 수 있다.

/var/log/aws/codedeploy-agent/codedeploy-agent.log

 

 

Comments

잘못된 정보가 있다면, 꼭 댓글로 알려주세요(비로그인 익명도 가능).

여러분의 피드백이 저와 방문자 모두를 올바른 정보로 인도할 수 있습니다.

감사합니다. -현록

후원해주실 분은 여기로→