๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
DevOps

GitHub Actions์„ ํ™œ์šฉํ•˜์—ฌ ํด๋ผ์šฐ๋“œ VM ์„œ๋ฒ„์— ์Šคํ”„๋ง ๋ถ€ํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ jar ํŒŒ์ผ ๋ฐฐํฌํ•˜๊ธฐ

by ํ‘์‹œ๋ฐ” 2024. 5. 25.

๐Ÿ™„ GitHub Actions?

GitHub Actions๋Š” GitHub์—์„œ ์ œ๊ณตํ•˜๋Š” CI/CD(Continuous Integration/Continuous Deployment) ํ”Œ๋žซํผ์ด๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž๋Š” ์ฝ”๋“œ๋ฅผ ๋นŒ๋“œ, ํ…Œ์ŠคํŠธ, ๋ฐฐํฌํ•˜๋Š” ์ž๋™ํ™”๋œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. GitHub Actions๋Š” ๋‹ค์–‘ํ•œ ์ด๋ฒคํŠธ(์˜ˆ: ์ฝ”๋“œ ํ‘ธ์‹œ, ํ’€ ๋ฆฌํ€˜์ŠคํŠธ ์ƒ์„ฑ ๋“ฑ)์— ๋ฐ˜์‘ํ•˜์—ฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์‚ฌ์ด๋“œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ œ์ž‘ํ•˜๋Š”๋ฐ ์  ํ‚จ์Šค(Jenkins)๊นŒ์ง€๋Š” ๋ถ€๋‹ด์Šค๋Ÿฝ๊ณ , ๊ฐ€๋ณ๊ณ  ์‰ฌ์šด ๋ฐฐํฌ ๋ฐฉ์‹์„ ์„ ํƒํ•˜๊ณ  ๊ณ ๋ฏผํ•œ๋‹ค๋ฉด GitHub Actions๋Š” ๊ดœ์ฐฎ์€ ๋Œ€์•ˆ์ด ๋  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

1. ์ค€๋น„

ํ•ด๋‹น ํฌ์ŠคํŠธ๋Š” GitHub Actions๋ฅผ ํ™œ์šฉํ•ด์„œ ํด๋ผ์šฐ๋“œ VM ์„œ๋ฒ„์— ์Šคํ”„๋ง ๋ถ€ํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ jar ํŒŒ์ผ์„ ๋ฐฐํฌํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์„ค๋ช…ํ•œ๋‹ค.

 

์ค€๋น„๋œ ํ™˜๊ฒฝ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 

- JDK 17

- Spring Boot 3

- Gradle

- Github Actions

- GCP VM ์ธ์Šคํ„ด์Šค (Ubuntu 22 LTS)

- Github Private Repository

 

ํ•ด๋‹น ํฌ์ŠคํŠธ๋Š” Docker ๋ฐฉ์‹์ด ์•„๋‹Œ ๊ฐ„๋‹จํ•˜๊ฒŒ ์Šคํ”„๋ง ๋ถ€ํŠธ jar ํŒŒ์ผ์„ ์‹คํ–‰์‹œํ‚ค๋Š” ๋ฐฐํฌ ๋ฐฉ์‹์„ ๋‹ค๋ฃฌ๋‹ค.

Docker ๋ฐฉ์‹์œผ๋กœ ๋ฐฐํฌํ•˜๋Š” ๊ฑธ ์›ํ•œ๋‹ค๋ฉด ๋‹ค๋ฅธ ํฌ์ŠคํŠธ๋ฅผ ์ฐพ์•„์•ผ ํ•œ๋‹ค.

2. Private Repository ์ƒ์„ฑ

Spring Boot 3, Gradle, Jdk 17 ํ™˜๊ฒฝ์œผ๋กœ ์ƒˆ๋กœ์šด Git Repository๋ฅผ Private์œผ๋กœ ์ƒ์„ฑํ•œ๋‹ค.

 

3. Secrets ์„ค์ •ํ•˜๊ธฐ

๋ฐฐํฌ์šฉ yml ํŒŒ์ผ ์ž‘์„ฑ ์ „์— Secret ๊ฐ’์„ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.

 

