λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
  • μž₯원읡 κΈ°μˆ λΈ”λ‘œκ·Έ
🀷🏼‍♀️ Etc.../- linux, aws, docker, k8s

Github Action κ³Ό Elastic Beanstalk 둜 μ„œλ²„ λ°°ν¬ν•˜κΈ° - Github Actions μ •μ˜ν•˜κΈ°

by Wonit 2022. 1. 23.

ν•΄λ‹Ή μ‹œλ¦¬μ¦ˆλŠ” 3개의 κΈ€λ‘œ κ΅¬μ„±λ˜μ–΄μžˆμŠ΅λ‹ˆλ‹€. 각 λ‹¨κ³„μ˜ μžμ„Έν•œ 사항은 μ•„λž˜ 링크λ₯Ό μ°Έμ‘°ν•΄μ£Όμ„Έμš”

 

μ§€λ‚œ μ‹œκ°„...

 

μ§€λ‚œ μ‹œκ°„ μš°λ¦¬λŠ” Spring Boot λ₯Ό μ΄μš©ν•΄μ„œ Application μ„œλ²„λ₯Ό μƒμ„±ν–ˆκ³  Elastic Beanstalk λ₯Ό 생성 ν–ˆλ‹€.

 

이번 μ‹œκ°„μ—λŠ” Github Actions λ₯Ό μ΄μš©ν•˜μ—¬ Master branch 의 변경사항이 μžˆλ‹€λ©΄ μžλ™μœΌλ‘œ λ°°ν¬ν•˜λŠ” 배포 μžλ™ν™”μ— λŒ€ν•΄μ„œ μ•Œμ•„λ³΄μž.

 

Github Actions 에 λŒ€ν•΄μ„œ 더 μžμ„Ένžˆ

 

Github Actions λŠ” κΉƒν—ˆλΈŒμ—μ„œ κ³΅μ‹μ μœΌλ‘œ μ œκ³΅ν•˜λŠ” workflow μžλ™ν™” νˆ΄μ΄λ‹€

 

Workflow μžλ™ν™”λΌκ³  ν•œλ‹€λ©΄ Continous Delivery, Deploy 인 CD 에 λŒ€ν•΄μ„œ 이야기가 자주 λ‚˜μ˜€μ§€λ§Œ 이듀은 μ—„μ—°νžˆ λ‹€λ₯Έ λΆ„λ₯˜λΌκ³  ν•œλ‹€.

 

이에 λŒ€ν•œ λ‚΄μš©μ€ 좔후에 더 κ³΅λΆ€ν•˜κ³  λ‹€λ€„λ³΄κΈ°λ‘œ ν•˜κ³  Github Actions μ—μ„œ μ‚¬μš©ν•˜λŠ” κ°œλ…λ“€μ΄ μžˆλ‹€ ν•˜γ…λ‹ˆ μ•Œμ•„λ³΄μž.

 

