[AWS] - Spring Boot ํ”„๋กœ์ ํŠธ ๋ฐฐํฌ(1)

๊ฐœ๋ฐœ ํ™˜๊ฒฝ

๐Ÿ’ป OS : M1 Mac Ventura 13.1

๐Ÿƒ Spring : Spring Boot 2.7.7

๐Ÿ› ๏ธ Java : Amazon corretto 17

๐Ÿ“ฆ Stack : AWS : S3, CodeDeploy, EC2(Amazon Linux), RDS

 

ํ•ด๋‹น ๊ธ€์€ ๊ฐœ๋ฐœ ๊ณผ์ •์„ ๊ธฐ๋กํ•˜๊ธฐ ์œ„ํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.
ํ•„์š”ํ•œ ๋ถ€๋ถ„์€ ๋ณธ์ธ์˜ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ๋ฐ ์ƒํ™ฉ์— ๋งž๊ฒŒ ๋ฐ”๊ฟ”์„œ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

CI/CD Flow

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2023-02-16 แ„‹แ…ฉแ„’แ…ฎ 11 56 12

1๏ธโƒฃ : ๋ฐฐํฌ ๋ธŒ๋žœ์น˜์— Push ๋  ๋•Œ, Github Actions ์‹คํ–‰

2๏ธโƒฃ : Actions๋ฅผ ํ†ตํ•ด ๋นŒ๋“œํ•œ ํ›„ AWS IAM ์ธ์ฆ์„ ๊ฑฐ์นœ ๋’ค, ์ „์ฒด ํŒŒ์ผ์„ .zip ํŒŒ์ผ๋กœ ๋ฌถ์–ด S3์— ์—…๋กœ๋“œ

3๏ธโƒฃ : S3์— ์˜ฌ๋ผ๊ฐ„ ํŒŒ์ผ๋ช…์„ ํ† ๋Œ€๋กœ CodeDeploy์— ๋ฐฐํฌ ์š”์ฒญ

4๏ธโƒฃ : ๋ฐฐํฌ ์š”์ฒญ์„ ๋ฐ›์œผ๋ฉด S3์—์„œ ํŒŒ์ผ์„ ๋ฐ›์•„์™€ EC2์— ๋ฐฐํฌ

5๏ธโƒฃ : deploy.sh๋ฅผ ํ†ตํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰

CI ํ™˜๊ฒฝ ๊ตฌ์ถ•

์„ค๋ช…ํ•˜๊ธฐ ์•ž์„œ application*.yml(properties) ํŒŒ์ผ๋“ค์€ ๋ชจ๋‘ .gitignore์— ๋“ฑ๋ก๋œ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.
๋˜ํ•œ ํ•˜๋‚˜์˜ actions.yml ํŒŒ์ผ์„ ๊ฐ€์ง€๊ณ  ์ƒํ™ฉ์— ๋งž๊ฒŒ ์ง€์†์ ์œผ๋กœ ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์„ค๋ช…ํ•  ์˜ˆ์ •์ด๋ฉฐ, ์ตœ์ข…๋ณธ์€ ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ์ถ”๊ฐ€ํ•ด๋†“๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค!

Properties ํŒŒ์ผ ๋“ฑ๋ก

์œ„์—์„œ ์„ค๋ช…ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์ด ์„ค์ • ํŒŒ์ผ๋“ค์€ .gitignore์— ๋“ฑ๋ก๋˜์–ด ์žˆ์–ด master ๋ธŒ๋žœ์น˜์— ์˜ฌ๋ผ๊ฐ€์žˆ์ง€ ์•Š์€ ์ƒํƒœ๋‹ค.

๋•Œ๋ฌธ์— build๋ฅผ ํ•˜๋Š” ๊ณผ์ •์—์„œ ์—๋Ÿฌ๊ฐ€ ๋‚  ์ˆ˜ ์žˆ๊ณ , ์ตœ์ข…์ ์œผ๋กœ ๋ฐฐํฌ ๋˜์—ˆ์„ ๋•Œ ์‹คํ–‰์กฐ์ฐจ ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์—,
์„ค์ • ํŒŒ์ผ์„ Actions Secret์— ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

 

image

 

์œ„ ์‚ฌ์ง„๊ณผ ๊ฐ™์ด ํด๋ฆญํ•˜๋ฉด ์ƒˆ๋กœ์šด secret์„ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋‹ค.

Name : CI/CD๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉํ•  actions.yml์—์„œ ์‚ฌ์šฉํ•  ์ด๋ฆ„(๋Œ€๋ฌธ์ž ์‚ฌ์šฉ)

Secret : Name์— ๋Œ€ํ•œ ์ƒ์„ธ ๋‚ด์šฉ ์ž‘์„ฑ

image

ํ•„์ž๋Š” application.yml์— ๊ตฌ๋™์— ํ•„์š”ํ•œ ํ•„์ˆ˜ ํ•ญ๋ชฉ์„ ์ž‘์„ฑํ•˜๊ณ ,
application-prod.yml์—๋Š” ๋ฐฐํฌ ํ™˜๊ฒฝ์— ํ•„์š”ํ•œ RDS ์ •๋ณด์™€ ๊ฐ™์€ ๊ฒƒ์„ ์ž‘์„ฑํ•ด๋†“์€ ์ƒํƒœ๊ธฐ ๋•Œ๋ฌธ์— ๋”ฐ๋กœ ๊ตฌ๋ถ„ํ–ˆ๋‹ค.(+ ์ถ”ํ›„ ๊ฐœ๋ฐœ ์„œ๋ฒ„๋„ ๋„์šฐ๊ธฐ ์œ„ํ•จ)

