깃 허브에서 제공해주는 깃 액션과 aws 서비스들을 이용하여 Https 서버를 자동으로 배포하게끔 만들어 보았다.
먼저 깃 액션으로 서버를 자동 배포하기 위해서는 깃허브 Actions 탭을 눌러 준뒤 New workflows 를 눌러 workflows 파일을 생성해 줄 필요가 있다.
다음과 같이 depoly.yml 파일을 만들어 주는데 코드는 아래와 같으며 주석을 통해 설명하겠다.
#main 브랜치에 푸시가 일어날때마다 동작
on:
push:
branches:
- main
name: Deploy String boot to Amazon EC2
env:
PROJECT_NAME: action_codedeploy
#실행되는 서버 사양은 우분투 18.04버전
jobs:
deploy:
name: DEPLOY
runs-on: ubuntu-18.04
#작동확인
steps:
- name: Checkout
uses: actions/checkout@v2
#프로젝트와 같은 jdk 17과 java17로 서버 내 설정
- name: Set up JDK 17
uses: actions/setup-java@v1
with:
java-version: 17
#뒤에 일어날 작업을 위해 gradlew에 대한 권한 설정
- name: Grant execute permission for gradlew
run: chmod +x gradlew
shell: bash
#깃 이그노어 처리되어 깃 레포지토리에 저장되지 않은 properties 파일 깃액션 서버내 생성
- name: make application.properties
run:
mkdir ./src/main/resources |
touch ./src/main/resources/application.properties
shell: bash
#생성한 properties 파일에 깃 허브 내 secrets 경로에 환경변수로 저장한 properties 값을 저장
- name: deliver application.properties
run: echo "${{ secrets.PROPERTIES }}" > ./src/main/resources/application.properties
shell: bash
#깃 레포지토리 파일 빌드
- name: Build with Gradle
run: ./gradlew build
shell: bash
#zip 파일로 압축
- name: Make zip file
run: zip -qq -r ./$GITHUB_SHA.zip .
shell: bash
#한국지역의 AWS에 접근하기 위한 ACCESS_KEY_ID와 SECRET_ACCESS_KEY를 secrets 경로에 환경변수로 저장한 각 키 값을 불러옴
- 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
#aws s3버킷에 깃액션이 생성한 $GITHUB_SHA.zip파일 업로드. 이때 한국지역에서 S3버킷을 만들었으므로 --region ap-northeast-2로 설정, aws에 생성할 버킷명 sim-deploy을 다음 s3 주소에 추가. s3://버킷명(sim-deploy)/$PROJECT_NAME/$GITHUB_SHA.zip
- name: Upload to S3
run: aws s3 cp --region ap-northeast-2 ./$GITHUB_SHA.zip s3://sim-deploy/$PROJECT_NAME/$GITHUB_SHA.zip
#aws 에서 제공해주는 Code Deploy 서비스 사용. 이때 생성한 Code Depoly 어플리케이션 명 greenstep을 --application-name 뒤에 추가, 또한 Code Deploy가 받아올 S3 버킷명 sim-deploy를 --s3-location bucket= 뒤에 추가해준다.
- name: Code Deploy
run: aws deploy create-deployment --application-name greenstep --deployment-config-name CodeDeployDefault.OneAtATime --deployment-group-name dev --s3-location bucket=sim-deploy,bundleType=zip,key=$PROJECT_NAME/$GITHUB_SHA.zip
위 코드를 통해 깃 레포지토리상의 파일을 깃액션상에서 자동으로 빌드, 압축 후 S3 버킷으로 보내주며, S3 버킷에 보내진 빌드 파일을 서버 배포를 도와주는 Code Deploy 애플리케이션에 저장시켜 주는게 이 deploy.yml의 핵심 기능이다.
부가적으로 설명하자면 이 yml에서 사용되는 secrets 경로의 키 값들은 아래와 같은 방법으로 만들어준다.
Settings 탭을 누른뒤 Secrets 메뉴를 클릭, 서브 메뉴 중 Actions 메뉴를 누르면 Actions Secrets 이라는 페이지가 뜨는데, New Reposioty secret를 통해 시크릿 파일을 생성해 주면 된다.
이때 파일명은 각각 PROPERTIES, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY로 만들어 주며 각각의 secret(환경변수) 값들을 넣어 파일을 생성해 주면 된다.
이때 프로젝트의 properties 유형의 파일의 값을 그대로 집어넣으면 되는 PROPERTIES와 달리, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY의 경우 IAM의 값을 넣어줄 필요가 있는데 이에 대해서는 IAM 서비스 과정에서 서술하겠다.
다음으로 위 사진과 같이 appspec.yml, beforeinstall.sh, deploy.sh 파일을 생성해 주면 깃 레포지토리 상에서의 서버 자동 배포 작업은 모두 끝이 난다.
아래는 각 파일들을 생성할 때 사용된 코드들이다.
appspec.yml
#배포될 서버가 리눅스라 설정해줌
version: 0.0
os: linux
#아래 경로에서 실행
files:
- source: /
destination: /home/ubuntu/app
#실행 주체가 누구인지
permissions:
- object: /home/ubuntu/app
owner: ubuntu
group: ubuntu
mode: 755
hooks:
# 배포 이전 실행될 파일 beforeInstall.sh 파일은 이전에 배포된 파일을 삭제해줌
BeforeInstall:
- location: beforeInstall.sh
timeout: 60
runas: root
# 배포 시 실행될 파일, deploy.sh는 배포파일을 우분투 내에 실행시켜줌
AfterInstall:
# location은 프로젝트의 root경로를 기준
- location: deploy.sh
timeout: 60
runas: root
ㄱbeforeinstall.sh
#!/usr/bin/env bash
#첫번째 줄 #!/usr/bin/env bash는 주석이 아니다 배쉬 경로 설정에 필요
#해당 경로의 레포지토리들을 삭제해줌
REPOSITORY=/home/ubuntu/
if [ -d $REPOSITORY/app ]; then
rm -rf $REPOSITORY/app
fi
mkdir -vp $REPOSITORY/app
deploy.sh
#!/usr/bin/env bash
#첫번째 줄 #!/usr/bin/env bash는 주석이 아니다 배쉬 경로 설정에 필요
#해당 경로에 nohup으로 빌드 파일 강제실행
REPOSITORY=/home/ubuntu/app
cd $REPOSITORY
APP_NAME=greenstep
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 -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 &
다음으로 AWS의 설정들이다.
EC2 인스턴스를 우분투 18.04버전으로 설치하였고, 기본 포트인 80포트와 스프링 포트인 8080 포트를 포트포워딩 해주었다는 과정하에 설명을 이어가겠다.
먼저 생성한 EC2 인스턴스에 태그를 하나 붙여 주어야 한다.
EC2 서비스로 들어가 인스턴스 메뉴를 누른뒤 태그 탭을 클릭하면 다음과 같은 화면을 볼 수 있다.
태그관리를 눌러보자.
키 종류와 키 값을 임의로 설정하여 설정한 인스터스를 불러올 수 있는 태그를 만들어보자.
그 뒤 저장을 누르면 인스턴스에 태그가 붙여진 것을 볼 수 있을 것이다.
다음으로 AWS에서 제공해주는 Identity and Access Management(IAM) 서비스에서 역할을 부여해 주어야 한다.
IAM 서비스에들어가 역할을 부여해 보자.
역할 메뉴를 클릭, 역할 만들기 버튼을 누르면 다음과 같은 화면이 뜬다.
신뢰할 수 있는 엔터티 유형을 AWS 서비스를 선택해 준뒤, 일반 사용 사례를 EC2를 선택, 이후 다음 버튼을 눌러주자.
CodeDeployFullAccess,
S3FullAccess
을 각각 검색 후 체크해준다. 다음 정책이름을 검색하기 전에 이전 정책검색으로 인해 생성된 필터를 X버튼을 눌러 지워줘야한다.
필터를 지워주지 않으면 다음 정책 이름이 검색되지 않으니 검색되지 않는다면 필터를 안 지운 것이 아닌지 다시 한번 확인해보자.
각 정책들을 체크 한뒤에는 다음 버튼을 눌러준다.
이제 해당 액세스들이 부여된 역할의 이름을 임의로 설정해주자(임의로 EC2-Deploy로 설정하였다)
역할 생성 버튼을 누르면 역할이 생성된다.
이와 같은 방식으로 CODE-Deploy 역할도 만들어 준다. 이때 일반 사용사례 대신 다른 aws 사용사례에서 codedeploy를 권한 정책의 경우 AWSCodeDeployRole 를 부여해준뒤 생성해 주면 된다.
이 생성된 역할을 서버를 가동 시킬 EC2 인스터스와 연결해 줘야 한다.
다시 EC2 서비스로 돌아가 인스턴스 메뉴를 클릭, 사용중인 인스턴스 id를 클릭해보자.
작업 탭을 클릭, 보안을 누르고, IAM 역할 수정을 눌러준다.
생성해 두었던 IAM 역할을 선택해준뒤, IAM 역할 업데이트를 눌러주면 역할과 인스턴스와의 연결 설정은 완료된다.
이제 이 역할을 사용할 사용자를 추가해줘야 하다.
다시 IAM 서비스로 돌아가보자.
액세스 관리의 사용자 메뉴를 누르면 뜨는 화면의 사용자 추가 버튼을 누르면 아래와 같은 화면이 뜬다.
사용자 이름은 임의의 값(임의로 service-deploy-user라 만들어 주었다. 사진의 끝에 붙은 숫자 2는 삭제)을 입력한 뒤 AWS 자격 증명 유형은 액세스 키로, 그뒤 다음:권한 버튼을 눌러 다음으로 넘어가 주자.
기존 정책 직접 연결을 선택해 준뒤 정책 필터를 통해
AmazonS3FullAccess,
AWSCodeDeployFullAccess
이 2개 필터를 체크해 주자.
그뒤 다시 다음:태그를 눌러 다음으로 넘어가자.
인스턴스와 마찬가지로 키 종류와 값을 임의로 만들어 IAM 태그를 생성한뒤 다음:검토 버튼을 눌러보자.
다시 사용자 만들기 버튼을 클릭하면 IAM 사용자가 추가된다.
바로 닫지 말고 아래 화면이 뜰텐데 액세스 키 ID와 비밀 액세스 키를 복사해 따로 메모장 같은 곳에 저장해 놓자.
비밀 액세스 키의 경우 표시 버튼을 누르면 나타나는 값을 복사해 주면된다.
그뒤 다시 깃 레포지토리에 돌아가 앞서 깃허브의 시크릿 경로에 만들어 두었던 AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY에 각각 액세스 키 ID와 비밀 액세스 키의 값들을 넣주면 IAM에 대한 설정을 끝이난다.
이제 jar 파일을 업로드할 배포용 S3 버킷을 만들어 보자.
AWS 에서 제공해주는 S3 서비스에 들어가 버킷 메뉴를 누르면 위 사진과 같은 화면을 볼 수 있다.
버킷 만들기 버튼을 누른다.
생성할 버킷 이름을 임의로 설정(임의로 sim-deploy로 설정)해주고 다른 설저들은 디폴트 값으로 건드리지 않았다.
버킷 만들기 버튼을 눌러 버킷을 생성 해준다.
이제 자동 배포의 핵심이 되는 CodeDeploy 어플리케이션을 만들어 보자.
AWS에서 제공하는 CodeDeploy서비스에 들어간다.
애플리케이션 메뉴를 누른뒤 애플리케이션 생성버튼을 눌러준다.
애플리케이션 이름을 임의로 설정(프로젝트명인 greenstep으로 임의로 설정함) 컴퓨팅 플랫폼은 EC2/온프레미스를 선택, 애플리케이션 생성 버튼을 눌러준다.
다시 애플리케이션 화면으로 돌아가 생성한 애플리케이션 이름을 클릭해준다.
배포 그룹 탭을 클릭, 배포 그룹 생성을 눌러준다.
배포 그룹 명을 임의로 설정해주자.(임의로 dev로 설정)
이후 서비스 역할 입력 부에 code-deploy를 선택해주자.
배포유형은 아직 무중단 배포를 시도하는 것이 아니기에 현재위치로 선택.
환경구성은 Amazon EC2 인스턴스를 선택해준다.
태그 그룹은 인스턴스에 붙여넣은 태그 값을 넣어준다.
배포 구성은 CodeDeployDefault.AllAtOnce를 선택해준다.
로드 밸런싱 활성화는 아직 Http로 배포하기 때문에 비활성화 해주고 변경 사항 저장 버튼을 클릭한다.
이제 깃배쉬를 통해 생성한 EC2 인스턴스에 접속해보자.
jdk를 프로젝트 버전에 맞게 설치하고, 방금 생성해둔 codedeploy를 사용하기 위해 `codedeploy agent를 설치해주다.
aws 공식문서(Ubuntu Server용 CodeDeploy 에이전트 설치 - AWS CodeDeploy (amazon.com))에 들어가보면 설치방법에 대해 서술되어 있는데
sudo apt-get update
sudo apt-get install ruby
sudo apt-get install wget
cd /home/ubuntu
wget https://bucket-name.s3.region-identifier.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto
다음 순서에 맞게 설치해주면 된다.
이때 한국리전을 사용하기 위해서는 wget https:// 다음에 나오는 bucket-name 부분을 aws-codedeploy-ap-northeast-2로 바꾸고, 그뒤 region-identifier를 ap-northeast-2로 바꿔줘야한다.
sudu service codedeploy-agent status를 사용해서 실행 유무를 확인해 주자.
다음과 같이 running으로 active 상태가 표시되어 있으면 정상적으로 실행중인 상태이다.
만약 실행중인 상태가 아니라면 sudo service codedeploy-agent start를 사용해서 실행해 주면 된다.
이후 깃허브의 depoly.yml 로 돌아가 버킷 네임등을 생성한 값과 비교하여 맞추면 http 자동 배포가 완성된다.
다음은 정상적으로 실행됐을때의 모습이다.
깃허브의 액션을 눌러보면 다음과 같이 main 브랜치에 머지가 일어날때마다 머지 내역과 함께 체크 표시가 뜨는 것을 확인 할 수 있을것이다. 실패했을경우 X가 표시도니다.
해당 머지 내역을 눌러보자.
다음 페이지에서 Deploy를 눌러보면 아래 사진과 같이 빌드 후 파일 압축 S3버킷에 업로드 후 Code Deploy에 보내 주는 과정까지 정상적으로 작동되는 것을 확인 할 수 있다.
다음으로 Code Deploy가 정상적을 작동되는지 확인해 보자.
CodeDeploy 서비스에서 배포 메뉴를 누르면 배포 성공 유무를 확인해 볼 수 있다.
여기까지 완료되었다면 서버가 정상적으로 배포되는것을 확인 할 수 있다.
(자세한 해결 방법은 위 과정에 서술하였기 때문에 아래의 트러블 슈팅은 어떠한 문제들이 발생했고 어떻게 해결했는지 간략이 적었습니다.)
깃액션 빌드 부분에서 계속해서 빌드에 실패하는 문제.
>프로젝트를 깃 레포지토리에 저장시 properties 파일이 이그노어 처리되어 있어 레포지토리에 존재하지 않는 것이 문제.
그렇다고 주요 키값들을 깃허브내에 저장해서는 안되기 때문에 deploy.yml 파일에 시크릿 경로에서 properties 파일값을 불러와 레포지토리 밖에서 생성하는 방식을 추가.
SSE를 이용한 실시간 알림 구현 (0) | 2022.10.02 |
---|---|
깃액션과 aws를 이용한 HTTPS 서버 자동 배포(2) (0) | 2022.09.18 |
실전프로젝트를 시작하면 추가한 새로운 기능 (0) | 2022.09.04 |
인스타그램을 클론코딩하며 신경 쓴 기술구현들 (0) | 2022.08.28 |
첫 협업을 진행하며 느낀 것들 (0) | 2022.08.21 |