Github Actions 의 κ°œλ…

 

  • Workflow
    • μžλ™ν™”λœ 전체 ν”„λ‘œμ„ΈμŠ€λ‘œ ν•˜λ‚˜ μ΄μƒμ˜ Job 으둜 κ΅¬μ„±λ˜λ©° Event 에 μ˜ν•΄ 트리거 λ˜κ±°λ‚˜ μ˜ˆμ•½λ  수 μžˆλ‹€.
    • 배포λ₯Ό ν¬ν•¨ν•˜μ—¬ ν…ŒμŠ€νŠΈ, infra ꡬ성등 λͺ¨λ‘ ν•˜λ‚˜λ‘œ λ³΄λŠ” κ°œλ…μ΄λ‹€.
    • Jenkins 의 Pipeline κ³Ό λΉ„μŠ·ν•œ κ°œλ…μ΄λ‹€.
  • Event
    • Workflow λ₯Ό νŠΈλ¦¬κ±°ν•˜λŠ” νŠΉμ •ν•œ ν™œλ™μ΄λ‚˜ κ·œμΉ™μ΄λ‹€.
    • 보톡 master, main, release λΈŒλžœμΉ˜μ— 트리거 κ·œμΉ™μ„ 정해놓곀 ν•œλ‹€.
    • 즉, master 브랜치의 μ½”λ“œ 변경사항이 μžˆλ‹€λ©΄ Workflow λ₯Ό λ°œλ™μ‹œν‚¨λ‹€.
  • Job
    • 단일 가상 ν™˜κ²½μ—μ„œ μ‹€ν–‰λ˜λŠ” μž‘μ—…λ“€μ˜ λ‹¨μœ„μ΄λ‹€.
    • μ—¬λŸ¬ Jobκ³Ό 의쑴 관계λ₯Ό 맺을 수 있으며 독립, λ³‘λ ¬λ‘œ 싀행될 수 μžˆλ‹€.
  • Step
    • Job μ•ˆμ—μ„œ 순차적으둜 μ‹€ν–‰λ˜λŠ” ν”„λ‘œμ„ΈμŠ€ λ‹¨μœ„μ΄λ‹€.
  • Action
    • job 을 κ΅¬μ„±ν•˜κΈ° μœ„ν•œ step 의 쑰합이닀.
    • Github Actions Marcket Place 에 λ§Žμ€ Actions κ°€ μ •μ˜λ˜μ–΄ μžˆμ–΄μ„œ μ‰½κ²Œ κ°€μ Έλ‹€ μ‚¬μš©ν•  수 μžˆλ‹€.
  • Runner
    • Github Action Runner κ°€ μ„€μΉ˜λ  λ¨Έμ‹ μœΌλ‘œ Workflow κ°€ 싀행될 μΈμŠ€ν„΄μŠ€λ₯Ό μ˜λ―Έν•œλ‹€

 

Github Action μƒμ„±ν•˜κΈ°

 

Github Actions λ₯Ό μƒμ„±ν•˜λŠ” 방법은 맀우 κ°„λ‹¨ν•˜λ‹€.

 

Project Repository 에 .github/workflows 디렉토리λ₯Ό μƒμ„±ν•˜κ³  yml 포맷의 파일둜 Workflow λ₯Ό μ •μ˜ν•΄μ£Όλ©΄ 끝이닀.

 

μš°λ¦¬κ°€ μ•žμ„œ μƒμ„±ν•œ ν”„λ‘œμ νŠΈ λ ˆν¬μ§€ν† λ¦¬μ— λ‹€μŒκ³Ό 같은 ꡬ쑰둜 디렉토리와 νŒŒμΌμ„ μƒμ„±ν•΄λ³΄μž

 

 

todo-master-deploy.yml

name: todo-master-to-beanstalk

on:
  push:
    branched:
      - master # action 트리거 브랜치
  workflow_dispatch: # μˆ˜λ™ μ‹€ν–‰ μ˜΅μ…˜ (μƒλž΅)

jobs:
  build:
    runs-on: ubuntu-latest # action μŠ€ν¬λ¦½νŠΈκ°€ μž‘λ™λ  OS

    steps: # μž‘μ—… 단계
      - name: Checkout source code # 단계별 이름, κ΅¬λΆ„μžλ‘œ μ†ŒμŠ€λ₯Ό κ°€μ Έμ˜΄
        uses: actions/checkout@v2

      - name: Set up JDK 1.8 # JDK μ„€μΉ˜
        uses: actions/setup-java@v1 # (5)
        with:
          java-version: 1.8

      - name: Grant execute permission for gradlew
        working-directory: ./server-app
        run: chmod +x ./gradlew
        shell: bash

      - name: Build with Gradle
        working-directory: ./server-app
        run: ./gradlew clean build
        shell: bash

      - name: Get current time
        uses: 1466587594/get-current-time@v2
        id: current-time
        with:
          format: YYYYMMDDTHHmm
          utcOffset: "+09:00"

      - name: Generate deployment package
        run: |
          mkdir -p deploy
          cp server-app/build/libs/server-app.jar deploy/todo-application-prod-ebextensions-1.jar
          cp Procfile deploy/Procfile
          cp -r .ebextensions deploy/.ebextensions
          cd deploy && zip -r todo-application-prod-label-${{steps.current-time.outputs.formattedTime}}-${{github.sha}} .

      - name: Deploy Consumer to EB
        uses: einaregilsson/beanstalk-deploy@v14
        with:
          aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          application_name: todo-application-prod
          environment_name: Todoapplicationprod-env
          version_label: todo-application-prod-label-${{steps.current-time.outputs.formattedTime}}-${{github.sha}}
          region: ap-northeast-2
          deployment_package: deploy/todo-application-prod-label-${{steps.current-time.outputs.formattedTime}}-${{github.sha}}.zip

 

