DevLog ๐Ÿ˜ถ

[Jenkins] AWS ์ธ์Šคํ„ด์Šค๋ฅผ ์  ํ‚จ์Šค๋กœ ๋ฐฐํฌํ•ด๋ณด๊ธฐ - 2ํŽธ ๋ณธ๋ฌธ

๊ฐœ๋ฐœ์ผ์ง€

[Jenkins] AWS ์ธ์Šคํ„ด์Šค๋ฅผ ์  ํ‚จ์Šค๋กœ ๋ฐฐํฌํ•ด๋ณด๊ธฐ - 2ํŽธ

dolmeng2 2023. 5. 30. 20:32

๐ŸŒฑ ๋“ค์–ด๊ฐ€๊ธฐ ์ „

์ง€๋‚œ ํฌ์ŠคํŒ…์€ ์  ํ‚จ์Šค๋ฅผ ์„ค์น˜ํ•˜๊ณ  ํ•„์š”ํ•œ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์„ค์น˜ํ•˜๋Š” ๊ณผ์ •๊นŒ์ง€ ์ง„ํ–‰ํ•˜์˜€๋‹ค.

 


๐ŸŒฑ ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ WebHook ๋“ฑ๋กํ•˜๊ธฐ

์šฐ๋ฆฌ๋Š” ๊นƒํ—ˆ๋ธŒ ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ์˜ ํŠน์ • ๋ธŒ๋žœ์น˜์— push ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ž๋™์œผ๋กœ ๋ฐฐํฌ๊ฐ€ ์ผ์–ด๋‚˜๊ฒŒ ๋งŒ๋“ค ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—, ํ•ด๋‹น push ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด์„œ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก 'webhook'์ด๋ผ๋Š” ์นœ๊ตฌ๋ฅผ ๋“ฑ๋กํ•ด์•ผ ํ•œ๋‹ค.

 

๋“ฑ๋กํ•˜๊ณ  ์‹ถ์€ ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ์˜ Settings > Webhooks > Add webhook์„ ํด๋ฆญํ•œ๋‹ค.

์ด๋Ÿฐ ์‹์œผ๋กœ payload URL๊ณผ content-type์„ ์ง€์ •ํ•ด์ค€๋‹ค.

aws ์ธ์Šคํ„ด์Šค๋กœ ๋„์› ๋‹ค๋ฉด publicIP:8081๊ณผ ๊ฐ™์€ ํ˜•ํƒœ๊ฐ€ ์œ„ URL์— ๋“ค์–ด๊ฐˆ ๊ฒƒ์ด๋‹ค.

โญ๏ธ ์—ฌ๊ธฐ์„œ ์ œ์ผ ์ค‘์š”ํ•œ ๊ฑฐ, ๋์— ๊ผญ /github-webhook/ ๋ถ™์—ฌ์ค˜์•ผ ํ•œ๋‹ค... ์ด๊ฑฐ ๋•Œ๋ฌธ์— 1์‹œ๊ฐ„ ๋„˜๊ฒŒ ์‚ฝ์งˆํ–ˆ๋‹ค.

 

์„ฑ๊ณต์ ์œผ๋กœ ์›นํ›…์„ ๋“ฑ๋กํ–ˆ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋ชฉ๋ก์— ๋œจ๊ฒŒ ๋œ๋‹ค.

 


๐ŸŒฑ ๊นƒํ—ˆ๋ธŒ ํ† ํฐ ๋ฐœ๊ธ‰๋ฐ›๊ธฐ

์  ํ‚จ์Šค์—์„œ ๊นƒํ—ˆ๋ธŒ์— ๋Œ€ํ•œ ์ ‘๊ทผ ๊ถŒํ•œ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊นƒํ—ˆ๋ธŒ์—์„œ ํ‚ค๋ฅผ ๋ฐœ๊ธ‰๋ฐ›์•„ ์  ํ‚จ์Šค์—๊ฒŒ ์„ค์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

๊นƒํ—ˆ๋ธŒ ๊ณ„์ •์— ๋Œ€ํ•œ settings์— ๋“ค์–ด๊ฐ€์ค€๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์™ผ์ชฝ์— ์žˆ๋Š” 'Developer Settings'์— ๋“ค์–ด๊ฐ„๋‹ค.

