본문 바로가기
personal project/pcmoa

CI/CD를 통해 AWS EC2로 배포

by choi-dev 2024. 2. 28.

현재 EC2 인스턴스가 구성되어있는 상태이고 Github Actions를 통해 CI/CD 파이프라인 또한 구축되어 있는 상태이다. 이 두 가지를 모두 완료한 상태에서 글을 읽는 것을 추천한다.

 

S3 버킷 생성

버킷을 생성해야 하는 이유는 CI/CD에 대한 구조때문이다. 해당 부분은 CI/CD에 대해 따로 정리해둘 예정이어서 간단히 파일을 압축해 zip 파일을 S3에 업로드하기 위함이다.

 

검색에서 S3를 입력하고 새로운 버킷 생성을 통해 들어오면 일반 구성부터 항목이 쫙 보일 것이다. 버킷 이름은 본인이 하고 싶은대로 한다.

 

IAM 사용자를 통해 S3 저장소에 접근할 것이기에 모든 퍼블릭 액세스를 차단한다.

 

올바르게 생성되었다.

 

IAM 사용자 생성

IAM이라는 걸 좀 설명하자면 AWS 리소스에 대한 액세스를 안전하게 제어할 수 있는 웹 서비스를 말한다. 우리는 지금 Github Actions라고 하는 외부 요소를 통해 AWS 리소스에 접근하려고 하기 때문에 IAM 사용자에 대한 생성이 필요하다. Github Actions에서 S3와 CodeDeploy에 대한 모든 권한을 허용해주어야 CI/CD를 구축할 수 있다.

 

IAM을 검색하면 사용자를 생성할 수 있는 항목이 나온다. 본인이 사용할 이름을 적는다.

 

디폴트는 그룹에 사용 추가라고 되어 있을텐데 직접 정책 연결로 변환한다. 변환하면 아래에 단락들이 생기는데 S3FullAccess, DeployFullAccess 라고 검색하여 Github Actions가 AWS 리소스에 접근할 수 있게 해준다.

 

이런 식으로 권한을 확인했으면 사용자 생성을 한다.

 

빨간 네모칸이 현재 활성화되지 않음이라고 나올 것이다. 위 이미지의 경우에는 액세스 키를 생성한 경우에 공개해서는 안되기 때문에 하얀색으로 칠했다. 여기서 보안 자격 증명의 항목을 간다.

 

액세스키를 생성한다.

 

이 단락을 선택해준다.

 

태그 값을 설정하라는 부분이 있을텐데 그건 본인이 액세스 키에 설명을 붙이는 것이라 생각하면 된다. 그럼 이렇게 액세스키와 비밀 액세스키가 생성이 된다. 이 액세스키가 외부에 노출되면 아주 많이 문제가 되기 때문에 절대로 외부에 유출해서는 안된다. IAM이 외부에서 AWS 리소스를 허가해주도록 만드는 것이기에 노출되면 인도 같은 나라에서 당신의 RDS를 마구마구 범해버릴 것이다. 실제로 몇천만원의 금액지불이 요구되기도 했었으니 꼭 실수하지말자. 또한 csv 파일은 지금 보는 이게 마지막이기 때문에 저장을 잘해두자.

 

Repository에 생성한 시크릿 키 부여

하지만 우리가 deploy를 하려면 시크릿 키가 보여질 수밖에 없다. 그래서 깃허브에서는 해당 키 값을 따로 가지고 있어 외부에 유출되지 않도록 도와주고 있다.

 

위와 같이 본인의 Repository에서 Settings 단락을 들어가고 Secrets and variables 단락에 Actions 항목에 들어간다. 

 

New repository secret을 통해 내가 적은 형태대로 csv 파일을 열어서 그 값을 넣어주면 된다.

 

EC2 IAM 역할 수정

해당 부분에 IAM 역할 수정 버튼을 누른다.

 

현재 나는 생성해둔 상태인데 새 IAM 역할 생성에서 위에서 했던 것처럼 S3와 CodeDeploy 리소스의 접근을 허용해줄 수 있는 것을 받아 저장해서 인스턴스에 업데이트해준다.

 

CodeDeploy Agent 설치

# apt 업데이트
sudo apt-get update && sudo apt-get upgrade

# JDK 17 설치
sudo apt-get install openjdk-17-jdk

# Ruby 설치 (3.xx 버전 설치됨)
sudo apt install ruby-full

# wget 모듈 설치
sudo apt install wget

cd /home/ubuntu

# codedeploy 파일 다운로드
sudo wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install

해당 명령어를 차례대로 입력한다. 제대로 입력했다면 install 파일이 생성되어있다.

 

# 권한 설정
sudo chmod +x ./install

# 출력을 임시 로그파일에 씀
sudo ./install auto > /tmp/logfile

# aws cli 설치
sudo apt-get install awscli

# 서울 리전에서 사용 가능한 codedeploy 버전 확인
sudo aws s3 ls s3://aws-codedeploy-region-identifier/releases/ | grep '\.deb$'

마찬가지로 명령어를 실행시켜준다. 마지막 서울 리전에서 사용가능한 codedeploy 경우, region-identifier 부분에 ap-northeast-2를 넣어주면 실행될 것이다.

 