뭐가 맀우 많고 ν—·κ°ˆλ¦°λ‹€.

 

ν•˜μ§€λ§Œ κ±±μ •ν•  것이 μ „ν˜€ μ—†λ‹€.

 

 

μ•žμ„œ μ΄μ•ΌκΈ°ν–ˆλ“― 각각의 Job 을 μ‹€ν–‰μ‹œν‚€λŠ” 방법듀을 λͺ…세해놓은 것이고 이듀을 λͺ¨λ‘ μ™Έμš°κ³  μžˆμ§€ μ•Šμ•„λ„ Marcket Place μ—μ„œ μ‰½κ²Œ λ³΅μ‚¬ν•˜μ—¬ λΆ™μ—¬λ„£μœΌλ©΄ λœλ‹€.

 

그럼 μ•„κΉŒ 이야기 ν–ˆλ˜ Github Actions 의 κ°œλ…μ„ μ μš©ν•΄μ„œ μ–΄λ–€ ꡬ쑰둜 yml 이 κ΅¬μ„±λ˜μ–΄μžˆλŠ”μ§€ μ•Œμ•„λ³΄μž.

 

μœ„μ˜ yml 을 μž‘κ²Œ 뢄해해보겠닀.

 

Workflow μ •μ˜

name: todo-master-to-beanstalk

on:
  push:
    branched:
      - master # action 트리거 브랜치
  workflow_dispatch: # μˆ˜λ™ μ‹€ν–‰ μ˜΅μ…˜ (μƒλž΅)
jobs:
  build:
    runs-on: ubuntu-latest # action μŠ€ν¬λ¦½νŠΈκ°€ μž‘λ™λ  OS

 

ν•΄λ‹Ή workflow λŠ” todo-master-to-beanstalk λΌλŠ” μ΄λ¦„μ˜ workflow 이닀.

 

master 브랜치둜 push λœλ‹€λ©΄ 이벀트λ₯Ό λ°œμƒμ‹œν‚€κ³  workflow_distpatch λŠ” μƒλž΅ν•˜μ˜€λŠ”λ°, μ΄λŠ” μˆ˜λ™μœΌλ‘œ μ‹€ν–‰ν•  λ•Œ μ£ΌλŠ” μ˜΅μ…˜ 값이닀.

 

λ˜ν•œ Job 이 싀행될 OS λŠ” ubuntu μ—μ„œ 싀행이 λœλ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€.

 

Job μ •μ˜ - 1. source code

- name: Checkout source code # 단계별 이름, κ΅¬λΆ„μžλ‘œ μ†ŒμŠ€λ₯Ό κ°€μ Έμ˜΄
  uses: actions/checkout@v2

 

μœ„μ˜ step 블둝은 ν•΄λ‹Ή Workflow κ°€ λ ˆν¬μ§€ν† λ¦¬μ— μ•‘μ„ΈμŠ€ν•  수 μžˆλ„λ‘ μ‚¬μš©λ˜λŠ” 곡식 Action 이닀.

 

Job μ •μ˜ - 2. JDK μ„€μΉ˜

- name: Set up JDK 1.8 # JDK μ„€μΉ˜
  uses: actions/setup-java@v1 # (5)
  with:
    java-version: 1.8

 

보면 λ°”λ‘œ μ•Œ 수 μžˆλ“― JDK Action 을 가져와 μ‹€ν–‰ν•œλ‹€.

 

JDK 버전은 1.8 λ²„μ „μœΌλ‘œ Java8 을 μ‚¬μš©ν–ˆλ‹€.

 

Job μ •μ˜ - 3. Gradle μ„€μ •

- name: Grant execute permission for gradlew
  working-directory: ./server-app
  run: chmod +x ./gradlew
  shell: bash

- name: Build with Gradle
  working-directory: ./server-app
  run: ./gradlew clean build
  shell: bash

 

