새소식

AWS

AWS EC2 Blue/Green Deployment (Feat. Jenkins, CodeBuild, CodeDeploy) - Part 2

  • -

2023.10.05 - [AWS] - AWS EC2 Blue/Green Deployment (Feat. Jenkins, CodeBuild, CodeDeploy) - Part 1

 

이전글에 이어서 Jenkins 구성 및 Build, Deploy 를 진행합니다.

 

 

Source Code Tree

Source Code 는 아래와 같은 구조로 되어있습니다.

src/main/resources/codedeploy 하위에 AWS CodeDeploy 에서 사용될 파일들을 포함합니다.

(appspec.yml 및 restart.sh)

part1 에서 설정한 buildspec 의 artifacts 내용에 따라 아래 파일들이 zip 파일로 압축됩니다.

discard-paths : yes 를 설정해야 모든 파일들이 root 디렉토리에 위치하게 됩니다.

artifacts:
  files:
    - target/demo-0.0.1-SNAPSHOT.jar
    - src/main/resources/codedeploy/*
    - src/main/resources/codedeploy/script/*
  name: "#${CODEBUILD_BUILD_NUMBER}-demo-application-$(date +%y%m%d%H%M).zip"
  discard-paths: yes

 

 

CodeBuild 에서 사용될 appspec.yml 과 AfterInstall 에서 사용될 restart.sh 입니다.

appspec.yml

version: 0.0
os: linux
files:    
  - source: /
    destination: /home/ec2-user/app/
    overwrite: yes

permissions:
  - object: /
    pattern: "**"
    owner: ec2-user
    group: ec2-user
    mode: 755
    
hooks:
  AfterInstall:
    - location: restart.sh
      timeout: 60
      runas: ec2-user

 

 

restart.sh

#!/bin/bash
BUILD_JAR=$(ls /home/ec2-user/app/*.jar)
JAR_NAME=$(basename $BUILD_JAR)
echo "## build name: $JAR_NAME"
 
echo "## copy build file"
DEPLOY_PATH=/home/ec2-user/
cp $BUILD_JAR $DEPLOY_PATH

CURRENT_PID=$(pgrep -f $JAR_NAME)
echo "## current application pid: $CURRENT_PID"

if [ -z $CURRENT_PID ]
then
  echo "## application is not running"
else
  echo "## kill -15 $CURRENT_PID"
  kill -15 $CURRENT_PID
  sleep 5
fi

DEPLOY_JAR=$DEPLOY_PATH$JAR_NAME
echo "## DEPLOY_JAR: $DEPLOY_JAR"
nohup java -jar $DEPLOY_JAR  > $DEPLOY_PATH/nohup.out 2>&1 &

 

 

Jenkins

Jenkins 설치 및 Plugin 설치

EC2 에 Jenkins 를 설치합니다. 자세한 설치 가이드는 아래 공식문서를 참고하시면 됩니다.

https://www.jenkins.io/doc/book/installing/docker/

 

Docker

After downloading, installing and running Jenkins using one of the procedures above (except for installation with Jenkins Operator), the post-installation setup wizard begins. This setup wizard takes you through a few quick "one-off" steps to unlock Jenkin

www.jenkins.io

 

Jenkins 설치 완료 후 아래 플러그인을 설치합니다.

Jenkins 구성

Jenkins 설치 완료 후 로그인 하여 폴더와 프로젝트를 생성합니다.

 

폴더생성

Jenkins 메인 페이지에서 아래 이미지를 참고하여 폴더를 생성합니다.

 

Build 프로젝트 생성

아래 이미지를 참고하여 생성된 폴더 내에 Freestyle project 를 생성합니다.

 

 

Repository 설정

소스 코드 저장소를 Jenkins 와 연동합니다.

이 예제에서는 svn 을 사용하였습니다. 

위에서 생성한 demo-application 으로 이동하여 구성을 시작합니다.

 

 

 

소스 코드 관리에서 Subsersion 을 선택하고 Repository URL, Credentials 을 입력합니다.

빌드 환경에서 'Delete workspace before build starts' 를 체크합니다.

 

 

Build 구성

Build Step 및 AWS CodeBuild 를 추가합니다.

AWS CodeBuild Credentials 을 등록합니다.

Project Configuration 에는 AWS Console 에서 생성한 CodeBuild 프로젝트 정보를 입력해 줍니다.

Build Test

Build 가 정상적으로 성공하는지 확인합니다.

Build output 이 AWS CodeBuild 의 아티팩트에 설정한 S3 로 upload 되었는지 확인합니다.

 

Deploy 프로젝트 생성

새로운 item 을 클릭하여 Pipeline 프로젝트를 생성합니다.

아래와 같이 프로젝트를 구성합니다.

Active Choices Parameter 를 추가하여 S3 에 upload 된 artifact 파일 정보를 CodeDeploy CLI parameter 로 넘겨줍니다.

 

 

Groovy Script 에 아래 code 로 작성합니다 S3 버킷명은 각자 환경에 맞게 수정합니다.

def aws_s3_ls_output = "aws s3 ls s3://gyko-demo-codedeploy-bucket/".execute() \
                       | ['awk', '{ print $NF }'].execute()
aws_s3_ls_output.waitFor() // might be needed if execution is too long
def files = aws_s3_ls_output.text.tokenize().reverse().take(10)

return files

 

Pipeline 을 작성합니다.

 

각자 환경에 맞게 아래 pipline script 를 수정합니다.

pipeline {
    agent any
    stages {
        stage('Deploy'){
            steps {
                script{
                    try {
                        
                        sh"""
                            aws deploy create-deployment \
                            --application-name demo-application \
                            --deployment-group-name demo-application-deploy \
                            --region ap-northeast-2 \
                            --s3-location bucket=gyko-demo-codedeploy-bucket,bundleType=zip,key=${params.artifact} \
                            --file-exists-behavior OVERWRITE \
                            --output json > DEPLOYMENT_ID.json
                            cat DEPLOYMENT_ID.json
                        """
                        
                        def DEPLOYMENT_ID = readJSON file: './DEPLOYMENT_ID.json'
                        echo "${DEPLOYMENT_ID.deploymentId}"
                        sh "rm -rf ./DEPLOYMENT_ID.json"
                        def DEPLOYMENT_RESULT = ""
                        while("$DEPLOYMENT_RESULT" != "\"Succeeded\"") {
                            DEPLOYMENT_RESULT = 
                                sh(
                                    script:"aws deploy get-deployment \
                                    --query \"deploymentInfo.status\" \
                                    --region ap-northeast-2 \
                                    --deployment-id ${DEPLOYMENT_ID.deploymentId}",
                                    returnStdout: true
                                ).trim()
                                
                            echo "$DEPLOYMENT_RESULT"
                            if ("$DEPLOYMENT_RESULT" == "\"Failed\"") {
                                throw new Exception("CodeDeploy Failed")
                                break
                            }
                            sleep(30)
                        }
                        currentBuild.result = 'SUCCESS'
                    } catch (error) {
                        print(error)
                        echo 'Remove Deploy Files'
                        sh "sudo rm -rf /var/jenkins_home/workspace/${env.JOB_NAME}/*"
                        currentBuild.result = 'FAILURE'
                    }
                }
            }
        }
    }
}

 

 

Deploy Test

배포를 테스트합니다.

위에서 생성한 Deploy 프로젝트를 실행하여 Blue/Green 배포가 정상적으로 성공하는지 확인합니다.

파미미터와 함께 빌드 버튼을 클릭하여 배포할 artifact 를 선택 후 배포를 진행합니다.

artifact 변수는 S3 버킷에 upload 되어있는 artifact.zip 파일의 목록입니다.

배포가 진행중이며 Console Output 에서 진행 상태를 30초 간격으로 확인할 수 있습니다.

 

AWS Console 로 이동하여 Blue Green 배포가 정상적으로 진행되는지 확인합니다.

 

 

AWS Console 의 AutoScaling Group(ASG) 화면으로 이동해 보면 기존 Application 이 배포된 ASG 를 복제하여 새로 배포할 Application 용 ASG 가 생성된 것이 확인됩니다.

 

 

 

 

배포에 성공하였고 기존 Application 으로의 Traffic 도 차단되었습니다.

 

 

Jenkins console output 에서도 배포 상태 확인이 가능합니다.

 

 

Blue/Green 배포에 성공하게 되면 기본 Application 이 배포되었던 ASG 는 삭제되고 현재 배포된 Application 의 ASG 만 남게 됩니다.

다음 배포때에도 마찬가지로 CodeDeploy 가 현재 ASG 를 복제하여 새로운 ASG 를 생성후 새로운 Application 을 배포 및 기존 ASG 삭제 작업을 거치게 됩니다.

 

 

ALB 의 domain 으로 배포 내역을 확인합니다.

 

이상으로 Jenkins, AWS CodeBuild, AWS CodeDeploy 를 이용한 Application Blue/Green Deploymenet 에 대해 알아보았습니다.

 

AWS CodeDeploy 를 이용하면 AutoScaling 이 적용된 Application 을 Service downtime 없이 손쉽게 Blue/Green 배포가 가능합니다.

 

The End.

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.