๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐ŸŽ‹ AWS

[ Jenkins ] Jenkins Pipeline์„ ์ด์šฉํ•œ CI/CD + SSHAgent

by MuGeon Kim 2023. 4. 23.
๋ฐ˜์‘ํ˜•

 

[ 1. ๊ธ€์„ ์ž‘์„ฑํ•˜๋Š” ์ด์œ  ] 

ํ”„๋กœ์ ํŠธ๋ฅผ ํ•˜๋ฉด์„œ ๋งˆ์ง€๋ง‰์œผ๋กœ Jenkins๋ฅผ ์ด์šฉํ•œ ํŒŒ์ดํ”„๋ผ์ธ CI/CD๋ฅผ ํ•˜๋ฉด์„œ ๋„ˆ๋ฌด ๋งŽ์€ ์˜ค๋ฅ˜๋ฅผ ๋งŒ๋‚ฌ์Šต๋‹ˆ๋‹ค. ํ•™์Šตํ•œ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•˜๋Š” ์‹œ๊ฐ„์„ ๊ฐ€์ง€๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ด ์ž‘์„ฑ ๊ธ€์—๋Š” ์ค‘๋ณต์ ์ธ ๋‚ด์šฉ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ„์— ๊ธ€์„ ๋ณด์‹œ๋ฉด ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

 

[ 2. Jenkins Pipeline์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž ] 

์ด๋ฒˆ์— ์ง„ํ–‰ํ•  ๋ฐฐํฌ๋Š” ํŒŒ์ดํ”„๋ผ์ธ์„ ์ด์šฉ์„ ํ•ด์„œ ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ผ๋‹จ ๊ธฐ๋ณธ์ ์œผ๋กœ Jenkins ์ธ์Šคํ„ด์Šค์™€ Workspace ์ธ์Šคํ„ด์Šค๋ฅผ ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด SSH ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. 

์ดํ›„ Jenkins์—์„œ ๋นŒ๋“œํ•œ jarํŒŒ์ผ์„ Docker์— ์˜ฌ๋ ค์„œ Workspace์— ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉ์„ ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. 

์ถ”๊ฐ€์ ์œผ๋กœ Git์— Git Webhook์„ ์ด์šฉํ•ด์„œ ๋ณ€๊ฒฝ๋œ ์‚ฌํ•ญ์„ ํŒŒ์•…ํ•˜์—ฌ Jenkins ์ธ์Šคํ„ด์Šค์— push ํ•˜๊ฒŒ ์ถ”๊ฐ€์ ์ธ ์ž‘์—…์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

[ 3. Jenkins Pipeline ์‹คํ–‰ํ•˜๊ธฐ]

์ €ํฌ๊ฐ€ ์ด์ „์— ์ž‘์„ฑํ•œ ์ž‘์„ฑ๊ธ€์— ์†Œ๊ฐœ๋ฅผ ํ–ˆ๋˜ ๋ฉ”๋ชจ๋ฆฌ Swap , Docker, Jenkins์— ๋Œ€ํ•œ ์„ค์ •์„ ์ค€๋น„๋ฅผ ํ•ฉ๋‹ˆ๋‹ค.

 

[ Jenkins ] Jenkins Item Freestyle CI/CD ๋ฐฐํฌ

1. ์„œ๋ก  ์•ˆ๋…•ํ•˜์„ธ์š”. ์ด๋ฒˆ์—๋Š” AWS EC2์—์„œ Jenkins Item์— FreeStyle ๋ฐฐํฌ์— ๋Œ€ํ•ด์„œ ํ•™์Šตํ•œ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๊ธ€์„ ์ž‘์„ฑ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฐฐํฌ๋ฅผ ํฌ๊ฒŒ 2๊ฐœ๋กœ ๋‚˜๋ˆ„์–ด Github๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ฐฉ์‹๊ณผ ์‚ฌ์šฉํ•˜

pos04167.tistory.com

Memory Swap

sudo dd if=/dev/zero of=/swapfile bs=128M count=32

sudo chmod 600 /swapfile

sudo mkswap /swapfile

sudo swapon /swapfile

sudo swapon -s

sudo vi /etc/fstab
--------------------
[ vi์— ํ•˜๋‹จ์— ์ถ”๊ฐ€ ] 
/swapfile swap swap defaults 0 0
----------------------
## ์šฉ๋Ÿ‰ ํ™•์ธ
free

 

Docker ์„ค์น˜ํ•˜๊ธฐ

