Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

forest_moon

Git actions+CodeDeploy(CICD) 설정하기 본문

카테고리 없음

Git actions+CodeDeploy(CICD) 설정하기

rokga 2022. 9. 22. 15:48

git action + CodeDeploy에 대한 기본적인 플로우나 개념에 대해서는 더 정리 잘 해 주신분들이 많아

많은 설명은 하지 않고 필요한 간단한 설명, 설정하는 방법에 대해서만 정리하는 글입니다.

Github Actions란?

Github Actions는 Github 저장소를 기반으로 Github에서 제공하는 Workflow 자동화 도구 입니다.

Workflow는 Github 저장소에서 발생하는 build, test, release, deploy 등 다양한 이벤트를 기반으로 직접 원하는 Workflow를 만들 수 있습니다.

 

혹시나 더 궁금하신 분들은 위해 아래를 링크를 통해 공식문서를 확인 할 수 있습니다.

https://docs.github.com/en

 

GitHub Action 의 주요 개념

1 . Workflow

  • Workflow는 프로젝트를 빌드, 테스트, 패키지, 릴리스 또는 배포하기 위한 전체적인 프로세스이다.
  • Workflow는 여러개의 Job으로 구성되어 event기반으로 동작한다.
  • 여러 Job으로 구성되며 최상위 개념이다.
  • 나만의 동작을 정의한 Workflow file을 만들어 전달하면 Github Actiond이 실행한다.
  • Workflow 파일은 YAML으로 작성되고, Github Repository의 .github/workflows 폴더 아래에 저장됨

2 . Event

  • Workflow를 Trigger(실행)하는 특정 활동이나 규칙
  • 예를 들어 다음과 같은 상황을 사용할 수 있다.
    • 특정 브랜치로 Push
    • 특정 브랜치로 Pull Request
    • 특정 시간대에 반복(Cron)
    • Webhook을 사용해 외부 이벤트를 통해 실행

3.  Job

  • Job은 여러 Step으로 구성되고, 가상 환경의 인스턴스에서 실행된다.
  • 다른 Job에 의존 관계를 가질 수 있고, 독립적으로 병렬 실행도 가능하다.

4 . Step

  • Step은 순차적으로 명령어를 수행한다.
  • Task들의 집합으로, 커맨드를 날리거나 action을 실행할 수 있다.

5 . Action

  • Workflow의 가장 작은 블럭
  • Job을 만들기 위해 Step들을 연결할 수 있다.
  • 재사용이 가능한 컴포넌트
  • 개인적으로 만든 Action을 사용할 수도 있고, Marketplace에 있는 공용 Action을 사용할 수도 있음

6 . Runner

  • Gitbub Action Runner 어플리케이션이 설치된 머신으로, Workflow가 실행될 인스턴스
  • Github에서 호스팅해주는 Github-hosted runner와 직접 호스팅하는 Self-hosted runner로 나뉨
  • Github-hosted runner는 Azure의 Standard_DS2_v2로 vCPU 2, 메모리 7GB, 임시 스토리지 14GB

 

프로젝트 진행 간 Github Actions을 사용한 이유 ?

 

도입이유 - 자동배포를 이용하여 수정사항에 대해서 빠르게 반영하고 업무적 효율을 개선하기 위해 반영

문제상황 - 협업 간 error 사항 발생 시 즉각적인 수정을 통해서 반영해서 정상화를 해야하는데 

build fileZilla 이용하여 배포 하는데에 사소하지만 시간이 많이 소요됨.

해결방안 - 1.Git actions 도입

                 2.Jenkins 도입

의견조율 - 1. Jenkins를 사용하기 위해서는 추가적으로 서버를 설치하는 불편함.

                 2.Git actions 별다른 환경설정 세팅 없이 사용하는 git에서 사용 가능해서 편리함.

의견결정 -Jenkins 비교하여 Github Actions 별도의 server 필요없고 설정이 간편하여 적용하기에 용이해 사용

 

Github Action 적용하기 !

깃허브 액션 생성

프로젝트를 깃허브 레포지토리에 연동한 후

actions 에서  java with Gradle 을 눌러서 .yml 파일을 생성

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle

name: Java CI with Gradle

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