ν•΄λ‹Ή λΈ”λŸ­μ€ Gradle κ³Ό κ΄€λ ¨λœ 섀정이닀.

 

chmod λ₯Ό ν†΅ν•΄μ„œ Application Server λ””λ ‰ν† λ¦¬μ˜ gradlew μ—κ²Œ μ‹€ν–‰ κΆŒν•œμ„ λΆ€μ—¬ν•˜κ³  앱을 build ν•œλ‹€.

 

working-directory λ₯Ό μ΄μš©ν•΄μ„œ ./server-app 이 μž‘μ—…μ„ μˆ˜ν–‰ν•  λ””λ ‰ν† λ¦¬μž„μ„ λͺ…μ‹œν•˜μ˜€λ‹€.

 

Job μ •μ˜ - 4. μ‹œκ°„ μ„€μ •

- name: Get current time
  uses: 1466587594/get-current-time@v2
  id: current-time
  with:
    format: YYYYMMDDTHHmm
    utcOffset: "+09:00"

 

μ„œλ²„λ₯Ό 배포할 λ•ŒλŠ” μ„œλ²„μ˜ 버저닝이 맀우 μ€‘μš”ν•˜λ‹€.

 

이 버저닝을 μœ„ν•΄μ„œ get-current-time μ΄λΌλŠ” Action 을 가져와 μ‚¬μš©ν•˜λΌλŠ” λΈ”λŸ­μ΄λ‹€.

 

Job μ •μ˜ - 5. 배포 μ„€μ •

- name: Generate deployment package
  run: |
    mkdir -p deploy
    cp server-app/build/libs/server-app.jar deploy/todo-application-prod-ebextensions-1.jar
    cp Procfile deploy/Procfile
    cp -r .ebextensions deploy/.ebextensions
    cd deploy && zip -r todo-application-prod-label-${{steps.current-time.outputs.formattedTime}}-${{github.sha}} .

 

이 Job 이 ν˜„μž¬ κ΅¬μ„±ν•œ Actions μ •μ˜λ“€ 쀑 κ°€μž₯ κΉŒλ‹€λ‘œμš΄ 뢀뢄이닀.

 

μš°μ„  λ„˜μ–΄κ°€κ³  μ•„λž˜μ—μ„œ μžμ„Ένžˆ μ•Œμ•„λ³΄μž

 

Job μ •μ˜ - 6. Elastic Beanstalk Consumer μ—°κ²°

- name: Deploy Consumer to EB
  uses: einaregilsson/beanstalk-deploy@v14
  with:
    aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
    aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    application_name: todo-application-prod
    environment_name: Todoapplicationprod-env
    version_label: todo-application-prod-label-${{steps.current-time.outputs.formattedTime}}-${{github.sha}}
    region: ap-northeast-2
    deployment_package: deploy/todo-application-prod-label-${{steps.current-time.outputs.formattedTime}}-${{github.sha}}.zip

 

Beanstalk λ₯Ό μ—°κ²°ν•˜λŠ” 뢀뢄이닀.

 

μ—¬κΈ°μ„œ μ•žμ„œ μ •μ˜ν•œ EB의 Application 이름과 environment 이름을 μ„€μ •ν•˜κ³  SECRET 을 톡해 μ—°κ²°ν•΄μ€€λ‹€.

 

이제 μ •μ˜ 5번 6λ²ˆμ— λŒ€ν•΄μ„œ μžμ„Ένžˆ μ•Œμ•„λ³΄μž.

 

배포 μ„€μ • μžμ„Ένžˆ 보기 - Procfile

 

Procfile 은 Elastic Beanstalk μ—κ²Œ μ‹€ν–‰ν•  JAR λ₯Ό μ•Œλ €μ£ΌλŠ” ν”„λ‘œμ„ΈμŠ€ ꡬ성 νŒŒμΌμ΄λ‹€.

 

ν”„λ‘œμ νŠΈ λ£¨νŠΈμ— Procfile νŒŒμΌμ„ μƒμ„±ν•˜μž.

 

그리고 ν•΄λ‹Ή 파일의 web λΈ”λŸ­μ— μ‹€ν–‰ν•  jar νŒŒμΌμ„ μΆ”κ°€μ‹œμΌœμ£Όλ©΄ λœλ‹€.

 

