Infra - Doo-re Infra(9) - GITHUB ACTION 코드 살펴보기
서론
BDD(부산 개발자 소모임)의 Doo-re 프로젝트에서 인프라를 담당하게 되었습니다. BDD는 문서화를 굉장히 중요시하기 때문에 인프라를 구축하면서 필요한 개념과 과정들을 모두 작성하기로 했습니다.
이번 문서에서는 GITHUB ACTION을 활용한 CICD 코드에 대해서 STEP별로 알아보도록 하겠습니다. 전체 코드는 Doo-re Repository에서 확인하실 수 있습니다.
본론
# GITHUB ACTION의 이름을 설정합니다.
name: Deploy BDD Development Server
# 이 Event는 GITHUB UI에서 수동으로 버튼을 눌러 아래의 Job이 실행되도록 합니다.
# 여러 방법이 있지만 대부분 push를 사용합니다. push는 특정 브랜치로 push할 경우 자동으로 아래의 Job이 실행되도록 합니다.
# doo-re 에서는 안정화된 코드인지를 확인한 후 자동 배포하도록 결정해 아래의 방식으로 결정했습니다.
on: workflow_dispatch
jobs:
deploy_development:
# 우분투 22.04 버전에서 Git Flow가 실행되도록 합니다.
# 자세한 설명은 [공식 문서](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners)에서 확인하실 수 있습니다.
# 아래의 flow가 10분 이상 지속되면 종료하도록 설정했습니다. 이유는 10분이 넘어갈 경우 비정상적인 동작이라 생각했고, 한정된 자원(500분)을 아끼기 위해서 입니다.
runs-on: ubuntu-22.04
timeout-minutes: 10
# 아래는 Configure AWS Credntials STEP을 진행하기 위해 필요한 설정입니다.
# 제가 작성한 [문서](https://02ggang9.github.io/trouble/ConfigureAwsCredentials/)에서 발생한 에러 이름과 해결 방법에 대해서 확인하실 수 있습니다.
permissions:
id-token: write
contents: read
steps:
# 저장소를 체크아웃 합니다. 아래는 [Github Marketplace](https://github.com/marketplace?type=)에서 제공하는 일종의 라이브러리입니다.
# 깃허브에서 관리하는 라이브러리를 사용하지 않으면 굉장히 복잡한 작업을 수행해야 하지만 라이브러리를 사용한다면 쉽게 저장소를 체크아웃 할 수 있습니다.
- name: Checkout
uses: actions/checkout@v4
# AWS 자격 증명을 설정합니다. 자격 증명을 설정하는 방법은 제가 작성한 [문서](https://02ggang9.github.io/infra/DooreInfra7/)에서 확인하실 수 있습니다.
# 이 단계에서는 워크플로우가 AWS 서비스와 상호작용할 수 있도록 합니다. 아래의 STEP에서 EC2와 S3에 접근하는데 그때 필요한 밑 작업입니다.
# 과거 코드와의 차이점은 role 기반의 자격 증명을 사용하기 때문에 보안적으로 훨씬 안전하다고 합니다.
# 이 또한 Github Marketplace에서 제공하는 라이브러리를 이용했습니다.
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: $
aws-region: $
# ECR에 로그인합니다. ECR을 설정하는 방법은 제가 작성한 [문서](https://02ggang9.github.io/infra/DooreInfra8/)에서 확인하실 수 있습니다.
# 이 단계에서는 아래 "Build & Test" Step에 필요한 밑 작업입니다. 이유는 제가 작성한 [Docker-compose 작성](https://02ggang9.github.io/infra/DooreInfra4/#docker-compose-%EC%9E%91%EC%84%B1)확인하실 수 있습니다.
# db 컨테이너를 실행시켜야 하는데 이때 필요한 이미지가 ECR에 저장되어 있습니다.
# 이 또한 Github Marketplace에서 제공하는 라이브러리를 이용했습니다.
- name: Login to ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
# 아래에서 Gradle을 사용한 빌드와 테스트를 진행하는데 필요한 Java를 셋팅합니다. 자바 버전을 17로 설정한 이유는 [Doo-re-Discussion](https://github.com/BDD-CLUB/01-doo-re-back/discussions/3)에서 확인하실 수 있습니다.
# 이 또한 Github Marketplace에서 제공하는 라이브러리를 이용했습니다.
- name: Setup JDK
uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
# ECR에서 가져온 Docker Image를 저장하기 위한 Directory를 생성합니다.
- name: Create Cache Docker Image Directory
run: mkdir -p ~/db-docker-image
# Docker Images를 pull하고 로컬에 save하는 과정입니다.
# $은 "Login to ECR" 과정에서 가져온 registry의 경로입니다.
- name: Pull DB Image From ECR
env:
ECR_REGISTRY: $
run: |
docker pull $ECR_REGISTRY/doo-re-dev:$
docker save -o \
~/db-docker-image/doo-re-db.tar \
$ECR_REGISTRY/doo-re-dev:$
# 아래의 "Start Containers" Step에서 필요한 환경 파일을 .env 파일로 저장합니다. 이는 민감한 정보이므로 시크릿 처리 했습니다.
# 또, 아래의 Step에서 ECR_REGISTRY 값도 사용되기 때문에 .env 파일에 추가로 저장했습니다.
- name: Create Docker Env File
# working-directory: ./docker
run: |
echo '$' >> .env
echo "ECR_REGISTRY=$" >> .env
# develop 브랜치에 docker/docker-compose 파일 생성 후 삭제 예정
# Docker Container를 실행시키기 위해서 필요한 docker-compose.yml 파일을 가져옵니다. 이 또한 중요한 정보이기 때문에 시크릿 처리를 했습니다.
- name: Create Docker Compose File
run: |
echo '$' >> docker-compose.yml
# "Build & Test" Step에서 필요한 application.yml 파일을 덮어쓰고, CD에 필요한 application-deploy.yml 파일을 저장합니다.
# 이 곳에서 트러블이 발생했는데 자세한 내용은 옆의 [문서](https://02ggang9.github.io/trouble/DuplicateKeyException/)에서 확인하실 수 있습니다.
# 이 또한, 매우 중요한 정보이기 때문에 시크릿 처리를 했습니다.
- name: Create application.yml
working-directory: ./src/main/resources
env:
APPLICATION_YML: $
run: |
echo '$' > application.yml
echo '$' >> application-deploy.yml
# DB Container를 실행시키는 Step입니다.
- name: Start Containers
run: docker-compose -p doo-re up -d
# DB Container를 실행시키고 Gradle을 사용해 build 후 파일을 .jar로 압축하고 있습니다.
# 이에 관한 자세한 내용은 [Infra - Doo-re Infra(2) - Gradle과 JAR](https://02ggang9.github.io/infra/DooreInfra3/)에서 확인하실 수 있습니다.
- name: Build & Test
run: |
./gradlew build --daemon --build-cache --parallel
java -Djarmode=layertools -jar build/libs/doore-0.0.1-SNAPSHOT.jar extract
# 4개의 파일로 분리해 압축을 진행하고 있는데 이와 관련된 내용은 [Gradle, Layered Jar 그리고 Dockerbuild 최적화](https://velog.io/@ssol_916/Gradle-Layered-Jar-%EA%B7%B8%EB%A6%AC%EA%B3%A0-Dockerbuild-%EC%B5%9C%EC%A0%81%ED%99%94)에서 확인하실 수 있습니다.
- name: Compress
run: |
tar -zcf ${GITHUB_SHA::8}.tar.gz \
dependencies \
snapshot-dependencies \
spring-boot-loader \
application
# 위의 Step에서 압축한 파일을 S3에 저장하는 과정입니다. S3 설정과 저장할 파일 이름을 커밋이름의 8글자로 정한 이유는 아래의 문서에서 확인하실 수 있습니다.
# [Doo-re Infra(7) - S3 버킷 생성 방법과 Slack 연동 방법](https://02ggang9.github.io/infra/DooreInfra9/)
# [톰 선배님의 나의 첫 CICD 고도화 이야기](https://redundant4u.com/post/advanced_cicd)
- name: Upload to S3
run: |
aws s3 mv --region $ \
${GITHUB_SHA::8}.tar.gz \
$/${GITHUB_SHA::8}.tar.gz
# 이 Step은 위의 "Upload to S3" Step에서 저장한 파일을 EC2 인스턴스에 배포하기 위해 EC2 인스턴스에 저장된 자동 배포 스크립트를 실행하는 과정입니다.
# 자동 배포 스크립트 [Git Repo](https://github.com/02ggang9/01-doo-re-infrastructure/blob/main/doo-re/deploy/deploy_server.sh)에서 확인하실 수 있습니다.
# 아래의 시크릿 값은 자신의 EC2 인스턴스의 퍼블릭 IP와 이름, key 값과 포트 정보입니다.
- name: Deploy
uses: appleboy/ssh-action@master
with:
host: $
username: $
port: $
key: $
envs: GITHUB_SHA
script: |
cd ~/01-doo-re-infrastructure/doo-re/deploy
chmod +x ./deploy_server.sh
sudo ./deploy_server.sh ${GITHUB_SHA::8} dev
# CICD 과정이 실패했는지 성공했는지 알여주는 Step 입니다.
# Slack 환경 설정은 [Doo-re Infra(7) - S3 버킷 생성 방법과 Slack 연동 방법](https://02ggang9.github.io/infra/DooreInfra9/)에서 확인하실 수 있습니다.
- name: Notify Slack
if: always()
uses: 8398a7/action-slack@v3
env:
SLACK_WEBHOOK_URL: $
with:
status: $
author_name: DOO_RE Devlopment Backend CICD
fields: repo, commit, message, author, action, took
결론
자동 배포를 위한 CICD 코드에 대해서 알아봤습니다. CICD 코드 이해는 쉽지만 그 전에 선행되어야 하는 환경 설정이 정말 힘들다고 느꼈습니다. 주기적으로 블로그 글을 보면서 추가적인 설명이 필요하다고 생각이 들면 추가하도록 하겠습니다.