본문 바로가기
Backend boot camp/Session4

[Cloud] 배포 자동화

by orioncsy 2022. 12. 9.

Automated Deployment

배포 자동화

  • 손쉽게 전체 배포 과정을 자동으로 진행하는 것
  • 수동적이고 반복적인 배포 과정을 자동화하여 시간 절약
  • 휴먼 에러를 방지

배포 자동화 파이프라인

  1. source stage
    • 원격 저장소에 관리되고 있는 소스 코드에 변경 사항이 일어날 경우 이를 감지하고 다음 단계로 전달
  2. Build stage
    • source stage에서 전달받은 코드를 컴파일, 빌드, 테스트하여 가공하고 생성물을 다음 단계 전달
  3. Deploy stage
    • 전달받은 결과물을 실제 서비스에 반영

AWS 개발자 도구

  • 배포 자동화 파이프라인 구축 가능

CodeCommit

  • source stage에서 CodeCommit 서비스를 사용
  • github와 유사한 버전 관리 도구
  • 보안과 관련 기능 강점을 가지고 있으나 과금이 존재

CodeBuild

  • Build stage에서 CodeBuild를 사용
  • 유닛 테스트, 컴파일, 빌드 같은 단계에서 실행

CodeDeploy

  • Deploy stage에서 사용
  • 실시간으로 변경 사항을 전달 가능
  • S3 버킷을 통해 업로드된 정적 웹 사이트 변경 사항을 실시간으로 전달 및 반영 가능

CodePipeline

  • 각 단계를 연결하는 파이프라인을 구축할 때 사용

AWS Pipeline을 통한 배포 자동화

개발 환경 구축

JAVA 설치

  • EC2 인스턴스에서 JAVA 설치
  • sudo apt update
  • sudo apt install openjdk-11-jre-headless

AWS CLI 설치

CodeDeploy Agent 설치

EC2 인스턴스 역할 부여 튜토리얼

  • EC 대시보드에서 인스턴스로 이동
  • 인스턴스 선택 후 태그 탭 접속
    • 태그는 key-value 값으로 cohort 태그와 개인 소유 리소스를 식별하기 위한 name 태그 존재
  • 인스턴스의 보안 → IAM 역할을 확인
    • 역할을 클릭하면 역할에 연결되어있는 권한과 역할 등 다양한 정보 확인 가능
    • 권한 추가 → 정책 연결하여 검색창을 통해 AmazonS3FullAccess, AmazonEC2RoleforAWSCodeDeploy, AWSCodeDeployRole, AmazonSSMFullAccess를 선택 후 정책 연결
  • 권한 정책 항목에 권한 확인
  • 신뢰 관계 항목에서 편집

EC2를 활용한 파이프라인 구축

AWS CodeDeploy

  • 로컬 환경에서 적용할 실습 파일에 appspec.yml 파일 추가하고 내용을 추가
version: 0.0
os: linux

files:
  - source: /
    destination: /home/ubuntu/build

