๋ก์ปฌ์์ ์ ํจ์ค๋ก ๋ธ๋ฃจ/๊ทธ๋ฆฐ ๋ฌด์ค๋จ ๋ฐฐํฌ ํ ์คํธํ๊ธฐ (3) - ์ ํจ์ค ํ์ผ ์์ฑ, ๋ฐฐํฌ ํ ์คํธ ์งํ
๐ก ์ด ๊ธ์ 3ํธ์ผ๋ก 2ํธ์ธhttps://suzuworld.tistory.com/418์ ์ด์ด ์ฐ๋ ๊ธ์ด๋ค.
๐ก 1ํธ๋ถํฐ ๋ณด๋ ค๋ฉด ์ด๊ณณ์ผ๋ก https://suzuworld.tistory.com/419
๐ JenkinsFile ์์ฑ ์ค๋น
- ์ด์ ์ ํจ์ค์ ๋ก๊ทธ์ธํด ๋ณด์.
- ๊ธฐ์กด์ ๊นํ๋ธ ์์ด๋์ ๋ํ Credential ๋ฑ๋ก์ ์ด๋ฏธ ํ๋ค๊ณ ๊ฐ์ ํ๋ค.
- ์ ๋ชจ๋ฅด๊ฒ ๋ค๋ฉด, ์ฌ๊ธฐ๋ฅผ ๋ณด๊ณ ๋ฐ๋ผ ํ๋ฉด ๋๋ค. ๋งค์ฐ ์์ธํ ์ ์ด ๋์๋ค.
- ์๋ก์ด Item์ ํด๋ฆญํ๋ค.
- Item์ Jenkins์์ ๊ด๋ฆฌ๋๋ ๋ชจ๋ ํญ๋ชฉ์ ์๋ฏธํ๋ค. ์ผ๋ฐ์ ์ผ๋ก ํ๋ก์ ํธ, ์์ , ๋น๋, ํ์ดํ๋ผ์ธ, ๋ทฐ ๋ฑ์ด ์๋ค.
- ์ฌ๊ธฐ์ Pipeline์ ์ ํํ๊ณ item์ ์ด๋ฆ์ ๊ธฐ์
ํ๋ค.
- ๋๋ jenkinTest๋ผ๊ณ ์ง์๋ค. ์ด๋ jenkinsFile์ ์์ฑํ ๋ ์คํฌ๋ฆฝํธ ๋ด๋ถ์ ํ์ฌ ๊ฒฝ๋ก๊ฐ ๋๋ค.
- /workspace/jenkinsTest๊ฐ ๊ธฐ๋ณธ ๊ฒฝ๋ก๊ฐ ๋ ๊ฒ์ด๋ค.
- jenkins๋ฅผ ์ค์นํ๋ฉด ์ผ๋ฐ์ ์ผ๋ก jenkins_home์ด๋ผ๋ ํด๋๊ฐ ๋๋ ํฐ๋ฆฌ ์ด๋๊ฐ์ ์์ฑ๋์ง๋ง, m2 ๋งฅ๋ถ์์ด๋ก ํ ์คํธ ์ /Users/<user๋ช >/.jenkins ๊ฒฝ๋ก์ ์์ฑ๋์๋ค.
- ๋๋ jenkinTest๋ผ๊ณ ์ง์๋ค. ์ด๋ jenkinsFile์ ์์ฑํ ๋ ์คํฌ๋ฆฝํธ ๋ด๋ถ์ ํ์ฌ ๊ฒฝ๋ก๊ฐ ๋๋ค.
- Pipeline์ FreeStyle๋ณด๋ค ํจ์ฌ ๋ง์ ์์ ๋๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ ์คํฌ๋ฆฝํธ ํ์ผ์ ์ง์ ์์ฑํด์ผ ํ๋ค๋ ๋ถ๋ด์ด ์๋ค.
- ๊ทธ๋ฌ๋ ํฌ๊ฒ ์ด๋ ต์ง๋ ์๋ค.
- ๋จผ์ GitHub project ์ฒดํฌ๋ฐ์ค๋ฅผ ํด๋ฆญํ๊ณ Project url์ ์ค์ ํ๋ค.
๐ก ๋น๋ ๋งค๊ฐ๋ณ์ ์ถ๊ฐ
- jar ํ์ผ ์คํ์ ํ๊ธฐ ์ํด ๋น๋ ์ ๋งค๊ฐ๋ณ์๋ฅผ ์ถ๊ฐํด์ผ ํ๋ค.
- ์ฌ๊ธฐ์์๋ ๊ฝค๋ ์๊ฐ์ ์ก์๋จน์๋ค..
- JenkinsFile์ ์์ฑ๋๋ ์คํฌ๋ฆฝํธ ๋ด์ฉ์ด ๋๋๋ฉด ์คํ ๋ด์ฉ์ ์ ๋ถ kill ํด๋ฒ๋ฆฌ๊ธฐ ๋๋ฌธ์ด๋ค.
- nohup์ผ๋ก ์์ฑํด๋ ํ์ดํ๋ผ์ธ ์คํฌ๋ฆฝํธ์ ์์ฑํ๋ ๋ด์ฉ์ ์ ๋ถ ์ฃฝ์ฌ๋ฒ๋ฆฌ๊ธฐ ๋๋ฌธ์ ํจ๊ป kill ๋๋ค.
- ์ด ์ค์ ์ ํด๋์ง ์์ผ๋ฉด nohup์ผ๋ก ์คํ์ํจ ์คํ๋ง๋ถํธ ํ์ผ์ด ๋น๋ ๋ฐฐํฌ๊ฐ ์ข ๋ฃ๋จ๊ณผ ๋์์ process kill ๋๋ค.
- ์์ ๊ฐ์ด ๋งค๊ฐ๋ณ์ ๋ช ์๋ JENKINS_NODE_COOKIE, Value์๋ dontKillMe๋ฅผ ์ถ๊ฐํด ์ฃผ์.
โ๏ธ์ ๊น
- pipeline ์คํฌ๋ฆฝํธ๋ฅผ ์์ฑํ๋ ๊ฒฝ์ฐ์๋ BUILD_ID ๋์ ์ JENKINS_NODE_COOKIE๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๊ณ ๊ณต์๋ฌธ์์ ๋์์๋ค.
โ๐ป JenkinsFile ์์ฑ
- ์ข ์๋๋ก ๋ด๋ฆฌ๋ฉด pipeline ์์ฑ๋์ด ๋์จ๋ค.
- ์ด๊ณณ์ ์คํฌ๋ฆฝํธ ํ์ผ์ ์์ฑํ๋ฉด ๋๋ค.
๐ฅ scripted Pipeline VS declarative Pipeline
- Script ์ ๋ ฅ์ฐฝ ์ค๋ฅธ์ชฝ ์๋จ์ ๋ณด๋ฉด sample Pipeline์ ์ ํํ ์ ์๋ค.
- ์ํ๋ค์ ํด๋ฆญํด ๋ณด๋ฉด ๋ญ๊ฐ ๋น์ทํด ๋ณด์ด๋ฉด์๋ ๋ค๋ฅด๊ฒ ์๊ฒผ๋ค.
- ์ผ์ชฝ์ Scripted Pipeline์ด๋ฉฐ, ์ค๋ฅธ์ชฝ์ Declarative Pipeline์ด๋ค.
- Scripted Pipeline๊ณผ Declarative Pipeline ๋ชจ๋ ์ ํจ์ค์์ ์ฌ์ฉ๋๋ ํ์ดํ๋ผ์ธ ์คํฌ๋ฆฝํธ์ด๋ค.
- ์ด ๋ ๊ฐ์ง ํ์ดํ๋ผ์ธ์ ์ ํจ์ค๋ฅผ ์ฌ์ฉํ์ฌ CI/CD(์ง์์ ์ธ ํตํฉ/์ง์์ ์ธ ๋ฐฐํฌ) ์ํฌํ๋ก์ฐ๋ฅผ ๊ตฌ์ฑํ๋ ๋ฐ ์ฌ์ฉ๋๋ค.
๐ก Scripted Pipeline
- ๊ธฐ์กด์ ์ ํจ์ค ํ์ดํ๋ผ์ธ ์คํฌ๋ฆฝํธ๋ก Groovy๋ผ๋ ์คํฌ๋ฆฝํธ ์ธ์ด๋ฅผ ์ฌ์ฉํ์ฌ ๋ง๋ ๋ค.
- Groovy๋ Java ํ๋ซํผ์์ ์คํ๋๋ ๋์ ์ธ์ด๋ก ์๋ฐ ๋ฌธ๋ฒ์ ๊ธฐ๋ฐ์ผ๋ก ์ฌ๋ฌ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
- Scripted Pipeline์ ์์ ๋๊ฐ ๋๊ณ ์ ์ฐํ๋ฉฐ, ๋ณต์กํ ์ํฌํ๋ก์ฐ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ ์ ํฉํ๋ค.
๐ก Declarative Pipeline
- ์ ํจ์ค 2.5 ๋ฒ์ ๋ถํฐ ๋์ ๋ ์๋ก์ด ํ์์ ํ์ดํ๋ผ์ธ ์คํฌ๋ฆฝํธ์ด๋ค.
- ํ์ดํ๋ผ์ธ์ ๊ตฌ์กฐ์ ๋จ๊ณ๋ฅผ ๋ ๋ช ํํ๊ฒ ์ ์ํ ์ ์๋๋ก ์ค๊ณ๋์๋ค.
- ์ด ์ญ์ Groovy ๊ธฐ๋ฐ์ผ๋ก ์์ฑ๋๋ฉฐ Scripted Pipeline์ ๋นํด ๋ณด๋ค ๊ฐ๊ฒฐํ๊ณ ๊ฐ๋ ์ฑ์ด ๋์ ๋ฌธ๋ฒ์ ์ ๊ณตํ๋ค.
- ์ผ๋ฐ์ ์ธ CI/CD ์ํฌํ๋ก์ฐ๋ฅผ ์ฝ๊ฒ ์์ฑํ ์ ์๋๋ก ๊ตฌ์ฑ ์์๋ฅผ ์ฌ์ ์ ์ ์ํ๊ณ ์ฌ์ฌ์ฉํ ์ ์๋ ํ ํ๋ฆฟ์ ์ ๊ณตํ๋ค.
- ํ์ดํ๋ผ์ธ์ ๊ตฌ์กฐ๋ฅผ ์๊ฐ์ ์ผ๋ก ํํํ๊ณ ๋ชจ๋ํฐ๋งํ ์ ์๋ ๊ธฐ๋ฅ๋ ์ ๊ณตํ๋ค.
๐ ์ ๋ฆฌ
- ์ด ๋ ๊ฐ์ง ํ์ดํ๋ผ์ธ์ ์ ํ์ ํ๋ก์ ํธ์ ์๊ตฌ ์ฌํญ๊ณผ ๊ฐ๋ฐ์์ ์ ํธ๋์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ค.
- Scripted Pipeline์ ์์ ๋ก์๊ณผ ์ ์ฐ์ฑ์ ์ํ๋ ๋ณต์กํ ์ํฌํ๋ก์ฐ์ ์ ํฉํ๋ค.
- Declarative Pipeline์ ๋ณด๋ค ๊ฐ๊ฒฐํ๊ณ ๊ตฌ์กฐํ๋ ์ํฌํ๋ก์ฐ๋ฅผ ์ํ๋ ๊ฒฝ์ฐ์ ์ ์ฉํ๋ค.
- ๊ด๋ จ ๋ด์ฉ์ ๋ค๋ฃฌ ๋ธ๋ก๊ทธ๋ฅผ ์ข ๋ ์ฐพ์๋ณธ ๊ฒฐ๊ณผ ์ต๊ทผ์ CI/CD๋ Declarative๊ฐ ๋์ธ๋ผ๊ณ ํ๋ฉฐ, Github Actions ์ญ์ YAML ๊ธฐ๋ฐ์ Declarative๋ฅผ ์ง์ํ๋ค๊ณ ํ๋ค.
- ๋๋ ๋ณด๋ค ๊ฐํธํ๊ณ ๋์ธ์ธ Declarative ํ์์ ์ฌ์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ๋ค.
๐ Jenkinsfile
- ์ด ๋ถ๋ถ์์๋ ์ง๋ ๊ธ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์์ ๋ถ๋ถ์ผ๋ก ์ชผ๊ฐ ์ค๋ช ํ ํ ์์ฑ๋ณธ์ผ๋ก ๋ณด์ฌ์ฃผ๊ฒ ๋ค.
pipeline {
agent any
stages {...}
}
- pipeline
- ํ์ดํ๋ผ์ธ ๋ธ๋ก์ ์ ์ํ๋ค.
- ์ด ๋ธ๋ก ์์๋ ํ์ดํ๋ผ์ธ์ ์ ์ฒด ๊ตฌ์กฐ๊ฐ ํฌํจ๋๋ค.
- agent any
- ํ์ดํ๋ผ์ธ์ด ์คํ๋ ์์ด์ ํธ๋ฅผ ์ง์ ํ๋ค.
- any๋ ์ด๋ค ์์ด์ ํธ์์๋ผ๋ ํ์ดํ๋ผ์ธ์ ์คํํ ์ ์์์ ์๋ฏธํ๋ค.
- stages
- ํ์ดํ๋ผ์ธ์ ๋จ๊ณ๋ฅผ ์ ์ํ๋ ๋ธ๋ก์ด๋ค.
- stages ๋ธ๋ก ์์๋ ์ฌ๋ฌ ๊ฐ์ stage ๋ธ๋ก์ด ํฌํจ๋ ์ ์๋ค.
- ๊ฐ stage๋ ํ์ดํ๋ผ์ธ์ ํน์ ๋จ๊ณ๋ฅผ ๋ํ๋ด๋ฉฐ, ๋จ๊ณ๋ณ๋ก ์คํ๋ ์์ ์ ์ ์ํ ์ ์๋ค.
- ํ์ดํ๋ผ์ธ์ ์คํํ๋ฉด, ์ ์๋ ๋จ๊ณ์ ์์ ์ด ์์ฐจ์ ์ผ๋ก ์คํ๋๋ค.
โจ๏ธ stage('Backup & Clean Workspace')
stages {
stage('Backup & Clean Workspace') {
steps {
script {
sh """
rm -rf /Users/wonyong/.jenkins/workspace/backup/*
cp -r /Users/wonyong/.jenkins/workspace/jenkinsTest /Users/wonyong/.jenkins/workspace/backup
rm -rf *
"""
}
}
}
- stages ์์ ์ ์ํ ๊ฐ stage๊ฐ ์์ฐจ์ ์ผ๋ก ์คํ๋๋๋ฐ ๊ทธ ์ด๋ฆ์ ์ง์ ์ค์ ํ ์ ์๋ค.
- sh """ """ ์์ ๋ด์ฉ์ ์ ์ผ๋ฉด ๊ฐํ๋ ๋ถ๋ถ๋ ์ ๋ถ ์คํฌ๋ฆฝํธ ์ฒ๋ฆฌ๊ฐ ๋๋ค.
- rm -rf /Users/wonyong/.jenkins/workspace/backup/*
- ๊ธฐ์กด์ jenkins workspace ๋ด๋ถ์ backup ํด๋๋ฅผ ์์ฑํ๊ณ ๋ด๋ถ์ backup ํด๋๋ฅผ rm -rf ๋ช ๋ น์ด๋ฅผ ๋น์ด๋ค.
- cp -r /Users/wonyong/.jenkins/workspace/jenkinsTest /Users/wonyong/.jenkins/workspace/backup
- /Users/wonyong/.jenkins/workspace/jenkinsTest(๊นํ๋ธ๋ก๋ถํฐ ์๋ก ํด๋ก ํ ํด๋)๋ฅผ ์์์ ๋น์๋ ๋ฐฑ์ ํด๋์ ๋ฃ๋๋ค.
- r ์ต์ ์ ์ฌ๊ท์ ์ผ๋ก ๋ณต์ฌํ๋ผ๋ ์๋ฏธ์ด๋ฉฐ, ๋๋ ํฐ๋ฆฌ๋ฅผ ๋ณต์ฌํ ๋ ํ์ ๋๋ ํฐ๋ฆฌ์ ํ์ผ๋ ํจ๊ป ๋ณต์ฌํ๋ค.
- rm -rf *
- ๊ธฐ์กด ์ํฌ์คํ์ด์ค์ jenkinsTest ํด๋ ๋ด๋ถ ์ ์ฒด๋ฅผ ๋น์ด๋ค.
- ์ฆ, stage์์ ์คํ๋๋ ๊ธฐ๋ณธ ํด๋์ ํ์ฌ ๊ฒฝ๋ก๋ ํด๋น ์ํฌ์คํ์ด์ค ๋ด ๋น๋ ํ ์คํธ ์ด๋ฆ์ด๋ค.(์๋ ์์ฑ๋๋ค.)
- ์ด ๋ถ๋ถ์ ๊ตณ์ด ํ์์๋ค. ๋์ ๊ฒฝ์ฐ backup ํด๋๊ฐ ํ์ํ๋ค๊ณ ํ๋จํด ๋ง๋ค์๋ค.
๐ stage('Github Clone')
stage('Github Clone') {
steps {
git branch: 'main',
credentialsId: 'github_token',
url: 'https://github.com/wonyongg/jenkinsTest'
}
}
- github ๋ ํ์งํ ๋ฆฌ์์ clone ํ๋ ๋จ๊ณ์ด๋ค.
- ์ฌ๊ธฐ์ credentialsId๋ ์ ํจ์ค ๊ธฐ๋ณธ ์ค์ ์์ ๋ง๋ Credential ์ ๋ณด์ด๋ค.
- ์์ ๋งํฌ์ ๋์ผํ๋ค. ์ด๊ณณ์ผ๋ก ๋ค์ด๊ฐ credentials ์ ๋ณด๋ฅผ ๋ฑ๋กํ๋ ๋ฐฉ๋ฒ์ ์ฐธ๊ณ ํ์.
๐ stage('Build')
stage('Build') {
steps {
script {
sh """
cd forJenkins
perl -i -pe 'y|\r||d' gradlew
./gradlew build
"""
}
}
}
- ์ด ๋ถ๋ถ์ด ์๋นํ ์ ๋จน์ ๋ถ๋ถ์ด๋ค.
- ๋๋ ์ด ํ ์คํธ๋ฅผ ์ธํ ๋งฅ๋ถ ํ๋ก์ m2 ๋งฅ๋ถ ์์ด ๋ ๊ธฐ๊ธฐ๋ก ์งํํ๋ค.
- ์ธํ ๋งฅ๋ถ์์๋ perl -i -pe 'y|\r||d' gradlew ์ด ๋ช ๋ น์ด๋ฅผ ๋ฃ์ ํ์๊ฐ ์๋ค.
- m2 ๋งฅ๋ถ์์๋ ์ด ๋ช
๋ น์ด ์์ด ์๋์์ผฐ์ ๋ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
- ์ด ๋ฌธ์ ๊ฐ ์ ์๊ธฐ๋์ง ์ ํํ ์ ์๋ ์์ผ๋ m2 ๋งฅ๋ถ ๋ก์ปฌ์์ ๊นํ๋ธ๋ก ํ๋ก์ ํธ๋ฅผ ํธ์ํ๊ณ ์ด๋ฅผ ์ ํจ์ค์์ ๊ฐ์ ธ์ ๋ก์ปฌ์ ๋ค์ ํด๋ก ํ๋ ๊ณผ์ ์์ gradlew ํ์ผ์ด ๋ณํ๋ ๊ฒ ๊ฐ๋ค. ์ด์์ฒด์ ์ ์ฐจ์ด๋ผ๊ณ ํ๋๋ฐ ์ธํ ๋งฅ๋ถ์์๋ ์๋ฌด ๋ฌธ์ ์์ด ๋์ง๋ง m2 ๋งฅ๋ถ์์๋ gradlew๋ฅผ ์คํํ์ "zsh: ./gradlew: bad interpreter: /bin/sh^M: no such file or directory"์ ๊ฐ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
- ์ด๋ ์ฃผ๋ก ์๋์ฐ ํ๊ฒฝ์์ ์์ฑ๋ ํ์ผ์ ๋ฆฌ๋ ์ค/์ ๋์ค ํ๊ฒฝ์์ ์ฌ์ฉํ ๋ ๋ฐ์ํ๋ ๋ฌธ์ ๋ผ๊ณ ํ๋ค.
- ์ ํํ ์์ธ์ ๋ชจ๋ฅด๊ฒ ๋ค. ๊น๊ฒ ์ฐพ์๋ณด์ง ์์๋ค. ์๋ฌดํผ ๊ฐ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค๋ฉด ์ ๋ช ๋ น์ด๋ฅผ ์ถ๊ฐํด ์ฃผ์.
- perl : Perl ์ธํฐํ๋ฆฌํฐ๋ฅผ ์คํํ๋ ๋ช ๋ น์ด์ด๋ค.
- -i : "in-place" ๋ชจ๋๋ก ํ์ผ์ ์์ ํ๋ ์ต์ ์ด๋ค. ์ด ์ต์ ์ ์ฌ์ฉํ๋ฉด ์๋ณธ ํ์ผ์ด ๋ณ๊ฒฝ๋๋ค.
- -pe : -p ์ต์ ์ ์ ๋ ฅ ํ์ผ์ ํ ์ค์ฉ ์ฝ์ด ๋ค์ด๊ณ , -e ์ต์ ์ ์ฃผ์ด์ง Perl ์ฝ๋๋ฅผ ์คํํ๋ค.
- 'y|\r||d' : y ์ฐ์ฐ์๋ ๋ฌธ์์ด์์ ํน์ ๋ฌธ์๋ฅผ ๋ค๋ฅธ ๋ฌธ์๋ก ์นํํ๋ ์ญํ ์ ํ๋ค. ์ฌ๊ธฐ์๋ \r ๋ฌธ์๋ฅผ ์ญ์ ํ๋ค. d ํ๋๊ทธ๋ ์นํ๋ ๋ฌธ์์ด์ ์ญ์ ํ๋ผ๋ ์๋ฏธ์ด๋ค.
- ์ฃผ์ด์ง ๋ช ๋ น์ด๋ฅผ ์คํํ๋ฉด gradlew ํ์ผ์์ \r ๋ฌธ์๊ฐ ์ญ์ ๋ ํ์ผ์ด ์์ฑ๋๋ค. (\r ๋ฌธ์๊ฐ ์ถ๊ฐ๋๋๋ณด๋ค..)
๐ stage('Deploy')
stage('Deploy') {
steps {
script {
sh """
cd forJenkins/script && perl -i -pe 'y|\r||d' deploy.sh switch.sh default_switch.sh
./deploy.sh
"""
}
}
}
}
}
- ์ด ๋ถ๋ถ๋ ๋ง์ฐฌ๊ฐ์ง์ด๋ค. ์์ ๊ฐ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค๋ฉด perl -i -pe 'y|\r||d' deploy.sh switch.sh default_switch.sh ์ด ๋ช ๋ น์ด๋ฅผ ์ถ๊ฐํด ์ฃผ๋ฉด ๋๋ค.
- jenkinsTest์ forJenkins ํ๋ก์ ํธ ํ์ผ๋ก ๋ค์ด๊ฐ script์ deploy.sh ํ์ผ์ ์คํํจ์ผ๋ก์จ ์ด์ ๊ธ์์ ์์ฑํ ๋ฐฐํฌ ์คํฌ๋ฆฝํธ ํ์ผ์ ์คํ์ํค๋ ๊ฒ์ด๋ค.
โจ๏ธ JenkinsFile ์์ฑ๋ณธ
pipeline {
agent any
stages {
stage('Backup & Clean Workspace') {
steps {
script {
sh """
rm -rf /Users/wonyong/.jenkins/workspace/backup/*
cp -r /Users/wonyong/.jenkins/workspace/jenkinsTest /Users/wonyong/.jenkins/workspace/backup
rm -rf *
"""
}
}
}
stage('Github Clone') {
steps {
git branch: 'main',
credentialsId: 'github_token',
url: 'https://github.com/wonyongg/jenkinsTest'
}
}
stage('Build') {
steps {
script {
sh """
cd forJenkins
perl -i -pe 'y|\r||d' gradlew
./gradlew build
"""
}
}
}
stage('Deploy') {
steps {
script {
sh """
cd forJenkins/script && perl -i -pe 'y|\r||d' deploy.sh switch.sh default_switch.sh
./deploy.sh
"""
}
}
}
}
}
- perl -i -pe 'y|\r||d' ์ด ๋ช ๋ น์ด๊ฐ ํ์ ์๋ค๋ฉด ๋นผ์ ์ฌ์ฉํ๋ฉด ๋๋ค.
๐ ๋ฐฐํฌ ํ ์คํธํด ๋ณด๊ธฐ
- ๋๋์ด ๋ฐฐํฌ ํ ์คํธ์ด๋ค.
- ์ฌ๊ธฐ์ ์ ๋ฆฌ๋ฅผ ํ๊ฒ ๋ค.
- ํ ์คํธ๋ github์ผ๋ก ํธ์ํ์ฌ webhook์ผ๋ก ๋น๋ํ๋ ๊ณผ์ ์ ์๋ตํ๊ณ ์ง์ ๋น๋๋ก ์งํํ๋ค.
- ์ง์ ๋น๋
- ๋ฒํผ ํด๋ฆญ
- stage('Backup & Clean Workspace')
- ๋ก์ปฌ ๋ด ์ํฌ์คํ์ด์ค์ ๊ธฐ์กด ๋ฐฑ์ ํ์ผ ์ญ์ -> ๊ธฐ์กด ํ๋ก์ ํธ ํ์ผ ๋ฐฑ์ ํ์ผ๋ก ๋ณต์ฌ -> ๊ธฐ์กด ํ๋ก์ ํธ ํ์ผ ์ญ์
- stage('Github Clone')
- jenkins credential ์ฌ์ฉ -> github ๋ ํ์งํ ๋ฆฌ์์ ํด๋ก -> ์ํฌ์คํ์ด์ค ํ๋ก์ ํธ ํ์ผ ์์ฑ(์๋ค๋ฉด ๋ฎ์ด์ฐ๊ธฐ)
- stage('Build')
- cd ๋ช ๋ น์ด๋ก ํ๋ก์ ํธ ํ์ผ๋ก ๋ค์ด๊ฐ ./gradlew build ์คํ
- stage('Deploy')
- ์ง๋ ๊ธ์ ์์ฑํ deploy.sh ์คํ
- if) ๋ธ๋ฃจ, ๊ทธ๋ฆฐ ๋ชจ๋ ์คํ์ค์ด ์๋๋ผ๋ฉด deploy.sh -> default_switch.sh -> ๋ธ๋ฃจ ํฌํธ ์คํ
- else if) ๋ธ๋ฃจ๊ฐ ์คํ์ค์ด ์๋๋ผ๋ฉด deploy.sh -> switch.sh -> ๊ทธ๋ฆฐ ํฌํธ ์คํ -> ๋ธ๋ฃจ kill
- else if) ๊ทธ๋ฆฐ์ด ์คํ์ค์ด ์๋๋ผ๋ฉด deploy.sh -> switch.sh -> ๋ธ๋ฃจ ํฌํธ ์คํ -> ๊ทธ๋ฆฐ kill
- ์คํฌ๋ฆฝํธ ์ข ๋ฃ, ๋ฐฐํฌ ์๋ฃ
- ์ง๋ ๊ธ์ ์์ฑํ deploy.sh ์คํ
- Dashboard์์ ํด๋น item์ ๋ค์ด๊ฐ "ํ๋ผ๋ฏธํฐ์ ํจ๊ป ๋น๋"๋ฅผ ํด๋ฆญํ๋ค.
- ์ดํ ๋งค๊ฐ๋ณ์ ๊ฐ์ ํ์ธํ๊ณ ์ด๋ก์ ๋น๋ ๋ฒํผ์ ๋๋ฅธ๋ค.
- ๋น๋๊ฐ ์งํ ์ค์ด๊ณ ์ฑ๊ณตํ ๊ฒ์ด๋ค.
๐ ํ์ดํ๋ผ์ธ ๋ก๊ทธ
Skip to content
[Jenkins]Jenkins
๊ฒ์ (โ+K)
1
ํฉ์์ฉ
๋ก๊ทธ์์
Dashboard
jenkinsTest
#21
Status
Changes
Console Output
View as plain text
Edit Build Information
Delete build ‘#21’
Parameters
Git Build Data
Restart from Stage
Replay
Pipeline Steps
Workspaces
Previous Build
์ฝ์ ์ถ๋ ฅ
Started by user ํฉ์์ฉ
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /Users/wonyong/.jenkins/workspace/jenkinsTest
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Backup & Clean Workspace)
[Pipeline] script
[Pipeline] {
[Pipeline] sh
+ rm -rf /Users/wonyong/.jenkins/workspace/backup/jenkinsTest
+ cp -r /Users/wonyong/.jenkins/workspace/jenkinsTest /Users/wonyong/.jenkins/workspace/backup
+ rm -rf forJenkins
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Github Clone)
[Pipeline] git
The recommended git tool is: NONE
using credential github_token
> git rev-parse --resolve-git-dir /Users/wonyong/.jenkins/workspace/jenkinsTest/.git # timeout=10
Fetching changes from the remote Git repository
> git config remote.origin.url https://github.com/wonyongg/jenkinsTest # timeout=10
Fetching upstream changes from https://github.com/wonyongg/jenkinsTest
> git --version # timeout=10
> git --version # 'git version 2.39.2 (Apple Git-143)'
using GIT_ASKPASS to set credentials
> git fetch --tags --force --progress -- https://github.com/wonyongg/jenkinsTest +refs/heads/*:refs/remotes/origin/* # timeout=10
> git rev-parse refs/remotes/origin/main^{commit} # timeout=10
Checking out Revision 1e4436fc668e08130c8645ca6e4cbbff4bddec3f (refs/remotes/origin/main)
> git config core.sparsecheckout # timeout=10
> git checkout -f 1e4436fc668e08130c8645ca6e4cbbff4bddec3f # timeout=10
> git branch -a -v --no-abbrev # timeout=10
> git branch -D main # timeout=10
> git checkout -b main 1e4436fc668e08130c8645ca6e4cbbff4bddec3f # timeout=10
Commit message: "exit 0"
> git rev-list --no-walk 1e4436fc668e08130c8645ca6e4cbbff4bddec3f # timeout=10
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Build)
[Pipeline] script
[Pipeline] {
[Pipeline] sh
+ cd forJenkins
+ perl -i -pe 'y|
||d' gradlew
+ ./gradlew build
Starting a Gradle Daemon, 1 incompatible Daemon could not be reused, use --status for details
> Task :compileJava
> Task :processResources
> Task :classes
> Task :bootJarMainClassName
> Task :bootJar
> Task :jar
> Task :assemble
> Task :compileTestJava
> Task :processTestResources NO-SOURCE
> Task :testClasses
> Task :test
> Task :check
> Task :build
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/8.4/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD SUCCESSFUL in 5s
7 actionable tasks: 7 executed
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Deploy)
[Pipeline] script
[Pipeline] {
[Pipeline] sh
+ cd forJenkins/script
+ perl -i -pe 'y|
||d' deploy.sh switch.sh default_switch.sh
+ ./deploy.sh
-> ๐จ๐ป๐ผ <Jenkins ๋ฐฐํฌ ์์>
-> ๐ฆ ํ์ฌ ๊ตฌ๋์ค์ธ Spring Boot Profile ํ์ธ
-> โ ๏ธ profile not found : ์ผ์นํ๋ Profile์ด ์์ต๋๋ค.
-> โ ๏ธ set default profile : ๊ธฐ๋ณธ Profile์ธ blue๋ฅผ ํ ๋นํฉ๋๋ค.
-> โ ๏ธ ๋ธ๋ฃจ, ๊ทธ๋ฆฐ์ด ๋ชจ๋ ๋์์ค์ด ์๋์์ผ๋ฏ๋ก, blue๋ง ๋ฐฐํฌํ๊ณ ์คํฌ๋ฆฝํธ๋ฅผ ์ข
๋ฃํฉ๋๋ค.
-> ๐ blue ๋ฐฐํฌ
-> ๐ nohup java -jar /Users/wonyong/.jenkins/workspace/jenkinsTest/forJenkins/build/libs/forJenkins.jar --spring.profiles.active=blue > /dev/null &
-> ๐ blue : 10์ด ํ Health Check Start
-> ๐ curl -s http://localhost:8081/actuator/health
-> ๐จ [1 ๋ฒ์งธ Health Check]
-> โ
Health Check ์ฑ๊ณต!!!
-> ๐ NGINX : Default Port๋ก ํ๋ก์ ์ค์
-> โก๏ธ set default port : ๊ธฐ๋ณธ ํฌํธ์ธ 8081 ๋ฅผ ํ ๋นํฉ๋๋ค.
-> ๐ NGINX ์ปจํ
์ด๋ ๋ด์ ํ๋ก์ ๋ฐฉํฅ ์ค์
-> ๐ฅณ set $service_url http://127.0.0.1:8081;
-> ๐ NGINX ์ฌ์์
-> ๐จ๐ป๐ผ <Jenkins ๋ฐฐํฌ ์ฑ๊ณต> ์คํฌ๋ฆฝํธ๋ฅผ ์ข
๋ฃํฉ๋๋ค.
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
REST API
Jenkins 2.433
- ๊ธฐ๋ณธ์ ์ผ๋ก blue, green ๋ชจ๋ ์๋ ์ค์ด ์๋ ์ blue ํฌํธ๋ก ์คํ๋ง๋ถํธ๋ฅผ ์คํ์ํค๊ณ ํ๋ก์ ๋ฐฉํฅ์ blue๋ก ์ค์ ํ๋ค.
๐ blue -> green ํ๋ก์ ๋ณ๊ฒฝ
-> ๐จ๐ป๐ผ <Jenkins ๋ฐฐํฌ ์์>
-> ๐ฆ ํ์ฌ ๊ตฌ๋์ค์ธ Spring Boot Profile ํ์ธ
-> ๐ก ํ์ฌ ๊ตฌ๋์ค์ธ Profile : blue
-> ๐ green ๋ฐฐํฌ
-> ๐ nohup java -jar /Users/wonyong/.jenkins/workspace/jenkinsTest/forJenkins/build/libs/forJenkins.jar --spring.profiles.active=green > /dev/null &
-> ๐ green : 10์ด ํ Health Check Start
-> ๐ curl -s http://localhost:8082/actuator/health
-> ๐จ [1 ๋ฒ์งธ Health Check]
-> โ
Health Check ์ฑ๊ณต!!!
-> ๐คผ NGINX ํฌํธ ์ค์์นญ ์คํฌ๋ฆฝํธ ์์
-> ๐ก ํ์ฌ ๊ตฌ๋์ค์ธ Spring Boot Port : blue
-> โก๏ธ ํ์ฌ NGINX ํ๋ก์ ํฌํธ : 8081
-> โก๏ธ ๋ณ๊ฒฝํ NGINX ํ๋ก์ ํฌํธ : 8082
-> ๐ NGINX ์ปจํ
์ด๋ ๋ด์ ํ๋ก์ ๋ฐฉํฅ ๋ณ๊ฒฝ
-> ๐ฅณ set $service_url http://127.0.0.1:8082;
-> โ
NGINX ์ฌ์์
-> ๐ซ ๊ธฐ์กด ํฌํธ์ธ blue ํฌํธ : 8081 KILL
-> ๐ฆ blue ์ PID : 3962
-> ๐จ๐ป๐ผ <Jenkins ๋ฐฐํฌ ์ฑ๊ณต> ์คํฌ๋ฆฝํธ๋ฅผ ์ข
๋ฃํฉ๋๋ค.
- blue๊ฐ ์ด์์์ ๋ green์ ์ด๋ฆฌ๊ณ nginx์ ํ๋ก์ ๋ฐฉํฅ์ ๋ณ๊ฒฝํ ํ blue๋ฅผ kill ํ๋ค.
๐ green -> blue ํ๋ก์ ๋ณ๊ฒฝ
-> ๐จ๐ป๐ผ <Jenkins ๋ฐฐํฌ ์์>
-> ๐ฆ ํ์ฌ ๊ตฌ๋์ค์ธ Spring Boot Profile ํ์ธ
-> ๐ก ํ์ฌ ๊ตฌ๋์ค์ธ Profile : green
-> ๐ blue ๋ฐฐํฌ
-> ๐ฆ blue ์ PID : 6668
-> ๐ nohup java -jar /Users/wonyong/.jenkins/workspace/jenkinsTest/forJenkins/build/libs/forJenkins.jar --spring.profiles.active=blue > /dev/null &
-> ๐ blue : 10์ด ํ Health Check Start
-> ๐ curl -s http://localhost:8081/actuator/health
-> ๐จ [1 ๋ฒ์งธ Health Check]
-> โ
Health Check ์ฑ๊ณต!!!
-> ๐คผ NGINX ํฌํธ ์ค์์นญ ์คํฌ๋ฆฝํธ ์์
-> ๐ก ํ์ฌ ๊ตฌ๋์ค์ธ Spring Boot Port : green
-> โก๏ธ ํ์ฌ NGINX ํ๋ก์ ํฌํธ : 8082
-> โก๏ธ ๋ณ๊ฒฝํ NGINX ํ๋ก์ ํฌํธ : 8081
-> ๐ NGINX ์ปจํ
์ด๋ ๋ด์ ํ๋ก์ ๋ฐฉํฅ ๋ณ๊ฒฝ
-> ๐ฅณ set $service_url http://127.0.0.1:8081;
-> โ
NGINX ์ฌ์์
-> ๐ซ ๊ธฐ์กด ํฌํธ์ธ green ํฌํธ : 8082 KILL
-> ๐ฆ green ์ PID : 6596
-> ๐จ๐ป๐ผ <Jenkins ๋ฐฐํฌ ์ฑ๊ณต> ์คํฌ๋ฆฝํธ๋ฅผ ์ข
๋ฃํฉ๋๋ค.
- green๊ฐ ์ด์์์ ๋ blue์ ์ด๋ฆฌ๊ณ nginx์ ํ๋ก์ ๋ฐฉํฅ์ ๋ณ๊ฒฝํ ํ green๋ฅผ kill ํ๋ค.
๐ ์ต์ข ์ ๋ฆฌ
- ngrok์ผ๋ก github webhook ์ฐ๊ฒฐํ์ฌ ํ
์คํธํ๋ ๋ถ๋ถ์ ์๋ตํ๋ค.
- ๊ฐ์ ์ค๋ช ๋ฐ๋ณต์ด๊ธฐ๋ ํ๊ณ ๊ฒฐ๊ตญ ์ธ๋ถ ์๋ฒ๋ก ์ฐ๊ฒฐํ๋๊ฒ ๋ชฉํ์ด๊ธฐ ๋๋ฌธ์ ๊ตณ์ด ๋ก์ปฌ๋ก ngrok์ ์ฌ์ฉํ์ฌ ์ธ๋ถ์ ๋ ธ์ถํ๋ ๊ณผ์ ๊น์ง ๋ณด์ฌ์ค ํ์๊ฐ ์๋ค๊ณ ํ๋จํ๋ค.
- ngrok์ผ๋ก ์ธ๋ถ์ ์๋ฒ๋ฅผ ์คํํ๊ณ ์นํ ์ผ๋ก ๋ฐฐํฌ ์๋ํ + ๋ฌด์ค๋จ ๋ฐฐํฌ ํ ์คํธ๋ฅผ ํ๊ณ ์ถ๋ค๋ฉด ์ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ ํ์ฌ ์งํํ๋ฉด ๋๋ค.
- ์ค์ ์ธ๋ถ ์๋ฒ๋ก jar ํ์ผ์ ๋ณด๋ด๊ธฐ ์ํด์๋ ssh ์ฐ๊ฒฐ๋ก ์งํํ ํ
๋ฐ ๊ทธ ๋ถ๋ถ์ ์ค๋ฌด์ ์ ์ฉํด ๋ณด๋ฉด์ ๊ฒฝํํด ๋ณผ ์์ ์ด๋ค.
- ์คํ๋ ค ๊ทธ ๋ถ๋ถ์ด ์ฌ์ธ ์ ์๋ค. ๋ก์ปฌ์์ ๋ก์ปฌ๋ก ๋ณด๋ด๋ ๊ฒ ์๊ฐ๋ณด๋ค ๊น๋ค๋ก์ด ๋ถ๋ถ์ด ๋ง์๋ค.
- ๊ธฐ๋ณธ์ ์ผ๋ก ๋ก์ปฌ PC๋ macOS ๊ธฐ๋ฐ์ด๋ผ ๋ฆฌ๋ ์ค์๋ ์ฝ๊ฐ์ ์ฐจ์ด๊ฐ ์๋ ๋ถ๋ถ(sudo ๋ช ๋ น์ด๋ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฐ) ๋ฑ ์ฌ์ํ ๋ฌธ์ ๋ฅผ ๋ชจ๋ ํด๊ฒฐํ๋๋ฐ ๊ฝค๋ ์๊ฐ์ด ๊ฑธ๋ ธ๋ค.
jenkins ๊ด๋ จ ๊ตฌํ ์ ์ฐธ๊ณ ํ๊ฑฐ๋ ์๋ฌ ํธ๋ค๋ง์ ๋์์ ์ค ๋งํฌ์ด๋ค.
๊ตฌํ
https://hyunminh.github.io/nonstop-deploy/
https://hudi.blog/zero-downtime-deployment-with-jenkins-and-nginx/
https://hudi.blog/continuous-deploy-with-jenkins-1-backend/
https://wiki.jenkins.io/display/JENKINS/ProcessTreeKiller
์๋ฌ ํธ๋ค๋ง
https://be-developer.tistory.com/14
https://stackoverflow.com/questions/8646762/cannot-run-program-gradle-in-jenkins
https://stackoverflow.com/questions/17131249/how-to-solve-bad-interpreter-no-such-file-or-directory