# Actions Secrets
PROPERTIES_MAIN_PROD : appication.yml
PROPERTIES_PROD : application-prod.yml

GitHub Actions

image

 

๋ฐฐํฌ๋ฅผ ํ•˜๊ณ ์žํ•˜๋Š” Github Repository์˜ Actions์— ๋“ค์–ด๊ฐ€ actions.yml์„ ์ž‘์„ฑํ•ด์ค€๋‹ค.

 

# Actions์—์„œ ๋ณด์—ฌ์งˆ workflow ์ด๋ฆ„
name: CI/CD

# ํŠธ๋ฆฌ๊ฑฐ ์ง€์ •
# master ๋ธŒ๋žœ์น˜์— push๊ฐ€ ์ผ์–ด๋‚  ๋•Œ ์‹คํ–‰
on:
  push:
    branches:
      - master

jobs:
  CI-CD:
    runs-on: ubuntu-latest
    steps:

      ## Setting JDK
      ## ๋ณธ์ธ spring ๋ฒ„์ „์— ๋งž๋Š” ๋ฒ„์ „ ์ง€์ •
      ## https://github.com/actions/setup-java
      - uses: actions/checkout@v3
      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          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-

      ## Create application.yml
      - name: make prod application.yml
        if: contains(github.ref, 'master')
        run: |
          cd ./src/main/resources
          touch ./application.yml
          echo "${{ secrets.PROPERTIES_MAIN_PROD }}" > ./application.yml
        shell: bash

      ## Create application-prod.yml
      - name: make prod application-prod.yml
        if: contains(github.ref, 'master')
        run: |
          cd ./src/main/resources
          touch ./application-prod.yml
          echo "${{ secrets.PROPERTIES_PROD }}" > ./application-prod.yml
        shell: bash

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

      ## Gradle Build
      - name: Build with Gradle
        run: ./gradlew build

์ž‘์„ฑ์„ ๋‹ค ์ž‘์„ฑํ•œ ๋’ค์— Start Commit์„ ํ†ตํ•ด master ๋ธŒ๋žœ์น˜์— ๋ฐ”๋กœ push ํ•ด์ค€๋‹ค.

์ด ๊ณผ์ •์—์„œ ์ƒ๊ธฐ๋Š” ์˜ค๋ฅ˜๋“ค์€ ๋ฏธ๋ฆฌ ํ•ด๊ฒฐํ•ด ๋†“๋Š”๊ฒŒ ๋ง˜ ํŽธํ•˜๋‹ค!

๋ณ€๊ฒฝํ•  ์‚ฌํ•ญ ์ •๋ฆฌ

  • Setting JDK
    • ๋ณธ์ธ Spring ๋ฒ„์ „์— ๋งž๋„๋ก ์ง€์ •
  • Create *.yml
    • properties ํŒŒ์ผ์€ ์™ธ๋ถ€์— ๊ณต๊ฐœํ•˜๋ฉด ์•ˆ ๋˜๋Š” ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋‹ค.
    • ๋•Œ๋ฌธ์— Setting - Secretes - Actions์—์„œ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.
    • ํ•„์š”์— ๋”ฐ๋ผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ์ง€์›Œ์ฃผ๊ณ , yml์ด ์•„๋‹ˆ๋ฉด properties๋กœ ๋ฐ”๊ฟ”์ฃผ๋ฉด ๋œ๋‹ค.

์˜ค๋ฅ˜ ์ •๋ฆฌ

Build With Gradle
Run ./gradlew build
  ./gradlew build
  shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
  env:
    JAVA_HOME: /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/11.0.18-10/x64
    JAVA_HOME_11_X64: /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/11.0.18-10/x64
Error: Could not find or load main class org.gradle.wrapper.GradleWrapperMain
Caused by: java.lang.ClassNotFoundException: org.gradle.wrapper.GradleWrapperMain
  • Project ์ž๋ฐ” ๋ฒ„์ „๊ณผ ๋™์ผํ•˜๊ฒŒ ์„ค์ •ํ–ˆ๋Š”์ง€ ํ™•์ธ
/home/runner/work/.../src/main/java/com/.../app/config/security/CustomAuthenticationFailureHandler 2.java:
13: error: class CustomAuthenticationFailureHandler is public, should be declared in a file named CustomAuthenticationFailureHandler.java
  • ํ”„๋กœ์ ํŠธ์— ClassName 2.java๊ณผ ๊ฐ™์ด ๋‹ค๋ฅธ ํด๋ž˜์Šค ํŒŒ์ผ๊ณผ ์ค‘๋ณต๋˜๋Š” ํŒŒ์ผ์ด ์žˆ๋Š”์ง€ ํ™•์ธ
* What went wrong:
Execution failed for task ':test'.
> There were failing tests. See the report at: 
  • ์‹คํŒจํ•œ ํ…Œ์ŠคํŠธ๊ฐ€ ์กด์žฌํ•  ๊ฒฝ์šฐ ์œ„์™€ ๊ฐ™์ด ๋œฐ ์ˆ˜ ์žˆ์Œ
  • ํ˜น์€ ํŠน์ • Test์—์„œ ์‚ฌ์šฉ๋˜๋Š” ํŠน์ • ํŒŒ์ผ, Properties๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์—†์„ ๊ฒฝ์šฐ ๋ฐœ์ƒ ๊ฐ€๋Šฅ

