자 CI/CD를 한번 구현해 보자. 이거에 대한 트러블 슈팅도 엄청 많다. 물론 내가 처음 해봐서 무지성으로 한 것도 있지만
이 트러블 슈팅과 이 과정을 통해 다음번에 CI/CD를 구현할 때는, 깃허브 액션에서만큼은 조금 더 헤매지 않고 보다 더 빠른 시간 안에 구현할 수 있지 않을까 생각해 본다.
[Setup] GitHub Actions 기반 CI/CD 파이프라인 구성
GitHub Actions를 통해 CI/CD 파이프라인을 구성하여 애플리케이션을 자동으로 빌드, 테스트, 배포
보안을 위해 AWS Certificate Manager로 SSL 인증서를 관리하고, 컨테이너화된 애플리케이션은 ECS를 통해 배포하며, Docker 이미지는 ECR에 저장
GitHub Actions 워크플로우 파일 작성
Docker 이미지 빌드 및 ECR 푸시 단계 구현
ECS 서비스로 자동 배포 단계 구현
GitHub Secrets에 AWS 인증 정보 설정
CI/CD 파이프라인 테스트 및 디버깅
성공적인 배포 후 모니터링 및 알림 설정
-----이렇게 이슈를 작성해 봤다.
GitHub Actions 워크플로우 파일 작성을 해야 한다.
자기 프로젝트 안에. github > workflows > @@.yml 이렇게 작성을 해야 한다.
나는 처음에는 ci와 cd를 나눠서 작성했다. 다른 사람 프로젝트와 블로그들을 참고하니 이렇게 해서 그렇다.
name: Java CI with Gradle
on:
push:
branches: [ "dev" ]
pull_request:
branches: [ "dev" ]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read # 리포지토리의 콘텐츠에 대한 읽기 권한
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4 # JDK 21
with:
java-version: '21'
distribution: 'temurin'
- name: Grant execute permission for gradlew
run: chmod +x gradlew # gradlew에 실행 권한을 부여
# Gradle 빌드 및 테스트 실행
- name: Build and Test with Gradle
run: ./gradlew clean build test # 빌드와 테스트를 한 번에 실행
일단 처음에는 이렇게 CI를 작성했다.
dev에 push와 pr 했을 때 돌아가게 하고, ubuntu 환경에서 작업을 실행하고, 레포지토리의 내용을 읽기 권한을 주고,
체크아웃 후, 가져오고 우리 프로젝트는 JDK 21이니깐 21로 설정하고, gradle 이용해서 clean build test까지 했다.
이렇게 하면 dev 브랜치에 push or pr을 했을 때 자동으로 빌드와 테스트가 수행해야 한다.
과연 한 번에 됐을까? 그랬으면 좋았겠지만 그렇지 않았다. 바로 아래와 같이 오류가 떴다.
이 오류를 알기까지 많은 시행착오가 있었다. 사실, 로그를 잘 확인했어야 했는데, 그걸 놓쳐서 어려움을 겪었다. 마치 "낫 놓고 기역 자도 모른다"는 느낌이었다. 이번 경험을 통해 앞으로는 오류 로그를 꼼꼼히 살펴보는 습관을 들여야겠다고 다짐했다. 로그는 문제 해결의 첫걸음이니까, 이를 잘 활용해야겠다.
그런데, 이 문제를 어떻게 해결했느냐고 묻는다면, 사실 해결했다기보다는 회피했다는 표현이 더 적절할 것 같다.
이 오류는 Gradle 테스트 실패로 인해 빌드가 중단된 것이었기 때문이다.
./gradlew clean build test 명령어를 실행했을 때, 여러 개의 테스트가 실패하면서 빌드가 실패하는 문제가 발생했다.
그래서 일단 테스트를 생략하고 빌드를 진행하기로 했다. 그래서 명령어를 ./gradlew clean build -x test로 변경했다.
물론, 이 방법은 테스트 오류를 근본적으로 해결한 것은 아니다. 문제를 잠시 피할 수는 있지만, 장기적으로는 테스트 실패 원인을 분석하고 수정하는 것이 필요하다. 이 점을 꼭 기억해야겠다.
그다음 CD도 작성해놨다.
# CD: Docker 이미지를 빌드하고 AWS ECR에 푸시 및 ECS에 배포
name: Java CD with Docker and ECS
on:
push:
branches: [ "dev" ] # dev 브랜치에 푸시될 때마다 트리거
env:
ECR_REPOSITORY_NAME: my-java-app-repo # ECR에 저장될 Docker 이미지의 이름
ECS_CLUSTER_NAME: MyEchoCluster # AWS ECS 클러스터 이름
ECS_SERVICE_NAME: EchoBackService # AWS ECS 서비스 이름
AWS_REGION: ap-northeast-2 # AWS 리전 설정
jobs:
build-and-push:
name: Build and Push Docker Image to ECR
runs-on: ubuntu-latest # 최신 Ubuntu 가상 머신에서 실행
steps:
- name: Checkout code
uses: actions/checkout@v4 # GitHub 리포지토리에서 코드를 체크아웃
- name: Set up JDK 21
uses: actions/setup-java@v4 # JDK 21
with:
java-version: '21'
distribution: 'temurin' # Temurin JDK 배포판을 사용
# 1. Amazon ECR에 로그인
- name: Log in to Amazon ECR
run: aws ecr get-login-password --region ${{ env.AWS_REGION }} | docker login --username AWS --password-stdin ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com
# 2. Docker 이미지를 빌드
- name: Build Docker image
run: docker build -t ${{ env.ECR_REPOSITORY_NAME }}:latest .
# 3. 빌드된 Docker 이미지를 태그
- name: Tag Docker image
run: docker tag ${{ env.ECR_REPOSITORY_NAME }}:latest ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/${{ env.ECR_REPOSITORY_NAME }}:latest
# 4. Docker 이미지를 ECR에 푸시
- name: Push Docker image to ECR
run: docker push ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/${{ env.ECR_REPOSITORY_NAME }}:latest
deploy:
name: Deploy to ECS
runs-on: ubuntu-latest # 최신 Ubuntu 가상 머신에서 실행
needs: build-and-push # Docker 이미지를 ECR에 푸시한 후에 실행
steps:
# 1. ECS 서비스 업데이트: 새로운 Docker 이미지를 사용하도록 ECS 서비스를 업데이트
- name: Deploy Service to ECS
run: |
aws ecs update-service --cluster ${{ env.ECS_CLUSTER_NAME }} --service ${{ env.ECS_SERVICE_NAME }} --force-new-deployment
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_KEY }}
dev 브랜치에 코드가 푸시 될 때마다 이 워크플로우가 실행된다. 먼저 환경 변수들을 설정해 주었는데, 여기에는 ECR 레포지토리 이름, ECS 클러스터 및 서비스 이름, AWS 리전 등이 포함된다.
이후 ECR에 Docker 이미지를 푸시 하기 위한 작업을 작성했다. Ubuntu 환경에서 실행되며, 코드 체크아웃 후 JDK 21을 설정한다. 그리고 ECR에 로그인하여 Docker를 통해 이미지를 푸시 할 수 있도록 설정하고, 이미지를 빌드 한 다음, ECR에 푸시 할 수 있도록 이미지를 태그 한다. 그 후 태그 된 Docker 이미지를 ECR에 푸시 한다.
마지막으로, Deploy to ECS 작업을 수행한다. 새로운 Docker 이미지가 자동으로 생성되면, 그 이미지를 사용하도록 강제 배포 트리거를 통해 ECS 서비스를 업데이트해 준다.
CD는 과연 바로 됐을까? 그렇지 않았다. 처음에는 자격 증명 오류부터 시작해서, 도커 이미지를 찾을 수 없다는 오류까지 정말 많은 오류가 발생했고, 그로 인해 머리가 아플 정도로 복잡했다.
이 오류들이 발생했을 때 바로바로 트러블슈팅 기록을 작성해두었어야 했는데, 그걸 놓쳐서 아쉽다. 하지만, 만약 모든 것이 한 번에 잘 됐다면, 그 또한 의심스러웠을 것이다. 오류가 발생하는 건 당연한 일이었다. 처음 시도하는 것이었으니, 앞으로 나아가면서 지금 겪은 오류들을 반복하지 않도록 하고, 새로운 오류들을 마주칠 때마다 이를 해결하다 보면, 나의 실력도 점차 성장할 것이라고 믿는다.
다음TIL로!
'TIL' 카테고리의 다른 글
TIL - 2024/08/19 (0) | 2024.08.19 |
---|---|
TIL - 2024/08/15 (0) | 2024.08.16 |
TIL - 2024/08/13 (0) | 2024.08.16 |
TIL - 2024/08/12 (0) | 2024.08.16 |
TIL - 2024/08/09 (0) | 2024.08.16 |