web: java -jar todo-application-prod-ebextensions-1.jar

 

우리의 μ„œλ²„λ₯Ό νŒ¨ν‚€μ§•ν•˜λ©΄ 2개의 jar 파일이 μƒμ„±λ˜λŠ”λ°, EBμ—μ„œλŠ” μ–΄λ–€ jar νŒŒμΌμ„ μ‹€ν–‰μ‹œμΌœμ•Όν•˜λŠ”μ§€ λͺ¨λ₯΄κΈ° λ•Œλ¬Έμ— μœ„μ™€ 같이 Procfile 을 생성해주고 EB λ‚΄λΆ€λ‘œ λ„£μ–΄μ€˜μ•Ό ν•œλ‹€.

 

배포 μ„€μ • μžμ„Ένžˆ 보기 - ebextensions

 

.ebextenstions λŠ” config νŒŒμΌμ„ μ΄μš©ν•΄μ„œ κ³ κΈ‰ ν™˜κ²½ ꡬ성을 ν•  수 μžˆλ„λ‘ ν•œλ‹€.

 

Timezone 섀정을 μœ„ν•΄ μ‚¬μš©ν•˜μ˜€λŠ”λ°, 이 μ—­μ‹œ EB λ‚΄λΆ€λ‘œ λ„£μ–΄μ£Όμ–΄μ•Ό ν•œλ‹€.

 

commands:
  set_time_zone:
    command: ln -f -s /usr/share/zoneinfo/Asia/Seoul /etc/localtime

Consumer μžμ„Ένžˆ 보기 - Github Secret μ„€μ •

 

Job μ •μ˜ 6번 을 λ‹€μ‹œ 봐보자

 

- name: Deploy Consumer to EB
  uses: einaregilsson/beanstalk-deploy@v14
  with:
    aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
    aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    application_name: todo-application-prod
    environment_name: Todoapplicationprod-env
    version_label: todo-application-prod-label-${{steps.current-time.outputs.formattedTime}}-${{github.sha}}
    region: ap-northeast-2
    deployment_package: deploy/todo-application-prod-label-${{steps.current-time.outputs.formattedTime}}-${{github.sha}}.zip

aws_access_key 와 aws_secret_key λ₯Ό 보면 μ‹€μ œ 값을 λ…ΈμΆœμ‹œν‚€λŠ” 것이 μ•„λ‹ˆλΌ μ™ΈλΆ€ μ„€μ •μ—μ„œ κ°€μ Έμ˜€κ³  μžˆλ‹€.

 

 

이λ₯Ό μœ„ν•΄μ„œ Repository Setting μ—μ„œ Key λ₯Ό λ“±λ‘μ‹œμΌœμ£Όμž.

 

Repository 의 Setting μ—μ„œ Secret 탭에 λ“€μ–΄κ°€μ„œ μƒˆλ‘œμš΄ Action Secret 을 μƒμ„±ν•΄μ£Όμž

 

μ•žμ„œ μƒμ„±ν•œ IAM 의 Access 와 Secret 을 등둝해주면 λœλ‹€.

 

 

그럼 μœ„μ˜ Job μ •μ˜ 6λ²ˆμ—μ„œ μ™ΈλΆ€ 섀정을 κ°€μ Έμ˜¬ 수 있게 λœλ‹€.

 

μ½”λ“œ ν‘Έμ‹œν•˜μ—¬ Actions 와 EB μ—°κ²°ν•˜κΈ°

 

이제 λͺ¨λ“  μ€€λΉ„κ°€ λ‹€ λ˜μ—ˆλ‹€!

 

github 에 master 브랜치둜 push ν•˜μ—¬ EBλ₯Ό Trigger ν•΄λ³΄μž

 

 

그럼 μœ„μ™€ 같이 λŒ€κΈ°μ€‘μ΄ 뜨며 결ꡭ은 Success κ°€ λ“€μ–΄μ˜€κ²Œ 되며 μƒˆλ‘œμš΄ λ²„μ „μœΌλ‘œ 잘 λ™μž‘ν•˜λŠ” 것을 μ•Œ 수 μžˆλ‹€.

 

λŒ“κΈ€