1) Settings - Security-Sercrets and variables - Actions ํƒญ ๋“ค์–ด๊ฐ€๊ธฐ

 

 

2) Secret ๊ฐ’ ๋“ฑ๋กํ•˜๊ธฐ

 

์ด 4๊ฐœ์˜ Secret์„ ๋“ฑ๋กํ•ด์•ผ ํ•˜๋ฉฐ ๊ฐ Secret์€ ๋‹ค์Œ ๊ฐ’๋“ค์„ ์˜๋ฏธํ•œ๋‹ค.

 

GCP_SSH_PRIVATE_KEY : SSH private key
GCP_SSH_USER : SSH๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ณ„์ •
GCP_VM_IP : GCP VM ์ธ์Šคํ„ด์Šค์˜ IP ์ฃผ์†Œ
JAR_NAME : ํ”„๋กœ์ ํŠธ ๋นŒ๋“œํ•˜๋ฉด ๋‚˜์˜ค๋Š” jar ํŒŒ์ผ์˜ ์ด๋ฆ„

 

๊ฐ Secret์„ GCP ํ™˜๊ฒฝ์—์„œ ํš๋“ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•œ๋‹ค.

1. GCP_SSH_PRIVATE_KEY

Github Actions์—์„œ SSH๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ์„œ๋ฒ„๋กœ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด PRIVATE ๊ฐ’์„ ํ•„์š”๋กœ ํ•œ๋‹ค.

ํ•ด๋‹น ๊ฐ’์€ VM ์„œ๋ฒ„์—์„œ ssh-keygen ๋ช…๋ น์–ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด ํš๋“ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

ssh-keygen -t ed25519 -f ~/.ssh/id-rsa -C [์‚ฌ์šฉ์ž ๊ณ„์ • ID]

 

[์‚ฌ์šฉ์ž ๊ณ„์ • ID] ์—๋Š” VM ์„œ๋ฒ„์— ๋ฐฐํฌํ•˜๋Š” ์‚ฌ์šฉ์ž ๊ณ„์ •์˜ ID๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค.

๋ฐฐํฌ์šฉ ์‚ฌ์šฉ์ž๊ฐ€ ๋”ฐ๋กœ ์กด์žฌํ•œ๋‹ค๋ฉด ํ•ด๋‹น ID๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ , ๋”ฐ๋กœ ์—†๋‹ค๋ฉด SSH ์ ‘์† ๊ฐ€๋Šฅํ•œ ๋‹ค๋ฅธ ๊ณ„์ •์„ ์ถ”๊ฐ€ํ•œ๋‹ค.

 

์ดํ›„ ~/.ssh ์œ„์น˜๋กœ ์ด๋™ํ•ด์„œ ํŒŒ์ผ ๋ชฉ๋ก์„ ์ฐพ์•„๋ณด๋ฉด  authorized_keysid-rsaid-rsa.pub 3๊ฐœ์˜ ํŒŒ์ผ๋“ค์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ์ค‘ id-rsa ํŒŒ์ผ ๋‚ด์šฉ ์ „์ฒด(-----BEGIN OPENSSH ๋ถ€ํ„ฐ PRIVATE KEY ----- ๊นŒ์ง€)๋ฅผ ๋ณต์‚ฌํ•ด์„œ GCP_SSH_PRIVATE_KEY๋กœ ๋“ฑ๋กํ•˜๋ฉด ๋œ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  id-rsa.pub ํŒŒ์ผ ๋‚ด์šฉ ์ „์ฒด๋ฅผ ๋ณต์‚ฌํ•ด์„œ authorized_keys ํŒŒ์ผ์— ๋ถ™์—ฌ ๋„ฃ๊ธฐ ํ•œ๋‹ค.

2. GCP_SSH_USER 

GCP_SSH_PRIVATE_KEY ์ƒ์„ฑํ•  ๋•Œ [์‚ฌ์šฉ์ž ๊ณ„์ • ID]๋กœ ์ž…๋ ฅํ•œ ๊ณ„์ •์„ ๋“ฑ๋กํ•˜๋ฉด ๋œ๋‹ค.

3. GCP_VM_IP