AWS

IAM

AWS๋Š” ์„œ๋น„์Šค์˜ ๋ณด์•ˆ์„ ์œ„ํ•ด ์™ธ๋ถ€ ์ ‘๊ทผ์„ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ฐจ๋‹จํ•œ๋‹ค. ๋•Œ๋ฌธ์— IAM(Identify & Access Management)์„ ์ด์šฉํ•ด์„œ ์™ธ๋ถ€์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋ฃจํŠธ๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค.

 

image

 

์ƒ๋‹จ ๊ฒ€์ƒ‰์ฐฝ์„ ํ†ตํ•ด IAM์— ๋“ค์–ด๊ฐ€ ์‚ฌ์šฉ์ž ํƒญ์˜ ์‚ฌ์šฉ์ž ์ถ”๊ฐ€๋ฅผ ๋ˆŒ๋Ÿฌ์ค€๋‹ค.

 

imageimage

 

AWSCodeDeployFullAccess, AmazonS3FullAccess 2๊ฐ€์ง€ ์ •์ฑ…์„ ์—ฐ๊ฒฐํ•ด์ค€๋‹ค.

๋‹ค๋ฅธ ๊ฒƒ์€ ๊ฑด๋“ค์ด์ง€ ์•Š๊ณ  ๋‹ค์Œ์„ ๋ˆ„๋ฅธ ๋’ค, ์‚ฌ์šฉ์ž๋ฅผ ์ƒ์„ฑํ•ด์ค€๋‹ค.

 

image

 

์ด IAM์„ ๊ฐ€์ง€๊ณ  GitHub์—์„œ ์ฆ๋ช…์„ ํ•ด์ค˜์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— Access Key๋ฅผ ๋ฐœ๊ธ‰ ๋ฐ›์•„์•ผ ํ•œ๋‹ค.

 

imageimage

 

์„ค๋ช…์€ ์„ ํƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฑด๋“ค์ด์ง€ ์•Š๊ณ  ์ง„ํ–‰

 

image

 

Access Key, Secret Key๋Š” ๋”ฐ๋กœ ๋ฉ”๋ชจ๋ฅผ ํ•ด๋†“๊ณ , .csv ํŒŒ์ผ์€ ๋‹ค์šด์„ ๋ฐ›์•„๋†“์ž!

 

Secret ๋“ฑ๋ก

๊นŒ๋จน๊ธฐ ์ „์— ์œ„์—์„œ ๋ฐœ๊ธ‰ ๋ฐ›์€ ํ‚ค๋ฅผ GitHub Secrets์— ๋“ฑ๋กํ•˜์ž!

image
# Actions Secrets
AWS_IAM_ACCESS_KEY : ์•ก์„ธ์Šค ํ‚ค
AWS_IAM_SECRET_KEY : ๋น„๋ฐ€ ์•ก์„ธ์Šค ํ‚ค

์—ญํ•  ์ถ”๊ฐ€

IAM์„ ๊ฐ€์ง€๊ณ  S3, CodeDeploy, EC2์— ์ ‘๊ทผ์„ ํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ ์„œ๋น„์Šค์— ๋Œ€ํ•ด ์—ญํ• ์„ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

EC2 Role

EC2์—์„œ๋Š” S3์— ์žˆ๋Š” ํŒŒ์ผ์„ ๋ฐ›์•„์™€์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์•„๋ž˜์™€ ๊ฐ™์ด ๋“ฑ๋กํ•ด์ค€๋‹ค.

 

imageimageimage

 

AmazonEC2RoleforAWSCodeDeploy ๊ฒ€์ƒ‰ ํ›„ ์ฒดํฌ

 

image

 

์ด ์™ธ ๋‚ด์šฉ์€ ๋ชจ๋‘ ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ์—ญํ• ์„ ๋งŒ๋“ ๋‹ค.

 

CodeDeploy Role

CodeDeploy์—์„œ๋Š” S3์— ์žˆ๋Š” ๊ฒƒ์„ EC2์— ๋ณด๋‚ธ ๋’ค, ๋ฐฐํฌ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์•„๋ž˜์™€ ๊ฐ™์ด ๋“ฑ๋กํ•ด์ค€๋‹ค.

 

imageimage

 

CodeDeploy์˜ ์ •์ฑ…์€ 1๊ฐ€์ง€๋งŒ ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋Œ€๋กœ ๋‹ค์Œ์„ ๋ˆŒ๋Ÿฌ์ค€๋‹ค.

 

image

 

๋™์ผํ•˜๊ฒŒ ์ด๋ฆ„์„ ์ž˜ ์ง€์–ด์ฃผ๊ณ  ์—ญํ• ์„ ๋งŒ๋“ ๋‹ค.

 

S3

CI ๊ณผ์ •์„ ํ†ตํ•ด ๋นŒ๋“œ๋œ ํŒŒ์ผ๋“ค์„ ์ €์žฅํ•  S3 Bucket์„ ์ƒ์„ฑํ•ด์ค€๋‹ค.

S3 Bucket ์ƒ์„ฑ

imageimageimage

