1. Github Action을 통한 배포 자동화 Flow를 설명할 수 있다.
2. 자동화를 진행하는 파일들의 단계별 진행 내용을 이해할 수 있다.
- Github Actions를 통한 배포 Flow
✔︎ Github가 공식적으로 제공하는 빌드, 테스트 및 배포 파이프라인을 자동화할 수 있는 CI / CD 플랫폼
✔︎ Pull Request
, push
같은 이벤트를 트리거로 GitHub 작업 워크플로(Workflow) 구성 가능
✔︎ 워크플로
.yml
(또는 .yaml
) 파일에 의해 구성.github/workflows
디렉토리에 위치
✔︎ Github Actions
.yml
)에 따라 Github Repository에 특정 변동사항을 트리거로 작동✔︎ S3
✔︎ Code Deploy
appspec.yml
설정 파일에 의해 쉘 스크립트 등 단계에 따라 특정 동작 수행✔︎ EC2
.yml
(설정 파일)과 .sh
(쉘 스크립트)에 의해 각 배포 결과를 로그로 저장하여 빌드 파일 (.jar
) 실행
- 리소스 설정
✔︎ Public Repository 생성 및 프로젝트 업로드
✔︎ Git Actions 생성
Actions
탭 클릭Java with Gradle
⇒ Configure
Start commit
⇒ Commit new file
클릭< gradle.yml 파일 내용 >
name: Java CI with Gradle
on:
push:
branches: [ "main" ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Build with Gradle
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
with:
arguments: build
✔︎ Github Secret 등록
Settings
클릭Secrets
⇒ Actions
⇒ New repository secret
클릭✔︎ Github Action 설정파일 수정
...
permissions:
contents: read
# 해당 부분 추가 (1)
env:
S3_BUCKET_NAME: be-0-name # 해당되는 버킷 이름 입력
...
# 해당 부분 추가 (2)
# build한 후 프로젝트를 압축합니다.
- name: Make zip file
run: zip -r ./practice-deploy.zip .
shell: bash
# Access Key와 Secret Access Key를 통해 권한을 확인합니다.
# 아래 코드에 Access Key와 Secret Key를 직접 작성하지 않습니다.
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }} # 등록한 Github Secret이 자동으로 불려옵니다.
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # 등록한 Github Secret이 자동으로 불려옵니다.
aws-region: ap-northeast-2
# 압축한 프로젝트를 S3로 전송합니다.
- name: Upload to S3
run: aws s3 cp --region ap-northeast-2 ./practice-deploy.zip s3://$S3_BUCKET_NAME/practice-deploy.zip
🌟 pull
진행하여 레포지토리와 로컬 파일을 동일하게 만들어줘야 함 ‼️
🚨 주의❗️
'~/gradlew' is not executable.
에러 발생 가능Build with Gradle
이전 ./gradlew
에 권한 부여하는 단계 추가- name: Add permission
run: chomod +x ./gradlew
- 빌드파일 배포 및 실행
✔︎ CodeDeploy 애플리케이션 생성
CodeDeploy
로 이동 ⇒ 배포
⇒ 애플리케이션
⇒ 애플리케이션 생성
클릭애플리케이션 이름
작성 (ex. be-00-name) ⇒ 컴퓨팅 플랫폼
선택 (ex.EC2/온프레미스)✔︎ 배포 그룹 생성
배포 그룹 생성
클릭배포 그룹 이름
입력 (ex. be-00-name-group)서비스 역할
: CodeDeploy IAM 역할 연결 (ex. githubAction-CodeDeploy-Role
)Amazon EC2 인스턴스
⇒ 키 : Name
, 값 : be-00-name
)배포 그룹 생성
✔︎ 최상위 디렉토리 구조에 appspec.yml 파일 생성
< appspec.yml 파일 내용 >
version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/action # 왼쪽 디렉토리 내 배포 진행
overwrite: yes
permissions:
- object: /
pattern: "**"
owner: ubuntu
group: ubuntu
hooks:
ApplicationStart:
- location: scripts/deploy.sh # 최상위 디렉토리에 scripts 내 쉘 스크립트 실행
timeout: 60
runas: ubuntu
✔︎ shell script 생성
#!/bin/bash
# 빌드 파일의 이름이 콘텐츠와 다르다면 다음 줄의 .jar 파일 이름을 수정하시기 바랍니다.
BUILD_JAR=$(ls /home/ubuntu/action/build/libs/practice-githubAction-deploy-0.0.1-SNAPSHOT.jar)
JAR_NAME=$(basename $BUILD_JAR)
echo "> 현재 시간: $(date)" >> /home/ubuntu/action/deploy.log
echo "> build 파일명: $JAR_NAME" >> /home/ubuntu/action/deploy.log
echo "> build 파일 복사" >> /home/ubuntu/action/deploy.log
DEPLOY_PATH=/home/ubuntu/action/
cp $BUILD_JAR $DEPLOY_PATH
echo "> 현재 실행중인 애플리케이션 pid 확인" >> /home/ubuntu/action/deploy.log
CURRENT_PID=$(pgrep -f $JAR_NAME)
if [ -z $CURRENT_PID ]
then
echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다." >> /home/ubuntu/action/deploy.log
else
echo "> kill -9 $CURRENT_PID" >> /home/ubuntu/action/deploy.log
sudo kill -9 $CURRENT_PID
sleep 5
fi
DEPLOY_JAR=$DEPLOY_PATH$JAR_NAME
echo "> DEPLOY_JAR 배포" >> /home/ubuntu/action/deploy.log
sudo nohup java -jar $DEPLOY_JAR >> /home/ubuntu/deploy.log 2>/home/ubuntu/action/deploy_err.log &
- EC2 배포 진행 상황별 로그를 기록하고 새로 배포된 빌드 파일 실행
✔︎ CodeDeploy 연결
< gradle.yml 파일 내용>
...
# CodeDeploy에게 배포 명령을 내립니다.
- name: Code Deploy
run: >
aws deploy create-deployment --application-name be-0-name
--deployment-config-name CodeDeployDefault.AllAtOnce
--deployment-group-name be-0-name-group
--s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=practice-deploy.zip
push
하여 Github Actions 실행
- 배포 결과 및 로그 확인
✔︎ 배포 결과 확인
✔︎ EC2 인스턴스에서 배포 로그 확인
✔︎ EC2 인스턴스에서 배포 로그 확인
cat
명령어로 로그 확인 가능✔︎ 파일 수정 후 배포 자동화 테스트
push
진행✔︎ 이전 실습 내용이 보여지는 경우
✔︎ EC2 인스턴스에 빌드 결과물이 없는 경우
✔︎ EC2 인스턴스에 빌드 결과물이 있는 경우
☞ 어제 AWS Pipeline 배포 자동화 실습에 이어 오늘은 Github Actions를 이용한 배포 자동화를 실습해봤다.
수월히 진행되어 예상된 시간보다 훨씬 빨리 마무리할 것으로 보였으나...
오늘도 역시 맘대로 안된다!!!
✅ 첫 번째 에러 핸들링
배포 결과 및 로그는 확인되는데 git 레포지토리와 로컬 파일의 불일치가 발생하여 pull
과 push
명령어가 먹통이 되어버렸다... git push origin +main
명령어를 통해 강제로 입력하다보니 레포지토리의 gradle.yml파일이 날라간다...
내가 actions를 생성하면서 만들어진 gradle.yml 파일을 까먹고 로컬에 pull
하지 않은 채, 로컬 프로젝트 내용을 바꿔서 강제 push
해버리는 바람에 뒤엉켜버린 것이다 🥲
교육 와아아아안~전 초창기 때 git을 학습하면서 충돌 상황이 발생했던 것이 떠올라 다시 해당 내용을 훑어보며 되돌릴려고 노력했다.
7일차 학습내용 참고
직접 소스 코드도 되돌리고 수정해봤지만 이미 강제 푸쉬를 해버리는 바람에 가버린 것 같다...
결국 다시 처음부터 작성 ^^❗️❗️❗️
✅ 두 번째 에러 핸들링
다시 작성하고 github action 생성 후 만들어진 gradle.yml 파일을 로컬에 pull 해주는 것도 잊지 않았다!!
마지막까지 이상없이 작성하였는데... EC2 주소에 접속이 되지 않는다 😂
EC2 인스턴스에 연결하여 알아보니 빌드는 됐는데, 자동으로 실행이 안됐다...
java -jar build/libs/ ~ .jar
명령어를 통해 수동으로 실행해보니 잘된다 🤔
그러나 우리의 목적은 배포 자동화이기에 이것 저것 뒤적뒤적 만져보며 무엇이 문제인지 고민했다.
AWS의 Code Deploy에 배포 그룹에 들어가보니 상태가 실패... install 과정에서 실패가 발생했단다 🥲
github 상에 빌드는 잘됐고, 수동으로 실행은 잘됐는데 왜 배포에서 오류가 나지 고민을 엄청 많이 했다.
배포 내역의 실패된 배포 ID를 들어가 오류 내용을 확인해보았다.
배포에 실패한 개별 인스턴스가 너무 많거나 배포에 사용할 수 있는 정상 인스턴스가 너무 적거나 배포 그룹의 일부 인스턴스에 문제가 발생하여 전체 배포가 실패했습니다.
... 무슨 말?!!!
느낌 상으로는 인스턴스가 많이 생성된 문제 같아 이전 실습 내용때문인가 해서 EC2 인스턴스의 프로세스 상황을 다시 확인하니 이상이 없다 😕 그렇다면 아마 내가 pull push 문제로 새로 만들기 전 처음 생성한 action과 겹치는 문제라고 얼추 생각이 들었다.
AWS 배포 내역에 실패된 배포 ID 안의 내용들을 좀 더 살펴보았다.
하단에 배포 생명 주기 이벤트라는 곳에 실패된 이벤트가 있길래 거기에 View Event라는 것을 눌러보았다.
추가적인 에러 메세지를 확인할 수 있었다.
이미 존재한단다.
그리고 친절히 경로까지 알려줬다.
이걸 보고 느낌이 딱! 와서 다시 EC2 인스턴스에 연결하여 /home/ubuntu의 action 디렉토리를 죽였다.
sudo rm -rf action
죽이고 다시 action을 동작시켜 실행하니 잘 동작됐다!!! 나도 모르게 실제 환호가 나왔다 😊😊
에러는 해결할 때마다 언제나 늘 짜릿 ⚡️ :D
・ Proxy Server
・ 수평 확장
・ 웹 서버
・ VPC