permissions:
  contents: read

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Set up JDK 11
      uses: actions/setup-java@v3
      with:
        java-version: '11'
        distribution: 'temurin'
    - name: Build with Gradle
      uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
      with:
        arguments: build

이게  기본으로 생성된 .Github/ workflows  / yml 파일

 

1. EC2 설정 (Ubuntu 18.04)

우선 터미널에서 EC2 서버로  접속 해서 아래 명령어들을 통해서 설치 해 준다.   

( 자바 버전의 경우 프로젝트에 맞는 버전을 설치 하면 된다)

# 자바 설치
sudo apt install openjdk-11-jdk
java -version

# codeDeploy 설치
sudo apt update
# Ubuntu 18.04 제외한 OS
sudo apt install ruby
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

# codeDeploy 확인
sudo service codedeploy-agent status
# 멈추면
sudo service codedeploy-agent start

 

2.1  IAM 사용자 생성

 

사용자 이름을 입력하고 기존정책 직접 연결에서 검색을 통해 위 3가지

AmazonEC2FullAccess

AmazonS3FullAccess

AWSCodeDeployFullAccess

 

3가지 정책을 추가 후 다음.   >>. 태그 추가(선택 사항) 은 그냥 패스!   >>  사용자 만들기를 하면

 

이런식으로 엑세스 키가 생성된다 ,    csv 다운로드해서 따로 보관하는 것을 추천.

 

다시 깃허브 레포지토리  settings  >> secrets >> actions  에서 New secret를 눌러서 위 사용자 키를 각각 추가 해준다. 

 

 

3. S3 생성

aws에서  s3 버킷을 생성     

 

IAM에서 만든 사용자로 S3 FullAccess를 얻을 수 있기 때문에  보안을 위해 모든 퍼블릭 액세스를 차단한 후 생성

그 후 main.yml을 수정

name: myProject

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

