jojoldu / freelec-springboot2-webservice

1.07k stars 462 forks source link

[정보] p.320 ~ 367 CodeDeploy 유료화로 변경되어 GitHubAction으로 변경해 보았습니다. #806

Open ItsWard opened 2 years ago

ItsWard commented 2 years ago

기존에 올라온 질문이 아닌지 먼저 검색해주세요!

가장 자주 나온 제보

어떤 오류인가요?

오류설명: CodeDeploy 유료화로 GitHubAction으로 무료 변경

이 문서는 이동욱님 저서 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 를 기준으로 작성하였습니다.

Travis의 유료화로 인해, 기본 요금을 사용하려면 신용카드를 등록해야 하는 번거로움과, 1달 이후 유료로 전환이 되어 새로운 방법을 찾아야 했고, 다른 프로젝트에서도 GitHub Action을 이용해 사용하기 위해 고민하다 작성합니다.

gitHub Action은 처음 사용해보고, 배워가는 단계라서 틀린 부분이 많을 수 있습니다. 해당 문서는 동작 에 핵심을 두었고, 자세한 내용은 추가로 포스팅 하여 첨부할 예정입니다.
Github Actions 는 개인 Github 코드 저장소에서 빌드 / 배포 환경을 구축할 수 있는 도구입니다.
public 저장소에서는 무료로 지원합니다.

해당 버전은 Date : 2022.07.06 JAVA 11 Spring Boot 2.4.1 Gradle 7.4 기준으로 작성하였습니다. 버전 문제로 진행되지 않을 수 있습니다.

GitHub Actions 연동하기

Page 323 ~ 324 해당 내용은 위에 서술한 바와 같이 Travis의 유료화로 진행하지 않습니다.

Page 325 ~ 327

해당하는 레파지토리에서 Actions 를 선택한 후 Publish Java Package with Gradle - Configure을 선택합니다. 위에 set up a workflow yourself를 선택해도 괜찮습니다.

new gitHub Action


선택했으면, 다음과 같이 작성합니다.

name: deploy # (0) GitHub Action에서 보여질 이름을 지정합니다. 

on:
  release:
    types: [push] # (1) push시 자동으로 실행됩니다.
  push:
    branches: [main] # (2) main 브랜치에서 동작합니다.
  workflow_dispatch: # (3) 수동으로도 실행이 가능힙니다.

jobs:
  build: 
    runs-on: ubuntu-latest # (4) 해당 스크립트를 작동할 OS 입니다.
    permissions: 
      contents: read 
      packages: write

    steps:
    - name: Checkout 
      uses: actions/checkout@v3  # (5) 프로젝트 코드를 CheckOut합니다.    

    - name: Set up JDK 11 
      uses: actions/setup-java@v3 # (6) 
      with:
        java-version: '11' 
        distribution: 'temurin' 

    - name: Grant execute permission for gradlew
      run: chmod +x ./gradlew # (7)
      shell: bash

    - name: Build with Gradle
      run: ./gradlew clean build -x test # (8)
      shell: bash