์ด ์™ธ์˜ ์„ค์ •์€ ๊ฑด๋“ค์ด์ง€ ์•Š๊ณ  ๋ฒ„ํ‚ท ๋งŒ๋“ค๊ธฐ๋ฅผ ๋ˆŒ๋Ÿฌ์ฃผ๋ฉด ๋!

EC2

๋’ค์—์„œ ์„ค์ •ํ•  CodeDeploy์—์„œ ํŒŒ์ผ์„ ๋ฐ›์•„์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ์—ญํ• 

EC2 ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ

imageimageimageimage

์ƒˆ ํ‚คํŽ˜์–ด๋ฅผ ์ƒ์„ฑํ•˜๋ฉด, ec2-keypair.pem ํŒŒ์ผ์„ ๋‹ค์šด๋ฐ›๊ฒŒ ๋œ๋‹ค. ๋‹ค์šด๋กœ๋“œํ•œ ํŒŒ์ผ์„ ๋ฐ”ํƒ•ํ™”๋ฉด์— aws ํด๋”๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๊ด€ํ•ด๋†“์ž!

ํด๋” ์ด๋ฆ„์ด๋‚˜ ๊ฒฝ๋กœ๋Š” ๋ณธ์ธ์ด ์›ํ•˜๋Š” ๊ณณ์œผ๋กœ ๋ฐ”๊ฟ”๋„ ๋œ๋‹ค! ๋‹จ, ec2-keypair.pem ํŒŒ์ผ์— ๋Œ€ํ•œ ์ด๋ฆ„ ์ˆ˜์ •์€ ํ•˜๋ฉด ์•ˆ ๋œ๋‹ค.

 

image

 

๊ธฐ์กด ์œ„์น˜ ๋ฌด๊ด€์—์„œ ๋‚ด IP๋กœ ๋ณ€๊ฒฝ!

 

image

ํ”„๋ฆฌํ‹ฐ์–ด ๊ธฐ์ค€ 30๊ธฐ๊ฐ€๊นŒ์ง€ ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— 30๊ธฐ๊ฐ€๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ๋‹ค๋ฅธ ์˜ต์…˜์€ ์•„๋ฌด๊ฒƒ๋„ ๊ฑด๋“ค์ง€ ๋ง์ž

gp2 ๊ฐ™์€ ๊ฒฝ์šฐ ๋ฒ”์šฉ์ด ์•„๋‹Œ ๊ฒƒ์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ๊ณผ๊ธˆ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ!

๋‹ค๋ฅธ ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค๋ฉด ์ธ์Šคํ„ด์Šค ์‹œ์ž‘์„ ๋ˆŒ๋Ÿฌ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ์‹œ์ž‘ํ•ด์ฃผ์ž

IAM ์—ญํ•  ๋ถ€์—ฌ

image

 

์ƒˆ๋กœ ๋งŒ๋“  ์ธ์Šคํ„ด์Šค๋ฅผ ์šฐํด๋ฆญํ•˜์—ฌ ๋ณด์•ˆ - IAM ์—ญํ•  ์ˆ˜์ •์„ ํด๋ฆญํ•ด์ค€๋‹ค.

 

image

 

์•ž์„œ ๋งŒ๋“ค์—ˆ๋˜ EC2์˜ IAM ์—ญํ• ์„ ์ ์šฉํ•ด์ค€๋‹ค.

 

image

 

์—ญํ• ์„ ์žฌ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ธ์Šคํ„ด์Šค๋ฅผ ์žฌ๋ถ€ํŒ…ํ•ด์ค€๋‹ค. ์žฌ๋ถ€ํŒ… ๊ณผ์ •์€ 1 ~ 3๋ถ„ ์ •๋„ ์†Œ์š”๋˜๋‹ˆ ๋‹ค์Œ ๊ณผ์ •์„ ์ฒœ์ฒœํžˆ ์ง„ํ–‰ํ•˜์ž!

ํƒ„๋ ฅ์  IP ์ ์šฉ

์ธ์Šคํ„ด์Šค๊ฐ€ ์žฌ๋ถ€ํŒ…๋  ๋•Œ๋งˆ๋‹ค ํผ๋ธ”๋ฆญ ์ฃผ์†Œ๋Š” ๊ณ„์†ํ•ด์„œ ๋ณ€๊ฒฝ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํƒ„๋ ฅ์  IP ์ฃผ์†Œ๋ฅผ ํ†ตํ•ด ๊ณ ์ • ํผ๋ธ”๋ฆญ IP๋ฅผ ์ƒ์„ฑํ•ด์ค€๋‹ค.

 

imageimage

 

์•„๋ฌด๊ฒƒ๋„ ๊ฑด๋“ค์ด์ง€ ์•Š๊ณ  ํ• ๋‹น์„ ํด๋ฆญํ•ด ๋ถ€์—ฌํ•ด์ค€๋‹ค!

 

imageimage

 

์•ž์„œ ๋งŒ๋“  ์ธ์Šคํ„ด์Šค๋ฅผ ์„ ํƒํ•ด์ฃผ๊ณ , ํ•ด๋‹น ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ํ”„๋ผ์ด๋น— IP๋ฅผ ์„ ํƒํ•œ ๋’ค, ์—ฐ๊ฒฐ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ์ค€๋‹ค.

ssh ์ ‘์†

