이전 발행글에서 이어지는 내용입니다. 처음부터 따라오고 싶으시다면 이전 포스팅을 참고해주세요
📌 CodeDeploy
CodeDeploy Agent 설치
본 CI/CD 실습에 사용되는 EC2 인스턴스의 운영체제 및 버전은 Ubuntu - 22.04 version 입니다.
(다른 버전에서는 문제가 발생할 수 있습니다. 설치되는 모듈의 버전 및 호환성을 공식 문서를 통해 확인해주세요)
다음의 명령어를 차례대로 입력합니다.
# apt 업데이트
sudo apt-get update && sudo apt-get upgrade
# JDK 11 설치
sudo apt-get install openjdk-11-jdk
# Ruby 설치 (3.xx 버전 설치됨)
sudo apt install ruby-full
# wget 모듈 설치
sudo apt install wget
cd /home/ubuntu
# codedeploy 파일 다운로드
sudo wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
다음의 명령어를 차례대로 수행하였다면 디렉토리에 install 파일이 생성되어 있어야합니다.
다음의 명령어를 차례대로 입력하여 설정 및 사용 가능한 codedeploy의 버전을 확인합니다.
# 권한 설정
sudo chmod +x ./install
# 출력을 임시 로그파일에 씀
sudo ./install auto > /tmp/logfile
# aws cli 설치
sudo apt-get install awscli
# 서울 리전에서 사용 가능한 codedeploy 버전 확인
sudo aws s3 ls s3://aws-codedeploy-region-identifier/releases/ | grep '\.deb$'
다음과 같이 사용 가능한 버전을 확인할 수 있습니다. 여기서, 가장 최신 버전인 1.6.0 버전을 사용하겠습니다.
다음과 명령을 통해 1.6.0 버전의 codedeploy-agent를 설치합니다.
# 1.6.0-49 버전의 codedeploy-agent 설치
sudo ./install auto -v releases/codedeploy-agent_1.6.0-49_all.deb > /tmp/logfile
# 서비스가 실행중인지 확인
sudo service codedeploy-agent status
"sudo service codedeploy-agent status" 명령어를 입력하면 다음과 같이 codedeploy-agent service가 Active 된 상태임을 확인할 수 있습니다.
CodeDeploy 생성
이제는 AWS에서도 CodeDeploy 애플리케이션을 생성해보겠습니다.
1. 새 IAM 역할 생성
생성에 앞서, EC2에 IAM 역할을 부여한 것처럼 CodeDeploy를 위한 IAM 역할을 생성하겠습니다.
"다른 AWS 서비스의 사용 사례 → CodeDeploy"를 클릭하면 자동으로 CodeDeploy에 대한 모든 권한이 부여된 상태가 됩니다.
2. CodeDeploy 애플리케이션 생성
AWS 콘솔에서 CodeDeploy서비스를 선택하여 새 애플리케이션을 생성합니다.
애플리케이션 이름을 지정하고 EC2/온프레미스를 선택하여 애플리케이션을 생성합니다.
3. 배포 그룹 생성
생성된 CodeDeploy 애플리케이션을 클릭하고 배포 그룹을 생성합니다.
배포 그룹 명을 지정하고 서비스 역할에는 방금 생성했던 IAM 역할을 선택합니다.
배포 유형은 현재 위치, 환경은 EC2 인스턴스를 선택하고 태그 값에 앞서 생성했던 EC2 인스턴스를 지정합니다.
배포 구성은 애플리케이션 배포를 어떻게 수행할지에 대한 선택입니다. AllAtOnce는 한번에 모든 인스턴스를 배포합니다.
로드 밸런서를 사용하지 않고 있기 때문에 체크를 해제합니다. 만약, 로드 밸런서를 사용중이라면 활성화를 클릭하여 대상 그룹을 선택하면 됩니다.
📌 build-deploy.yml 에 배포 동작 추가
name: Build and Deploy Spring Boot to AWS EC2
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
# --------------------------추가
env:
PROJECT_NAME: moduform_project
BUCKET_NAME: moduform-cicd-bucket
CODE_DEPLOY_APP_NAME: moduform_cicd
DEPLOYMENT_GROUP_NAME: moduform_instance
# --------------------------추가
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Permission for gradlew
run: chmod +x ./gradlew
shell: bash
- name: Build and Test
run: ./gradlew build test
# --------------------------추가
- name: Make Zip File
run: zip -qq -r ./$GITHUB_SHA.zip .
shell: bash
- 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_PRIVATE_ACCESS_KEY }}
aws-region: ap-northeast-2
- name: Upload to S3
run: aws s3 cp --region ap-northeast-2 ./$GITHUB_SHA.zip s3://$BUCKET_NAME/$PROJECT_NAME/$GITHUB_SHA.zip
- name: Code Deploy To EC2 instance
run: aws deploy create-deployment
--application-name $CODE_DEPLOY_APP_NAME
--deployment-config-name CodeDeployDefault.AllAtOnce
--deployment-group-name $DEPLOYMENT_GROUP_NAME
--s3-location bucket=$BUCKET_NAME,bundleType=zip,key=$PROJECT_NAME/$GITHUB_SHA.zip
# --------------------------추가
build-deploy.yml 파일을 다음과 같이 수정합니다.
- env: yml 파일에서 사용되는 변수를 선언합니다.
- PROJECT_NAME: 프로젝트 이름을 설정합니다. S3 경로 설정에 사용됩니다.
- BUCKET_NAME: 앞서 생성한 S3 버킷 이름을 넣어줍니다.
- CODE_DEPLOY_APP_NAME: CodeDeploy '애플리케이션 이름'을 넣어줍니다.
- DEPLOYMENT_GROUP_NAME: CodeDeploy '배포 그룹 이름'을 넣어줍니다.
- 앞서 생성한 S3 및 CodeDeploy 의 이름을 넣어주면 됩니다.
- jobs - steps에 다음과 같은 동작을 정의합니다.
- Make Zip File - zip 파일을 생성합니다.
- Configure AWS Credentials - ACCESS TOKEN을 통해 AWS 계정의 서비스에 접근할수 있는 권한을 얻습니다.
- Upload to S3 - S3 버킷에 zip 파일을 업로드합니다.
- Code Deploy To EC2 instance - CodeDeploy에 배포 요청을 날립니다.
- 보기 편하게 하기 위해 명령어 행을 나누었는데, 실제는 한줄로 작성하면 됩니다.
- 배포 관련 cli 명령어는 다음 공식 문서에서 확인할 수 있습니다. AWS Docs - CodeDeploy awscli
appspec.yml 생성
배포할 프로젝트 최상단 경로에 appspec.yml 파일을 생성합니다. appspec 파일은 배포시, codedeploy가 참조하는 파일입니다.
yml 파일을 다음과 같이 작성합니다.
version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/moduform
permissions:
- object: /home/ubuntu/moduform/
owner: ubuntu
group: ubuntu
hooks:
AfterInstall:
- location: scripts/deploy.sh
timeout: 60
runas: ubuntu
- version
- appspec.yml 파일 버전을 정의합니다. 현재는 0.0 이외의 버전이 지원되지 않습니다.
- files
- 배포할 파일 및 디렉토리를 정의합니다. 위의 예시에서는 애플리케이션을 루트 디렉토리에서 가져와 "/home/ubuntu/moduform" 디렉토리로 복사합니다.
- permissions
- 애플리케이션 파일에 대한 권한을 정의합니다. 위의 예시에서는 "/home/ubuntu/moduform" 디렉토리의 그룹과 소유자를 ubuntu로 설정합니다.
- hooks
- 배포 단계에서 실행할 훅 스크립트를 정의합니다. 위의 예시에서는 배포 후 실행할 스크립트인 deploy.sh 파일을 지정하고, 스크립트 실행 시간 제한을 60초로 설정합니다.
- AfterInstall
- 여러 배포 단계 중 AfterInstall 단계에서 스크립트를 실행합니다.
scripts/deploy.sh 배포 쉘 스크립트 생성
다음과 같이 배포 스크립트를 작성합니다. 이 스크립트는 Spring Boot 애플리케이션을 배포하기 위해 사용되며, 이전에 실행중인 프로세스를 중단하고 최신 버전의 JAR 파일을 실행하는 작업을 수행합니다.
#!/usr/bin/env bash
REPOSITORY=/home/ubuntu/moduform
cd $REPOSITORY
APP_NAME=moduform
JAR_NAME=$(ls $REPOSITORY/build/libs/ | grep 'SNAPSHOT.jar' | tail -n 1)
JAR_PATH=$REPOSITORY/build/libs/$JAR_NAME
CURRENT_PID=$(pgrep -f $APP_NAME)
if [ -z $CURRENT_PID ]
then
echo "> 종료할 애플리케이션이 없습니다."
else
echo "> kill -9 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 5
fi
echo "> Deploy - $JAR_PATH "
nohup java -jar $JAR_PATH > /dev/null 2> /dev/null < /dev/null &
만약 Action이나 CodeDeploy의 배포 단계에서 문제가 발생한다면 AWS 서비스 이름이 알맞게 입력되었는지, 프로젝트 경로나 쉘 스크립트 명령어가 제대로 작성되었는지를 확인해보시길 바랍니다.
제가 겪었던 문제 해결 과정은 다음 포스팅에 기록해두었습니다.
2023.04.20 - [DevOps] - Github Actions CI/CD - 트러블 슈팅 정리 (submodule, 파일 중복, ec2 용량)
🔨 CI/CD Test
EC2 인스턴스에 Spring Boot 애플리케이션을 배포한 상태입니다.
http://"ec2 public IP":8080 접속
현재는 왼쪽 로고 밑에 2줄의 문구가 있는 상태입니다.
다음과 같이 문구 추가 후 Master 브랜치에 PUSH 합니다.
Master 브랜치에 새로운 코드가 Push 되고 Action이 자동으로 실행되어 테스트, 빌드, 배포 작업이 수행됩니다.
다시 똑같은 IP로 접속해보면?
다음과 같이 새 코드가 EC2 인스턴스에 배포된 것을 확인할 수 있습니다.
배포 내역은 CodeDeploy 에서도 확인할 수 있습니다.
참고
- https://www.youtube.com/watch?v=UF2Giz9PE-E&t=301s
- https://codechacha.com/ko/ubuntu-install-open-jdk11/
- AWS Docs - AppSpec
- AWS Docs - CodeDeploy agent
- AWS Docs - CodeDeploy awscli
- Github Actions Docs