Github Actions + S3 + CodeDeploy + Nginx 무중단 배포(1)

ran·2023년 7월 12일

CI/CD

목록 보기
1/3
post-thumbnail

요즘 날씨가 너무 덥다... 그래서 유독 연구실에서 시간을 많이 보내는것 같다.
현재 프로젝트를 3개 진행중인데, 해당 프로젝트에서 무중단 배포를 진행해보고 싶어서 기술 경험하고, 정리해보기 위헤 해당 글을 작성한다.

우선 나는 아래의 블로그를 보고 무중단 배포를 경험했다.
Github Actions + CodeDeploy + Nginx 로 무중단 배포하기 (1)
해당 글이 2020년이라 현재는 안맞는 명령어 등등이 있어서 내 입맛에 맞게 세세하게 정리해보려고 한다.


시스템 아키텍쳐


해당 그림은 내가 현재 진행하는 프로젝트에서 사용하려는 시스템 아키텍쳐중 일부이다.

  1. 인텔리제이에서 깃허브 메인브랜치로 push를 진행한다.
  2. github actions에서 메인브랜치의 push를 감지하고, yml 파일을 읽고 실행한다.(프로젝트 빌드 후 S3에 업로드)
  3. CodeDeploy에게 S3에 있는 jar을 가지고 배포를 하라고 CodeDeployAgent에게 명령한다.
  4. CodeDeploy Agent는 jar 파일을 S3에서 받아 스크립트를 읽고 배포를 진행한다.
  5. 그러면 기존의 Spring Boot WAS말고 새로운 WAS를 띄우고, Nginx 스위칭을 통해 무중단 배포가 되도록, Agent에게 배포 스크립트를 제공한다.

테스트 프로젝트

이제 프로젝트를 생성해보겠다.

프로젝트 구성

  • Spring Boot:2.7.13
  • dependencies: web
  • Java: 11

간단하게 위의 기술 스택을 이용하고, 직접 무중단 배포를 경험하는게 의의가 있어서 최소한의 구성으로 진행하고, 코드도 간략하게 작성할것 이다.

application.yml

version: 1.0

application.yml은 원래 깃허브상에 절대 노출시키면 안된다.
나는 cicd 구축한다고 실수로 올렸는데, 아주 골치아픈일을 겪었다..


yml파일이 없으면 배포에 지장이 가지만 아래와 같이 다양한 방법으로 배포를 하는 방법이 있다.!!

  1. github secret 에 yml 담기: https://velog.io/@sun1203/Github-Action-Spring-Application.properties-%EB%AF%BC%EA%B0%90%EC%A0%95%EB%B3%B4-%EA%B4%80%EB%A6%AC%ED%95%98%EA%B8%B0
  2. submodule 사용 : https://resilient-923.tistory.com/422

자 다시 본론으로 돌아와서 위와 같이 yml을 설정하고, 간단한 컨트롤러를 만들겠다.

  • Test
package com.example.cicd_hwan;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Test {

    @Value("${version}")
    private String version;

    @GetMapping("/")
    public String version() {
        return String.format("Project Version : %s", version);
    }

    @GetMapping("/health")
    public String checkHealth() {
        return "healthy";
    }
}

yml로 부터 버전 정보를 받아와서 기본 루트로 접속시에는 버전 정보가 뜨는 api 하나와 health-check용으로 api 하나 만들었다.

위와 같이 간단하 구조로 프로젝트를 구성했다.
이제 위의 코드를 작성하고 레포지토리에 푸시해보자.


Github Actions

Github Actions란?

GitHub에서 제공하는 서비스로, 빌드, 테스트, 배포 파이프라인을 자동화할 수 있는 CI(Continuous Integration, 지속 통합)와 CD(Continuous Deployment, 지속 배포) 플랫폼이다. GitHub Actions를 사용하면 GitHub 리포지토리에서 손쉽게 CI/CD 결과를 확인하고 관리할 수 있습니다. 또한, YAML 포맷을 사용하여 가독성이 높고, 이미 구현되어 있는 수많은 액션을 활용하여 간단하게 CI/CD 플로우를 작성할 수 있습니다.(카카오 엔터프라이즈 기술블로그에서)
추가로 public repo의 경우 무료이다.

Workflow 생성

워크플로는 쉽게 말해 '작업의 흐름'으로, 특정한 목적을 위한 일련의 실행 트리거, 환경, 기능들을 모두 포함한다. 워크플로는 코드 저장소 내의 github/workflows 폴더 아래에 YAML 파일로 작성하면 된다.

  1. 저장소의 Actions에서 set up a workflow yourself 로 새 작업 시작.

  2. yml 파일 작성.

    여기서 Github actions의 장점이 나온다. yml파일을 작성하기 위해 오른쪽의 MarketPlace 와 Document를 활용할 수 있다.

그럼 이제 yml 스크립트를 작성하겠다.

# main.yml

name: cicd_hwan

on:
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest

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

      - name: Setup Java JDK 11
        uses: actions/setup-java@v1
        with:
          java-version: 11

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew
        shell: bash

      - name: Build with Gradle
        run: ./gradlew build
        shell: bash