hooks:
  BeforeInstall:
    - location: server_clear.sh
      timeout: 3000
      runas: root
  AfterInstall:
    - location: initialize.sh
      timeout: 3000
      runas: root
  ApplicationStart:
    - location: server_start.sh
      timeout: 3000
      runas: root
  ApplicationStop:
    - location: server_stop.sh
      timeout: 3000
      runas: root
  • CodeDeploy-agent가 인식하는 파일
  • buildspec.yml 파일 추가하고 내용 추가
    • CodeBulid-Agent가 인식하는 파일
    version: 0.2
    
    phases:
      install:
        runtime-versions:
          java: corretto11
      build:
        commands:
          - echo Build Starting on `date`
          - cd DeployServer
          - chmod +x ./gradlew
          - ./gradlew build
      post_build:
        commands:
          - echo $(basename ./DeployServer/build/libs/*.jar)
    artifacts:
      files:
        - DeployServer/build/libs/*.jar
        - DeployServer/scripts/**
        - DeployServer/appspec.yml
      discard-paths: yes
    
  • 최상위에 scripts 디렉터리를 생성한 뒤 initialize.sh, server_clear.sh, server_start.sh, server_stop.sh 파일 4개 생성
    #!/usr/bin/env bash
    chmod +x /home/ubuntu/build/**
    
    • server_clear.sh(build 디렉터리 제거)
    #!/usr/bin/env bash
    rm -rf /home/ubuntu/build
    
    • server_start.sh(빌드 결과물 실행)
    #!/usr/bin/env bash
    cd /home/ubuntu/build
    sudo nohup java -jar {빌드된 파일} > /dev/null 2> /dev/null < /dev/null &
    
    • server_stop.sh(실행 중인 Spring Boot 프로젝트 종료)
    #!/usr/bin/env bash
    sudo pkill -f 'java -jar'
    
  • 변경 사항을 저장하고 commit 후 main으로 push
  • AWS CodeDeploy 대시보드로 이동 후 애플리케이션 탭으로 이동
    • 애플리케이션 생성 버튼을 클릭
    • 애플리케이션 이름을 작성하고 컴퓨팅 플랫폼은 EC2/온프레미스 선택 후 생성
  • 생성 후 배포 그룹 탭을 선택해서 배포 그룹 생성 클릭
  • 배포 그룹의 이름을 지정하여 입력하고 서비스 역할 영역을 클릭하면 연결할 수 있는 IAM 역할 목록 중 본인 소유의 EC2 인스턴스에 연결되어 있는 IAM 역할 선택
  • 환경 구성에 Amazon EC2 인스턴스 선택 후 태그 그룹에 name 태그 키와 값을 선택
  • 로드 밸런싱 활성화를 체크 해제 후 배포 그룹 생성 버튼 클릭

AWS CodePipeline

  • AWS CodePipeline 대시보드로 이동 후 파이프라인 생성 클릭
  • 파이프라인 이름 작성
  • github(버전2)로 소스 스테이지 공급자로 선택
    • github에 연결 버튼 클릭 후 연결을 누른다.
    • 새 앱 설치를 클릭 후 자신 github 계정을 선택 후 only select repositories를 통해 해당 repository 선택하고 install 누른 후 연결 완료
  • 레퍼지토리 이름은 이전에 선택한 파이프라인 이름값으로 설정하고 브랜치 이름은 main, 출력 아티팩트 형식은 codePipeline 기본값으로 지정 후 다음
  • 빌드 공급자를 AWS CodeBuild를 클릭 후 프로젝트 생성 클릭
    • 프로젝트 이름을 설정
    • 환경에서 운영체제는 Amazon Linux2, 런타임 standard, 이미지는 aws/codebuild/amazonlinux2-x86_64-standart:3.0 선택
    • buildspec 이름에 DeployServer/buildspec.yml 입력
    • codepipeline으로 계속 클릭
  • 다음으로 넘어가 배포 스테이지에서 배포 공급자는 AWS CodeDeploy 선택
  • 애플리케이션 이름과 배포 그룹 설정
  • 설정 내용 확인 후 파이프라인 생성 버튼 클릭
  • 파이프라인 생성과 동시에 소스 코드 배포 자동 실행
  • 구축한 파이프라인 중 deploy 스테이지에서 실패가 발생하는 경우
    • EC2 인스턴스에 cd /opt/codedeploy-agent/deployment-root/deployment-logs 명령어 입력
    • codedeploy-agent-deployments.log를 vi나 nano를 통해 확인
    • tail,head, grep 명령어로 확인 가능하고 프로세스 실행 중인지 확인하려면 sudo lsof -i :(실행한 포트번호) 명령어로 확인 가능
  • EC2 IP주소와 8080포트를 통해 접속 확인

환경 변수 설정

서버 환경 변수 설정

환경 변수 생성 후 EC2에 전달

  • AWS Parameter Store 서비스를 이용하여 EC2 인스턴스에 환경 변수 전달 가능
  • Parameter Store 대시보드 이동 후 파라미터 생성
  • spring.datasource.url, spring.datasource.username, spring.datasource.password 파라미터 값을 각각 생성
    • 이름은 /prefix/name/key 형식을 갖추어야 한다. (예시 /spring-boot-aws/be-0-NAME/key)
  • build.gradle에 dependencies에 implementation 'org.springframework.cloud:spring-cloud-starter-aws-parameter-store-config' 추가
  • build.gradle에 아래 항목 추가
  • dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-starter-parent:Hoxton.SR12" } }
  • src/main/resources/bootstrap.yml 파일을 생성 후 아래 작성
  • aws: paramstore: enabled: true prefix: /spring-boot-aws name: [리소스 이름] profileSeparator: _
  • src/main/resources/application.properties 파일에서 파라미터로 전달하는 변수 값은 #으로 주석 처리한다.
  • 수정 사항을 commit 하고 main으로 push하여 파이프라인을 통해 변경 사항 전달

Github Actions를 통한 배포 자동화

사전 준비

프로젝트 준비

  • spring boot 프로젝트를 spring web 의존 모듈만 선택해서 간단하게 생성

S3 버킷 비우기

  • 버킷 내용물을 삭제
  • 버킷 속성에 정적 웹사이트 호스팅 비활성화

이전 리소스 삭제

  • CodeBuild, CodeDeploy, CodePipeline 삭제

Github Actions를 통한 배포 Flow

Github Actions

  • Github가 공식적으로 제공하는 빌드,테스트, 배포 파이프라인을 자동화할 수 있는 CI/CD 플랫폼이다.
  • 레포지터리에서 pull request나 push 같은 이벤트를 트리거로 workflow 구성
  • .yml 파일에 의해 workflow가 구성되고 생성된 워크플로우는 .github/workflows 디렉터리에 위치
  • 비공개 레포지터리의 경우 용량과 시간제한이 있고 공개 레포지토리는 무료 사용 가능

배포 flow

  • github Actions는 설정 파일에 따라 레포지터리의 변동사항을 트리거로 동작
  • 빌드를 마친 프로젝트는 S3 버킷에 저장하고 CodeDeploy에 S3에서 EC2로 명령을 내린다.

S3

  • Github Actions를 통한 배포 자동화에서 저장소로의 기능으로 사용

Code Deploy

  • Github actions에서 배포 명령을 받아 S3에 저장되어 있는 빌드 결과물을 EC2 인스턴스로 이동
  • appspec.yml 설정 파일에 의해 쉘 스크립트 단계에 따라 동작
  • Ec2 인스턴스에 Code Deploy Agent의 설치가 필요

EC2

  • Code Deploy에 의해 빌드가 된 프로젝트를 EC2 인스턴스가 받아서 .yml 설정 파일과 .sh 쉘 스크립트에 의해 배포 결과를 로그로 저장하고 빌드 파일을 실행

리소스 설정

Github Actions 생성

  • github에서 Public Repository 생성 및 생성한 spring boot 프로젝트 업로드
  • Actions 탭 클릭 후 Java with Gradle의 configure을 접속하여 gradle 빌드가 기본 설정되어있는 추천 구성 사용 가능
  • Github Actions 워크플로를 생성하기 위해 start commit 버튼 클릭 후 commit new file 클릭
    • gradle.yml 파일이 생성됨과 동시에 워크플로에 작성되어 있는 트리거로 인해 Github Actions 실행
    • Actions 탭에서 워크플로 진행 상황 확인 가능
    • 워크플로 성공하면 초록색 체크, 실패하면 X 표시
    • 레포지토리 최근 커밋 내역과 함께 표시된다.
    • gradle is not executable 오류가 발생 시 git update-index —chmod=+x gradlew 와 git commit 후 git push origin +main을 통해 권한을 변경해야 한다.

Github Action 수정

  • Github Actions를 실행화는 과정에서 액세스 키가 필요한데 공개되면 보안 이슈가 발생하여 github secret을 이용해 액세스 키 저장 후 사용
    • github 레포지터리에서 settings → Secrets → Actions로 이동하고 new repository secret 클릭
    • Name에 변수 이름, Value에는 변수 값 저장
    • 액세스 키 ID 값과, 비밀 액세스 키 값을 저장
  • gradle.yml에 코드를 수정
name: Java CI with Gradle

on:
  push:
    branches: [ "main" ]

permissions:
  contents: read

env:
  S3_BUCKET_NAME: #S3 버킷 이름

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

    - name: Make zip file
      run: zip -r ./practice-deploy.zip .
      shell: bash

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
        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 ./practice-deploy.zip s3://$S3_BUCKET_NAME/practice-deploy.zip
  • bulid 후 프로젝트 압축하고 압축한 프로젝트를 S3로 전송하는 내용이다.
  • push하여 github Actions 동작
  • 성공한다면 S3 버킷에 압축파일 전송되었는지 확인

빌드 파일 배포 및 실행

  • CodeDeploy 설정
    • CodeDeploy로 이동 후 애플리케이션 생성
    • 애플리케이션 이름 작성하고 EC2/온프레미스로 플랫폼 선택
    • 애플리케이션 내에 배포 그룹 생성
      • 배포 그룹 이름 작성 및 서비스 역할을 선택
    • EC2 인스턴스 태그를 이용해 배포 그룹 환경 구성
      • 환경 구성에 Amazon EC2 인스턴스 선택, 키와 값에 name, 리소스 이름 작성
      • 로드 밸런서 활성화를 체크 해제
    • 최상위 디렉터리 구조에 appspec.yml 생성
    • version: 0.0 os: linux files: - source: / destination: /home/ubuntu/action overwrite: yes permissions: - object: / pattern: "**" owner: ubuntu group: ubuntu hooks: ApplicationStart: - location: scripts/deploy.sh timeout: 60 runas: ubuntu
    • Scripts 폴더를 생성하고 내부에 deploy.sh 파일 생성
    • #!/bin/bash BUILD_JAR=$(ls /home/ubuntu/action/build/libs/practice-githubAction-deploy-0.0.1-SNAPSHOT.jar) JAR_NAME=$(basename $BUILD_JAR) echo "> 현재 시간: $(date)" >> /home/ubuntu/action/deploy.log echo "> build 파일명: $JAR_NAME" >> /home/ubuntu/action/deploy.log echo "> build 파일 복사" >> /home/ubuntu/action/deploy.log DEPLOY_PATH=/home/ubuntu/action/ cp $BUILD_JAR $DEPLOY_PATH echo "> 현재 실행 중인 애플리케이션 pid 확인" >> /home/ubuntu/action/deploy.log CURRENT_PID=$(pgrep -f $JAR_NAME) if [ -z $CURRENT_PID ] then echo "> 현재 구동 중인 애플리케이션이 없으므로 종료하지 않습니다." >> /home/ubuntu/action/deploy.log else echo "> kill -9 $CURRENT_PID" >> /home/ubuntu/action/deploy.log sudo kill -9 $CURRENT_PID sleep 5 fi DEPLOY_JAR=$DEPLOY_PATH$JAR_NAME echo "> DEPLOY_JAR 배포" >> /home/ubuntu/action/deploy.log sudo nohup java -jar $DEPLOY_JAR >> /home/ubuntu/deploy.log 2>/home/ubuntu/action/deploy_err.log &
    • gradle.yml 최하단에 Code Deploy 배포 명령 추가
    • - name: Code Deploy run: > aws deploy create-deployment --application-name {애플리케이션 이름} --deployment-config-name CodeDeployDefault.AllAtOnce --deployment-group-name {배포 그룹 이름} --s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=practice-deploy.zip
    • 수정을 마치고 push하면 Github Actions 실행

배포 결과 확인

  • EC2 인스턴스를 클릭하고 퍼블릭 DNS로 접속하여 접근 가능한지 확인
    • whitelabel Error page가 정상(화면 구성을 하지 않았기 때문)
    • 응답 자체에 에러가 발생하는지 확인
  • EC2 인스턴스에서도 배포 및 프로젝트 실행 확인
    • appspec.yml과 deploy.sh에 작성한 대로 action 디렉터리 내에 빌드 파일이 이동했고 실행 중인 프로세스를 검색해 확인
      • ps -ef | grep java로 확인 가능
  • 배포 로그 확인
    • deploy.sh에는 배포 진행될 때마다 상황 기록
    • 배포를 마치면 action 디렉토리 내 deploy.log, deploy_err.log 두 개의 파일 생성
      • 빌드 과정은 deploy.log에 정상적으로 실행하지 못하면 deploy_err.log에 기록
      • cat이나 에디터로 내용 확인 가능
    • 스프링 프로젝트를 수정하고 push하여 배포 자동화가 이루어졌는지 로그를 통해 확인 가능
  •  

수동 배포와 자동 배포 workflow

수동 배포

자동 배포 - AWS Pipeline

자동배포 - Gitub Actions

'Backend boot camp > Session4' 카테고리의 다른 글

웹 애플리케이션 로컬 배포  (1) 2022.12.13
[Cloud] 운영 전략  (0) 2022.12.09
[Cloud]배포 컨테이너  (1) 2022.12.09
[Cloud] 운영 환경 구성  (1) 2022.12.09
[Spring WebFlux] Spring WebFlux  (0) 2022.12.09