Personal access tokens > Tokens (classic) > Generate new token > Generate new token (classic)์„ ํด๋ฆญํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  Select Scopes์—์„œ repo, admin:org, admin:repo_hook 3๊ฐ€์ง€์— ๋Œ€ํ•œ ๊ถŒํ•œ์„ ์ค€๋‹ค.

๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๋ฉด ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ์— ๋Œ€ํ•œ ๊ถŒํ•œ, orgnaization์— ๋Œ€ํ•œ ๊ถŒํ•œ, ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ ํ›…(์›นํ›… ๊ฐ™์€)์— ๋Œ€ํ•œ ๊ถŒํ•œ์„ ์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

Generate token์„ ํด๋ฆญํ•˜๋ฉด ํ† ํฐ ์ •๋ณด๊ฐ€ ๋‚˜์˜ฌ ํ…๋ฐ, ์žŠ์–ด๋ฒ„๋ฆฌ์ง€ ์•Š๊ฒŒ ๋‹ค๋ฅธ ๊ณณ์— ๋ณต์‚ฌํ•ด๋‘์ž.

 


 

๐ŸŒฑ ์  ํ‚จ์Šค์™€ ๊นƒํ—ˆ๋ธŒ ์—ฐ๋™ํ•ด์ฃผ๊ธฐ - ํ† ํฐ ์—ฐ๋™ 

๋จผ์ €, ์œ„์—์„œ ๋ฐœ๊ธ‰๋ฐ›์€ ๊นƒํ—ˆ๋ธŒ ํ† ํฐ ์ •๋ณด๋ฅผ ์  ํ‚จ์Šค์— ๋“ฑ๋กํ•ด์ฃผ๋Š” ๊ณผ์ •์„ ์ง„ํ–‰ํ•ด์•ผ ํ•œ๋‹ค.

๊นƒํ—ˆ๋ธŒ ๋Œ€์‹œ๋ณด๋“œ์—์„œ Manage Jenkins > ์•„๋ž˜์ชฝ์˜ Credentials ํด๋ฆญ!

 

Stores Scope to Jenkin์—์„œ Domains์˜ (globals) ํด๋ฆญ. (์ „์—ญ์ ์œผ๋กœ ์„ค์ •์„ ๋“ฑ๋กํ•ด์ค˜์•ผ ํ•จ)

Add Credentials ํด๋ฆญ. (1ํŽธ๋ถ€ํ„ฐ ๋”ฐ๋ผํ–ˆ๋‹ค๋ฉด ์›๋ž˜ ์—ฌ๊ธฐ์— ssh ํ‚ค๋„ ์žˆ์–ด์•ผ ํ•˜๋Š”๋ฐ, ์ด์ „์— ์บก์ณํ•œ ์ž๋ฃŒ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š๋ผ ์ด๋ ‡๊ฒŒ ๋๋‹ค... ใ…Žใ…Ž)

 

์ดํ›„ Username with password ์ง€์ • ํ›„,  ๊นƒํ—ˆ๋ธŒ ์•„์ด๋””์™€ ์œ„์—์„œ ๋ฐœ๊ธ‰๋ฐ›์€ token ์ •๋ณด, ๊ทธ๋ฆฌ๊ณ  id๋ฅผ ์ง€์ •ํ•ด์ค€๋‹ค.

์ตœ์ข…์ ์œผ๋กœ ์ด๋Ÿฐ ๋ชจ์Šต์œผ๋กœ ๋“ฑ๋ก์ด ์™„๋ฃŒ๋˜์—ˆ์„ ๊ฒƒ์ด๋‹ค.

๐Ÿ’ก ์—ฌ๊ธฐ์„œ secret-id๋Š” ์ง€๊ธˆ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š์•„๋„ ๋œ๋‹ค. ๋ฐ”๋กœ ์•„๋ž˜์—์„œ ์ง„ํ–‰ํ•  ์˜ˆ์ •์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค ใ…Žใ…Ž

 


 

๐ŸŒฑ ์  ํ‚จ์Šค์™€ ๊นƒํ—ˆ๋ธŒ ์—ฐ๋™ํ•ด์ฃผ๊ธฐ - ๊นƒํ—ˆ๋ธŒ ์„œ๋ฒ„ ์—ฐ๋™