์ด์ œ ์ •์ƒ์ ์œผ๋กœ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•ด์กŒ๋Š”์ง€ ํ™•์ธํ•ด๋ณด์ž!

 

image

 

์ธ์Šคํ„ด์Šค ์ƒ์„ธ ํŽ˜์ด์ง€์—์„œ ์šฐ์ธก ์ƒ๋‹จ์— ์žˆ๋Š” ์—ฐ๊ฒฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๊ณ , SSH ํด๋ผ์ด์–ธํŠธ ํ…์— ๊ฐ€์žฅ ์•„๋ž˜ ์˜ˆ์‹œ ssh ์—ฐ๊ฒฐ ์ฃผ์†Œ๋ฅผ ๋ณต์‚ฌํ•ด ํ„ฐ๋ฏธ๋„์— ์ž…๋ ฅํ•ด์ฃผ์ž!

 

ํ•ด๋‹น ๊ณผ์ •์€ .pem์ด ์žˆ๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ ์ง„ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

image

CodeDeploy ์„ค์น˜

S3์— ์˜ฌ๋ผ๊ฐ„ ํŒŒ์ผ์„ CodeDeploy๋ฅผ ํ†ตํ•ด EC2์— ์ „๋‹ฌํ•ด ๋ฐฐํฌ๋ฅผ ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ssh์— ์—ฐ๊ฒฐ๋œ ์ƒํƒœ์—์„œ ์„ค์น˜๋ฅผ ํ•ด์ค€๋‹ค.

image

# CodeDeploy ์„ค์น˜
aws s3 cp s3://aws-codedeploy-ap-northeast-2/latest/install . --region ap-northeast-2
# ์„ค์น˜ ํŒŒ์ผ์— ๊ถŒํ•œ ๋ถ€์—ฌ
chmod +x ./install
# ๋‹ค์šด ๋ฐ›์€ ํŒŒ์ผ์„ ์„ค์น˜ํ•˜๊ธฐ ์œ„ํ•ด ruby ์„ค์น˜
sudo yum install ruby;
# CodeDeploy ์„ค์น˜
sudo ./install auto
# ์„œ๋น„์Šค ์ƒํƒœ ํ™•์ธ
sudo service codedeploy-agent status

CodeDeploy

S3์— ์˜ฌ๋ผ์˜จ .zip ํŒŒ์ผ์„ EC2์— ๋ฐฐํฌํ•˜๋Š” ์—ญํ• 

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒ์„ฑ

imageimage

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ด๋ฆ„์€ ๋‚˜์ค‘์— actions.yml์— ๋“ค์–ด๊ฐ€๋‹ˆ ๋‹ค๋ฅธ ์ด๋ฆ„๊ณผ ํ—ท๊ฐˆ๋ฆฌ์ง€ ์•Š๊ฒŒ ์ง€์–ด์ค€๋‹ค!

๋ฐฐํฌ ๊ทธ๋ฃน ์ƒ์„ฑ

imageimage

 

๋ฐฐํฌ ๊ทธ๋ฃน ์ด๋ฆ„์€ ๋งˆ์Œ๋Œ€๋กœ ์ง€์–ด์ฃผ๊ณ , ์„œ๋น„์Šค ์—ญํ• ์€ IAM์—์„œ ๋งŒ๋“ค์–ด๋†จ๋˜ codedeploy-role์„ ์ ์šฉํ•ด์ค€๋‹ค.

 

image

 

์œ„ ๊ณผ์ •์—์„œ ๋งŒ๋“  EC2 ์ธ์Šคํ„ด์Šค๋ฅผ ์—ฐ๊ฒฐํ•ด์ค€๋‹ค.

 

image

๋งˆ์ง€๋ง‰์œผ๋กœ CodeDeployDefault.AllAtOnce๋กœ ์„ค์ • ๋˜์–ด์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ๋Š” ๋น„ํ™œ์„ฑํ™” ํ•ด์ค€๋‹ค.

RDS

imageimageimage

 

์—”์ง„ ๋ฒ„์ „์€ ํ˜„์žฌ Spring Boot์—์„œ ์‚ฌ์šฉ ์ค‘์ธ ์—”์ง„ ๋ฒ„์ „๊ณผ ๋™์ผํ•˜๊ฒŒ ๋งž์ถฐ์•ผ ํ•œ๋‹ค!

 

imageimage

 

DB ์ธ์Šคํ„ด์Šค ์‹๋ณ„์ž๋Š” host์™€ ๊ด€๋ จ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ ๋‹นํžˆ ์ž˜ ์ง€์–ด์ฃผ๊ณ , ๋งˆ์Šคํ„ฐ ์‚ฌ์šฉ์ž ์ด๋ฆ„๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ง์ ‘ ์ง€์ •ํ•ด์ค€๋‹ค.

 

image

 

์Šคํ† ๋ฆฌ์ง€ ์ž๋™ ์กฐ์ •์„ ํ™œ์„ฑํ™”ํ•˜๋ฉด ๊ณผ๊ธˆ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋น„ํ™œ์„ฑํ™” ํ•ด์ค€๋‹ค!

 

image

 

