새로운 프로젝트를 슬슬 시작하는 과정에 있다. 편리함을 위해 이번 프로젝트에서는 CICD 도입을 맡게 되었다. 스프링 부트 기반의 프로젝트를 CICD 연결했던 과정을 기록해보겠다!
준비물
- 스프링부트 기반 프로젝트
- 깃허브 액션
- AWS Code Deploy
- AWS EC2
위 레포지토리를 CICD 연결했다!
CI (Continuous Integration)
지속적 통합은 새로운 코드의 변경 사항이 정기적으로 빌드 및 테스트 되어 한 레포지토리에서 통합되는 것을 의미한다. 협업을 진행할 때 코드 충돌을 방지할 수 있기 때문에 효율적으로 작업을 진행할 수 있도록 해준다.
CI는 깃허브 액션으로 빠르고 쉽게 세팅할 수 있다.
프로젝트의 루트에서 .github/workflows/deploy.yml 파일을 생성해준다.
name: deploy
on:
push:
branches: [ develop ]
pull_request:
branches: [ develop ]
jobs:
build:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: 17
distribution: 'temurin'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew
shell: bash
- name: Build with Gradle
run: ./gradlew build
shell: bash
develop 브랜치로 push 또는 pull_request 할 때 위 deploy.yml 파일이 실행된다. CI 단계에서는 java 세팅, 권한 부여, 빌드 과정이 이루어진다.
파일을 생성했으면 commit하고, develop 브랜치로 push 하거나 push한 다른 브랜치에서 develop 브랜치로 PR을 날리면 CI가 정상적으로 진행되는 지 확인할 수 있다.
위와 같은 화면이 보이면 아주 잘 되고 있는 것이다!
CD (Continuous Deployment)
지속적 배포는 새로운 코드의 변경 사항이 레포지토리를 넘어서 프로덕션 환경까지 릴리즈 되는 것을 의미한다. 특정 브랜치에 PR 또는 push 하기만 하면 자동으로 배포해주니, 수동으로 배포해야하는 상황과 비교해서 훨씬 편리함을 제공한다.
CD는 다음과 같은 과정이 필요하다.
1. CodeDeploy 생성
2. EC2 작업 (java 및 codedeploy-agent) 설치
3. 관련 코드 추가
CodeDeploy 생성
AWS에서 CodeDeploy를 생성해야 한다. 이는 AWS에서 제공하는 배포 서비스로, CodeDeploy를 통해서 EC2에 자동 배포해준다.
CodeDeploy IAM 역할 생성
먼저 CodeDeploy 접근 권한이 있는 역할이 필요하다. IAM > 역할 > 역할 만들기 로 들어가 역할을 생성해주자.
1단계 신뢰할 수 있는 엔티티 선택. AWS 서비스와 사용 사례에서 CodeDeploy를 선택하고 다음으로 넘어간다.
2단계는 권한 정책을 확인하고 별다른 행위 없이 바로 3단계로 넘어가면 된다.
3단계 이름 지정, 검토 및 생성. 역할 이름을 부여해주고 세부 사항을 검토한 후 역할 생성을 클릭해준다.
정상적으로 생성되었다면, IAM > 역할에서 방금 생성한 역할을 확인할 수 있다.
CodeDeploy 애플리케이션 생성
다음으로 애플리케이션을 생성해주어야 한다. CodeDeploy > 애플리케이션 > 애플리케이션 생성 으로 들어가자.
애플리케이션 이름과 컴퓨팅 플랫폼을 EC2/온프레미스로 지정해주고 애플리케이션을 생성한다.
마찬가지로 잘 생성되었으면 CodeDeploy > 애플리케이션에서 생성된 애플리케이션을 확인할 수 있다.
배포 그룹 생성
이어서 배포 그룹이 필요하다. 생성한 애플리케이션에 들어가서 배포 그룹 생성을 클릭해주자.
배포 그룹 이름을 지정해주고, 서비스 역할에는 위에서 생성한 IAM codedeploy 역할을 선택해준다.
단일 인스턴스에 배포한다는 가정 하에, Amazon EC2 인스턴스를 선택하고, 태그 그룹에서 키와 값을 선택해준다. (여기서 키 값은 배포할 EC2이다.)
나머지는 그래도 두고 배포 그룹을 생성해준다.
EC2 설정
이제 배포할 EC2에 권한을 부여하고, 접속하여 몇가지 설치를 진행해주어야 한다.
IAM 역할 생성
EC2에 부여할 역할을 생성하자.
다시 IAM > 역할 > 역할 만들기 로 들어가준다.
AWS 서비스와 EC2를 선택한다.
AWSCodeDeployFullAccess 와 AmazonS3FullAccess 권한을 선택한다.
역할 이름을 지정하고 역할을 생성해준다.
EC2 > 인스턴스로 들어가자.
EC2 역할 수정
EC2에게 권한을 부여해주어야 한다. 배포할 EC2를 선택하고, 작업 > 보안 > IAM 역할 수정을 클릭해주자.
IAM 역할 수정에서 위에서 생성한 역할을 선택해준다. 선택 후, IAM 역할 업데이트 해준다.
이제 EC2로 접속하자. 우분투 22.04 기준이다.
Java 설치
sudo apt install openjdk-17-jdk
위 코드로 자바를 설치하자. JDK 17이 필요해서 17 버전으로 설치했다. 이미 설치되어 있어서 위 이미지처럼 나오지만, 대충 됐다는 로그가 뜨면 성공이다.
java --version
코드로 자바 버전을 확인해서, 버전이 출력되면 잘 설치된 것이다!
Codedeploy-agent 설치
$ sudo apt update
$ sudo apt install ruby-full
$ sudo apt install wget
$ cd /home/ubuntu
$ wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
$ chmod +x ./install
$ sudo ./install auto > /tmp/logfile
위 명령어를 입력하여 codedeploy-agent를 설치해준다.
$ sudo service codedeploy-agent status
$ sudo service codedeploy-agent restart
위 명령어로 codedeploy-agent가 제대로 설치되었는 지 확인한다. status로 상태를 확인하고, 실행 중이지 않으면 restart 명령어를 입력해주면 된다.
* 위 과정을 실패한다면 *
$ wget https://aws-codedeploy-ap-northeast-2.s3.amazonaws.com/latest/install
먼저 위 명령어에서 wget 명렁어를 다음과 같이 입력하고, 아래 과정을 그대로 다시 진행한다.
그래도 안돼면
일단 당시 배포 과정에서는 위 codedeploy-agent가 제대로 설치되지 않았었다. 그래서 구글링 끝에 한 포스팅을 따라 보고 입력했는데, codedeploy-agent를 성공적으로 설치할 수 있었다. 해당 글을 밑에서 공유하도록 하겠다.
https://stackoverflow.com/questions/73301858/aws-codedeploy-agent-not-installing-on-ubuntu-22-04
여기까지 왔으면 CodeDeploy 및 EC2 설정은 끝났다!!
CD 설정
이제 진짜진짜 CD 과정을 세팅해보도록 하자.
사용자 추가
배포 자동화를 위해서 S3부터 CodeDeploy 까지 접근 가능한 사용자가 필요하자. IAM > 사용자 > 사용자 추가로 들어가자. (이미 접근 가능한 사용자가 있으면 생략해도 좋다)
사용자 이름을 지정한다.
다음으로 넘어가 직접 정책 연결을 선택하고, AWSCodeDeployFullAccess와 AmazonS3FullAccess 권한을 추가해준다.
이후로는 정책 검토 후 계속 넘어가서 사용자 추가를 클릭해주면 된다. 사용자를 추가하면 최초로 Access Key Id와 Secret Access Key를 받을 수 있다. 해당 페이지를 넘어가면 다시는 재발급 받을 수 없으니 복붙 해놓거나 CSV를 저장해두자. 꼭!!
정상적으로 추가된 것은 사용자 리스트에서 확인할 수 있다.
발급 받은 Access Key를 깃허브 시크릿 키에 등록시킨다.
Settings > Security > Secrets and variables > Actions 탭으로 접속하면 된다. New repository secret 버튼을 클릭하여 2개의 access key를 등록해주면 된다.
S3 생성
CodeDeploy에서 배포하기 위해서는 빌드한 압축파일을 S3에 업로드 후 배포할 수 있다. 때문에 S3가 필요하다.
S3 > 버킷 > 버킷 만들기로 접속하자.
버킷 이름을 지정하고 리전만 확인하고 바로 버킷을 생성해주자.
코드 추가
마지막 단계이다. 이제 배포를 실행할 명령어가 담긴 파일을 생성해준다.
.github/workflows/deploy.yml
name: deploy
on:
push:
branches: [ develop ]
pull_request:
branches: [ develop ]
jobs:
build:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: 17
distribution: 'temurin'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew
shell: bash
- name: Build with Gradle
run: ./gradlew build
shell: bash
## 추가 ##
- name: Make zip file
run: zip -qq -r ./$GITHUB_SHA.zip .
shell: bash
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1-node16
with:
aws-access-key-id: ${{ secrets.ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.ACCESS_KEY_SECRET }}
aws-region: ap-northeast-2
- name: Upload to AWS S3
run: |
aws deploy push \
--application-name {애플리케이션_이름} \
--ignore-hidden-files \
--s3-location s3://{버킷_이름}/$GITHUB_SHA.zip \
--source .
- name: Code Deploy
run: aws deploy create-deployment --application-name {애플리케이션_이름}
--deployment-config-name CodeDeployDefault.AllAtOnce
--deployment-group-name {배포그룹_이름}
--s3-location bucket={버킷_이름},bundleType=zip,key=$GITHUB_SHA.zip
앞서 생성한 deploy.yml 파일에 deploy 관련 코드를 추가해준다.
Make zip file: 빌드한 파일을 압축한다. $GITHUB_SHA로 랜덤한 이름을 생성한다.
Configure AWS credentials: AWS에 인증하는 과정이다. 깃허브 시크릿 키에 등록한 값인 access key 정보 값을 들고온다.
Upload to AWS S3: 압축한 빌드 파일을 S3 버킷에 업로드 한다.
Code Deploy: CodeDeploy를 실행한다.
appspec.yml
version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/build
overwrite: yes
permissions:
- object: /home/ubuntu
pattern: '**'
owner: ubuntu
group: ubuntu
hooks:
AfterInstall:
- location: scripts/deploy.sh
timeout: 1000
runas: ubuntu
배포 후 배포 과정 명령어가 포함된 파일을 실행하도록 하는 파일이다.
/hom/ubuntu/build 위치에 파일 생성, 권한 부여, 배포 파일 실행 과정이 포함되어 있다.
scripts/deploy.sh
REPOSITORY=/home/ubuntu/build
cd $REPOSITORY
APP_NAME=pearls
JAR_NAME=$(ls $REPOSITORY/build/libs/ | grep '.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 -15 $CURRENT_PID"
sudo kill -15 $CURRENT_PID
sleep 5
fi
echo "> $JAR_PATH 배포"
nohup java -jar /home/ubuntu/build/build/libs/pearls-1.0.jar > /dev/null 2> /dev/null < /dev/null &
배포 명령어 파일을 생성해준다. pearls-1.0.jar 파일로 빌드되기 때문에, 앱 이름과 jar 이름은 위와 같이 지정해주었다.
이제 develop으로 push 하거나 pull_request를 날려보자!!
위에서 CI 과정을 확인한 방식과 같은 방식으로 확인하면 된다. 정상적으로 실행되었으면 초록색 체크가 이쁘게 보일 것이다 :D
다음으로 AWS의 CodeDeploy > 배포에 들어가면 배포 내역을 확인할 수 있다. 최상단에 배포 내역이 성공 상태이면 잘 배포된 것이다.
혹시 배포까지 완료됐는데 EC2 IP 접속이 안된다면?
EC2의 보안 그룹에서 인바인드 규칙에서 접근하려는 포트 번호와 ip주소가 허용되어있는지 확인하해보자. 아마 접속이 안돼면 이 경우일 확률이 매우 높다. 허용되어 있지 않다면 인바인드 규칙 편집으로 들어가서 접속 허용하려는 ip 주소를 추가해주자.
처음 설정은 어렵게 느껴지고 변수도 많은 CICD 설정 과정이지만,, 설정해두고 개발을 시작하면 삶의 질이 매우 올라가는 것을 느낄 수 있고, 설정 과정에서 인프라도 경험해볼 수 있으므로 꼭 추천한다!
References
https://shinsunyoung.tistory.com/120
https://stackoverflow.com/questions/73301858/aws-codedeploy-agent-not-installing-on-ubuntu-22-04