DevOps

Github Action 배포 자동화

MIRACLE LIFE 2024. 1. 7. 23:15

Github Action을 이용하여 새로운 코드 반영 시 ec2에 서버가 자동으로 배포되도록 하였다.

AWS CodeDeploy를 이용한다.

 

목차

  1. workflow 작성
  2. AppSpec 작성
  3. AWS 서비스 설정(CodeDeploy, S3)

 

1. workflow 작성

workflow 파일을 먼저 생성해준다.

workflow에는 코드를 푸시하는 시점부터 서버를 배포하는 시점까지의 과정을 설정한다.

 

위와 같이 새로운 workflow를 생성할 수 있다. 나는 Java with Gradle을 선택하였고 파일 이름은 deploy-dev로 설정하였다.

생성을 완료하면 /.github/workflows/deploy-dev.yml과 같은 파일이 생성된다.

name: Deploy to Dev
on:
  push:
    branches: [ "release/v0.1" ]
    
permissions:
  contents: read
  
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up JDK 11
      uses: actions/setup-java@v3
      with:
        distribution: 'adopt'
        java-version: '11'
        
    - name: Cache Gradle dependencies
      uses: actions/cache@v3
      with:
        path: |  # Gradle의 종속성과 wrapper를 캐시하는 디렉토리
          ~/.gradle/caches
          ~/.gradle/wrapper
        key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}  
        restore-keys: |
          ${{ runner.os }}-gradle-

    - name: Configure application credentials
      run: echo "${{ secrets.APPLICATION_DEV }}" > ./server/src/main/resources/application-dev.yml
        
    - name: Build with Gradle
      working-directory: ./server
      run: ./gradlew build
      
    - name: Make Zip File
      run: zip -qq -r ./code-deploy-dev.zip appspec.yml scripts ./server/build/libs/server-0.0.1-SNAPSHOT.jar

    - name: Upload artifact
      uses: actions/upload-artifact@v2
      with:
        name: code-deploy-dev
        path: ./code-deploy-dev.zip

  deploy:
    needs: build
    runs-on: ubuntu-latest

    steps:
    - name: Download artifact
      uses: actions/download-artifact@v2
      with:
        name: code-deploy-dev
        path: .

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ap-northeast-2
        
    - name: Upload to S3
      run: |
        aws s3 cp ./code-deploy-dev.zip s3://deploy-quokka/code-deploy-dev.zip
        
    - name: Deploy to EC2 using CodeDeploy
      run: |
        aws deploy create-deployment \
          --application-name quokka \
          --deployment-config-name CodeDeployDefault.AllAtOnce \
          --deployment-group-name codeDeploy \
          --s3-location bucket=deploy-quokka,bundleType=zip,key=code-deploy-dev.zip

deploy-dev.yml

 

영역을 크게 트리거(on), 권한 설정(permissions), 작업(jobs) 으로 구분할 수 있다.


on:
  push:
    branches: [ "release/v0.1" ]

 

액션이 실행되는 조건을 설정한다. 이 경우는 release/v0.1 브랜치에 push가 발생할 경우 실행된다.


    - name: Make Zip File
      run: zip -qq -r ./code-deploy-dev.zip appspec.yml scripts ./server/build/libs/server-0.0.1-SNAPSHOT.jar

 

appspec.yml 파일과 scripts 폴더, jar 파일을 압축한다.


    - name: Upload artifact
      uses: actions/upload-artifact@v2
      with:
        name: code-deploy-dev
        path: ./code-deploy-dev.zip

 

압축된 파일을 Artifact로 업로드한다.
(나처럼 작업단계를 build와 deploy로 나누지 않고 하나의 작업에서 모든 과정을 처리하는 경우에는 해당 과정이 필요하지 않다. build 작업에서 생성한 압축파일에 deploy 작업에서는 접근할 수 없기 때문에 artifact라는 공유 가능한 저장소를 이용한다.)


  deploy:
    needs: build
    runs-on: ubuntu-latest

 

build 작업이 성공적으로 완료된 후에 deploy 작업을 실행한다.


- name: Download artifact
      uses: actions/download-artifact@v2
      with:
        name: code-deploy-dev
        path: .

 

build 작업에서 생성한 Artifact를 다운로드한다.

 

나머지 코드의 역할은 name을 통해 어렵지 않게 유추할 수 있을 것이다.

 

2. AppSpec 작성