EC2์—์„œ ๋“ค์–ด๊ฐ€๋Š” ์š”์ฒญ๋งŒ ํ—ˆ์šฉํ•˜๊ธฐ ์œ„ํ•ด EC2 ์ปดํ“จํŒ… ๋ฆฌ์†Œ์Šค์— ์—ฐ๊ฒฐ์„ ์„ ํƒํ•ด์ฃผ๊ณ , ์•ž์„œ ์ƒ์„ฑํ•œ EC2 ์ธ์Šคํ„ด์Šค๋ฅผ ์„ ํƒํ•ด์ค€๋‹ค. VPC๋Š” Default๋กœ ๋‘๋ฉด ๋œ๋‹ค!

 

image

 

ํผ๋ธ”๋ฆญ ์—‘์„ธ์Šค ๊ฐ€๋Šฅ์œผ๋กœ ๋ณ€๊ฒฝ! ๋งŒ์•ฝ ๊ฐ€๋Šฅ์œผ๋กœ ๋ณ€๊ฒฝ์ด ์•ˆ ๋œ๋‹ค๋ฉด, ๋ถˆ๊ฐ€๋Šฅ์œผ๋กœ ์ง„ํ–‰ํ•œ ๋’ค, RDS ์ƒ์„ฑ ํ›„ ์ง„ํ–‰ํ•  VPC ์„ค์ •์„ ๋งˆ์น˜๊ณ  ๋‹ค์‹œ ์ˆ˜์ •์„ ํ†ตํ•ด ๋ณ€๊ฒฝํ•˜๋ฉด ๋œ๋‹ค!

 

image

 

๋‚˜์ค‘์— ๋กœ์ปฌ์—์„œ ์ ‘์†์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ทœ์น™์„ ๋„ฃ์„ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ๋กœ์šด vpc ๋ณด์•ˆ ๊ทธ๋ฃน์„ ์ƒ์„ฑํ•ด์ค€๋‹ค.

 

image

 

์ž๋™ ๋ฐฑ์—…์„ ๋น„ํ™œ์„ฑํ™” ์‹œ์ผœ์ฃผ๊ณ , ์ดˆ๊ธฐ DB๋ฅผ ์ƒ์„ฑํ•˜๋ ค๋ฉด ์ด๋ฆ„์„ ์ž‘์„ฑํ•ด์ฃผ๊ณ , ํ•„์š”์—†๋‹ค๋ฉด ๋นˆ ์นธ์œผ๋กœ ๋ƒ…๋‘์ž!

 

image

 

๋ฒ„์ „์ด ์ž๋™์œผ๋กœ ์˜ฌ๋ผ๊ฐ€๋ฉด, Spring Boot์—์„œ๋„ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ณ ์ • ๋ฒ„์ „์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋น„ํ™œ์„ฑํ™” ํ•ด์ฃผ์ž!

์ด ์ƒํƒœ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒ์„ฑํ•˜๋ฉด ๋!

 

๊ทœ์น™ ์ •์˜

imageimage

 

์ƒ์„ฑ๋œ DB์— ๋“ค์–ด๊ฐ€์„œ ์—ฐ๊ฒฐ & ๋ณด์•ˆ ํƒญ ์•„๋ž˜์— ๋ณด์•ˆ๊ทธ๋ฃน ๊ทœ์น™์—์„œ ์œ ํ˜•์ด CIDR/IP - Inbound์ธ ๊ฒƒ์„ ํด๋ฆญํ•ด์„œ ๋“ค์–ด๊ฐ€์ž!

 

image

 

๊ธฐ์กด์— ๋“ฑ๋ก๋˜์–ด ์žˆ๋˜ MYSQL/Aurora๋ฅผ ๋ชจ๋“  ํŠธ๋ž˜ํ”ฝ์œผ๋กœ ๋ณ€๊ฒฝ ํ›„ ๊ทœ์น™ ์ €์žฅ!

VPC ์„ธํŒ…

image

 

์ƒ๋‹จ ๊ฒ€์ƒ‰์ฐฝ์— VPC๋ฅผ ๊ฒ€์ƒ‰ํ•œ ๋’ค, ๋ผ์šฐํŒ… ํ…Œ์ด๋ธ” ํƒญ์— ๋“ค์–ด๊ฐ€๋ณด์ž. ๋ณดํ†ต RDS-Pvt-rt๋กœ ๋œ ํ…Œ์ด๋ธ”์ด 1๊ฐœ๋งŒ ์กด์žฌํ•  ๊ฒƒ์ด๋‹ค. (ํ•„์ž๋Š” RDS 2๊ฐœ๋ฅผ ๋„์›Œ๋†”์„œ 2๊ฐœ์ž„)

ํ•ด๋‹น ํ…Œ์ด๋ธ” ID๋ฅผ ํด๋ฆญํ•ด ์ƒ์„ธ ํŽ˜์ด์ง€๋กœ ๋“ค์–ด๊ฐ„ ๋‹ค์Œ ๋ผ์šฐํŒ… ํŽธ์ง‘์„ ๋ˆŒ๋Ÿฌ์ฃผ์ž

 

image

 

local์€ ๊ทธ๋Œ€๋กœ ๋ƒ…๋‘๊ณ , ๋ผ์šฐํŒ… ์ถ”๊ฐ€๋ฅผ ๋ˆŒ๋Ÿฌ ์‚ฌ์ง„๊ณผ ๊ฐ™์ด ๋งž์ถฐ์ฃผ๋ฉด igw-012345678 ์ด๋Ÿฐ ์ฝ”๋“œ๊ฐ€ ์ƒ์„ฑ๋  ๊ฒƒ์ด๋‹ค. ์ด ์ƒํƒœ๋กœ ๋ณ€๊ฒฝ์‚ฌํ•ญ ์ €์žฅ!