# 1.6.0-49 버전의 codedeploy-agent 설치
sudo ./install auto -v releases/codedeploy-agent_1.6.0-49_all.deb > /tmp/logfile

# 서비스가 실행중인지 확인
sudo service codedeploy-agent status

서비스가 실행중인지 확인하면 Active된 상태임을 확인할 수 있다.

 

CodeDeploy 생성

AWS에서도 CodeDeploy 애플리케이션을 생성하겠다.

 

IAM의 역할을 추가해보자. 다음과 같이 설정한다. 그리고 역할을 생성해준다.

 

CodeDeploy 애플리케이션 생성

리소스 검색에서 CodeDeploy를 검색한다.

 

다음과 같이 설정한다.

 

배포 그룹을 생성해보자.

 

서비스 역할은 본인이 만든 IAM CodeDeploy에 관한 것을 넣는다.

 

배포 유형은 디폴트 값인 현재 위치를 선택해둔다.

 

환경 구성은 EC2 인스턴스를 체크해주고 만들었던 키 페어를 태그 그룹1로 지정해준다.

 

배포 설정은 한 번에 모든 인스턴스를 배포하는 AllAtOnce를 선택해주고 로드 밸런서의 경우에는 내가 사용 중이지 않기 때문에 해제했다.

 

yml에 배포 동작 추가

env:
  PROJECT_NAME: pcmoa_project
  BUCKET_NAME: pcmoa
  CODE_DEPLOY_APP_NAME: pcmoa-cicd
  DEPLOYMENT_GROUP_NAME: pcmoa

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build:

    runs-on: ubuntu-latest
    permissions:
      contents: read

    steps:
    - uses: actions/checkout@v4
    - name: Set up JDK 17
      uses: actions/setup-java@v4
      with:
        java-version: '17'
        distribution: 'temurin'

    # Configure Gradle for optimal use in GiHub Actions, including caching of downloaded dependencies.
    # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
    - name: Setup Gradle
      uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0

    - name: Build with Gradle Wrapper
      run: |
        chmod +x gradlew
        ./gradlew build
    - 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_PRIVATE_ACCESS_KEY }}
        aws-region: ap-northeast-2

    - name: Upload to S3
      run: aws s3 cp --region ap-northeast-2 ./$GITHUB_SHA.zip s3://$BUCKET_NAME/$PROJECT_NAME/$GITHUB_SHA.zip

    - name: Code Deploy To EC2 instance
      run: aws deploy create-deployment
        --application-name $CODE_DEPLOY_APP_NAME
        --deployment-config-name CodeDeployDefault.AllAtOnce
        --deployment-group-name $DEPLOYMENT_GROUP_NAME
        --s3-location bucket=$BUCKET_NAME,bundleType=zip,key=$PROJECT_NAME/$GITHUB_SHA.zip

해당 부분에서 환경변수를 정의한 것과 자바를 빌드해 테스트하고 그 이후의 작업이 추가되었다. 압축 파일을 생성해서 aws에 액세스키와 개인 액세스키를 통해 접근하고 S3에 업로드하여 EC2 인스턴스에 배포하게 된다. 그대로 복붙해서 작성하지말고 환경변수 선언부에 본인의 S3 버킷 이름, 배포 이름 등을 적어야 한다.

 

프로젝트 최상단 부에 appspect.yml을 추가한다.

 

version: 0.0
os: linux

files:
  - source: /
    destination: /home/ubuntu/pcmoa
permissions:
  - object: /home/ubuntu/pcmoa/
    owner: ubuntu
    group: ubuntu
hooks:
  AfterInstall:
    - location: scripts/deploy.sh
      timeout: 60
      runas: ubuntu

경로는 본인이 지정한 경로대로 수정해서 기입한다. 기입 후에 scripts 디렉토리를 하나 생성해주고 deploy.sh 스크립트를 생성한다. 

 

#!/usr/bin/env bash

REPOSITORY=/home/ubuntu/moduform
cd $REPOSITORY

APP_NAME=moduform
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 "> Deploy - $JAR_PATH "
nohup java -jar $JAR_PATH > /dev/null 2> /dev/null < /dev/null &

이 스크립트의 경우에는 Spring Boot 애플리케이션을 배포하기 위해 사용된다. 기존에 JAR 파일을 실행중이라면 프로세스를 중단하고 새로운 버전의 JAR 파일을 실행하는 작업을 수행한다. 스크립트를 다 작성했으면 메인 브랜치로 푸시를 진행한다.

 

인스턴스에서 퍼블릭 IPv4 DNS를 통해서 실행시켜보자.

 

아주 정상적으로 동작한다. 코드를 수정해서 배포해보자.

 

여기서 컨트롤러의 스트링 리턴을 살짝 변화를 주었다.

 

CI/CD를 통해 배포를 완료할 수 있게 되었다.

'personal project > pcmoa' 카테고리의 다른 글

PCMOA 초안  (0) 2024.02.29
AWS 인스턴스에 연결  (0) 2024.02.28
AWS EC2 인스턴스 생성  (0) 2024.02.27
CI/CD 자동화 구축  (0) 2024.02.27
프로젝트 계획서  (0) 2024.02.26