본 글은 AWS EC2, S3 설정에 대한 내용을 다루고 있지 않으며,
EC2 인스턴스 생성과 S3 버킷 생성이 완료되었다는 가정 하에 진행됩니다.
name: Build and Deploy for PROJECT_NAME to AWS EC2
# Event Trigger
on:
push:
# master(main) branch 기준으로 동작
branches: [ master ]
# PR도 반영되게 할 거라면 아래 부분 주석 해제
# pull_request:
# branches: [ master ]
jobs:
build:
# 실행 환경 지정
runs-on: ubuntu-latest
# Task의 sequence 명시
steps:
- uses: actions/checkout@v2
# JAVA 버전은 프로젝트에 맞게 설정
- name: Set up JDK 17
uses: actions/setup-java@v1
with:
java-version: 17
- name: Grant execute permission for gradlew
run: chmod +x gradlew
# Gradle build (Test 제외)
- name: Build with Gradle
run: ./gradlew clean build -x test
접속 방법(MAC OS)
1. pem키가 있는 디렉터리 경로로 이동
2. chmod 400 파일명.pem
3. ssh -i "파일명.pem" ec2-user@퍼블릭DNS!
헷갈릴 경우 인스턴스 - 연결로 들어가면 복사만 해서 사용 가능하게 방법을 다 안내해준다.
이렇게 연결 후 Ubuntu 서버에 맞게 CodeDeploy를 설치하면 된다.
보통 Ubuntu Server를 사용하니 아래 문서를 참고하면 된다.
https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/codedeploy-agent-operations-install-ubuntu.html
그런데 내 경우에는 AWS 설정을 다른 팀원이 진행했더니 계속 문제가 생겨서 버전 확인이 필요했다.
hostnamectl
위 코드를 실행하고 Operation System을 확인하면 버전을 알 수 있는데
우리 팀은 Amazon Linux로 설정되어 있었다. Ubuntu가 아니었다니.
https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/codedeploy-agent-operations-install-linux.html
Amazon Linux의 CodeDeploy 문서는 별도로 있어서 이 사이트를 참고해서 진행했다.
sudo yum update
sudo yum install ruby
sudo yum install wget
cd /home/ec2-user
wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
# wget https://bucket-name.s3.region-identifier.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto # 최신 버전 CodeDeploy 설치
bucket-name은 해당 리전의 CodeDeploy 리소스 키트 파일이 포함되어 있는 Amazon S3 버킷의 이름입니다. region-identifier는 리전의 식별자이다.
예를 들어, 미국 동부(오하이오) 리전의 경우 bucket-name을 aws-codedeploy-us-east-2로 바꾸고 region-identifier를 us-east-2로 바꾸면 된다고 한다.
위 코드는 아시아 태평양 (서울) 기준이므로 다신 리전을 사용할 경우 아래 사이트를 참고하여 변경해주자.
bucket-name & region-identifier 확인하기
sudo service codedeploy-agent status
"The AWS CodeDeploy agent is running" 메시지가 표시되어야 하며 혹시 "error: No AWS CodeDeploy agent running" 에러 메시지가 발생하면
sudo service codedeploy-agent start
sudo service codedeploy-agent status
이 두 명령어를 한 번에 하나씩 실행해준다.
애플리케이션 이름과 컴퓨팅 플랫폼을 선택 후 애플리케이션을 생성해준다. 이제 배포 그룹을 생성해주면 된다.
배포 그룹 이름을 입력하고, 서비스 역할은 위에서 설정한 IAM의 CodeDeploy 역할을 선택해준다. ![]
태그 그룹의 키는 EC2 인스턴스에 생성했던 태그의 키를 가져오면 된다. 만약 EC2 인스턴스 생성 시 태그를 추가하지 않았다면 추가해주자. 추가해주었는데 클릭했을 때 표시되지 않는다면 국가, 리전도 잘 확인해보자...ㅎ 배포 설정까지 확인하고 로드 밸런서 활성화 토글도 해제한 뒤 이제 배포 그룹을 생성해주자.
나는 기존에 S3 설정을 위해 생성해둔 사용자가 있기 때문에 해당 사용자에 권한을 추가하는 방식으로 진행하게 되었다. 만약 사용자가 없다면 IAM에서 사용자를 추가해 AmazonS3FullAccess 권한을 부여하면 동일한 상태가 될 것이다. 권한 추가를 눌러 이동한 뒤 아래 사진과 같이 진행해준다.
AWS에서 제공하는 정책 중 AWSCodeDeploy와 관련한 권한을 설정해준다.
CodeDeploy 사용을 위해 역할 생성과 연결까지 진행해보겠다. IAM - 역할 - 역할 만들기로 접근 후, 아래 사진과 같이 엔터티를 설정해준다. 다음으로 넘어가 역할 이름을 입력한 뒤 생성을 완료한다. 생성 완료!
사용자를 새롭게 생성했다면 생성 마지막 화면에 Access Key와 Secret Key를 csv로 다운 받을 수 있게 표시될 것이다. 꼭 다운로드 받아두자.
나처럼 Key 받아두는 것을 깜빡했더라도 걱정하지 말자. 사용자로 들어가 보안 자격 증명 - 액세스 키 만들기를 통해 다시 생성이 가능하다.
사용하지 않는 키는 삭제하거나 비활성화 해두자. 나는 다른 팀원이 쓸 수도 있어서 우선 그대로 두었다.
보안을 위해 Github 레포지터리 안에 Secrets로 위의 키 값들을 저장해둘 수 있다.
레포지터리에 들어간 후 Settings - Secrets - Actions - New repository secret으로 이동한다.
사용할 Name을 써주고 Secret 안에 키 값을 담아준다.
이렇게 Access key와 Secret key를 설정 해주면 아래 Repository secrets에서 확인이 가능하다. (키 값이 확인 가능한 것은 아니니 csv 파일은 계속 잘 보관해두자)
env, 권한부여, 압축파일 만들기, S3, CodeDeploy 부분 추가
name: Build and Deploy for MoramMoram server to AWS EC2
# Event Trigger
on:
push:
branches: [ master ]
# pull_request:
# branches: [ master ]
# 사용할 인프라의 이름을 변수 형태로 저장 가능
env:
# 버킷에 저장할 프로젝트 폴더 이름
PROJECT_NAME: morammoram_backend
# S3 생성 시 지정했던 이름
BUCKET_NAME: morambucket
# CodeDeploy의 앱 이름
CODE_DEPLOY_APP_NAME: moram-codedeploy
# CodeDeploy의 배포그룹 이름
DEPLOYMENT_GROUP_NAME: moram-codedeploy-deployment-group
jobs:
build:
# 실행 환경 지정
runs-on: ubuntu-latest
# Task의 sequence를 명시한다.
steps:
- uses: actions/checkout@v2
- name: Set up JDK 17
uses: actions/setup-java@v1
with:
java-version: 17
- name: Grant execute permission for gradlew
run: chmod +x gradlew
# Gradle build (Test 제외)
- name: Build with Gradle
run: ./gradlew clean build -x test
# 압축 파일 만들기
- name: Make Zip File
run: zip -qq -r ./$GITHUB_SHA.zip .
shell: bash
# 권한 부여
- 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 }}
aws-region: ap-northeast-2
# S3로 파일을 업로드하는 동작
- name: Upload to S3
run: aws s3 cp --region ap-northeast-2 ./$GITHUB_SHA.zip s3://$BUCKET_NAME/$PROJECT_NAME/$GITHUB_SHA.zip
# CodeDeploy에 배포단위를 생성하는 동작
- name: Code Deploy
run: aws deploy create-deployment --application-name $CODE_DEPLOY_APP_NAME --deployment-config-name CodeDeployDefault.OneAtATime --deployment-group-name $DEPLOYMENT_GROUP_NAME --s3-location bucket=$BUCKET_NAME,bundleType=zip,key=$PROJECT_NAME/$GITHUB_SHA.zip
https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/application-specification-files.html
AppSpec 파일을 작성하여 프로젝트의 어떤 파일들을 EC2의 어떤 경로에 복사할 지 설정하고, 배포 후 수행할 스크립트를 지정해서 자동으로 서버를 띄울 수도 있다고 한다.
# appsec.yml 파일 - 반드시 소스코드 루트 디렉터리에 위치 시킬 것
version: 0.0
os: linux
files:
- source: /
destination: /home/ec2-user/MoramMoram-backend
permissions:
- object: /home/ec2-user/MoramMoram-backend/
owner: ec2-user
group: ec2-user
hooks:
AfterInstall:
- location: scripts/deploy.sh
timeout: 60
runas: ec2-user
#!/usr/bin/env bash
REPOSITORY=/home/ec2-user/MoramMoram-backend/
cd $REPOSITORY
APP_NAME=MoramMoram-backend
JAR_NAME=$(ls $REPOSITORY/build/libs/ | grep 'SNAPSHOT.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 -9 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 5
fi
echo "> $JAR_PATH 배포"
nohup java -jar $JAR_PATH > /dev/null 2> /dev/null < /dev/null &
이렇게 파일을 생성하고 실행했는데 오류가 났다. 두둥.
An error occurred (DeploymentLimitExceededException) when calling the CreateDeployment operation: The Deployment Group 'moram-codedeploy-deployment-group (id=c9d2b3df-22ca-4684-91cc-850f793a6166)' already has an active Deployment 'd-B7SVXLF6K'
이미 배포가 이루어져서 안 된다고 해서 해당 에러를 찾아보니
https://kimtaehyun98.tistory.com/136
이 블로그에서 같은 문제를 겪으신 분을 발견할 수 있었다.
이미 파일이 존재할 경우 삭제 후 진행할 수도 있고, overwrite도 가능했는데 우선은 overwrite로 설정을 진행했다.
file_exists_behavior: OVERWRITE
appsec.yml에 코드를 추가해주었고 빌드에 성공했다!
처음 한 것 치고는...오류가 많이 안 난 게 아닐까 위안을 삼아 본다ㅎ
https://www.youtube.com/watch?v=UF2Giz9PE-E
https://bcp0109.tistory.com/363
이 두 곳의 자료가 없었으면 한참 또 헤맸을 것 같은데 다행이다.
이제 다시 열심히 개발해봐야지.
역시 세팅이 제일 어렵다는 느끼는 하루였다.
(분명 10분짜리 영상 보고 시작했는데 쉬는 시간 포함 4시간은 걸린 것 같다)