(#0) name: deploy

(#1) on: release: types: [push]

(#2) (on:) push:branches: [main]

(#1) (#2)push : main 브랜치가 푸쉬되면 해당 Action을 실행합니다.

(#3) workflow_dispatch:

(#4) jobs: build: runs-on: ubuntu-latest

(#5) uses: actions/checkout@v3

(#6) uses: actions/setup-java@v1

(#7) run: chmod +x ./gradlew

(#8)run: ./gradlew clean -x test build

파일 생성이 끝났으면, 해당 파일의 이름을 지정하고 commit 합니다.

Actions으로 이동해 Action을 확인합니다.

image

빌드를 클릭하면 자세한 정보를 확인할 수 있습니다.

image



image



당장은 해당 Action을 사용하지 않을 것 이기 때문에 사용하지 않는 Action은 바로바로 삭제합니다. 프리 요금제의 경우 1달에 2000시간을 초과하는 경우, 사용이 제한됩니다.

image



다음은 이메일 등록입니다. gitHub에서는 trigger가 될 때마다 이메일을 받을 수 있습니다. 책에 있는 내용에는 CI 실행 완료시에만 가도록 설정되어있지만, push되는 모든 알림에 메일이 오게 됩니다.

image



gitHub내에서 commit 하거나 외부에서 push하는 경우 메일로 확인 받을 수 있습니다.

GitHub Action와 AWS S3 연동하기


Page 327 ~ 332 책에 나와 있는 내용과 거의 흡사합니다. 변경된 내용이 없다고 생각하셔도 좋습니다.

간단하게 설명하면 깃허브 액션을 사용하면 다음과 같은 구조로 진행이 됩니다.

image



AWS S3는 파일 서버로, 이미지 파일 / 정적 파일 등을 관리하는 기능입니다. 실제 배포는AWS CodeDeploy에서 진행되는데, AWS CodeDeploy는 저장 기능이 없기 때문에, AWS S3와 연동하여 .jar 파일을 받아 배포할 수 있도록 진행됩니다.

AWS CodeDeploy에서도 빌드와 배포 모두 가능하지만 해당 실습에서는 AWS CodeDeploy는 배포를, 빌드는 GitHub Action에서 진행됩니다. 빌드없이 배포만 하는경우 AWS CodeDeploy 하나로 진행하는 경우 대응하기 어렵기 때문입니다.

AWS Key 발급

외부 서비스가 접근이 가능하도록 해당 권한을 가진 AWS Key를 생성하여야합니다. AWS에서는 해당 서비스를 IAM(Identity and Access Management) 에서 관리합니다.

사용자 -> 사용자 추가 버튼을 눌러 해당 서비스를 사용합니다.

image

image



사용자 이름을 지정하고 , 프로그래밍 방식 엑세스 유형을 선택합니다.

image



이후 기존 정책 직접 연결을 선택한 후 두 개의 권한을 체크하여 다음으로 넘어갑니다.

image

image



태그는 인지 가능한 이름으로 적용합니다.

image



이후, 생성 권한 설정 항목을 확인합니다.

image



굉장히 중요합니다.

엑세스 키와 비밀 엑세스 키는 개인으로 보관해야 하며, 해당 창을 넘어가면 비밀 엑세스 키는 더이상 저장할 수 없습니다. 반드시 다운로드를 받던, 메모장에 따로 보관하던 해주세요.

image



Page 333

해당 키를 GitHub Action에 등록해야 합니다.

추가사항으로 Action에서의 날짜는 실제 우리가 빌드한 날짜와 다르게 되어있습니다. 해당 내용을 yml 파일에 추가하면서, AWS 인증도 추가하도록 하겠습니다.

1. yml 작성 전 Action에서 키를 등록합니다. 우리의 GitHub는 public 이기 때문에, 해당 키를 그대로 저장할 경우 외부로 노출 됩니다.

다음과 같이 secret key를 지정하여 안전하게 보호합니다. 해당 Repository - Settings - Secrets - Actions -> New repository secret

image
총 두 개의 시크릿을 만들겁니다.

Name에는 각각 AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY

Value에는 각각 저장한 ACCESS_KEY와 SECRET_ACCESS_KEY를 입력합니다.

image

2. 저장이 완료되었다면, 해당 Repository - code의 맨 위에 github/workflows 로 이동하여 yml 파일을 다시 열어줍니다.


image

위에 언급한 추가사항인 Action에서의 날짜는 실제 우리가 빌드한 날짜와 다르게 되어있는 부분을 추가하도록 하겠습니다.


 ...code...

    - name: Build with Gradle
      run: ./gradlew clean -x test build # (8) 
      shell: bash

      # 이전에 추가했던 내용 아래에 작성하면 됩니다. 

    - name: Get current time
      uses: 1466587594/get-current-time@v2  # (9)
      id: current-time
      with:
        format: YYYY-MM-DDTHH-mm-ss 
        utcOffset: "+09:00"

    - name: Show Current Time
      run: echo "CurrentTime=${{steps.current-time.outputs.formattedTime}}" # (10)
      shell: bash

(#9) uses: 1466587594/get-current-time@v2

(#10) run: echo "CurrentTime=${{steps.current-time.outputs.formattedTime}}"

저장한 후 Actions으로 이동해 Action을 확인합니다. 이후 Action을 삭제합니다.

3. AWS S3에 저장할 수 있도록 버킷을 생성합니다.


image

image

버킷의 이름을 지정한 후 다른 설정 값은 변경하지 않고, 다음과 같이 생성합니다.

image image



4. Git Hub Action과 AWS를 연동합니다.

해당 Repository - code의 맨 위에 github/workflows 로 이동하여 yml 파일을 다시 열어줍니다.

다음과 같은 내용을 추가합니다.

# main.yml의 최상단입니다.
#새로 추가된 내용입니다. (11) 
env:  
  S3_BUCKET_NAME: ward-build 
  PROJECT_NAME: aws-web-service 

name: deploy # (0) GitHub Action에서 보여질 이름을 지정합니다. 

on:
  release:
    types: [push] # (1) push시 자동으로 실행됩니다.
  push:
    branches: [main] # (2) main 브랜치에서 동작합니다.
  workflow_dispatch: # (3) 수동으로도 실행이 가능합니다.

...code...

(#11) env

S3_BUCKET_NAME: 내가 설정한 S3 버킷 이름 PROJECT_NAME: 내 Git Hub 프로젝트 이름

으로 변경해야합니다.

또한 맨 아래에 다음과 같이 내용을 추가합니다 .

...code...

 - name: Show Current Time
      run: echo "CurrentTime=${{steps.current-time.outputs.formattedTime}}"    # (10)
      shell: bash
    # 아래부분이 추가되는 내용입니다.
    - name: Make zip file
      run: zip -r ./$PROJECT_NAME.zip .         # (12)
      shell: bash

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1      #(13)
      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 ./$PROJECT_NAME.zip s3://$S3_BUCKET_NAME/$PROJECT_NAME/$PROJECT_NAME.zip    #(14)

(#12) run: zip -r ./$PROJECT_NAME.zip .

(#13) uses: aws-actions/configure-aws-credentials@v1

(#14) run: aws s3 cp --region ap-northeast-2 ./$PROJECT_NAME.zip s3://$S3_BUCKET_NAME/$PROJECT_NAME/$PROJECT_NAME.zip

image



EC2에 IAM 역할 추가하기


AWS IAM를 검색하고, 역할 - 역할 만들기를 진행합니다.

image



image



image


정책에서 AmazonEC2RoleforAWSCodeDeploy 를 검색합니다. 권한 체크 후

image

EC2로 이동하여, 인스턴스 - 보안 - IAM 역할 수정을 진행합니다.



image

image

image



이후 재부팅을 진행합니다.

image

재부팅이 완료 되었으면, AWS CodeDeploy(배포 진행 서비스) 를 적용하여, 자동으로 배포하도록 진행합니다.

CodeDeploy 에이전트 설치

EC2에 접속하여 다음 명령어를 입력해 install 파일을 다운로드를 받습니다.

aws s3 cp s3://aws-codedeploy-ap-northeast-2/latest/install .--region ap-northeast-2

내려받기가 성공한 경우 다음과 같은 메세지가 콘솔에 출력됩니다.

install 파일에 실행 권한을 추가한 후 install 파일로 설치를 진행합니다.

  1. chmod +x ./install
  2. sudo ./install auto

설치가 끝났으면 Agent가 정상적으로 실행되는지 상태 검사를 진행합니다.

sudo service codedeploy-agent status

다음과 같이 running 메세지가 출력되면 정상입니다.

The AWS CodeDeploy agent is running as PID ~~~

CodeDeploy를 위한 권한 생성

CodeDeploy 에서 EC2에 접근하기 위해 권한 설정을 진행합니다. 한번 더 권한 생성을 위해 IAM으로 이동합니다.

image

아래의 다른 AWS 서비스의 사용 세례로 이동하여 Code Deploy를 검색합니다.

image



3가지 옵션 중 맨 위의 Code Deploy를 선택한 후 다음을 선택합니다.

image

image



따로 권한을 클릭할 것이 없습니다. 바로 다시 다음을 선택합니다.

image



역할 이름과 태그 값은 이후에 사용할 예정이므로, deploy인 것을 알아 볼 수 있도록 지정합니다.

image



CodeDeploy 생성

자동 배포의 마지막 단계입니다. 우리는 자동 배포를위해 Commit은 Git Hub으로, Buildl는 Git Hub Action을 이용했습니다. 마지막으로 배포단계는 Code Deploy를 이용해 자동으로 진행해보도록 하겠습니다.

먼저 CodeDeploy를 검색해 이동합니다.

image

이후 배포 - 애플리케이션으로 이동해 애플리케이션을 생성합니다.

image

애플리케이션 이름을 작성한 후 컴퓨팅 플랫폼은 EC2/온프레미스 를 선택합니다.

image

아래 배포 그룹 생성을 선택합니다.

image



  1. 배포 그룹 이름을 입력합니다.
  2. 서비스 역할은 직전에 만든 역할을 추가합니다.
  3. 배포방법은 현재위치로 진행합니다.
  4. 환경 구성은 Amazon EC2 인스턴스로 진행합니다(EC2를 만들었던 키/값을 이용합니다. 반드시 키와 값은 EC2 태그와 일치하여야합니다. (대소문자구분)

image

  1. 에이전트 구성은 사용하지 않습니다.
  2. 배포 설정은 CodeDeployDefault.AllAtOnce 입니다.
  3. 로드 밸런서는 비활성화합니다.

image


다시 EC2 서버에 접속하여 S3에서 넘겨받아 저장할 디렉토리를 생성합니다.

mkdir ~/app/step2 && mkdir ~/app/step2/zip

image

Git Hub Action이 Build가 끝나면 S3에 위 디렉토리로 파일이 전송되도록 진행 하도록 하겠습니다.

CodeDeploy가 전송된 해당 파일을 실행시키기 위해 appspec.yml이라는 설정 파일을 만들도록 하겠습니다.

appspec.yml는 프로젝트의 제일 상단에 위치하도록 만들어줍니다.

image

이후 아래 코드를 작성합니다.

version: 0.0
os: linux
files:
  - source: /
    destination: /home/ec2-user/app/step2/zip/ 
    overwrite: yes

source는 전달해준 파일 중 destination으로 이동시킬 대상입니다. / 인 경우 전체 파일을 지정하게 됩니다. destination는 파일을 받을 위치입니다.

또한 main.yml에도 다음과 같이 코드를 추가합니다.

# 코드의 맨 처음 부분입니다
env: 
  S3_BUCKET_NAME: ward-build
  PROJECT_NAME: aws-web-service
  CODE_DEPLOY_APP_NAME: webservice                    #(15)
  CODE_DEPLOY_GROUP_NAME: webservice-group

name: deploy # (0) GitHub Action에서 보여질 이름을 지정합니다. 

...code...

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1      #(13)
      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 ./deploy/$PROJECT_NAME.zip s3://$S3_BUCKET_NAME/$PROJECT_NAME/$PROJECT_NAME.zip  #(14)

    - name: Code Deploy
      run: aws deploy create-deployment --application-name $CODE_DEPLOY_APP_NAME --deployment-config-name CodeDeployDefault.AllAtOnce --deployment-group-name $CODE_DEPLOY_GROUP_NAME --s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=$PROJECT_NAME/$PROJECT_NAME.zip    #(16)

(15) CODE_DEPLOY_APP_NAME: webservice , CODE_DEPLOY_GROUP_NAME: webservice-group

image

image

(16) run: aws deploy create-deployment --application-name $CODE_DEPLOY_APP_NAME --deployment-config-name CodeDeployDefault.AllAtOnce --deployment-group-name $CODE_DEPLOY_GROUP_NAME --s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=$PROJECT_NAME/$PROJECT_NAME.zip


성공 전체 코드를 한번 확인하도록 하겠습니다. 

```C
env: 
  S3_BUCKET_NAME: ward-build
  PROJECT_NAME: aws-web-service
  CODE_DEPLOY_APP_NAME: webservice
  CODE_DEPLOY_GROUP_NAME: webservice-group

name: deploy # (0) GitHub Action에서 보여질 이름을 지정합니다. 

on:
  release:
    types: [push] # (1) push시 자동으로 실행됩니다.
  push:
    branches: [main] # (2) main 브랜치에서 동작합니다.
  workflow_dispatch: # (3) 수동으로도 실행이 가능합니다.

jobs:
  build: 
    runs-on: ubuntu-latest # (4) 해당 스크립트를 작동할 OS 입니다.
    permissions: 
      contents: read 
      packages: write

    steps:
    - name: Checkout 
      uses: actions/checkout@v3  # (5) 프로젝트 코드를 CheckOut합니다.    

    - name: Set up JDK 11 
      uses: actions/setup-java@v3 # (6) 
      with:
        java-version: '11' 
        distribution: 'temurin' 

    - name: Grant execute permission for gradlew
      run: chmod +x ./gradlew # (7)
      shell: bash

    - name: Build with Gradle
      run: ./gradlew clean -x test build # (8)
      shell: bash

    - name: Get current time
      uses: 1466587594/get-current-time@v2 
      id: current-time
      with:
        format: YYYY-MM-DDTHH-mm-ss # (9)
        utcOffset: "+09:00"

    - name: Show Current Time
      run: echo "CurrentTime=${{steps.current-time.outputs.formattedTime}}" # (10)
      shell: bash

    - name: Make zip file
      run: zip -r ./$PROJECT_NAME.zip .         # (12)
      shell: bash

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1      #(13)
      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 ./$PROJECT_NAME.zip s3://$S3_BUCKET_NAME/$PROJECT_NAME/$PROJECT_NAME.zip  #(14)

    - name: Code Deploy
      run: aws deploy create-deployment --application-name $CODE_DEPLOY_APP_NAME --deployment-config-name CodeDeployDefault.AllAtOnce --deployment-group-name $CODE_DEPLOY_GROUP_NAME --s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=$PROJECT_NAME/$PROJECT_NAME.zip

Action으로 가서 보면, 빌드가 성공해있고,

image

CodeDeploy로 이동하면, 배포가 성공한 것을 확인할 수 있습니다.

image

또한, putty EC2으로 이동해, 파일이 있는지 확인해 봅시다.

cd /home/ec2-user/app/step2/zip

image

연동이 모두 완료되었습니다.

배포 자동화 구성

배포 자동화 구성 전, 새로운 파일이 commit되면 이전 버전은 중단시킨 후 업데이트 된 jar을 실행하기 위해 먼저 pid commend값을 설정해야합니다.

인텔리제이 - 프로젝트 - application.properties 로 이동합니다.

application.properties에 다음 코드를 추가합니다.

# file path / 프로젝트명.pid
spring.pid.file=/home/ec2-user/app/step2/aws-web-service.pid 

aws-web-service는 제 프로젝트 명이고, 여러분들의 프로젝트명을 입력하시면 됩니다. 또한 Application Class로 이동합니다.

image

image

설정한 값을 pid commend로 사용하기 위해 main을 다음과 같이 수정합니다.

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(Application.class);
        application.addListeners(new ApplicationPidFileWriter());
        application.run(args);

    }

배포 자동화 구성

jar 파일을 실행할 수 있는 deploy.sh을 추가합니다. deploy.sh는 프로젝트의 제일 상단에 scripts 폴더를 생성한 후 내부에 생성합니다.

image




#!/bin/bash

REPOSITORY=/home/ec2-user/app/step2
PROJECT_NAME=aws-web-service #해당 위치에 properties에 작성한 프로젝트명과 동일하게 작성합니다.

echo "> Build 파일 복사"
cp $REPOSITORY/zip/*.jar $REPOSITORY/

echo "> 현재 구동 중인 애플리케이션 pid 확인"
CURRENT_PID=$(pgrep -f $PROJECT_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/*.jar | tail -n 1)

echo "> JAR_NAME: $JAR_NAME"
echo "> $JAR_NAME 에 실행권한 추가"
chmod +x $JAR_NAME

echo "> $JAR_NAME 실행"
nohup java -jar \
  -Dspring.config.location=classpath:/application.properties,/home/ec2-user/app/application-oauth.properties,/home/ec2-user/app/application-real-db.properties \
  -Dspring.profile.active=real \
  $JAR_NAME > $REPOSITORY/nohup.out 2>&1 &



또한, codedeploy가 자동으로 배포할 수 있도록 appsepec.yml에도 내용을 추가 합니다.

image


version: 0.0
os: linux
files:
  - source: /
    destination: /home/ec2-user/app/step2/zip/ 
    overwrite: yes

permissions:
  - object: /
    pattern: "**"
    owner: ec2-user
    group: ec2-user

hooks:
  ApplicationStart:
    - location: deploy.sh
      timeout: 60
      runas: ec2-user



마지막으로 main.yml에 내용을 수정하고, 추가합니다.


env: 
  S3_BUCKET_NAME: ward-build
  PROJECT_NAME: aws-web-service
  CODE_DEPLOY_APP_NAME: webservice
  CODE_DEPLOY_GROUP_NAME: webservice-group

name: deploy # (0) GitHub Action에서 보여질 이름을 지정합니다. 

on:
  release:
    types: [push] # (1) push시 자동으로 실행됩니다.
  push:
    branches: [main] # (2) main 브랜치에서 동작합니다.
  workflow_dispatch: # (3) 수동으로도 실행이 가능합니다.

jobs:
  build: 
    runs-on: ubuntu-latest # (4) 해당 스크립트를 작동할 OS 입니다.
    permissions: 
      contents: read 
      packages: write

    steps:
    - name: Checkout 
      uses: actions/checkout@v3  # (5) 프로젝트 코드를 CheckOut합니다.    

    - name: Set up JDK 11 
      uses: actions/setup-java@v3 # (6) 
      with:
        java-version: '11' 
        distribution: 'temurin' 

    - name: Grant execute permission for gradlew
      run: chmod +x ./gradlew # (7)
      shell: bash

    - name: Build with Gradle
      run: ./gradlew clean -x test build # (8)
      shell: bash

    - name: Get current time
      uses: 1466587594/get-current-time@v2 
      id: current-time
      with:
        format: YYYY-MM-DDTHH-mm-ss # (9)
        utcOffset: "+09:00"

    - name: Show Current Time
      run: echo "CurrentTime=${{steps.current-time.outputs.formattedTime}}" # (10)
      shell: bash

    - name: Generate deployment package # (final)
      run: |
        mkdir -p before-deploy
        cp scripts/*.sh before-deploy/
        cp appspec.yml before-deploy/
        cp build/libs/*.jar before-deploy/
        cd before-deploy && zip -r before-deploy *
        cd ../ && mkdir -p deploy
        mv before-deploy/before-deploy.zip deploy/$PROJECT_NAME.zip
      shell: bash

    - name: Make zip file
      run: zip -r ./$PROJECT_NAME.zip .         # (12)
      shell: bash

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1      #(13)
      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 #변경사항 있음! ./$PROJECT_NAME.zip ->  ./deploy/$PROJECT_NAME.zip 로 변경!!
      run: aws s3 cp --region ap-northeast-2 ./deploy/$PROJECT_NAME.zip s3://$S3_BUCKET_NAME/$PROJECT_NAME/$PROJECT_NAME.zip  #(14)

    - name: Code Deploy 
      run: aws deploy create-deployment --application-name $CODE_DEPLOY_APP_NAME --deployment-config-name CodeDeployDefault.AllAtOnce --deployment-group-name $CODE_DEPLOY_GROUP_NAME --s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=$PROJECT_NAME/$PROJECT_NAME.zip

자, 이제 모든 설정이 완료되었습니다. 깃 허브로 커밋과 푸쉬를 진행하면 자동으로 배포가 성공합니다.

image

image

정상적으로 작동하는 지 확인하기 위해 putty - EC2에서 pid를 조회해봅니다.

pgrep -f + 프로젝트 이름 으로 pid를 조회할 수 있습니다.

pgrep -f aws-web-service  

image

조회해보면 아무 값도 나오지 않는 경우가 있습니다. 이는 기존에 빌드한 파일명이 java로 되어 있어 생긴 문제입니다. 정상적으로 표기된다면, 아래 내용(pgrep -f )을 진행하지 않아도 괜찮습니다.

pgrep -f java 명령어를 입력해 pid값을 알아냅니다. 이후 kill pid값 명령어를 이용해 우선 해당 프로세스를 종료합니다.

image



Git Hub Action으로 이동해, 우선 기존에 진행했던 action을 모두 삭제합니다.

image



이후, 다시 Action을 실행합니다.

image


image

정상적으로 빌드가 된 것을 확인할 수 있습니다.

image



최종 확인

commit 변경점이 확인하고 싶다면, index.mustach의 타이틀을 ver.6으로 변경합니다.

image

또한 테스트코드도 꼭! 변경해야합니다. 테스트코드가 틀린경우 빌드에 실패합니다(왜인지는 모르겠어요)

image

모두 변경을 했다면, 다시 한번 커밋을 진행합니다.

image

image



정상적으로 push가 완료되었다면, Action 에서 빌드가 완료되고 배포가 성공적으로 완료되면, 정상적으로 업데이트 됨을 확인 할 수 있습니다.

image

image

image

혹시나 동일하게 진행하였는데도 안되는 부분이 있으면 메세지 바랍니다. 감사합니다.

SeolYoungKim commented 2 years ago

와우 감사합니다 선생님 덕분에 진도 문제없이 진행했어요

Hotmintchoco commented 2 years ago

설명을 잘해주신 덕분에 많이 해결했습니다. 혹시 마지막에 commit, push를 하면 배포 자동화가 되어야 하는데 저는 계속 Actions에서 직접 해줘야 하네요.

다른 점은 제 인텔리제이에 out폴더가 없습니다. 배포 자동화 외에는 다 되는데 뭐가 문제일까요..

SeolYoungKim commented 2 years ago

안녕하세요! 작성자는 아니지만, 도움을 드릴 수 있을까 하여 댓글 남깁니다. 제가 선생님의 댓글만 보고는 문제를 알 수 없기때문에, 혹시 GitHub 주소를 올려주시면 저도 함께 확인이 가능할 것 같습니다.

그래도 추측으로나마(?) 확인해볼 수 있는 부분은 yml 설정 파일입니다.

제가 구성하여 테스트한 GitHub Actions 설정 파일 전문을 올려드리오니, 확인 한번 해보시면 좋을 것 같습니다.

주로 보시면 좋을 것 같은 부분은 다음과 같습니다.

그래도 해결이 안되시면 GitHub 리포지토리 주소를 올려주세요! 한번 같이 확인해보겠습니다

## github-actions.yml의 최상단입니다.
env:
  S3_BUCKET_NAME: blog-aws-practice-build
  PROJECT_NAME: blog-aws-practice
  CODE_DEPLOY_APP_NAME: blog-aws-practice
  CODE_DEPLOY_GROUP_NAME: blog-aws-practice-group

name: deploy

on:
  release:
    types: [push]
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest  # runner
    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout  # step 이름 지정
        uses: actions/checkout@v3

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

      - name: Grant execute permission for gradlew
        run: chmod +x ./gradlew  # gradlew에 대한 권한설정 명령어 (runner에서 실행)
        shell: bash

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

      - name: Get current time
        uses: 1466587594/get-current-time@v2
        id: current-time
        with:
          format: YYYY-MM-DDTHH-mm-ss
          utcOffset: "+09:00"

      - name: Show Current Time
        run: echo "CurrentTime=${{steps.current-time.outputs.formattedTime}}"
        shell: bash

      - name: Generate deployment package
        run: |
          mkdir -p before-deploy
          cp scripts/*.sh before-deploy/
          cp appspec.yml before-deploy/
          cp build/libs/*.jar before-deploy/
          cd before-deploy && zip -r before-deploy *
          cd ../ && mkdir -p deploy
          mv before-deploy/before-deploy.zip deploy/$PROJECT_NAME.zip
        shell: bash

      # 아래 부분이 개인 설정
      - name: Make zip file
        run: zip -r ./$PROJECT_NAME.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: ap-northeast-2

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

      - name: Code Deploy
        run: aws deploy create-deployment --application-name $CODE_DEPLOY_APP_NAME --deployment-config-name CodeDeployDefault.AllAtOnce --deployment-group-name $CODE_DEPLOY_GROUP_NAME --s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=$PROJECT_NAME/$PROJECT_NAME.zip
Hotmintchoco commented 2 years ago

수동 배포는 잘되고 있습니다. commit, push를 이용한 배포는 이루어지지 않고 있고요. 설정 파일은 맞게 작성한 것 같습니다..

깃허브 주소는 https://github.com/Hotmintchoco/springboot-webservice 입니다.

SeolYoungKim commented 2 years ago

image

선생님 안녕하세요! 선생님의 리포지토리를 확인해보니 branch가 master 브랜치입니다.

image 선생님의 GitHubActions 설정 파일을 확인해보니 [main]이라고 적혀있는데요..! 혹시 해당 부분 master로 변경 후에도 문제가 있는지 확인해주실 수 있을까요??

Hotmintchoco commented 2 years ago

오.. 됐어요 감사합니다. 제 branch에 맞게 설정했어야 했군요. 정말 감사합니다.

SeolYoungKim commented 2 years ago

아닙니다 ㅎㅎ 도움이 되셔서 정말 다행입니다! 즐코하세요!

ho1121h commented 1 year ago

감사합니다!

riveroverflows commented 1 year ago

안녕하세요!

작성해주신 내용 따라하던 중에 CodeDeploy에서 Install 이벤트 단계에서 The deployment failed because a specified file already exists at this location: 에러가 발생했는데 처리 한 내용 공유드립니다!

우선 원인은 codedeploy-agent 업데이트로 인해 옵션 설정 방법이 달라진 것 같습니다.

appspec.yml 파일 속성 중 overwrite의 값을 yes로 줬음에도 불구하고 이미 파일이 존재한다는 에러가 계속 발생하여 찾아보다가 공식 문서에서 제시하는 방법을 찾았습니다.

다음과 같이 수정하면 됩니다.

files:
  - source: /
    destination: /home/ec2-user/app/step2/zip/
file_exists_behavior: OVERWRITE  # overwrite: yes 대신 이 옵션으로 대체

files와 같은 레벨에 file_exists_behavior: OVERWRITE 옵션을 줘야 파일 덮어쓰기가 됩니다.

참고한 공식문서 링크도 같이 남기겠습니다.

좋은 내용 작성해주신 덕분에 많은 도움 받았습니다. 정말 감사합니다!

zhtmr commented 1 year ago

안녕하세요. 올려 주신 글 감사히 잘 보면서 따라하는 중입니다.

한가지 궁금한 점이 있어서 질문드립니다.

배포 자동화 구성 부분에 스프링에서 pid 를 관리할 수 있는 파일을 생성하는 부분은 이해가 가는데 실제로 배포 과정에서 이 파일이 쓰이는 것 같지가 않아서요.. 해당 부분과 연계해서 deploy.sh 에서 pgrep 부분 뒤에서 이 pid 파일이 쓰여아 하지 않나 싶어서요

kill 부분에서도 마찬가지로..

kill -9 `cat aws-webservice.pid` 이런 식으로 pid 파일을 이용하기 위해 스프링에서 해당 설정을 한것이 아닌가 싶은데, 혹시 제가 잘못 이해 하고있는 건가요?

lyouxsun commented 9 months ago

많은 도움이 됐습니다. 감사합니다!!🙇🏻‍♀️