항해99 최종 프로젝트 / MVP / AWS를 통한 지속적 통합 및 지속적 전달 (CI/CD) 파이프라인 설정

song yuheon·2023년 10월 6일
0
post-thumbnail


참고 레퍼런스


https://bcp0109.tistory.com/363


AWS CI/CD 구축


EC2 인스턴스 생성 및 탄력적 IP 설정



EC2 인스턴스에 대한 추가 설정

태그(Tag) 설정

태그는 AWS의 자원 관리와 비용 추적에 사용되는 메타데이터로 간주된다. CodeDeploy에서 인스턴스를 특정하여 작업을 진행하기 위한 구분 값으로 사용되기 때문에 중요하다.

  • 인스턴스 생성 시점에서 이미 태그 설정이 완료되었으면, 해당 과정은 생략될 수 있다.

  • 태그 관리 방법

    1. EC2 대시보드에서 해당 인스턴스를 선택한다.
    2. '태그 관리' 옵션을 클릭한다.
    3. 필요한 키와 값을 입력한 후 저장한다.
    4. EC2 대시보드에서 해당 인스턴스의 태그 정보를 통해 설정한 태그의 적용 여부를 확인한다.

IAM 역할 설정

IAM 역할은 AWS 서비스를 위해 특정 권한을 부여하는 방식으로 동작한다. 이를 통해 EC2 인스턴스가 S3에 저장된 파일에 접근하는 권한을 부여한다.

  • IAM 역할 생성 방법
    1. IAM 대시보드에서 '역할' 섹션으로 이동한다.
    2. '새로운 역할 만들기'를 클릭한다.
    3. 'AWS 서비스'의 'EC2'를 선택한다.
    4. '권한 정책'에서 'AmazonS3FullAccess'를 검색하여 선택한다.
    5. 역할 이름을 설정한 후 생성한다.
    6. EC2 대시보드에서 해당 인스턴스를 선택하고 "작업 > 보안 > IAM 역할 수정"을 클릭한다. 방금 생성한 IAM 역할을 선택하고 연결한다.



CodeDeploy Agent 설치

CodeDeploy Agent는 AWS CodeDeploy 서비스와 통신하여 배포 작업을 수행하는 소프트웨어 패키지이다.

  • 설치 방법(Ubuntu 환경 기준)
    $ sudo apt update
    $ sudo apt install ruby-full
    $ sudo apt install wget
    $ cd /home/ubuntu
    $ wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
    $ chmod +x ./install
    $ sudo ./install auto > /tmp/logfile
    $ sudo service codedeploy-agent status
  • 다른 OS 또는 버전을 사용하는 경우 AWS 공식 문서를 참조해야 한다.
  • 설치 후 명령어를 통해 Agent의 상태를 확인하여 정상 작동 여부를 검증한다.


AWS S3 버킷 생성

AWS S3는 객체 스토리지 서비스로, 큰 양의 데이터를 저장하고 검색하는 데 적합하다.
이미지, zip 파일 등 다양한 데이터를 저장할 수 있다. 빌드된 프로젝트 코드를 압축하여 저장한 후, EC2 인스턴스에서 해당 코드를 불러오기 위해 사용한다.

S3 버킷 생성

  • 작업 순서

    1. AWS 관리 콘솔에서 S3 서비스로 이동한다.
    2. '버킷 만들기' 버튼을 선택한다.

버킷 구성 설정

  • 작업 순서
    1. 사용자가 원하는 버킷 이름을 지정한다. 이 이름은 전역적으로 고유해야 한다.
    2. 데이터 저장을 위한 AWS 리전을 선택한다.
    3. 'ACL(액세스 제어 목록)'은 기본 설정을 유지하여 비활성화한다.

추가 설정
버킷에 대한 추가 설정이 필요할 경우, 다음 사항을 참고한다

  • 액세스 제어, 버전 관리, 암호화
    이들 설정은 특별한 요구사항이 없는 한 기본값을 그대로 유지하는 것이 바람직하다.

버킷 생성 완료

  • 설정한 내용에 따라 버킷이 성공적으로 생성되면, 해당 내용이 AWS 관리 콘솔에 표시된다.

AWS CodeDeploy 설정

CodeDeploy는 AWS의 배포 서비스로, EC2 인스턴스나 온프레미스 환경 등에서 애플리케이션 배포를 지원한다.

