원래 어제는 CI만 하려고 했는데 생각보다 간단해서 CD까지 했다.
mysql, redis 연결까지 확인 완료 ! 일단은 Continuous Delivery까지만 끝냈다. (다음 글은 무중단 배포라는 뜻)
github action으로 배포, 리소스 사용량은?
우선 지난 게시글에서 살펴봤던 리소스 사용량부터 알아보자
github action없이 배포했을 때는 cpu를 13% 사용했었는데, 4-5%만 사용하였다.
역시나, 의존성 다운로드 과정을 하나도 거치지 않으니 네트워크 패킷 입력 개수도 눈에 띄게 줄었다.
직접 배포했을 땐 66480이었는데..
배포 시 입력량이 너무 적길래 좀 더 앞의 시간대도 살펴봤다.
앞서 살펴봤던 지표는 이미 이미지를 다운로드 한 시점일거란 생각에서 찾아봤는데,
2시 25분 도커이미지 다운로드 - 네트워크 패킷 입력 19757 / CPU 4.5% 역시나 크게 줄어든 모습이다.
github actions를 이용한 배포는 cpu사용량과 네트워크 부하를 크게 줄일 수 있는 효율적인 방법이라는 것을 깨달았다.
특히나 의존성 다운로드 과정이 생략되면서 네트워크 입력량이 거의 없다는 게 핵심적인 장점이다.
만약 jenkins를 사용했더라면 인스턴스 내부에서 리소스를 사용해야 하므로, 리소스를 아낄 수 없었을 것이다!
프로젝트에 적용된 CI/CD 배포 구조
dev용과 release용을 따로 만들었다.
dev에서는 gradlew 기반 ci만 수행하며, 테스트를 수행하지 않도록 했다. 딱 컴파일 에러만 잡아내는 용도로 구성했다.
release에서는 테스트를 수행한다. release브랜치에 풀리퀘스트를 올리면 deploy과정이 진행되도록 만들었고, 테스트도 수행하도록 했다.
release의 ci는 도커 허브로 이미지를 올리는 과정이고,
cd시에 인스턴스 내부에서 도커 허브에서 해당 이미지를 다운받아 컨테이너에서 실행한다.
ci-dev.yml
- name: Git Checkout
uses: actions/checkout@v4
- name: Setup JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
checkout actions: 코드를 가져온다.
setup-java: 필요한 자바 버전을 다운받는다. temurin이 안정적이라 사용했다
- name: Cache Gradle Packages
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
gradle-${{ runner.os }}-
gradle-
그래들 빌드 과정을 캐시해놓는 코드다. 의존성 관련을 캐싱해서 빌드 속도를 빠르게 할 수 있다.
key에서 runner.os쪽은 사실 모두 linux ubuntu에서 실행되기 때문에 의미없어보이지만, 뭐 혹시나 ci를 다른 os에서 할 수도 있으니..
restore-keys를 사용해 완전히 동일한 키가 없더라도 비슷한 키를 찾도록 설정했다
- name: Chmod gradlew
run: sudo chmod +x ./gradlew
- name: Build with Gradle (Check Build-Logs)
run: ./gradlew build --parallel --daemon --max-workers=2 -x test --info | tee build-log.txt
- name: Upload Build Logs
uses: actions/upload-artifact@v4
with:
name: gradle-logs
path: build-log.txt
gradlew 권한을 풀어주고 빌드를 실행한다.
-x test: 테스트는 실행하지 않는다
--parallel: 멀티스레드 빌드를 활성화하여 빌드 속도를 향상시킨다. --max-workers=2로 스레드는 두개를 사용하게 했다
--daemon: gradle 데몬을 활성화해 실행 속도를 최적화한다
--info, tee build-log.txt: 상세한 빌드 로그를 콘솔 출력하며 파일로 저장한다
upload-artiface actions: artifacts에 로그를 저장한다
- name: PR Quality Gate
if: failure()
run: |
echo "❌ Build failed. Check the logs in GitHub Actions." > build-failure.log
cat build-log.txt >> build-failure.log
exit 1
- name: Upload Failure Logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: build-failure-logs
path: build-failure.log
빌드 실패 시 머지를 차단하고, 실패 로그를 남긴다.
ci-cd-release.yml
checkout과 setup java actions로 코드를 가져오고 자바를 설치하는 과정은 동일하다.
- name: Create .env file
run: echo "$ENV_FILE" > .env
env:
ENV_FILE: ${{ secrets.ENV_FILE }}
.env파일을 생성한다. github secret에 올려두면 env파일을 레포지토리에 올리지 않고도 쉽게 생성할 수 있다.
이후 빌드를 gradle ci과정과 동일하게 진행하고
- name: Log in to Docker Hub
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
- name: Build Docker Image
run: |
docker build -t ${{ secrets.DOCKER_USERNAME }}/cheer-ha:latest .
- name: Push Docker Image to Docker Hub
run: |
docker push ${{ secrets.DOCKER_USERNAME }}/cheer-ha:latest
도커 허브에 로그인하고 -> 도커 이미지를 생성하고 -> 도커 허브에 이미지를 푸시한다.
이러면 ec2 내부 인스턴스에서 도커 허브에 로그인하여 해당 이미지를 다운받아 사용할 수 있는 구조다.
- name: Log in to Docker Hub
run: echo "${{ secrets.DOCKER_PASSWORD }}" | sudo docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
- name: Deploy using SSH
uses: appleboy/ssh-action@v0.1.6
with:
host: ${{ secrets.HOST_IP_ADDRESS }}
username: ubuntu
key: ${{ secrets.SSH_SECRET_KEY }}
script: |
mkdir -p ~/cheer-ha
echo "${{ secrets.ENV_FILE }}" > ~/cheer-ha/.env
sudo docker-compose -f ~/cheer-ha/docker-compose-release.yml down
sudo docker pull ${{ secrets.DOCKER_USERNAME }}/cheer-ha:latest
sudo docker-compose -f ~/cheer-ha/docker-compose-release.yml up -d
ec2 인스턴스 내부에서 수행할 코드다. 도커 관련 권한설정을 하지않아 sudo로 설정해야 했다.
도커를 실행할 때 필요한 도커컴포즈를 어디서 보낼지 고민이 좀 됐는데 그냥 ec2 내부에서 수정이 필요할 때 마다 vim으로 고쳐쓰기로 했다.
해당 사진은 git clone을 통해 compose파일만 따로 빼온 후인데, cat을 해봐도 내용물이 없길래 그냥 vi명령어로 로컬 코드를 복붙해서 사용했다
오히려 cd과정중에 불필요한 리소스(깃 클론 네트워크 리소스)를 줄일 수 있어서 좋은 방법이라고 생각한다.
이제 무중단 배포 가보자
'팀 프로젝트 > 최종 프로젝트' 카테고리의 다른 글
배포(3) 무중단 배포: 롤링 vs 블루-그린(https 배포완료) (0) | 2025.02.16 |
---|---|
배포(1) CI/CD와 github action 알아보기 (0) | 2025.02.15 |
트러블슈팅- 삭제된 RefreshToken 조회 시 500에러 (0) | 2025.02.15 |