๋‹ค์‹œ ์  ํ‚จ์Šค ๋Œ€์‹œ๋ณด๋“œ์—์„œ Manage Jenkins > System์„ ํด๋ฆญํ•œ๋‹ค.

๋‚ด๋ฆฌ๋‹ค ๋ณด๋ฉด GitHub๋ผ๋Š” ๊ฒŒ ์žˆ์„ ํ…๋ฐ, Name ์ง€์ • ํ›„ Credentials ๋ฐ‘์— ์žˆ๋Š” Add > Jenkins๋ฅผ ํด๋ฆญํ•ด์ค€๋‹ค.

 

๊ทธ๋Ÿผ ์ด๋Ÿฐ ์‹์œผ๋กœ ๋˜ ๋‹ค์‹œ Credential์„ ๋“ฑ๋กํ•˜๋Š” ๊ณผ์ •์ด ์žˆ์„ ํ…๋ฐ, ์—ฌ๊ธฐ์„œ ์œ„์—์„œ ๋ฐœ๊ธ‰๋ฐ›์€ ๊นƒํ—ˆ๋ธŒ token์„ ๋˜ ๋‹ค์‹œ ๋„ฃ์–ด์ค€๋‹ค.

์•ž์„œ ์›นํ›… ๋“ฑ๋ก์‹œ, ๊นƒํ—ˆ๋ธŒ ์ธก์—์„œ POST ์š”์ฒญ์œผ๋กœ ์šฐ๋ฆฌ์˜ ์  ํ‚จ์Šค ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค๊ณ  ํ–ˆ์—ˆ๋Š”๋ฐ, ์—ฌ๊ธฐ์„œ ์ธ์ฆ ์ •๋ณด๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๊ณผ์ •์ด๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

 Credentials์— ์œ„์—์„œ ์ง€์ •ํ•œ id ๊ฐ’์„ ์„ ํƒํ•ด์ฃผ๊ณ , Test Connection์ด ์„ฑ๊ณตํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.

 


 

๐ŸŒฑ ์  ํ‚จ์Šค ์žก ์ƒ์„ฑํ•˜๊ธฐ

๋‹ค์‹œ ๋Œ€์‹œ๋ณด๋“œ๋กœ ๋Œ์•„์™€์„œ, ์ด๋ฒˆ์—๋Š” New Item์„ ํด๋ฆญํ•œ๋‹ค.

์•„์ดํ…œ ์ด๋ฆ„์€ ์ž์œ ๋กญ๊ฒŒ ์„ค์ •ํ•ด์ฃผ๊ณ , Pipeline์„ ์„ ํƒํ•œ๋‹ค.

Github project, Build Triggers > Github hook trigger for GITscm polling์„ ์ฒดํฌํ•œ๋‹ค.

 


 

๐ŸŒฑ ํŒŒ์ดํ”„๋ผ์ธ ์Šคํฌ๋ฆฝํŠธ ์ž‘์„ฑํ•˜๊ธฐ

์ •๋ง ๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„์ด๋‹ค. ํŒŒ์ดํ”„๋ผ์ธ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

 

์šฐ์„ , ํ˜„์žฌ ๋‚˜์˜ EC2 ์ €์žฅ์†Œ์˜ ๊ตฌ์กฐ์ด๋‹ค.

 

pipeline {
    agent any
    tools {
        gradle 'gradle'
    }
    stages {
        stage('Git Clone') {
            steps {
                git branch: '{branch_name}', credentialsId: 'secret-id-github', url: '{Git Repository URL}'
            }
        }
        stage('Build') {
            steps {
                sh "./gradlew clean build"
            }
        }
        stage('Deploy') {
            steps {
                sshagent(credentials: ['journey-shop-ec2']) {
                    sh '''
                        ssh -o StrictHostKeyChecking=no ${DEPLOY_HOST} uptime
                        scp build/libs/jwp-shopping-order.jar ${DEPLOY_HOST}:/home/ubuntu/jwp-shopping-order
                        ssh -t ${DEPLOY_HOST} /home/ubuntu/jwp-shopping-order/deploy.sh
                    '''
                }
            }
        }
    }
    environment {
        DEPLOY_HOST = '{EC2 ์ ‘์† ์‚ฌ์šฉ์ž ์ด๋ฆ„}@{EC2 private IP}'
    }
}

