티스토리 뷰
공연 동행 구인 웹 서비스 프로젝트에 참여하며
CI/CD를 직접 적용해보게 되어 그 과정을 기록해보고자 합니다👣
이전에는 깃에 코드를 올리고, aws ec2를 통해 pull 받아와 jar 파일을 실행하는 방식으로 배포해왔었습니다.
매번 develop 브랜치가 업데이트 될 때마다 수동으로 빌드 후 jar 파일을 실행해야 하며 번거로웠기에
깃에서 제공해주는 "GitHub Action"을 통해 자동화를 적용하여 개발에 좀 더 집중해보고자 합니다😀
CI/CD란?
지속적 통합 및 지속적 배포
CI
Continuous Integration, 빌드와 테스트 자동화
새로운 코드 변경 사항이 정기적으로 빌드 및 테스트 되어
공유 레포지토리에 통합하는 것을 의미합니다.
CD
Continuous Delivery 혹은 Continuous Depolyment, 배포 자동화
개발자의 변경 사항이 레포지토리를 넘어,
고객의 프로덕션 환경까지 릴리즈 되는 것을 의미합니다.
정리하면
CI 빌드 -> 테스트 -> 통합
CD 배포
서버 구성
EC2, RDS, ElastiCache, S3, Code Deploy
전체적인 CI/CD 흐름
- 깃 레포지토리에 이벤트 발생
- 깃헙 액션 워크 플로우 동작
- build, test 성공
- s3에 레포지토리가 압축형태로 업로드
- CodeDeploy에서 S3의 파일을 이용해 EC2에 배포 시작
서버 구성 및 CI/CD 적용 과정
1. VPC 및 Subnet 생성
2. EC2 생성
생성한 VPC에 EC2를 생성하고, S3와 CodeDeploy 접근을 허용하는 역할을 생성하여 부여합니다.
SSH, MySQL, Redis, http, https로부터의 접근을 위한 인바운드 규칙을 생성합니다.
ip 주소 고정을 위해 탄력적 ip 주소를 생성 후 부여합니다.
EC2에 접속하여 자바와 CodeDeploy를 설치합니다.
- 자바 설치
sudo apt update sudo apt install openjdk-17-jdk
- codedeploy 설치
3. RDS(MySQL) 생성
VPC에 RDS(MySQL) 생성 후 EC2와 연결합니다.
4. ElastiCache(Redis) 생성
VPC에 Redis 캐시 생성 후, 접속을 위한 인바운드 규칙을 설정합니다.
➕ElastiCache는 같은 VPC 내부에서만 direct하게 접속이 가능하다.
redis 접근 시에는 SSH를 통해 EC2를 거쳐서 접속해야 합니다.
5. S3 생성
S3 버킷을 생성합니다.
6. Code Deploy 설정
Code Deploy 애플리케이션을 생성합니다.
7. Git Action 워크플로우 작성
develop 브랜치에 push 또는 pr 이벤트가 발생하면 스크립트에 정의해둔 깃헙 액션이 실행됩니다.
name: CI
on:
# develop 브랜치에서 일어난 push/pull request에 작동한다.
push:
branches: [ "develop" ]
pull_request:
branches: [ "develop" ]
workflow_dispatch:
env:
PROJECT_NAME: dongoorami
BUCKET_NAME: dongoorami-bucket
CODE_DEPLOY_APP_NAME: dongoorami-codedeploy
DEPLOYMENT_GROUP_NAME: dongoorami
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: JDK 17 설치
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'adopt'
# gitignore한 파일 생성해주기
- name: create applications.yml
shell: bash
run: |
if [ ! -d "./src/main/resources" ]; then
mkdir -p ./src/main/resources
fi
touch ./src/main/resources/application.yml
echo "${{ secrets.APPLICATION }}" >> ./src/main/resources/application.yml
# gradlew 파일 실행권한 설정
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew
# 빌드 시작
- name: Build with Gradle
run: ./gradlew build
# 프로젝트 zip파일로 압축
- name: Make Zip File
run: zip -qq -r ./$GITHUB_SHA.zip .
# aws 접근 id, key
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-2
# s3에 압축한 zip파일 업로드
- name: upload to S3
run: aws s3 cp --region ap-northeast-2 ./$GITHUB_SHA.zip s3://$BUCKET_NAME/$PROJECT_NAME/$GITHUB_SHA.zip
# s3에 업로드한 파일 code Deploy에서 배포 요청
- name: deploy with AWS codeDeploy
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
8. Appspec.yml 작성
CodeDeploy에서 배포를 관리하는 데 사용하는 YAML 형식 또는 JSON 형식의 파일
CodeDeploy가 가장 먼저 호출할 설정파일로 프로젝트 최상단에 생성합니다.
version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/dongoorami
overwrite: yes
permissions:
- object: /
pattern: "**"
owner: ubuntu
group: ubuntu
hooks:
ApplicationStart:
- location: /scripts/deploy.sh
timeout: 60
runas: ubuntu
9. deploy.sh 작성
appspec.yml 파일에서 deploy.sh 파일을 수행하게 됩니다.
기존에 실행중이던 jar 프로세스를 종료하고, 새로운 jar를 실행시키는 작업을 수행합니다.
#!/usr/bin/env bash
REPOSITORY=/home/ubuntu/dongoorami
cd $REPOSITORY
APP_NAME=dongoorami
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 "> $JAR_PATH 배포"
nohup java -jar "$JAR_PATH" > jarExecute.log 2>&1 < /dev/null &
CI/CD 확인👀
깃에서 작업 후 develop 브랜치로 push 또는 pr 시에 실행되는 것을 확인할 수 있습니다!
생각보다 서버 구성하면서 권한 설정, 보안 규칙 설정, 서브넷, VPC .. 등등 해주어야 하는 작업들이 많아서 복잡했지만, 자동화되어 편하게 개발에 집중할 수 있을 것 같습니다! 이번 계기로 AWS의 여러 서비스와 GitHub Action 다루어볼 수 있었습니다👍
'백엔드' 카테고리의 다른 글
Nginx의 역할에 대해 아시나요🤔 (0) | 2024.06.21 |
---|---|
다양한 HTTP 통신 방법(크롤링과 Open API)📻 (0) | 2024.05.09 |
S3와 이미지 생성 Util 클래스(+CORS 에러) (0) | 2024.03.19 |
ec2 ip 주소에 도메인 입혀보자! nginx를 이용한 https 설정까지!! (0) | 2024.03.05 |
객체지향이란? 절차지향과의 차이점! (0) | 2023.07.02 |