AppSpec파일은 AWS CodeDeploy에서 배포를 관리하는 데 사용하는 파일이다.

참조: AWS AppSpec 공식문서

 

version: 0.0
os: linux
files:
  - source: /
    destination: /home/ec2-user/code-deploy
permissions:
  - object: /home/ec2-user/
    owner: ec2-user
    group: ec2-user
hooks:
  # BeforeInstall:
  #   - location: scripts/install_dependencies.sh
  #     timeout: 300
  #     runas: root
  AfterInstall:
    - location: scripts/start_server.sh
      timeout: 300
      runas: ec2-user

appspec.yml

 

핵심은 hooks 섹션이다. 이 섹션은 배포 중 특정 배포 수명 주기 이벤트에서 실행되는 스크립트를 지정한다.

위의 경우 AfterInstall: 설치후에 scripts 폴더에 있는 start_server.sh 스크립트를 실행하란 뜻이다. 스크립트 파일 이름은 원하는 대로 설정이 가능하다.
참조: AWS AppSpec 'hooks' 섹션


2-1. scripts 작성

AppSpec 에서 사용하는 스크립트를 작성하는 단계이다.

CURRENT_PID=$(pgrep -f server-0.0.1-SNAPSHOT.jar)
sudo kill $CURRENT_PID
sudo nohup java -jar ./server/build/libs/server-0.0.1-SNAPSHOT.jar &

start_server.sh

 

기존 실행중이던 서버를 중지하고 새로운 서버를 실행한다.

 

 

3. AWS 서비스 설정

  • CodeDeploy 생성
  • EC2에 CodeDeploy Agent 설치
  • S3 버킷 생성

i. CodeDeploy 생성

CodeDeploy에서 애플리케이션을 생성한다.


생성한 애플리케이션에서 배포 그룹을 생성한다.


설명대로 CodeDeploy 권한이 있는 서비스 역할이 필요하다. 역할이 있다면 아래 사진과 같이 미리보기가 제공된다.

(역할을 생성하는 부분은 해당 포스트 제일 하단 참고)


CodeDeploy를 적용할 EC2를 선택한다.


나머지 설정은 그대로 두고 생성을 완료한다.

 

ii. EC2에 CodeDeploy Agent 설치

EC2에서 CodeDeploy를 실행하기 위해서는 CodeDeploy Agent 설치가 필요하다. 해당 과정은 공식 문서 첨부로 대체한다.

참조: CodeDeploy Agent 설치

 

iii. S3 버킷 생성

해당 포스트의 첫번째 과정인 workflow를 설정할 때 생성한 압축 파일을 담아두고 EC2에서 해당 파일을 가져와서 사용할 수 있도록 S3 버킷이 필요하다. 버킷을 생성할 때 workflow 파일에서 사용하는 S3 버킷 이름과 동일한 이름으로 생성하자.

 

 

3-1. IAM 역할 생성

CodeDeploy가 대상 인스턴스에 액세스하도록 허용하는 CodeDeploy 권한이 있는 IAM 역할을 생성한다.

 

1단계 - 아래 사진의 서비스 또는 사용 사례에서 CodeDeploy를 선택 후 다음으로 넘어간다. 


2단계 - CodeDeployRole 권한이 보일 것이다. 다음으로 넘어간다.

 


3단계 - 원하는 이름을 입력하고 역할 생성을 완료한다.

 

역할이 정상적으로 생성되었다면 배포 그룹 생성에서 서비스 역할 선택란에 해당 IAM 역할이 나타난다.

 

추가.

EC2에서 S3 버킷과 CodeDeploy 서비스에 액세스하게 할수 있도록 필요한 권한을 가진 IAM 역할을 생성해야 한다.

 

i. 역할 생성

서비스 또는 사용 사례에서 EC2를 선택 후 다음으로 넘어간다.

 


검색을 통해 AmazonS3FullAccess와 AWSCodeDeployFullAccess 권한을 찾아 선택 후 다음으로 넘어가 역할 생성을 완료한다.

 

 

ii. EC2의 IAM 역할 수정

인스턴스 선택 > 작업 > 보안 > IAM 역할 수정 클릭


생성해둔 s3와 CodeDeploy 접근 권한이 있는 역할을 선택한 후 업데이트 한다.

 

 

마무리

위 과정들을 모두 완료한다면 배포가 자동으로 이루어지는 것을 볼 수 있다.