๊ณผ์ •์€ ๊ฐ„๋‹จํ•˜๋‹ค.

์›ํ•˜๋Š” ๊นƒ ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ์˜ ๋ธŒ๋žœ์น˜์—์„œ clone์„ ํ•œ ๋‹ค์Œ, gradlew๋ฅผ ํ†ตํ•ด ๋นŒ๋“œ๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋ฐฐํฌ๋ฅผ ์‹œ์ž‘ํ•˜๋Š”๋ฐ, ssh agent๋ฅผ ์‚ฌ์šฉํ•œ ๋•๋ถ„์— ์œ„์™€ ๊ฐ™์ด ssh ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

1. ์›๊ฒฉ ํ˜ธ์ŠคํŠธ์— ๋Œ€ํ•ด์„œ SSH ์—ฐ๊ฒฐ ํ›„ uptime์„ ํ†ตํ•ด ์‹คํ–‰ ์‹œ๊ฐ„ ์ •๋ณด๋ฅผ ํ‘œ์‹œํ•œ๋‹ค. ์ด๋•Œ, ํ˜ธ์ŠคํŠธ์˜ ๊ณต๊ฐœ ํ‚ค๋ฅผ ๊ฒ€์‚ฌํ•˜์ง€ ์•Š๊ณ  SSH ์—ฐ๊ฒฐ์„ ์ง„ํ–‰ํ•œ๋‹ค.
2. ์œ„์—์„œ ๋นŒ๋“œ๋œ build/libs/jwp-shopping-order.jar ํŒŒ์ผ์„ ์ง€์ •ํ•œ ๊ฒฝ๋กœ๋กœ ๋ณต์‚ฌํ•œ๋‹ค.
3. ssh ์—ฐ๊ฒฐ ํ›„ deploy.sh ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. (๋ฐฐํฌ)

โญ๏ธ ์ด๋•Œ, ์›๊ฒฉ ํ˜ธ์ŠคํŠธ ์ •๋ณด๋Š” ์ด๋ฏธ ์  ํ‚จ์Šค ์ž์ฒด๊ฐ€ EC2 ์œ„์— ๋„์›Œ์ ธ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— private IP๋กœ ์ ‘์†ํ•ด์•ผ ํ•œ๋‹ค.

 

๋‚˜์˜ ๊ฒฝ์šฐ ์‰˜ ์Šคํฌ๋ฆฝํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•˜์˜€๋‹ค.

#!/bin/bash
REPOSITORY=/home/ubuntu/jwp-shopping-order
PROJECT_NAME=jwp-shopping-order
cd $REPOSITORY/$PROJECT_NAME/
echo "> ํ˜„์žฌ ๊ตฌ๋™์ค‘์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ pid ํ™•์ธ"
CURRENT_PID=$(sudo lsof -i tcp:8080 | awk 'NR!=1 {print$2}')
echo "ํ˜„์žฌ ๊ตฌ๋™์ค‘์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜pid: $CURRENT_PID"
if [ -z "$CURRENT_PID" ]; then
    echo "> ํ˜„์žฌ ๊ตฌ๋™์ค‘์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์—†์œผ๋ฏ€๋กœ ์ข…๋ฃŒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."
else
    echo "> kill -9 $CURRENT_PID"
    sudo kill -9 $CURRENT_PID
    sleep 5