DB ์—ฐ๋™

image

 

๋‹ค์‹œ RDS๋กœ ๋Œ์•„์™€์„œ ์—”๋“œํฌ์ธํŠธ๋ฅผ ๋ณต์‚ฌํ•ด์„œ DB ์—ฐ๊ฒฐ์„ ํ•ด๋ณด์ž!

์—”๋“œํฌ์ธํŠธ์˜ ์ฃผ์†Œ๋ฅผ Host์— ๋„ฃ์–ด์ฃผ๊ณ , ๊ธฐ์กด์— ์„ค์ •ํ•œ User์™€ Passowrd๋ฅผ ๋งž๊ฒŒ ์ž…๋ ฅํ•ด์ฃผ์ž!

 

image

CD ํ™˜๊ฒฝ ๊ตฌ์ถ•

์•ž์„œ CI ๊ณผ์ •์€ actions.yml์— ๋“ฑ๋ก๋˜์–ด ์žˆ์œผ๋‹ˆ ๊ตฌ์ถ•ํ•œ ๋‚ด์šฉ์„ ํ† ๋Œ€๋กœ CD ๊ณผ์ •์„ ์ถ”๊ฐ€ํ•˜์ž!

GitHub Actions

# Actions์—์„œ ๋ณด์—ฌ์งˆ workflow ์ด๋ฆ„
name: CI/CD

# ํŠธ๋ฆฌ๊ฑฐ ์ง€์ •
# master ๋ธŒ๋žœ์น˜์— push๊ฐ€ ์ผ์–ด๋‚  ๋•Œ ์‹คํ–‰
on:
  push:
    branches:
      - master

# env
env:
  S3_BUCKET_NAME: deploy-bucket
  PROJECT_NAME: project