CodeDeploy를 위한 IAM 역할 생성

  • IAM 역할 생성
    IAM 서비스에 접속하여 '역할 만들기'를 선택한다.
  • 서비스 선택
    AWS 서비스 리스트에서 'CodeDeploy'를 검색하고 기본 설정으로 선택한다.

  • 역할 이름 지정
    역할의 이름을 정의한다.

CodeDeploy 애플리케이션 생성

  • 작업 순서

    1. CodeDeploy 서비스로 이동한다.
    2. '애플리케이션 생성' 버튼을 클릭한다.
    3. 애플리케이션의 이름을 지정한다.
    4. 컴퓨팅 플랫폼으로 'EC2/온프레미스'를 선택한다.

CodeDeploy 배포 그룹 생성

  • 배포 그룹 선택
    생성한 애플리케이션 내에서 '배포 그룹 생성'을 클릭한다.

  • 배포 그룹 설정
    배포 그룹의 이름, 서비스 역할 등을 설정한다. 이 때, 앞서 생성한 IAM 역할을 선택할 수 있다.

  • 타겟 EC2 인스턴스 설정
    배포할 EC2 인스턴스를 선택한다. 태그를 통해 인스턴스를 지정할 수 있으며, 이전 단계에서 태그를 설정한 EC2 인스턴스를 선택한다.

  • 추가 설정 및 완료
    AWS Systems Manager의 선택은 별도의 요구사항이 없다면 기본 설정을 사용한다. 로드 밸런서를 사용하지 않는 경우, 해당 옵션의 체크를 해제한다. 모든 설정을 마친 후 '배포 그룹 생성' 버튼을 클릭하여 완료한다.


Github Actions 접근을 위한 AWS IAM 사용자 생성

AWS 리소스에 Github Actions 워크플로우를 통해 접근하려면 적절한 권한을 가진 IAM 사용자가 필요하다.

IAM 사용자 생성 절차 시작

  • 작업 순서
    1. AWS IAM 대시보드에 접속한다.
    2. '사용자' 섹션에서 '사용자 추가' 버튼을 클릭한다.

IAM 사용자 이름

  • 사용자의 이름을 지정한다.

필요한 권한 부여

  • '권한 설정'에서 워크플로우가 필요로 하는 권한을 지정한다. 이 경우, CodeDeploy 실행 권한과 S3 접근 권한이 필요하므로, AWSCodeDeployFullAccessAmazonS3FullAccess를 추가한다.


IAM 사용자 생성 완료

  • 태그 설정은 생략하고, 모든 설정 사항을 다시 한번 검토한 후 '사용자 생성'을 클릭하여 프로세스를 완료한다.

생성된 액세스 키 생성 및 확인

  • 사용자 생성 후, 액세스 키를 생성하고 제공되는 '액세스 키 ID'와 '비밀 액세스 키'를 복사하거나 기록한다. 이 키는 Github Actions 설정에 필요하다.
  • CI/CD설정을 위해 액세스 키는 서드 파티 서비스라 생성한다.

Github Secrets에 액세스 키 등록

  • Github Repository의 'Settings' 메뉴에서 'Secrets' 섹션으로 이동한다.
  • 복사한 '액세스 키 ID'와 '비밀 액세스 키'를 Github Secrets에 등록한다.
  • 키의 이름은 사용자의 편의에 따라 지정한다. 등록한 Secrets 값은 보안상의 이유로 직접 확인할 수 없으므로 별도로 안전한 곳에 저장하는 것이 좋다.

AppSpec 파일 구성

CodeDeploy 배포를 위한 핵심 파일인 AppSpec 파일을 작성한다.
이 파일은 AWS CodeDeploy가 애플리케이션을 EC2 인스턴스에 배포하는 방법을 지시한다.

# AppSpec 파일의 버전을 정의한다.
version: 0.0

# 배포 대상 운영 체제를 정의한다.
os: linux

# 배포 파일과 대상 디렉터리를 지정한다.
files:
  # 원본 파일 또는 디렉터리의 경로를 정의한다.
  - source:  /
    # 대상 인스턴스에서 해당 파일/디렉터리의 위치를 지정한다.
    destination: /home/ubuntu/app
    # 기존의 파일 또는 디렉터리가 존재하는 경우에 대체 여부를 지정한다.
    overwrite: yes