fi
echo "> ์ƒˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐฐํฌ"
JAR_NAME=$(ls -tr $REPOSITORY/*.jar | tail -n 1)
echo "> JAR Name: $JAR_NAME"
rm -rf $REPOSITORY/deploy.log $REPOSITORY/deploy-err.log
nohup sudo java -jar $JAR_NAME --spring.profiles.active=prod --spring.config.location=$REPOSITORY/application.yml >> $REPOSITORY/deploy.log 2> $REPOSITORY/deploy-err.log &

๊ทธ๋ƒฅ ์ด๋™ํ•˜๊ณ , 8080์œผ๋กœ ๋„์›Œ์ง„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ™•์ธ ํ›„ ๊ธฐ์กด์— ๋Œ์•„๊ฐ€๋Š” ๊ฒƒ์€ ์ œ๊ฑฐํ•œ๋‹ค.

์ƒˆ๋กญ๊ฒŒ ๋นŒ๋“œํ•˜๋ฉด ๊ธฐ์กด์˜ ๋กœ๊ทธ ํŒŒ์ผ์€ ์ œ๊ฑฐํ•œ ๋‹ค์Œ, cp๋กœ ์ธํ•ด ๋ณต์‚ฌ๋œ ํŒŒ์ผ์„ java-jar๋ฅผ ํ†ตํ•ด์„œ ์‹คํ–‰ํ•ด์ค€๋‹ค ใ…Žใ…Ž

config ์ •๋ณด์˜ ๊ฒฝ์šฐ ์™ธ๋ถ€๋กœ ๋…ธ์ถœ์‹œํ‚ค์ง€ ์•Š๊ธฐ ์œ„ํ•ด์„œ ์ธ์Šคํ„ด์Šค ๋‚ด๋ถ€์— ์ €์žฅํ•ด๋‘๊ณ  ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค ๐Ÿ˜Š

 

์•„๋ž˜๋Š” ์  ํ‚จ์Šค ์‚ฌ์šฉ ์ „ ์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์ธ๋ฐ, ํ˜น์‹œ ๋„์›€์ด ๋  ์ˆ˜๋„ ์žˆ์œผ๋‹ˆ ์ฒจ๋ถ€ํ•ด๋‘๊ฒ ๋‹ค.

#!/bin/bash
REPOSITORY=/home/ubuntu/jwp-shopping-order
PROJECT_NAME=jwp-shopping-order
cd $REPOSITORY/$PROJECT_NAME/
echo "> Git Pull"
git pull origin step1
echo "> ํ˜„์žฌ ๊ตฌ๋™์ค‘์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ pid ํ™•์ธ"
CURRENT_PID=$(sudo lsof -i tcp:8080 | awk 'NR!=1 {print$2}')
echo "ํ˜„์žฌ ๊ตฌ๋™์ค‘์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜pid: $CURRENT_PID"
if [ -z "$CURRENT_PID" ]; then
    echo "> ํ˜„์žฌ ๊ตฌ๋™์ค‘์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์—†์œผ๋ฏ€๋กœ ์ข…๋ฃŒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."
else
    echo "> kill -9 $CURRENT_PID"
    sudo kill -9 $CURRENT_PID
    sleep 5
fi
echo "> ํ”„๋กœ์ ํŠธ Build ์‹œ์ž‘"
./gradlew build -x test
echo "> Build ํŒŒ์ผ ๋ณต์‚ฌ"
cp $REPOSITORY/$PROJECT_NAME/build/libs/*.jar $REPOSITORY/
echo "> ์ƒˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐฐํฌ"
JAR_NAME=$(ls -tr $REPOSITORY/*.jar | tail -n 1)
echo "> JAR Name: $JAR_NAME"
rm -rf $REPOSITORY/deploy.log $REPOSITORY/deploy-err.log
nohup sudo java -jar --Dspring.profiles.active=prod $JAR_NAME --spring.config.location=$REPOSITORY/application.yml >> $REPOSITORY/deploy.log 2> $REPOSITORY/deploy-err.log &

 

์ตœ์ข…์ ์œผ๋กœ ๋ธŒ๋žœ์น˜์— push ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋ฉด, ์  ํ‚จ์Šค ํŒŒ์ดํ”„๋ผ์ธ์ด ๋Œ๋ฉด์„œ ์œ„์˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๋ฐฐํฌ์— ์„ฑ๊ณตํ•˜๊ฒŒ ๋œ๋‹ค!!

 


๋„ˆ๋ฌด ๊ฐ๊ฒฉ์ด๋‹ค... ๐Ÿฅน

๋งŽ์€ ๋„์›€์„ ์ค€ ๋ฒ ๋ฒ ์—๊ฒŒ ๋‹ค์‹œ ํ•œ ๋ฒˆ ๊ฐ์‚ฌ ์ธ์‚ฌ ์˜ฌ๋ฆฝ๋‹ˆ๋‹ค...

๐Ÿ™‡‍โ™€๏ธ

Comments