일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 객체지향설계
- 멀티모듈
- STL
- aws
- DP
- DIP
- SW마에스트로
- google calendar api
- 탄력적 ip
- 정렬
- BFS
- 서버타임존설정
- multi module
- 그리디
- 에러로깅
- 완전탐색
- EC2
- 구현
- 서버
- 개방주소법
- ZonedDateTime
- 비즈니스요구사항
- localdatetime
- 해시충돌
- OCP
- DFS
- C++
- 자료구조
- hashcollision
- web
- Today
- Total
레츠고✨
자동 배포 CI CD 파이프라인 구축기 : AWS S3 + Code deploy 본문
배경
GitHub Actions로만 구축한 CI/CD
기존에 우리 프로젝트에서는 GitHub actions 로만 CI/CD 구축해서 따로 AWS를 연결하지 않았었다.
기존 CI/CD 파이프라인은 아래와 같았다.
deploy.yml
name: Spring CI CD
on:
push:
branches: ["main"]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# jdk 17 설치
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
# gradle 실행 권한 부여
- name: Grant execute permission for gradlew
run: chmod +x gradlew
# gradle 빌드
- name: Build with Gradle
uses: gradle/gradle-build-action@v2.6.0
with:
arguments: build
# artifact 업로드
- name: Upload build artifact
uses: actions/upload-artifact@v2
with:
name: build-artifact # Artifact 이름 지정
path: build/libs/app-0.0.1-SNAPSHOT.jar # 폴더 지정
deploy:
needs: build
runs-on: ubuntu-latest
steps:
# artifact 다운로드
- name: Download build artifact
uses: actions/download-artifact@v2
with:
name: build-artifact
path: build/libs/
# LIGHTSAIL 배포
- name: Deploy to LIGHTSAIL
run: |
echo "${{ secrets.LIGHTSAIL_SSH_KEY }}" > private_key.pem
chmod 600 private_key.pem
scp -i private_key.pem -o StrictHostKeyChecking=no build/libs/app-0.0.1-SNAPSHOT.jar ${{ secrets.LIGHTSAIL_USERNAME }}@${{ secrets.LIGHTSAIL_HOST }}:/home/${{ secrets.LIGHTSAIL_USERNAME }}/app-0.0.1-SNAPSHOT.jar
ssh -i private_key.pem -o StrictHostKeyChecking=no ${{ secrets.LIGHTSAIL_USERNAME }}@${{ secrets.LIGHTSAIL_HOST }} "pgrep java | xargs kill -9; nohup java -jar /home/${{ secrets.LIGHTSAIL_USERNAME }}/app-0.0.1-SNAPSHOT.jar > app.log 2>&1 &"
rm -f private_key.pem
위 deploy.yml 파일의 내용을 간단히 설명하면 아래와 같다.
빌드
- GitHub actions에서 가상환경 구축
- open jdk 설치
- 소스 코드 build
- GitHub actions artifact에 업로드
배포
- GitHub actions artifact에서 다운로드
- 빌드 파일 배포
이 상태로 자동배포가 잘 되었기 때문에 아무 문제없이 사용하고 있었는데...
어느 순간 배포가 안 되기 시작했다. 에러 메세지를 보니
Error: Create Artifact Container falied: Artifact storage quota has been hit. Unable to upload any new artifacts
알아보니 GitHub actions에서 제공해주는 artifact 용량이 정해져 있었고, 그걸 전부 사용해서 더 이상 artifact를 생성할 수 없다는 것이었다.
1달에 artifact 용량이 1GB도 안되는데 한번 빌드파일 배포할 때마다 artifact에 약 500MB씩 쌓였기 때문에
급한대로 예전에 생성했던 artifact들을 모두 삭제했음에도 해결되지 않았다.
빠르게 배포를 해야했기에 AWS를 사용하지 않고 GitHub actions만 연결해 배포했지만 이런 문제를 만나게 될지는 몰랐다.
그래서 이제 GitHub actions의 artifact에 기대지 않고, aws s3와 code deploy를 사용해서 자동배포하도록 다시 CI/CD를 구축하기로 했다.
자동 배포 파이프라인 수정
배포 과정 구조도
AWS S3와 Code deploy를 활용해서 수정한 자동 배포 파이프라인의 구조도는 다음과 같다.
1. Github 에 코드를 푸시한다.
2. deploy.yml 파일에 작성된 브랜치에 푸시되었다면, 그 내용에 따라 GitHub actions가 동작한다.
3. GitHub actions는 코드를 빌드하여 생성된 빌드파일을 AWS S3에 업로드한다.
4. GitHub actions는 AWS Code deploy에게 배포를 요청한다.
5. AWS Code deploy는 S3에서 빌드파일을 가져온다.
6. 빌드파일을 EC2에 배포한다. (여기서 환경변수 주입 필요)
위 과정을 GitHub actions, AWS S3, AWS IAM, AWS Code deploy 로 나누어 더 자세히 살펴보자
AWS를 사용하기 때문에 IAM을 GitHub actions, S3, Code deploy, EC2에 모두 적용해줘야 하는데
과정을 따라가며 중간에 필요할 때마다 설명할테지만
그래도 복잡하니 마지막에 다시 따로 정리하기로 하자.
1. GitHub actions - deploy.yml
GitHub actions (1/2) build 단계
코드가 브랜치에 푸시되고 GitHub actions가 트리거되면
GitHub actions는 프로젝트에서 .github/workflows에 생성한 deploy.yml 파일의 내용에 따라서 작업을 수행된다.
아래는 현재 프로젝트에 적용한 dev 브랜치의 deploy.yml 파일이다.
name: Spring CI CD
on:
push:
branches: ["develop"]
jobs:
build:
runs-on: ubuntu-latest
steps:
# jdk 17 설치
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
# gradle 실행 권한 부여
- name: Grant execute permission for gradlew
run: |
chmod +x gradlew
# gradle 빌드
- name: Build with Gradle
uses: gradle/gradle-build-action@v2.6.0
with:
arguments: build
# make zip file
- name: Make zip file
run: zip -qq -r ./$GITHUB_SHA.zip .
shell: bash
# AWS 사용자 정보 입력
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_ID }}
aws-region: ap-northeast-2
# S3에 zip 파일 업로드
- name: Upload to S3
run: aws s3 cp --region ap-northeast-2 ./$GITHUB_SHA.zip s3://${{ secrets.S3_BUCKET_NAME }}/deploy/$GITHUB_SHA.zip --source .
deploy:
needs: build
runs-on: ubuntu-latest
steps:
# AWS 사용자 정보 입력
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_ID }}
aws-region: ap-northeast-2
# CodeDeploy에 배포 요청
- name: Code Deploy
run: |
aws deploy create-deployment \
--application-name ${{ secrets.CODE_DEPLOY_APP_NAME }} \
--deployment-config-name CodeDeployDefault.AllAtOnce \
--deployment-group-name ${{ secrets.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \
--s3-location bucket=${{ secrets.S3_BUCKET_NAME }},bundleType=zip,key=deploy/$GITHUB_SHA.zip
찬찬히 뜯어보자.
name: Spring CI CD
on:
push:
branches: ["develop"]
먼저 CI CD 파이프라인의 이름을 설정해준다.
그리고 trigger branch를 설정해줘야 하는데, 해당 branch로 코드가 푸시되었을 때 GitHub actions를 동작하겠다는 의미이다.
그 다음 본격적인 작업에 들어가는데, 첫번째 과정은 build이다.
jobs:
build:
runs-on: ubuntu-latest
steps:
# jdk 17 설치
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
# gradle 실행 권한 부여
- name: Grant execute permission for gradlew
run: |
chmod +x gradlew
# gradle 빌드
- name: Build with Gradle
uses: gradle/gradle-build-action@v2.6.0
with:
arguments: build
# make zip file
- name: Make zip file
run: zip -qq -r ./$GITHUB_SHA.zip .
shell: bash
# AWS 사용자 정보 입력
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_ID }}
aws-region: ap-northeast-2
# S3에 zip 파일 업로드
- name: Upload to S3
run: aws s3 cp --region ap-northeast-2 ./$GITHUB_SHA.zip s3://${{ secrets.S3_BUCKET_NAME }}/deploy/$GITHUB_SHA.zip --source .
GitHub actions가 동작할 때에도 GitHub actions는 알아서 가상 환경을 띄우고, 그곳에서 작업들을 진행한다.
build단계에서는 steps 하위에 작성된 작업들을 차례로 수행한다.
- spring code를 빌드해야 하기 때문에 jdk를 설치해준다.
- gradle 실행 권한을 부여해준다.
- gradle로 spring code를 빌드한다.
- 생성된 빌드 파일을 zip 하여 zip 파일을 생성한다.
- AWS S3에 업로드해야 하기 때문에 AWS 사용자 정보를 입력한다.
- AWS S3에 zip 파일을 업로드한다.
여기까지가 GitHub actions에서 build 단계이다.
여기서 AWS 사용자 정보를 입력할 때에 필요한 access key id와 secret access key id를 얻기 위해 AWS IAM 사용자를 생성해야 한다. 그리고 S3에 파일을 업로드하기 위한 S3 버킷도 만들어야 한다. 이 과정들은 deploy 단계까지 설명한 뒤에 이야기하도록 하자.
GitHub actions (2/2) deploy 단계
그 다음은 deploy 단계이다.
deploy:
needs: build
runs-on: ubuntu-latest
steps:
# AWS 사용자 정보 입력
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_ID }}
aws-region: ap-northeast-2
# CodeDeploy에 배포 요청
- name: Code Deploy
run: |
aws deploy create-deployment \
--application-name ${{ secrets.CODE_DEPLOY_APP_NAME }} \
--deployment-config-name CodeDeployDefault.AllAtOnce \
--deployment-group-name ${{ secrets.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \
--s3-location bucket=${{ secrets.S3_BUCKET_NAME }},bundleType=zip,key=deploy/$GITHUB_SHA.zip
여기서는 Code deploy에 배포를 요청하는 부분이 중요하다.
Code deploy 역시 AWS 리소스이므로 AWS 사용자 정보를 입력해야 한다.
근데 위에 build 단계에서 이미 AWS 사용자 정보를 입력했는데 왜 또 입력해야 할까?
deploy.yml 파일에서 jobs 하위에 build와 deploy를 나눠서 작성해놨는데 이럴 경우 두 작업이 따로 진행된다.
즉 build단계를 위해 가상환경이 생성되고 작업이 진행된 후에 해당 가상환경을 사라지게 되고,
다음 deploy단계를 위한 가상환경이 다시 생성된다. 그렇기 때문에 build 단계에서 AWS 사용자 정보를 입력했다고 하더라도 deploy단계에서는 알 수가 없는 것이다. 그래서 다시 AWS 사용자 정보를 입력해야 한다.
그리고 Code deploy에게 배포 요청을 한다.
여기서는 Code deploy 리소스의 정보들이 필요한다. 아직 AWS에서 Code deploy 리소스를 만들어주지 않았다.
AWS에서 Code deploy를 만들고 설정해야한다.
중간 정리
- 지금까지 GitHub actions의 deploy.yml 에 작성한 CI/CD 파이프라인 내용을 단계별로 살펴봤다.
- 이 파이프라인이 잘 동작하기 위해서 해야할 과제들이 남았다.
1. AWS S3 버킷 생성
2. AWS Code deploy 생성
* AWS IAM 사용자 생성 - GitHub actions, code deploy에 붙이기
2. AWS S3
AWS S3 버킷 만들기
깃허브 액션에서 빌드한 파일을 보관할 S3 버킷을 만든다.
S3와 Code deploy에 접근가능한 IAM 사용자 생성
우리가 만들어줘야 하는 첫번째 IAM 이다. (사용자)
- type : user
- policy : "S3", "Codedeploy"
- resource : GitHub actions, EC2
GitHub actions에서 AWS의 리소스를 사용하기 위해서는 권한이 필요하다. AWS IAM에서 그 권한을 설정해줄 것이다.
AWS IAM으로 들어가 'create user'를 클릭해 새로운 사용자를 만들어준다.
GitHub actions에서는 빌드한 zip 파일을 AWS S3에 업로드해야 하기 때문에 s3에 접근권한을 가진 사용자를 만들어
GitHub actions에게 그 정보를 알려줘야 한다.
user 이름을 cicd-user로 생성해주었다.(뒤에서 code deploy 사용을 위한 권한도 추가해줄 것이기 때문에 s3권한 code deploy권한을 모두 가진 user이기 때문에 cicd 파이프라인을 위한 사용자라는 의미이다.)
그렇기 때문에 사용자의 권한에 'AmazonS3FullAccess'를 추가해준다.
뒤에서 Code deploy에 배포 요청을 하기 위해서는 Code deploy에 접근할 수 있는 권한도 추가해줘야 한다.
같은 사용자로 S3와 Code deploy에 접근하기 위해 여기서 'AWSCodeDeployFullAccess' 권한도 추가해준다.
그 뒤로는 별다른 설정없이 바로 사용자를 생성해주면 된다.
사용자 생성한 뒤에 클릭해서 들어가면 맨 오른쪽처럼 Access key를 생성할 수 있다.
Create access key를 클릭하면 아래처럼 무엇을 위해 사용하는 건지 물어보는데, Application running outside AWS 를 선택해주었다. AWS 외부에서 GitHub actions를 위해 만드는 것이기 때문에 이걸 선택하긴 했는데 무엇을 선택하든 access key는 주어지기 때문에 크게 중요한 부분은 아닌 것 같다.
그리고 그 다음 description을 간단히 적고 나면 위와 같이 Acccess key와 Secrey access key가 발급되는데 이 값들을 GitHub actions에 넣어주는 것이다. 여기서 Secret access key는 이 페이지를 벗어나면 다시 받아올 수 없기 때문에 아래에 Download.csv file을 클릭해 access key 정보를 따로 저장해두는 것을 권장한다. (중요⭐️)
GitHub actions Secret 값 저장하기
하지만 당연히 위 access key들을 그대로 deploy.yml 파일에 적을 수는 없다.
보안 정보들이기 때문에 유출되면 위험할 수 있기 때문이다.
이런 정보들은 repository에서 settings > security > Secrets and variables > Actions 에 추가해야 한다.
New repository secret을 누르고 변수 명을 작성한 뒤, 값을 작성해주면 된다.
AWS 사용자 정보 중 AWS의 region도 입력해야 하는데, 대한민국에서 사용하는 경우에는 'ap-northeast-2'로 입력하면 된다.
이 AWS 사용자 정보들이 잘 주입이 되면 GitHub actions는 빌드파일을 AWS S3에 업로드할 수 있는 권한을 가지게 된다.
GitHub actions에 s3와 code deploy에 접근할 수 있는 권한을 가진 IAM 사용자까지 붙였다.
3. AWS Code deploy
Code deploy는 AWS에서 배포작업을 도와주는 리소스로 해당 리소스(배포그룹)를 생성한 뒤에 배포를 하기 위해 필요한 정보들(배포결과 저장 위치, 배포단계별 실행 명령어 등)을 스크립트 파일로 작성해줘야 한다.
따라서 Code deploy를 사용하기 위해서는
- Code deploy group 생성, 2. Code deploy agent 설치 3. 설정 파일 작성(appspec.yml, deploy.sh)
위와 같이 총 3개의 단계가 필요하다.
step1. Code deploy group 만들기
이 단계에서 중요한 것은 Code deploy group을 만들어 배포할 EC2 인스턴스와 연결시켜주는 것이다.
또한 배포 그룹에는 Code deploy Role을 추가해줘야 한다.
따라서 순서상 Code deploy Role을 만들고, 애플리케이션을 만들고, 해당 애플리케이션에서 배포 그룹을 만든다.
- AWS IAM에서 'AWSCodeDeployRole' 권한을 가진 role을 만든다.
- 애플리케이션 만들기
- 컴퓨터 플랫폼 : EC2/온프레미스
- 배포 그룹 만들기
- 배포 그룹 이름
- 위에서 만든 Code deploy role 추가
- 배포 타입 : In-place
- 환경 구성
- Amazon EC2 Instance
- 배포하고자 하는 EC2 Name 태그와 연동(Key: Name, Value: {EC2 인스턴스 이름})
- Code deploy agent는 여기서 설치하지 않고 따로 설치해주었다.
- 로드밸런서 사용 해제
우리가 만들어줘야 하는 두번째 IAM 이다. (역할)
- type : role
- policy : "Codedeploy"
- resource : Code deploy
step 2. EC2 인스턴스에 Code deploy agent 설치하기
EC2 인스턴스에 Code deploy agent를 설치해준다. Code deploy에서 해당 EC2에 배포 명령을 할 때, Code deploy agent가 배포를 실행한다.
이 때 주의할 것은, EC2와 Code deploy에 대한 IAM 역할을 설정해준 뒤에 agent를 실행해줘야 한다. 그렇지 않으면 Code deploy agent에서 권한을 제대로 찾을 수가 없어 권한 에러가 날 수 있다.
즉, 이 단계에서의 세부 단계는 1. EC2에게 Code deploy, S3 IAM 설정, 2. EC2에 Code deploy agent 설치 이다.
2-1. EC2에게 Code deploy, S3 IAM 설정
그럼 먼저 EC2에게 Code deploy와 S3에 대한 접근 권한을 설정해주자.
이를 위해서는 2가지 단계가 필요하다. AWS EC2 콘솔에서 바로 role을 붙여주고, 위에서 생성한 user는 EC2 CLI에서 붙여준다.
1) cicd role 생성해서 붙여주기
AWS IAM에서 아래 정책들을 가진 role을 생성해 EC2 인스턴스에 붙여준다.
AWS EC2 콘솔에 가서 Security > Modify IAM Role을 통해 붙여주면 된다.
우리가 만들어줘야 하는 세번째 IAM 이다. (역할)
- type : role
- policy : "S3", "Codedeploy", "EC2RoleforCodedeploy"
- resource : Code deploy
2) cicd user 정보 넣어주기
그리고 위에서 만들었던 첫번째 IAM인 cicd user 정보를 EC2 인스턴스 자체에 적용시켜 주어야 한다.
EC2 인스턴스에 접속해 아래 명령어를 입력해준다 (이 명령어를 인식하기 위해서는 aws cli를 설치해야 한다)
aws configure
그러면 AWS user access key 정보와 region name, output format 등을 입력하는 창이 나온다. 위에 저장해놓은 csv 파일을 참고해서 차례로 작성해준다. output format은 아무것도 입력하지 않고 엔터를 눌러도 된다.
$ aws configure
AWS Access Key ID [None]: <위에서 발급한 Key id>
AWS Secret Access Key [None]: <위에서 발급한 Secret Access Key>
Default region name [None]:
Default output format [None]:
2-2. EC2에 Code deploy agent 설치
이제 EC2 IAM 설정도 마쳤으니 Code deploy agent를 설치한다.
# 1. ruby 설치
sudo apt-get install ruby
# 2. wget 설치 (agent 설치 파일을 가져오기 위해 사용)
sudo apt-get install wget
# 3. 설치파일 다운로드
cd /home/ubuntu
wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
# 4. 실행권한 추가 및 설치
chmod +x ./install
sudo ./install auto
설치 잘 되었는지 확인하기
sudo service codedeploy-agent status
실행이 되지 않았다면 start 명령어로 실행시켜주기
sudo service codedeploy-agent start
setp 3. Code deploy 설정 및 실행 파일 작성하기
이제 프로젝트 코드 내에 appspec.yml 파일과 스크립트 파일을 작성해줘야 한다.
code deploy는 appspec.yml 파일에 적힌 정보를 기준으로 배포를 실행하게 된다.
appspec.yml
version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/oneit
overwrite: yes
file_exists_behavior: OVERWRITE
permissions:
- object: /home/ubuntu/oneit
owner: ubuntu
group: ubuntu
mode: 755
hooks:
AfterInstall:
- location: scripts/deploy.sh
timeout: 60
runas: ubuntu
- 인스턴스 내부에서 배포할 파일을 저장할 디렉토리를 지정하고 오버라이팅 여부와 디렉토리의 권한 설정 등을 할 수 있다.
- hooks에서는 배포의 세부 단계에서 실행할 스크립트 파일을 지정해준다.
- AWS Code deploy 콘솔로 들어가 deployments 로 들어가면 배포 실행 과정을 볼 수 있는데 View events를 클릭해 더 자세한 세부 단계를 확인해보면 아래와 같이 ApplicationStop, BeforeInstall, AfterInstall 등 세부 과정들이 순차적으로 실행된다. hooks에는 이와 같은 세부 단계에서 어떤 스크립트가 실행되어야 할지 정의해주는 것이다.
그리고 실제로 배포가 될 때에는 아래 deploy.sh 내용을 순서대로 수행하게 된다.
deploy.sh
# stop application
REPOSITORY=/home/ubuntu/app
APP_NAME=app
CURRENT_PID=$(pgrep -f $APP_NAME)
if [ -z "$CURRENT_PID" ]; then
echo "> No applications are currently running, so do not exit"
else
echo "> kill -15 $CURRENT_PID"
sudo kill -15 $CURRENT_PID
sleep 5
fi
# start applications
JAR_NAME=$(ls $REPOSITORY/build/libs/ | grep '.jar' | tail -n 1)
JAR_PATH=$REPOSITORY/build/libs/$JAR_NAME
echo "> $JAR_PATH deploy"
nohup java -jar -Dspring.profiles.active=dev $JAR_PATH > $REPOSITORY/nohup.out 2>&1 &
- 실제 배포가 진행되는 과정들을 담은 파일들이다.
- 배포가 시작되면 deploy.sh 파일들의 코드가 한 줄씩 실행된다.
사실 Code deploy 에서 배포가 시작되면 외부에서 환경변수를 받아올 수 없는 문제가 있다.
실제로 위 배포 스크립트대로 배포가 되면 환경변수 주입이 되지 않아 배포가 잘 되지 않을 것이다.
이를 위해서 Infisical 을 도입하게 되는데 이 과정에서도 엄청난 삽질이 있었기 때문에 따로 포스팅을 하기로 하겠다..
deploy.sh의 모든 코드가 실행되고 마지막에 배포 명령어까지 잘 수행되면 자동 배포가 완료된다.
AWS IAM 정리
중간중간 IAM 설정이 많아서 헷갈렸는데, 총 생성해서 사용한 IAM을 정리하면 아래와 같다.
1. S3와 Code deploy 권한을 가진 사용자 -> GitHub actions, EC2 인스턴스 (CLI)
2. Code deploy 역할 -> Code deploy
3. S3와 Code deploy 권한을 가진 역할 -> EC2 인스턴스
💣 Trouble Shooting
1. Code deploy agent 삭제가 제대로 되지 않을 때
권한 에러..가 처음에 났을 때에는 권한 설정을 한 뒤에 code deploy 설치를 해줘야 하는데 그 순서가 꼬여서 권한 설정이 제대로 되지 않았다고 생각했다.
그래서 권한 설정을 다 마친 뒤에 설치한 code deploy를 삭제하고 다시 설치해주려고 아래 명령어로 삭제를 해주었는데
sudo apt-get remove codedeploy-agent -y
삭제 및 설치가 제대로 되지 않았다.
(다시 install auto 해도 이미 최신 버전 있다고 설치를 스킵했음.. 지맘대로..)
그래서 엄청 삭제-설치를 반복하다가 삭제 명령어에 —purge 까지 들어간 명령어로 삭제해줬더니 삭제가 잘 되었던 것 같다.. 아래처럼 install auto 할 때 설치 단계를 스킵하는 것이 아니라 제대로 설치하는 과정이 보였다.
sudo apt-get remove --purge codedeploy-agent -y
sudo rm -rf /etc/codedeploy-agent
sudo rm -rf /var/log/aws/codedeploy-agent
sudo rm -f /etc/systemd/system/codedeploy-agent.service
sudo systemctl daemon-reload
그리고 관련된 파일도 모두 삭제해주고 daemon을 reload해주었다.
codedeploy-agent 이름으로 된 파일을 모두 검색해보니 모두 잘 나왔다
그런데 맨 처음 codedeploy-agent.service 파일에서 ExecStart와 ExecStop부분을 수정해줬었는데 service 파일은 다시 설치를 해도 자동 생성되지 않았다. 그래서 아래처럼 수동으로 작성하고 저장해줬다.
위치 : /etc/systemd/system/codedeploy-agent/service
이제 드디어 active가 정상적으로 나오는 것을 볼 수 있었다!
2. GitHub actions에서 빌드는 성공했으나 AWS Codedeploy에서 배포가 실패하는 에러
배포 로그를 보니 권한 에러(Access denied Exception) 였다.
해결방법 1. IAM을 적용시킨 뒤에 Code deploy agent를 설치 (순서 지켜야함)
- 이유를 찾아보니 IAM 적용과 Code deploy agent의 설치 순서가 중요하다고 한다.
- 나는 Code deploy 배포 그룹을 만들 때에 agent를 설치해주었는데, 그리고 나서 EC2에 IAM을 적용해주었었다.
- 이런 경우 Code deploy agent가 IAM 권한을 잘 인식하지 못해서 생기는 문제일 수도 있다고 한다.
- 그래서 위에서처럼 Code deploy agent를 완전히 삭제한 뒤에 IAM 적용을 모두 마치고 다시 설치해주었다.
해결방법 2. EC2 CLI에서 기존 권한 증명을 삭제
- 그래도 해결되지 않아서 다시 이유를 찾아보았는데 EC2에는 기존 권한이 부여되어 있어서
- 새로운 권한을 적용시켜주면 충돌이 날 수도 있다고 한다.
- 그래서 기존 권한 증명을 삭제해주고, Code deploy agent를 다시 시작해주었다.
# AWS 자격증명 파일 삭제
$ sudo rm -rf /root/.aws/credentials
# codedeploy-agent 재시작
$ sudo systemctl restart codedeploy-agent
참고글
Aws::CodeDeployCommand:: Errors::AccessDeniedException
Aws::CodeDeployCommand::Errors::AccessDeniedException 에러 해결기 (Error polling for host commands과 Cannot reach InstanceService)
velog.io
3. 그래도 배포는 자꾸 실패하게 되는데..
위까지 완료하면 구조상 배포가 잘 되어야 하는데,, 결론적으로 잘 되지 않았다.
1) 먼저 GitHub actions에서 빌드가 잘 되는가? (O)
2) S3에 업로그가 잘 되는가? (O)
3) Code deploy 배포 요청이 잘 되는가? (O)
4) 배포가 잘 이루어지는가? (X)
구조를 순서대로 따라가보았을 때, AWS Code deploy group에서도 모두 Success였지만
(즉, 위에서 작성한 deploy.sh 를 실행하는데에는 문제가 없다는 것)
결과적으로 EC2 인스턴스 내에서 실제로 배포를 할 때에 에러가 발생하고 있었다.
deploy.sh 파일의 코드를 한 줄 한 줄 EC2에 쳐보면서 발견한 원인은 바로 '환경변수 주입'문제였다.
Code deploy가 배포 시도를 하고, 내가 deploy.sh에 작성한 코드들은 문제없이 실행되지만
마지막 코드이자 배포 명령어인
nohup java -jar -Dspring.profiles.active=dev $JAR_PATH > $REPOSITORY/nohup.out 2>&1 &
이 명령어가 실행되고 나서 Code deploy는 자기 할 일 했다~ 하고 Success라고 표시한 것이고
실제 EC2내에서는 배포를 하다가 환경변수 주입이 잘 되지 않아 배포 실패한 것이다.
이 문제를 해결하기 위해서 Infisical (Secret 관리 Tool) 을 도입하게 되는데,
그 과정은 다음 포스팅에서 설명하도록 하겠다! (나의 삽질기 2탄 커밍쑨... 🫠)
'Infra' 카테고리의 다른 글
AWS Lightsail 도입에 대한 고민 - Lightsail vs EC2 비교 (2) | 2024.08.26 |
---|---|
[AWS] EC2 서버 구축하기 - (2) Nginx, Php, Mysql 설치 및 도메인 연결 (0) | 2023.10.02 |
[AWS] EC2 서버 구축하기 - (1) 인스턴스 생성하고 접속(Window) (0) | 2022.08.11 |