jobs:
  CI-CD:
    runs-on: ubuntu-latest
    steps:

      ## Setting JDK
      ## ๋ณธ์ธ spring ๋ฒ„์ „์— ๋งž๋Š” ๋ฒ„์ „ ์ง€์ •
      ## https://github.com/actions/setup-java
      - uses: actions/checkout@v3
      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          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-

      ## Create application.yml
      - name: make prod application.yml
        if: contains(github.ref, 'master')
        run: |
          cd ./src/main/resources
          touch ./application.yml
          echo "${{ secrets.PROPERTIES_MAIN_PROD }}" > ./application.yml
        shell: bash

      ## Create application-prod.yml
      - name: make prod application-prod.yml
        if: contains(github.ref, 'master')
        run: |
          cd ./src/main/resources
          touch ./application-prod.yml
          echo "${{ secrets.PROPERTIES_PROD }}" > ./application-prod.yml
        shell: bash

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

      ## Gradle Build
      - name: Build with Gradle
        run: ./gradlew build

      - 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_IAM_ACCESS_KEY }}
          aws-secret-access-key: ${{ secrets.AWS_IAM_SECRET_KEY }}
          aws-region: ap-northeast-2

      # script files ๋ณต์‚ฌ
      - name: Copy script
        run: cp ./scripts/*.sh ./deploy

      # S3์— ์—…๋กœ๋“œ
      - name: Upload to S3
        run: aws s3 cp --region ap-northeast-2 ./$GITHUB_SHA.zip s3://$S3_BUCKET_NAME/$PROJECT_NAME/$GITHUB_SHA.zip

      # Deploy
      - name: Deploy
        run: |
          aws deploy create-deployment \
          --application-name deploy-dev-app \
          --deployment-config-name CodeDeployDefault.AllAtOnce \
          --deployment-group-name deploy-dev \
          --file-exists-behavior OVERWRITE \
          --s3-location bucket=deploy-bucket,bundleType=zip,key=project/$GITHUB_SHA.zip \
          --region ap-northeast-2 \

๋ณ€๊ฒฝํ•  ์‚ฌํ•ญ ์ •๋ฆฌ

  • env
    • S3_BUCKET_NAME : S3 ๋ฒ„ํ‚ท ์ด๋ฆ„
    • PROJECT_NAME : S3 ๋ฒ„ํ‚ท ๋‚ด๋ถ€์— ๋นŒ๋“œ๋œ ํŒŒ์ผ์„ ์ €์žฅํ•  ํด๋”(ํ”„๋กœ์ ํŠธ) ์ด๋ฆ„
  • Deploy
    • application-name : CodeDeploy์˜ application ์ด๋ฆ„
    • deployment-group-name : ํ•ด๋‹น application์˜ ๋ฐฐํฌ ๊ทธ๋ฃน ์ด๋ฆ„
    • s3-location
      • bucket : S3 ๋ฒ„ํ‚ท ์ด๋ฆ„
      • key : env์— ์žˆ๋Š” PROJECT_NAME์˜ value์™€ ๋™์ผํ•˜๊ฒŒ ์ž‘์„ฑ

deploy.sh ์ƒ์„ฑ

CodeDeploy๋ฅผ ํ†ตํ•ด S3์—์„œ EC2๋กœ ๋ณด๋‚ด๋Š” ๊ณผ์ •์—์„œ ๋ฐฐํฌ๋ฅผ ์š”์ฒญํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ž‘์„ฑํ•ด์ค€๋‹ค.

SpringBoot ํ”„๋กœ์ ํŠธ ์ตœ์ƒ์œ„์— scripts ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋งŒ๋“  ๋’ค, ์•„๋ž˜ ๋‚ด์šฉ์˜ ์ฃผ์„์€ ์ง€์šฐ๊ณ  ์ž‘์„ฑ

 

image
#!/bin/bash
BUILD_JAR=$(ls /home/ec2-user/action/build/libs/*.jar)
JAR_NAME=$(basename $BUILD_JAR)
echo "> build ํŒŒ์ผ๋ช…: $JAR_NAME" >> /home/ec2-user/action/deploy.log

echo "> build ํŒŒ์ผ ๋ณต์‚ฌ" >> /home/ec2-user/action/deploy.log
DEPLOY_PATH=/home/ec2-user/action/
cp $BUILD_JAR $DEPLOY_PATH

echo "> ํ˜„์žฌ ์‹คํ–‰์ค‘์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ pid ํ™•์ธ" >> /home/ec2-user/action/deploy.log
CURRENT_PID=$(pgrep -f $JAR_NAME)

if [ -z $CURRENT_PID ]
then
  echo "> ํ˜„์žฌ ๊ตฌ๋™์ค‘์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์—†์œผ๋ฏ€๋กœ ์ข…๋ฃŒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." >> /home/ec2-user/action/deploy.log
else
  echo "> kill -15 $CURRENT_PID"
  kill -15 $CURRENT_PID
  sleep 5
fi

DEPLOY_JAR=$DEPLOY_PATH$JAR_NAME
echo "> DEPLOY_JAR ๋ฐฐํฌ"    >> /home/ec2-user/action/deploy.log
nohup java -jar $DEPLOY_JAR >> /home/ec2-user/deploy.log 2>/home/ec2-user/action/deploy_err.log &

appspec.yml ์ƒ์„ฑ

image

ํ•ด๋‹น ํŒŒ์ผ์€ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ์ตœ์ƒ์œ„์— ๋”ฐ๋กœ ๋งŒ๋“ค์–ด ์ค€๋‹ค.

์ตœ์ข…์ ์œผ๋กœ CodeDeploy๊ฐ€ EC2 ํ™˜๊ฒฝ์— S3์—์„œ ๊ฐ€์ ธ์˜จ jar ํŒŒ์ผ์„ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด์ฃผ๋Š” ํŒŒ์ผ

version: 0.0
os: linux
# S3์— ์žˆ๋Š” zip ํŒŒ์ผ์ด EC2์— ๋ฐฐํฌ๋  ์œ„์น˜๋ฅผ ์ง€์ •
files:
  # CodeDeploy์—์„œ ์ „๋‹ฌํ•ด ์ค€ ํŒŒ์ผ ์ค‘ destination์œผ๋กœ ์ด๋™์‹œํ‚ฌ ๋Œ€์ƒ์„ ๋ฃจํŠธ๋กœ ์ง€์ •(์ „์ฒดํŒŒ์ผ)
  - source: /
    # source์—์„œ ์ง€์ •๋œ ํŒŒ์ผ์„ ๋ฐ›์„ ์œ„์น˜, ์ดํ›„ jar๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋“ฑ์€ destination์—์„œ ์˜ฎ๊ธด ํŒŒ์ผ๋“ค๋กœ ์ง„ํ–‰
    destination: /home/ec2-user/action/ 
    overwrite: yes

# CodeDeploy์—์„œ EC2์„œ๋ฒ„๋กœ ๋„˜๊ฒจ์ค€ ํŒŒ์ผ๋“ค์„ ๋ชจ๋‘ ec2-user๊ถŒํ•œ์„ ๊ฐ–๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
permissions: 
  - object: /
    pattern: "**"
    owner: ec2-user
    group: ec2-user

# ApplicationStart ๋‹จ๊ณ„์—์„œ deploy.sh๋ฅผ ์‹คํ–‰์‹œํ‚ค๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
# CodeDeploy๋ฐฐํฌ ๋‹จ๊ณ„์—์„œ ์‹คํ–‰ํ•  ๋ช…๋ น์–ด๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
hooks:
  # deploy.sh๋ฅผ ec2-user๊ถŒํ•œ์œผ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  ApplicationStart: 
    - location: scripts/deploy.sh
      # ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰ 60์ดˆ ์ด์ƒ ์ˆ˜ํ–‰๋˜๋ฉด ์‹คํŒจ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
      timeout: 60 
      runas: ec2-user

๋ ˆํผ๋Ÿฐ์Šค

์ฃผํ˜•๋‹˜ ๋ธ”๋กœ๊ทธ - ๊ฐ€๋น„์•„ + Amazon Linux + Nginx + Cerbot/SSL์„ ํ™œ์šฉํ•œ https ์„ค์ •
Github Actions Variable
๋ฑ€๊ทค๋‹˜ ๋ธ”๋กœ๊ทธ
๊น€์žฌ์„ฑ๋‹˜ ๋ธ”๋กœ๊ทธ
danuri๋‹˜ ๋ธ”๋กœ๊ทธ
zzang9ha๋‹˜ ๋ธ”๋กœ๊ทธ

'DevOps > AWS' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[AWS] - Spring Boot ํ”„๋กœ์ ํŠธ ๋ฐฐํฌ(2)  (0) 2023.09.11