AWS

CodeDeploy를 통해 CICD/무중단배포를 해보자

cocodingding 2024. 2. 29. 02:18

CI/CD란 ?

  • CI - 빌드/테스트 자동화 과정 과정
    • CI는 개발자를 위한 자동화 프로세스인 지속적인 통합(Continuous Integration)을의미
    • CI를 성공적으로 구현할 경우 애플리케이션에 대한 새로운 코드 변경 사항이 정기적으로 빌드 및 테스트되어 공유 리포지토리에 통합되므로 여러 명의 개발자가 동시에 애플리케이션 개발과 관련된 코드 작업을 할 경우 서로 충돌할 수 있는 문제를 해결할 수 있음
  • CD - 배포 자동화 과정
    • CD는 지속적인 서비스 제공(Continuous Delivery) 또는 지속적인 배포(Continuous Deployment)를 의미하며 이 두 용어는 상호 교환적으로 사용됨
    • 두 가지 의미 모두 파이프라인의 추가 단계에 대한 자동화를 뜻하지만 때로는 얼마나 많은 자동화가 이루어지고 있는지를 설명하기 위해 별도로 사용되기도 함

무중단 배포 과정

  1. 개발자가 Github에 변경 코드를 배포 브랜치에 푸시함
  2. Github Action 을 통해 개발자가 변경사항을 감지하여 설정된 Workflow를 실행
  3. AWS 인증, 및 IAM에 설정 된 정책에 따라 4,5번 과정이 수행됨
  4. Workflow가 수행되어 생긴 압축 파일을 AWS S3 버킷에 올림
  5. CodeDeploy 서비스를 실행
  6. 새로운 인스턴스 시작됨
  7. S3 버킷에 올라가있는 결과물들이 새 인스턴스에 배포되고, 애플리케이션이 실행됨
  8. 새 인스턴스를 기본 인스턴스로 리라우팅하고, 기존 인스턴스 종료

블루/그린 배포의 장점

  • 블루/그린 배포는 하나의 버전만 프로덕션 되기 때문에 버전 관리 문제를 방지할 수 있음
  • 운영 환경에 영향을 주지 않고 실제 서비스 환경으로 새 버전 테스트가 가능
  • 새 버전으로 전환 후에 문제가 생겼을 시에 구 버전으로 되돌리기 위한 롤백이 용이함
  • 기존에 쓰던 방식 (EC2 + Docker)에서 Docker가 중지 - 새로 받아옴 - 재시작하는 과정이 없어져서 무중단 배포 가능

 

EC2, CodeDeploy 등 초기세팅들은 아래의 레퍼런스 참고

GithubActions 워크플로우 작성

name: CICD Test
run-name: Running
on:
  push:
    branches:
      - dev

env:
  AWS_REGION: ap-northeast-2
  AWS_S3_BUCKET: mytaek1-bucket
  AWS_CODE_DEPLOY_APPLICATION: mytaek1-cicd
  AWS_CODE_DEPLOY_GROUP: mytaek1-cicd-group
jobs:
  build-with-gradle:
    runs-on: ubuntu-22.04
    steps:
    - name: production 브랜치로 이동
      uses: actions/checkout@v3
      with:
        ref: dev
        
    - name: JDK 17 설치
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'corretto'
        
    - name: make application.properties
      if: |
        contains(github.ref, 'dev') 
      run: |
        cd ./src/main/resources
        touch ./application.properties
        echo "${{ secrets.PROPERTIES }}" > ./application.properties
      shell: bash
  
    - name: Setup Gradle Wrapper
      run: gradle wrapper --gradle-version 8.5
      shell: bash 
      
    - name: gradlew에 실행 권한 부여
      run: chmod +x ./gradlew
      
    - name: 프로젝트 빌드
      run: ./gradlew clean build -x test
      
    - name: AWS credential 설정
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-region: ${{ env.AWS_REGION }}
        aws-access-key-id: ${{ secrets.CICD_ACCESS_KEY }}
        aws-secret-access-key: ${{ secrets.CICD_SECRET_KEY }}
        
    - name: S3에 업로드
      run: aws deploy push --application-name ${{ env.AWS_CODE_DEPLOY_APPLICATION }} --ignore-hidden-files --s3-location s3://$AWS_S3_BUCKET/mytaek1/$GITHUB_SHA.zip --source .
    
    - name: EC2에 배포
      run: aws deploy create-deployment --application-name ${{ env.AWS_CODE_DEPLOY_APPLICATION }} --deployment-config-name CodeDeployDefault.AllAtOnce --deployment-group-name ${{ env.AWS_CODE_DEPLOY_GROUP }} --s3-location bucket=$AWS_S3_BUCKET,key=mytaek1/$GITHUB_SHA.zip,bundleType=zip

 