# 배포된 파일 또는 디렉터리의 권한을 설정한다.
permissions:
  # 권한 변경 대상 파일 또는 디렉터리를 정의한다.
  - object: /
    # 권한 적용 대상 패턴을 지정한다.
    pattern: "**"
    # 파일 또는 디렉터리의 소유자를 정의한다.
    owner: ubuntu
    # 파일 또는 디렉터리의 그룹을 정의한다.
    group: ubuntu

# 배포 프로세스 도중 실행될 스크립트를 정의한다.
hooks:
  # AfterInstall 이벤트 시 실행될 스크립트를 지정한다.
  AfterInstall:
    - location: scripts/stop.sh  # 스크립트의 경로를 지정한다.
      timeout: 60  # 허용되는 최대 실행 시간을 초로 지정한다.
      runas: ubuntu  # 스크립트 실행 사용자를 지정한다.

  # ApplicationStart 이벤트 시 실행될 스크립트를 지정한다.
  ApplicationStart:
    - location: scripts/start.sh  # 스크립트의 경로를 지정한다.
      timeout: 60  # 허용되는 최대 실행 시간을 초로 지정한다.
      runas: ubuntu  # 스크립트 실행 사용자를 지정한다.


배포 스크립트 정의


AppSpec Hooks에 명시된 stop.sh 및 start.sh 스크립트를 구현한다.

stop.sh

해당 스크립트는 현재 구동 중인 애플리케이션의 PID를 확인하고, 실행 중인 프로세스가 있다면 종료한다.

#!/usr/bin/env bash

PROJECT_ROOT="/home/ubuntu/app"
JAR_FILE="$PROJECT_ROOT/spring-server.jar"
CURRENT_PID=$(pgrep -f $JAR_FILE)

if [ -n "$CURRENT_PID" ]; then
    echo "$(date +%c) > app stop" >> $DEPLOY_LOG
    kill -15 $CURRENT_PID
fi

start.sh

이 스크립트는 애플리케이션을 실행한다. JAR 파일을 복사하고 해당 JAR 파일을 실행한다.

#!/usr/bin/env bash

PROJECT_ROOT="/home/ubuntu/app"
JAR_FILE="$PROJECT_ROOT/spring-server.jar"

cp $PROJECT_ROOT/build/libs/*.jar $JAR_FILE

# jar 파일 실행
nohup java -jar $JAR_FILE &

build.gradle 수정

Spring Boot 2.5 버전 이후로 빌드 시 기본 JAR 파일과 함께 -plain.jar 파일도 생성된다.
이를 방지하기 위해 build.gradle 파일에 수정이 필요하다.

build.gradle 파일에 다음을 추가한다.

jar {
    enabled = false
}

Github Actions 워크 플로우 정의


Github Actions 워크 플로우를 설정한다.

test.yml 파일 작성

name: Java CI with Gradle

on:
  push:
    branches: [ "deployTest"]
env:
  AWS_REGION: ap-northeast-2
  S3_BUCKET_NAME: team258-bucket
  CODE_DEPLOY_APPLICATION_NAME: team258-codedeploy-app
  CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: team258-codedeploy-deployment-group
  
permissions:
  contents: read

jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    environment: production

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Check current working directory
        run: pwd

      - name: List directory contents
        run: ls -al

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

      # properties 파일 수정
      - name: Update properties file
        run: |
          sed -i "s/spring.datasource.password=.*/spring.datasource.password=${{ secrets.DB_PASSWORD }}/" src/main/resources/application.properties
          
      - name: Grant execute permission for gradlew
        run: chmod +x gradlew

      - name: Build with Gradle
        uses: gradle/gradle-build-action@v2.6.0
        with:
          arguments: build

      - 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: ${{ env.AWS_REGION }}

      - name: Upload to AWS S3
        run: |
          aws deploy push \
            --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
            --ignore-hidden-files \
            --s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \
            --source .

      - name: Deploy to AWS EC2 from S3
        run: |
          aws deploy create-deployment \
            --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
            --deployment-config-name CodeDeployDefault.AllAtOnce \
            --deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \
            --s3-location bucket=$S3_BUCKET_NAME,key=$GITHUB_SHA.zip,bundleType=zip


실제 배포 확인

Github에 deployTest라는 브랜치를 임시로 만들고 push해서 배포 확인

CodeDeploy에서 배포 확인

PostMan으로 최종 동작 확인


profile
backend_Devloper

0개의 댓글