GCP VM ์ธ์Šคํ„ด์Šค์— ์ ‘์† ๊ฐ€๋Šฅํ•œ ์™ธ๋ถ€ IP๋ฅผ ๋“ฑ๋กํ•˜๋ฉด ๋œ๋‹ค.

4. JAR_NAME

์Šคํ”„๋ง ๋ถ€ํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋นŒ๋“œํ•˜๋ฉด ๋‚˜์˜ค๋Š” ์ด๋ฆ„ jar ํŒŒ์ผ์˜ ์ด๋ฆ„์„ ์ ์œผ๋ฉด ๋œ๋‹ค.

ํ”„๋กœ์ ํŠธ์— ์•„๋ฌด ๊ฒƒ๋„ ์„ค์ •ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด ๋นŒ๋“œ ํ›„์— build/libs์— ์žˆ๋Š” jar ํŒŒ์ผ ์ด๋ฆ„์„ ์ ๋Š”๋‹ค.

4. CI ๊ตฌ์ถ•

์ƒ์„ฑํ•œ ์ž๋ฐ” ํ”„๋กœ์ ํŠธ๋ฅผ jar ํŒŒ์ผ๋กœ ๋นŒ๋“œํ•˜๋Š” ์ž‘์—…์„ ์ž๋™ํ™”ํ•  ๊ฒƒ์ด๋‹ค.

 

1) Actions - Java with Gradle์˜ Configure๋ฅผ ์„ ํƒํ•œ๋‹ค.

2) Deploy.yml์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•œ๋‹ค.

 

name: Java CI with Gradle

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

jobs:
  build:

    runs-on: ubuntu-latest
    permissions:
      contents: read

    steps:
    # ๊ธฐ๋ณธ ์ฒดํฌ์•„์›ƒ
    - name: Checkout
      uses: actions/checkout@v4
    # Gradlew ์‹คํ–‰ ํ—ˆ์šฉ
    - name: Run chmod to make gradlew executable
      run: chmod +x ./gradlew
    # JDK 17 ์„ธํŒ…
    - name: Set up JDK 17
      uses: actions/setup-java@v4
      with:
        java-version: '17'
        distribution: 'temurin'
    # Gradle ์„ค์ •
    - name: Setup Gradle
      uses: gradle/actions/setup-gradle@v3
    # Gradle ๋นŒ๋“œ
    - name: Build with Gradle
      run: ./gradlew build
    # ๋ฐฐํฌ ํŒจํ‚ค์ง€ ์ค€๋น„
    - name: Prepare deployment package
      run: |
        mkdir -p deploy
        cp build/libs/${{ secrets.JAR_NAME }}.jar deploy/
    # SSH ํ‚ค ์ค€๋น„
    - name: Add SSH key
      uses: webfactory/ssh-agent@v0.9.0
      with:
        ssh-private-key: ${{ secrets.GCP_SSH_PRIVATE_KEY }}
    # GCP VM์— ๋ฐฐํฌ
    - name: Deploy to GCP VM
      run: |
        ssh -o StrictHostKeyChecking=no ${{ secrets.GCP_SSH_USER }}@${{ secrets.GCP_VM_IP }} 'sudo service shiba stop' 
        scp -o StrictHostKeyChecking=no deploy/${{ secrets.JAR_NAME }}.jar ${{ secrets.GCP_SSH_USER }}@${{ secrets.GCP_VM_IP }}:/home/${{ secrets.GCP_SSH_USER }}/app/ 
        ssh -o StrictHostKeyChecking=no ${{ secrets.GCP_SSH_USER }}@${{ secrets.GCP_VM_IP }} 'sudo service shiba start'

 

ํ•ด๋‹น ์›Œํฌํ”Œ๋กœ์šฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹จ๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.

 

1. ์ฝ”๋“œ ์ฒดํฌ์•„์›ƒ - actions/checkout@v4 ์•ก์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ €์žฅ์†Œ์˜ ์ฝ”๋“œ๋ฅผ ์ฒดํฌ์•„์›ƒํ•œ๋‹ค.

2. JDK 17 ์„ค์ • - actions/setup-java@v4 ์•ก์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ JDK 17์„ ์„ค์ •ํ•œ๋‹ค.