- 중요 정보들은 Secret에 작성해서 가져와야함

 

appsepc.yml 작성

version: 0.0
os: linux

files:
  - source:  /
    destination: /home/ubuntu/spring-github-action
    overwrite: yes

permissions:
  - object: /
    pattern: "**"
    mode: '755'
    owner: ubuntu
    group: ubuntu

hooks:
  AfterInstall:
    - location: scripts/stop.sh
      timeout: 60
  ApplicationStart:
    - location: scripts/start.sh
      timeout: 60

appspec.yml 은 aws의 공식 메뉴얼 사이트를 참고하면 좋다

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

 

AppSpec '후크' 섹션 - AWS CodeDeploy

배포의 시작 DownloadBundle, 설치 BlockTrafficAllowTraffic, 및 종료 이벤트는 스크립팅할 수 없으므로 이 다이어그램에서 회색으로 표시됩니다. 하지만 파일의 '파일' 섹션을 편집하여 설치 이벤트 중에

docs.aws.amazon.com

 

start.sh / stop.sh 작성

//start.sh

ROOT_PATH="/home/ubuntu/spring-github-action"
JAR="$ROOT_PATH/application.jar"

APP_LOG="/var/log/aws/codedeploy-agent/application.log"
ERROR_LOG="/var/log/aws/codedeploy-agent/error.log"
START_LOG="/var/log/aws/codedeploy-agent/start.log"

NOW=$(date +%c)

echo "[$NOW] $JAR 복사" >> $START_LOG
cp $ROOT_PATH/build/libs/mytaek1-0.0.1-SNAPSHOT.jar $JAR

echo "[$NOW] > $JAR 실행" >> $START_LOG
nohup java -jar $JAR > $APP_LOG 2> $ERROR_LOG &

SERVICE_PID=$(pgrep -f $JAR)
echo "[$NOW] > 서비스 PID: $SERVICE_PID" >> $START_LOG

//stop.sh
ROOT_PATH="/home/ubuntu/spring-github-action"
JAR="$ROOT_PATH/application.jar"
STOP_LOG="/var/log/aws/codedeploy-agent/stop.log"
SERVICE_PID=$(pgrep -f $JAR)

if [ -z "$SERVICE_PID" ]; then
  echo "서비스 NotFound" >> $STOP_LOG
else
  echo "서비스 종료 " >> $STOP_LOG
  kill -9 "$SERVICE_PID"
fi

 

이후 여러가지 에러를 겪다보면..

 

성공하게된다.

 

트러블슈팅

1. 로드밸런서로 연결해줬는데, BlockTraffic에서 막혀서 로드밸런서를 거치지 않고 바로 코드디플로이로 가게 변경

 -> 로드 밸런싱 활성화 체크를 해제해주었음

 

2. 루트에 액션 폴더가 생성이 안됨

 -> appspecs.yml파일의 files 부분의 destination의 경로가 잘못 설정되어있었음

 

3. stop.sh에서 어플리케이션이 종료가 되지 않아 시작도 되지 않음

#!/bin/bash

ROOT_PATH="/home/ubuntu/spring-github-action"
JAR="$ROOT_PATH/application.jar"
STOP_LOG="/var/log/aws/codedeploy-agent/stop.log"
SERVICE_PID=$(pgrep -f $JAR)

if [ -z "$SERVICE_PID" ]; then
  echo "서비스 NotFound" >> $STOP_LOG
else
  echo "서비스 종료 " >> $STOP_LOG
  kill -9 "$SERVICE_PID" # 강제 종료로 변경
fi

 

 

 

래퍼런스

 

실전! Github actions, AWS Code deploy로 Spring boot 배포 자동화하기

아휴 힘드러 🤮

velog.io

 

 

AppSpec '후크' 섹션 - AWS CodeDeploy

배포의 시작 DownloadBundle, 설치 BlockTrafficAllowTraffic, 및 종료 이벤트는 스크립팅할 수 없으므로 이 다이어그램에서 회색으로 표시됩니다. 하지만 파일의 '파일' 섹션을 편집하여 설치 이벤트 중에

docs.aws.amazon.com

 

댓글수0