env:
  S3_BUCKET_NAME: S3 버 킷 네 임 넣 기

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    
    - name: Set up JDK 11
      uses: actions/setup-java@v2
      with:
        java-version: '11'
        distribution: 'temurin'
        
    - name: Grant execute permission for gradlew
      run: chmod +x gradlew
    
    - name: Build with Gradle
      run: ./gradlew clean build
      
    # 디렉토리 생성
    - name: Make Directory
      run: mkdir -p deploy
        
    # Jar 파일 복사
    - name: Copy Jar
      run: cp ./build/libs/*.jar ./deploy

    - name: Make zip file
      run: zip -r ./coinTalk.zip ./deploy
      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

    - name: Upload to S3
      run: aws s3 cp --region ap-northeast-2 ./myProject.zip s3://$S3_BUCKET_NAME/

 

파일을 압축하고, s3에 업로드 하는 내용을 추가 및 커밋 약 1~2분 정도 기다리면 S3에 zip 파일이 잘 올라간 것을 확인 할 수 있다.

 

4. IAM 역할 생성

1) EC2용 역할

권한 정책에서 아래 2가지를 검색해 체크해서 추가

 

AmazonS3FullAccess

AWSCodeDeployFullAccess

역할 이름을 추가해서 나중에 IAM 역할을 받을때 구분 가능 하게 해준다.

 

 

2) Codedeploy 애플리케이션 그룹용 역할

CodeDeployRole 역할을 추가해 준다.

 

5. EC2에 역할 추가

인스턴스에서 오른쪽 버튼 클릭 후 보안 - IAM 역할 수정 만들어둔 ec2용 역할을 선택한 후 저장

 

 

이후 인스턴스 재부팅을 해준다.

 

6. CodeDeploy

CodeDeploy - 애플리케이션 - 애플리케이션 생성

 

 

애플리케이션은 그냥 생성하면 끝 

 

이후에 배포 그룹을 생성 해준다.  

 

 

 

IAM에서 생성한 CodeDeploy 역할을 추가 하고, 배포할 EC2 인스턴스를 설정 해주면 끝.

 

7. 자동 배포를 위한 스크립트 추가

제가 만든 레포지토리의 스크립트 위치들은 위 사진 과 같습니다. (위치를 변경 하고싶다면 main.yml에서 경로를 수정 하면 된다)

1) 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:
  ApplicationStart:
    # location은 프로젝트의 root 경로를 기준
#     - location: deploy.sh
#       timeout: 180
#       runas: root
    - location: scripts/run_new_was.sh
      timeout: 180
      runas: ec2-user
    - location: scripts/health_check.sh
      timeout: 180
      runas: ec2-user
    - location: scripts/switch.sh
      timeout: 180
      runas: ec2-user

2) deploy.sh        (scripts/deploy.sh)

#!/usr/bin/env bash

REPOSITORY=/home/ubuntu/app

echo "> 현재 구동 중인 애플리케이션 pid 확인"

JAR_NAME=$(ls -tr $REPOSITORY/*SNAPSHOT.jar | tail -n 1)

CURRENT_PID=$(pgrep -f $JAR_NAME)
echo "현재 구동 중인 애플리케이션 pid: $CURRENT_PID"

if [ -z "$CURRENT_PID" ]; then
  echo "현재 구동 중인 애플리케이션이 없으므로 종료하지 않습니다."
else
  echo "> kill -15 $CURRENT_PID"
  kill -15 $CURRENT_PID
  sleep 5
fi

echo "> 새 애플리케이션 배포"

JAR_NAME=$(ls -tr $REPOSITORY/*SNAPSHOT.jar | tail -n 1)

echo "> JAR NAME: $JAR_NAME"

echo "> $JAR_NAME 에 실행권한 추가"

chmod +x $JAR_NAME

echo "> $JAR_NAME 실행"
#-Duser.timezone=Asia/Seoul
nohup java -jar  $JAR_NAME >> $REPOSITORY/nohup.out 2>&1 &

3) main.yml 수정 (application.properties 추가)

name: asdf CI/CD

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
   
env:
  S3_BUCKET_NAME: 버킷

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    
    - name: Set up JDK 11
      uses: actions/setup-java@v3
      with:
        java-version: '11'
        distribution: 'temurin'  
        
    # gradle caching
    - name: Gradle Caching
      uses: actions/cache@v3
      with:
        path: |
          ~/.gradle/caches
          ~/.gradle/wrapper
        key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
        restore-keys: |
          ${{ runner.os }}-gradle-
          
    application.properties 파일 생성
    - name: make application.properties
      run: |
        cd ./src/main/resources
        touch ./application.properties
        echo "${{ secrets.PROPERTIES }}" > ./application.properties
      shell: bash

     #gradlew 파일 실행권한 설정   
    - name: Grant execute permission for gradlew
      run: chmod +x gradlew
      
    #빌드 시작
    - name: Build with Gradle
      run: ./gradlew build -x test  
      
    # 디렉토리 생성
    - name: Make Directory
      run: mkdir -p deploy
        
    # Jar 파일 복사
    - name: Copy Jar
      run: cp ./build/libs/*.jar ./deploy
      

    - name: Make zip file
      run: zip -r ./asdf.zip ./deploy
      shell: bash
          
    # appspec.yml 파일 복사
    - name: Copy appspec.yml
      run: cp appspec.yml ./deploy


    # script files 복사
    - name: Copy script
      run: cp ./scripts/*.sh ./deploy

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.IAMACCESSKEY }}
        aws-secret-access-key: ${{ secrets.IAMSECRETKEY }}
        aws-region: ap-northeast-2

    - name: Upload to S3
      run: aws s3 cp --region ap-northeast-2 ./asdf.zip s3://$S3_BUCKET_NAME/
      
    # Deploy
    - name: Deploy
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.IAMACCESSKEY }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.IAMSECRETKEY }}
      run: 
        aws deploy create-deployment 
        --application-name 어플리케이션
        --deployment-group-name 배포그룹
        --file-exists-behavior OVERWRITE 
        --s3-location bucket=버킷이름 ,bundleType=zip,key=asdf.zip
        --region ap-northeast-2
        --ignore-application-stop-failures

 

스크립트 추가 후 밑에 main.yml 에 있는 내용 및 asdf 까지 수정 하고 나서 main 에 pull , PR 을 하게 되면 자동으로 

빌드가 실행 되고 시간이 조금지나면 자동 배포가 되는 것을 확인 하실 수 있을 겁니다.. !?

 

 

 

문제가 있거나 잘못된 부분이 있다면 찝어주시면 감사하겠습니다 !