# ์˜ค๋ž˜๋œ ๋ฒ„์ „ ์‚ญ์ œ
sudo apt-get remove docker docker-engine docker.io containerd runc

sudo apt-get update
# repository ์„ค์ •
sudo apt-get -y install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

# Docker์˜ Official GPG Key ๋ฅผ ๋“ฑ๋ก
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# stable repository ๋ฅผ ๋“ฑ๋ก
echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update

# Docker Engine ์„ค์น˜
sudo apt-get -y install docker-ce docker-ce-cli containerd.io

# ์„ค์น˜ ์™„๋ฃŒ ํ™•์ธ, ๋ฒ„์ „ ํ™•์ธ
docker --version

# /var/run/docker.sock ์ ‘๊ทผ ๊ถŒํ•œ ํ—ˆ์šฉ
sudo chmod 666 /var/run/docker.sock

# docker hub ๋กœ๊ทธ์ธ id/pw ์ž…๋ ฅ
docker login

 

Docker ์ด์šฉํ•ด์„œ Jenkins ์„ค์น˜ํ•˜๊ธฐ

docker run \
  --name jenkins-docker \
  -p 8080:8080 -p 50000:50000 \
  -v /home/jenkins:/var/jenkins_home \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /usr/bin/docker:/usr/bin/docker \
  -u root \
  -d \
  jenkins/jenkins:lts
  
 
 # jenkins ์ปจํ…Œ์ด๋„ˆ ์ ‘์†
docker exec -it [jenkins ์ปจํ…Œ์ด๋„ˆID] bin/bash

# jenkins ์ปจํ…Œ์ด๋„ˆ log ํ™•์ธ
docker logs [jenkins ์ปจํ…Œ์ด๋„ˆID]

์ดํ›„ Jenkins์— ๋“ค์–ด๊ฐ€์„œ SSH Privateํ‚ค ์„ค์ •ํ•œ ์ดํ›„ SSH Agent๋ฅผ ์„ค์น˜๋ฅผ ํ•ด์•ผ ๋ฉ๋‹ˆ๋‹ค. 

ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ด€๋ฆฌ > Avaliable Plugins > SSH Agent Plugin > ์„ค์น˜ ํ›„ ์žฌ ์‹คํ–‰ > Installed plugins์— ์„ค์น˜๊ฐ€ ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  Item์— Pipeline์„ ์ด์šฉํ•ด์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑ์„ ํ•ฉ๋‹ˆ๋‹ค.

์ดํ›„ Pipeline์— script์— ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž…๋ ฅ์„ ํ•ด์ค๋‹ˆ๋‹ค. ์ €ํฌ๋Š” ์ด์ „์˜ node ๋ฒ„์ „์ด ์•„๋‹Œ stoarge๋ฐฉ์‹์„ ์‚ฌ์šฉ์„ ํ•ฉ๋‹ˆ๋‹ค.

pipeline {
    agent any
    stages {
       stage('Prepare') {
            steps {
                git branch: 'master',
                    url: 'https://github.com/Side-Challenge-Study-Time/StudyTime_BE.git'
            }
        }
		stage('Build Gradle') {
            steps{
                sh 'chmod +x gradlew'
                sh  './gradlew clean build'

                sh 'ls -al ./build'
            }
        }

		stage('Docker build image') {
            steps{
                sh 'docker build -t kimmugeon/docker-jenkins-github-test .'
            }
        }

		stage('Docker push image') {
            steps{
                sh 'docker login -u {id} -p {password}'
                sh 'docker push kimmugeon/docker-jenkins-github-test'
            }
        }

        stage('Run Container on SSH Dev Server'){
            steps{
                echo 'SSH'
                sshagent (credentials: ['ubuntu-server']) {
					sh "ssh -o StrictHostKeyChecking=no ubuntu@13.209.121.xxx 'whoami'"
                    sh "ssh -o StrictHostKeyChecking=no ubuntu@13.209.121.xxx 'docker ps -q --filter name=docker-jenkins-github-test | grep -q . && docker rm -f \$(docker ps -aq --filter name=docker-jenkins-github-test)'"
                    sh "ssh -o StrictHostKeyChecking=no ubuntu@13.209.121.xxx 'docker rmi -f kimmugeon/docker-jenkins-github-test'"
                    sh "ssh -o StrictHostKeyChecking=no ubuntu@13.209.121.xxx 'docker run -d --name docker-jenkins-github-test -p 8081:8080 kimmugeon/docker-jenkins-github-test'"
                }

            }

        }
    }
}

