AWS

GitHub Action + S3 + CodeDeploy를 이용한 CI/CD (2/2)

Beekei 2021. 10. 8. 17:04
반응형

앞서 GitHub Action,  Aws CodeDeploy, CI/CD가 무엇인지 알아보았다.

 

GitHub Action + AWS CodeDeploy를 이용한 CI/CD (1/2)

Github Action이란? Github 저장소를 기반으로 소프트웨어 개발 Workflow를 자동화 할 수 있는 CI/CD 도구이다. Workflow는 Github 저장소에서 발생하는 build, test, package, release, deploy 등 다양한 이벤트..

devbksheen.tistory.com

이번에는 GitHub Action + AWS CodeDeploy로 CI/CD 구현 예시를 정리해보았다.


구현 예시

1. EC2 인스턴스에 CodeDeploy Agent 설치

EC2 인스턴스(Amazon Linux 2 AMI (HVM), SSD Volume Type)를 생성하고 접속해 CodeDeploy Agent를 설치한다.

(인스턴스 유형을 프리티어로 생성하면 CodeDeploy에 오류가 발생하기 때문에 최소한 t2.small로 생성해야 한다.)

sudo yum update # yum 패키지 업데이트

sudo yum list | grep amazon-corretto # 설치가 가능한 amazon-corretto Java 버전을 확인

sudo yum install java-11-amazon-corretto.x86_64 # java 11 버전 사용

# sudo alternatives --config java # 자바 버전 변경

sudo yum install ruby # ruby 설치

cd /home/ec2-user # ec2-user로 이동

# 서울 region에 있는 CodeDeploy 리소스 키트 파일 다운로드
sudo wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install

chmod 777 ./install # 실행 권한 부여

sudo ./install auto # 설치

sudo service codedeploy-agent status # Agent 상태 확인

CodeDeploy Agent Status


2. IAM 역활 생성

2-1. EC2 인스턴스 IAM 역활 생성

생성한 EC2 인스턴스에 CodeDeploy가 접근할 수 있는 IAM 역활을 부여한다.

인스턴스 > 마우스 우 클릭 > 보안 > IAM 역활 수정
새 IAM 역활 생성 클릭
역활 만들기 버튼 클릭
AWS 서비스 > EC2 선택
AmazonEC2RoleforAWSCodeDeploy 선택

2-2. CodeDeploy IAM 역활 생성

AWS 서비스 > CodeDeploy 선택 
CodeDeploy 선택

CodeDeploy 정책은 AWSCodeDeployRole 하나밖에 없으므로 그대로 역활을 생성한다.


3. CodeDeploy 애플리케이션 생성 및 배포 그룹 생성

CodeDeploy 애플리케이션 생성
배포 그룹 생성 버튼 클릭
서비스 역활에는 위에서 생성한 CodeDeploy IAM 역활을 선택
값에는 배포할 EC2 인스턴스의 값을 선택
앞서 EC2 인스턴스에 접속해 CodeDeploy Agent를 설치했으므로 설치 안함 선택
CodeDeployDefault.AllAtOnce로 설정
로드 밸런서 활성화 해체


4. IAM(사용자) 생성

CodeDeploy와 S3를 사용할 사용자를 생성한다.

사용자(IAM) 추가
AWSCodeDeployFullAccess 정책 추가
AmazonS3FullAccess 정책 추가
엑세스키는 다시 볼 수 없으므로 csv로 다운로드 받아 보관해야한다.


5. secrets 설정

생성한 CodeDeploy와 사용자(IAM)의 정보를 secrets에 설정한다.


6. Github Action 생성

GitHub Repository Tab > Actions
Publish Java Package with Gradle 선택

name: CI # workflow의 이름을 지정

on:
  push:
    branches:
      - deploy # deploy branche가 push 됬을때 
  workflow_dispatch: # 수동으로 workflow 실행

jobs:
  build:
    runs-on: ubuntu-latest # ubuntu 최신 버전

    steps:
      - name: Checkout # 소스를 가져옴
        uses: actions/checkout@v2

      - name: Set up JDK 11 # JDK 11 셋업
        uses: actions/setup-java@v1
        with:
          java-version: 11

      - name: Grant execute permission for gradlew # gradlew 사용 권한 부여
        run: chmod 777 ./gradlew
        shell: bash

      - name: Clean build test with Gradle # clean build test
        run: ./gradlew clean build test
        shell: bash
        
      - name: Make zip file # zip 파일 생성
        run: zip -r ./$GITHUB_SHA.zip .
        shell: bash

      - name: Configure AWS credentials # AWS 자격 증명
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
          aws-region: ${{ secrets.AWS_REGION }}

      - name: Upload to S3 # S3 업로드
        run: aws s3 cp --region ${{ secrets.AWS_REGION }} ./$GITHUB_SHA.zip s3://${{ secrets.AWS_S3_BUCKET }}/CI/$GITHUB_SHA.zip

      - name: Code Deploy # CodeDeploy에 배포 요청
        run: aws deploy create-deployment --application-name ${{ secrets.AWS_CODEDEPLOY_NAME }} --deployment-config-name CodeDeployDefault.AllAtOnce --deployment-group-name ${{ secrets.AWS_CODEDEPLOY_GROUP }} --s3-location bucket=${{ secrets.AWS_S3_BUCKET }},bundleType=zip,key=CI/$GITHUB_SHA.zip

7. AppSpec 및 스크립트 추가

개발한 프로젝트 최상단에 appspec.yml, scripts/deploy.sh 파일 생성

  • appspec.yml
version: 0.0
os: linux
files:
  - source:  /
    destination: /home/ec2-user/projectName # 배포될 위치
    overwrite: yes

permissions:
  - object: /
    pattern: "**"
    owner: ec2-user
    group: ec2-user

hooks:
  ApplicationStart:
    - location: scripts/deploy.sh # ApplicationStart 단계에서 deploy.sh 실행
      timeout: 60
      runas: ec2-user
  • scripts/deploy.sh
#!/bin/bash
BUILD_JAR=$(ls /home/ec2-user/projectName/build/libs/*.jar)
JAR_NAME=$(basename $BUILD_JAR)
echo "> build 파일명: $JAR_NAME" >> /home/ec2-user/projectName/deploy.log

echo "> build 파일 복사" >> /home/ec2-user/projectName/deploy.log
DEPLOY_PATH=/home/ec2-user/sictak/
cp $BUILD_JAR $DEPLOY_PATH

echo "> 현재 실행중인 애플리케이션 pid 확인" >> /home/ec2-user/projectName/deploy.log
CURRENT_PID=$(pgrep -f $JAR_NAME)

if [ -z $CURRENT_PID ]
then
  echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다." >> /home/ec2-user/projectName/deploy.log
else
  echo "> kill -15 $CURRENT_PID"
  kill -15 $CURRENT_PID
  sleep 5
fi

DEPLOY_JAR=$DEPLOY_PATH$JAR_NAME
echo "> DEPLOY_JAR 배포"    >> /home/ec2-user/projectName/deploy.log
chmod +x $DEPLOY_JAR
nohup java -jar $DEPLOY_JAR >> /home/ec2-user/deploy.log 2>/home/ec2-user/projectName/deploy_err.log &

8. build

deploy 브랜치에 Push가 발생할때 빌드가 진행되고 성공하게 되면 S3에 zip파일이 업로드 되고 CodeDeploy에 배포가 성공한 것을 확인할 수 있다.

Build Success
S3에 zip 파일 업로드
Deploy Success

반응형