스트립트 설명을 하겠다.

  • name
    • workflow 의 이름을 지정한다.
  • on
    • 해당 workflow 가 언제 실행될건지 트리거를 지정할 수 있다.
    • 특정 브랜치가 push 되는 경우, Pull Request 가 생성될 경우, 또는 crontab 문법으로 스케줄링을 걸 수도 있다.
    • 현재는 main 브랜치에 push 되는 경우 트리거를 발생시켜서 workflow가 동작한다.
    • push 등으로 자동 배포가 위험한 경우 on:workflow_dispatch: 구조로 수동 배포도 가능하다.
  • job, steps
    • workflow 는 하나 혹은 그 이상의 job 을 가질 수 있고 각 job 은 여러 step 에 따라 단계를 나눌 수 있다.
  • runs-on
    • 해당 workflow 를 어떤 OS 환경에서 실행할 것인지 지정할 수 있다.
    • 저는 amazon linux를 사용할 것이므로 ubuntu로 설정했습니다.
  • uses: actions/checkout@v2 : GitHub Actions에서 제공하는 actions/checkout 액션을 사용하여 Git 리포지토리를 체크아웃하는 코드이다. Git 리포지토리를 클론하고 체크아웃하여 워크플로우에서 리포지토리의 소스 코드에 액세스할 수 있게 해준다. 쉽게 말해 그냥 클론 하는거라고 이해하면 될것같다.
  • uses: actions/setup-java@v1 : 자바 버전을 설정한다.
  • gradlew: 빌드하기 위해 gradlew에게 권한을 준다.
  • Build: 명령어로 빌드한다.

해당 스크립트를 푸시하고 action을 들어가면,

이처럼 자동으로 action이 실행되고, 완료된다.

참고로 간혹가다. Context error가 발생하는데, test 코드에서 발생하는 경우가 종종 있다.
이때는 스크립트의 Build 부분을

  • name: Build with Gradle
    run: ./gradlew clean build -x test # 테스트 제외하지 않으면 오류남
    shell: bash
    위와 같이 작성하면 에러가 해결된다.

S3에 빌드한 jar 업로드

S3 버킷 생성

AWS S3에 접속해서 버킷 만들기를 누른다.

버킷 이름을 입력하고, 별다은 옵션을 건들지 않고 넘어간다.

퍼블릭 엑세스 차단의 경우 꼭 차단 시켜야한다, 그러면 외부에서 접근을 못하다고 생각할 수 있지만, IAM에게 권한을 부여해서 접근하기 때문에 괜찮다.


이제 버킷이 생성됐다.

IAM 권한 사용자 생성

IAM에 접속하여 사용자를 추가한다.

예전 aws의 경우 해당 페이지에서 엑세스 키까지 발급이 가능하지만, 지금은 불가능하기 때문에 아래와 같이 설정하자.

그 후에 부여할 권한 정책을 선택한다.
기존정책 직접연결- AmazonS3FullAccessAWSCodeDeployFullAccess를 추가한다.

그 후에 aws console을 iam으로 접근할 수 있는 csv파일을 다운해준다.

이제 나와서 엑세스키를 발급받는다.
생성한 IAM 사용자에 들어가서 보안 자격 증명 탭의 엑세스 키 부분에서 엑세스 키 만들기를 눌러준다.

생성된 엑세스키 csv 파일을 저장해준다.

S3에 jar 파일 업로드하기

위에서 만든 S3에 IAM 신분으로 build한 jar을 업로드한다.
업로드시 zip 으로 압축해야하므로 내용을 추가했다.

# main.yml

name: cicd_hwan

on:
  push:
    branches: [ main ]

env: # 새로 추가한 부분
  S3_BUCKET_NAME: cicd-hwan
  PROJECT_NAME: cicd-hwan

jobs:
  build:
    runs-on: ubuntu-latest

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

      - name: Setup Java JDK 11
        uses: actions/setup-java@v1
        with:
          java-version: 11

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew
        shell: bash

      - name: Build with Gradle
        run: ./gradlew build
        shell: bash

      ### 새로 추가한 부분 ###
      - name: Make zip file
        run: zip -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: ${{ secrets.AWS_REGION }}

      - name: Upload to S3
        run: aws s3 cp --region ap-northeast-2 ./$GITHUB_SHA.zip s3://$S3_BUCKET_NAME/$PROJECT_NAME/$GITHUB_SHA.zip
  • env
    • 현재 스크립트에서 사용할 환경변수를 정의하여 사용한다.
  • $GITHUB_SHA
    • Github Actions 에서 제공하는 여러 기본 환경변수 중 하나로, 현재 workflow 를 실행시키는 커밋의 해쉬값이다.
  • ${{ secrets.KEY_이름 }}
    • secrets 는 저장소에 등록한 비밀 키값을 가져오는 키워드이다.
  • aws s3 cp
    • aws cli 명령어 중 하나이다. copy 명령어로 현재 위치의 파일을 S3로 업로드하거나, 반대로 S3의 파일을 현재 위치로 다운로드할 수 있다.

이제 Github Setting 에서 key Secrets를 설정하겠다.

위와 같이 설정하고, 위에서 짠 yml 스크립트를 push 해보고 S3를 확인해보겠다.

위와 같이 알맞게 폴더 구조로 저장된것을 확인할 수 있다.

다음편에 CodeDeploy에 대해 작성해보겠다.

profile
Backend Developer

0개의 댓글