์ผ๋‹จ ์Šคํฌ๋ฆฝํŠธ์— ๋Œ€ํ•ด์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค๋ช… ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ผ๋‹จ ์ˆœ์„œ๋กœ๋Š” Jenkins ์ธ์Šคํ„ด์Šค๋Š” Git Clone > Gradle build > Docker build > Docker push๋ฅผ ์ง„ํ–‰ํ•˜๋ฉฐ

SSH ์ธ์Šคํ„ด์Šค๋Š” Docker pull > Docker run

1. jenkins์ธ์Šคํ„ด์Šค git clone
2. jenkins์ธ์Šคํ„ด์Šค gradle build
3. jenkins์ธ์Šคํ„ด์Šค docker build
4. jenkins์ธ์Šคํ„ด์Šค docker push
5. jenkins์ธ์Šคํ„ด์Šค -> server์ธ์Šคํ„ด์Šค ssh์ ‘์†
6. server์ธ์Šคํ„ด์Šค docker pull
7. server์ธ์Šคํ„ด์Šค docker run

 

์ดํ›„ ์ €ํฌ๋Š” SSH Agent๋ฅผ ์ด์šฉํ•ด์„œ Jenkins Credential ์„ค์ •์—์„œ Secret text๋ฅผ ์ง„ํ–‰์„ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

Pipeline Sytax > Steps > Sample Step > ssgagent: SSH Agent > Add๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

์ดํ›„ Kind์— SSH Username with private key๋ฅผ ์„ ํƒ์„ ํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿ’ฃ์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์ธ Private Key๋ฅผ ์„ ํƒ์„ ํ•ด์•ผ ๋ฉ๋‹ˆ๋‹ค. ์ €ํฌ๋Š” AWS์— pem ํŒŒ์ผ๋‚ด์šฉ์„ ์„ ํƒ์„ ํ•ฉ๋‹ˆ๋‹ค.

-----BEGIN RSA PRIVATE KEY----- 

~~~~~ ssh ์ธ์Šคํ„ด์Šค์˜ pem ํŒŒ์ผ์„ ํด๋ฆญํ•˜๋ฉด ๋‚˜์˜ต๋‹ˆ๋‹ค

-----END RSA PRIVATE KEY-----

์ดํ›„ ์ €์žฅ์„ ํ•˜๊ณ  ์ง€๊ธˆ ๋นŒ๋“œ๋ฅผ ์„ ํƒ์„ ํ•˜๋ฉด ๋นŒ๋“œ๊ฐ€ ์‹คํ–‰์ด ๋œ๋‹ค. 

์ •์ƒ์ ์œผ๋กœ ๋นŒ๋“œ๊ฐ€ ๋œ ๊ฒƒ์„ ํ™•์ธ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

[ 4. Git WebHook ]

์ €ํฌ๊ฐ€ ์—ฐ๊ฒฐํ•˜๊ณ  ์‹ถ์€ Github Repository๋ฅผ ์„ ํƒ์„ ํ•ฉ๋‹ˆ๋‹ค.

Setting > Webhooks > Add webhook์„ ์„ ํƒ์„ ํ•ฉ๋‹ˆ๋‹ค.

 

GitHub - Side-Challenge-Study-Time/StudyTime_BE: ์Šคํ„ฐ๋”” ํƒ€์ž„ ํ”„๋กœ์ ํŠธ(Back_End)

์Šคํ„ฐ๋”” ํƒ€์ž„ ํ”„๋กœ์ ํŠธ(Back_End). Contribute to Side-Challenge-Study-Time/StudyTime_BE development by creating an account on GitHub.

github.com

์—ฌ๊ธฐ์„œ URL์€ WorkSpace์˜ ํƒ„๋ ฅ์  IP๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ํฌํŠธ ๋ฐ github-webhook์„ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

์ด๋•Œ ๊ผญ Json์„ ์„ ํƒ์„ ํ•ฉ๋‹ˆ๋‹ค.

http://{ํƒ„๋ ฅ์  IP}:8080/github-webhook/

์ดํ›„ Jenkins์— ์„ค์ •์— Github๋ฅผ ์ถ”๊ฐ€์ ์œผ๋กœ ์„ค์ •ํ•˜๋ฉด ์„ฑ๊ณต์ ์œผ๋กœ ํ™œ์„ฑํ™”๋ฉ๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•