3. Gradle ์„ค์ • - gradle/actions/setup-gradle@v3 ์•ก์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ Gradle์„ ์„ค์ •ํ•œ๋‹ค.

4. Gradle ๋นŒ๋“œ -./gradlew build ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ํ”„๋กœ์ ํŠธ๋ฅผ ๋นŒ๋“œํ•œ๋‹ค.

5. ๋ฐฐํฌ ํŒจํ‚ค์ง€ ์ค€๋น„ - ๋นŒ๋“œ๋œ jar ํŒŒ์ผ์„ deploy ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ๋ณต์‚ฌํ•œ๋‹ค.

6. SSH ํ‚ค ์ถ”๊ฐ€ - webfactory/ssh-agent@v0.9.0 ์•ก์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ SSH ํ‚ค๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

7. GCP VM์— ๋ฐฐํฌ - scp ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ jar ํŒŒ์ผ์„ GCP VM ์ธ์Šคํ„ด์Šค๋กœ ๋ณต์‚ฌํ•˜๊ณ , ssh ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›๊ฒฉ ์„œ๋ฒ„์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•œ๋‹ค. (๋ฐฉํ™”๋ฒฝ 22 ํฌํŠธ๊ฐ€ ๋ฐ˜๋“œ์‹œ ์—ด๋ ค์žˆ์–ด์•ผ ํ•œ๋‹ค.)

โ›”๏ธ  ๋ธŒ๋žœ์น˜ ๋ช…์ด main์ด ์•„๋‹Œ ๊ฒฝ์šฐ์—๋Š”, ๋ณธ์ธ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ํ™˜๊ฒฝ์— ๋งž๋Š” ๋ธŒ๋žœ์น˜๋กœ ์ˆ˜์ •ํ•ด์•ผ ํ•œ๋‹ค.

์šฐ๋ถ„ํˆฌ ํ™˜๊ฒฝ์—์„œ ์Šคํ”„๋ง ๋ถ€ํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋น„์Šค๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ ๊ฒŒ์‹œ๋ฌผ์„ ์ฐธ๊ณ ํ•œ๋‹ค.

 

Ubntu ํ™˜๊ฒฝ์—์„œ Spring Boot Application์„ ๋“ฑ๋กํ•˜๊ธฐ

 

์ž‘์„ฑ ํ›„์—, ์šฐ์ธก ์ƒ๋‹จ์— ์ปค๋ฐ‹ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ณ  Actions ํƒญ์œผ๋กœ ๋“ค์–ด๊ฐ€์„œ ๋นŒ๋“œ๊ฐ€ ์ˆ˜ํ–‰๋˜๋Š”์ง€ ํ™•์ธํ•ด ๋ณธ๋‹ค.

 

๋นŒ๋“œ๊ฐ€ ์„ฑ๊ณตํ–ˆ๋‹ค๋ฉด ์œ„ ์ด๋ฏธ์ง€์ฒ˜๋Ÿผ ์ดˆ๋ก์ƒ‰ ๋นŒ๋“œ ์ฒดํฌ ํ‘œ์‹œ๊ฐ€ ๋‚˜์˜จ๋‹ค.

5. ๋นŒ๋“œ ํ™•์ธ

์ดํ›„ VM ์„œ๋ฒ„์— ์ ‘์†ํ•ด์„œ app ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์ ‘๊ทผํ•˜๋ฉด Secret์œผ๋กœ ์„ค์ •ํ•œ SNAPSHOT ํŒŒ์ผ์ด ์กด์žฌํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

netstat -tnlp ๋ช…๋ น์–ด๋ฅผ ์ˆ˜ํ–‰ํ•ด์„œ ์ •์ƒ์ ์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํฌํŠธ๊ฐ€ ๋– ์žˆ๋Š”์ง€ ํ™•์ธํ•ด ๋ณด๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํŠธ๋กค๋Ÿฌ์— ๋“ฑ๋กํ•œ API๋ฅผ ํ˜ธ์ถœํ•ด ๋ณด์ž.

๐Ÿ“š REFERENCE

https://github.com/webfactory/ssh-agent

๋Œ“๊ธ€