์ง๊ธ๊น์ง์ ์ค์ ์ผ๋ก๋ ๋ฉ์ธ ๋ธ๋์น์ ์ฝ๋๊ฐ merge๋ ๋๋ง๋ค EC2์ ์ ์ํด์ ๋ฐฐํฌ๋ฅผ ์ํ ์ ์คํฌ๋ฆฝํธ ํ์ผ์ ์ง์ ์คํํด์ฃผ๋ ๊ณผ์ ์ ๊ฑฐ์ณ์ผ ํฉ๋๋ค.
์ด๋ฌํ ์ฃผ๊ธฐ๊ฐ ๋น๋ฒํ ์๋ก ๋งค๋ฒ EC2์ ์ ๊ทผํ์ฌ ์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๋ ๊ณผ์ ์ ๋์ฑ ๋ฒ๊ฑฐ๋ก์์ง๋๋ค.
์ด๋ฒ ๊ธ์์๋ CD ๊ธฐ์ ์ธ Jenkins๋ฅผ ์ ์ฉํ์ฌ ์์ ๋ฌธ์ ๋ค์ ํด๊ฒฐํด ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
๐ง CI/CD ํ๋ก์ฐ
๋ค์๊ณผ ๊ฐ์ ๊ณผ์ ์ผ๋ก CI/CD๊ฐ ์ด๋ฃจ์ด์ง๋๋ค.
- PR์ด ์์ฑ๋๋ฉด Github Actions์ผ๋ก ํ ์คํธ๋ฅผ ์งํํฉ๋๋ค.
- ์ ๊ณผ์ ์ด ์ฑ๊ณตํด์ผ๋ง main ๋ธ๋์น์ mergeํ ์ ์์ต๋๋ค.
- github์ ๋ฉ์ธ ๋ธ๋์น์ mergeํฉ๋๋ค.
- ์๋์ ๊ณผ์ ์ ์ ํจ์ค์์ ์งํํฉ๋๋ค.
- ํ ์คํธ๋ฅผ ์งํ (CI)
- JARํ์ผ ๋น๋
- JARํ์ผ์ EC2์ ์ ์ก
- EC2 ์ ์
- ๋ฐฐํฌ ์คํฌ๋ฆฝํธ ์คํ
๐ง ์ ํจ์ค๋ฅผ ์คํํ EC2 ์์ฑํ๊ธฐ
์์์ ์์, ์ ๋ ์ด๋ฏธ ํ๋ฆฌํฐ์ด EC2์ ๋ฌด๋ฃ ํ๊ฐํ EC2๋ฅผ ๋ชจ๋ ์ฌ์ฉํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์๋ก์ด EC2 ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ฒ ๋๋ฉด ๋์ ์ง๋ถํด์ผ ํฉ๋๋ค.
DB ์ฐ๊ฒฐ์ ์ด๋ฏธ ์งํํ๊ณ , ์์ผ๋ก์ ๊ณผ์ ์์ DB๋ฅผ ์ฌ์ฉํ ์ผ์ด ์๊ธฐ ๋๋ฌธ์ ์ ๋ DB ์ธ์คํด์ค๋ฅผ ์ง์ฐ๊ณ , Jenkins์ฉ EC2๋ฅผ ์์ฑํ์ฌ ํ๋ฆฌํฐ์ด๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ๋๋ก ํ๊ฒ ์ต๋๋ค.
์ด๋ฆ์ ๋ง์๋๋ก ์ง์ด์ฃผ์ธ์.
์ ํ๋ฆฌ์ผ์ด์ ๋ฐ OS์ด๋ฏธ์ง๋ Ubuntu - 22.04LTS(ํ๋ฆฌํฐ์ด ์ฌ์ฉ ๊ฐ๋ฅํ ์๋ฌด๊ฑฐ๋) - 64๋นํธ(x86)์ ์ ํํฉ๋๋ค.
์ธ์คํด์ค ์ ํ์ ํ๋ฆฌํฐ์ด ์ฌ์ฉ ๊ฐ๋ฅํ t2.micro๋ฅผ ์ ํํฉ๋๋ค.
ํค ํ์ด๋ ๊ธฐ์กด์ ์์ฑํด๋ ํค ํ์ด๋ฅผ ์ฌ์ฉํ๊ฒ ์ต๋๋ค.
๋คํธ์ํฌ ์ค์ ์ ์์ ๊ฐ์ต๋๋ค.
VPC๋ ๊ธฐ๋ณธ VPC๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๋ณด์ ๊ทธ๋ฃน์์ ์ฌ์ฉ์ ์ง์ TCP์ ํฌํธ ๋ฒ์๋ ์ ํจ์ค๋ฅผ ์คํํ ํฌํธ ๋ฒํธ๋ฅผ ์ ๋ ฅํด ์ฃผ๋ฉด ๋๋๋ฐ์, ์ ๋ 8081๋ก ์ค์ ํ๋๋ก ํ๊ฒ ์ต๋๋ค.
๋ง์ง๋ง์ผ๋ก ์คํ ๋ฆฌ์ง ๊ตฌ์ฑ์ ํ๋ฆฌํฐ์ด๋ก ์ค์ ๊ฐ๋ฅํ ์ต๋ ํฌ๊ธฐ์ธ 30์ ์ค์ ํฉ๋๋ค.
์ด์ ํด๋น EC2์ ์ ์ํ๋๋ก ํ๊ฒ ์ต๋๋ค.
์์ ํผ๋ธ๋ฆญ ์ฃผ์๋ฅผ ๋ณต์ฌํ ๋ค, ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํฉ๋๋ค.
ssh -i [ํคํ์ด] ubuntu@[ํผ๋ธ๋ฆญ IPv4 ์ฃผ์]
๐ง EC2์ ๋์ปค๋ก ์ ํจ์ค ์ค์นํ๊ธฐ
์ ํจ์ค๋ฅผ ์ค์นํ ๋ ๋์ปค๋ฅผ ํตํด ์ค์นํ ๊ฒ์ธ๋ฐ์, ์ ํจ์ค๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ์ฌ๋ฌ ์ค์ ๋ค(JDK ์ค์น, ํฌํธ, ๋ฐฉํ๋ฒฝ ์ค์ ๋ฑ๋ฑ)์ ํด์ฃผ์ด์ผ ํ์ง๋ง ์ฒ์ ์ฌ์ฉํ๋ ์ ์ฅ์์ ์ด๋ค์ ์ค์ ํ๋ ๊ฒ์ด ์กฐ๊ธ ์ด๋ ค์ธ ๊ฒ ๊ฐ๋ค๊ณ ํ๋จํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
๋์ปค๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฌํ ํ๊ฒฝ ์ค์ ์์ด ๊ฐ๋จํ๊ฒ ์ ํจ์ค๋ฅผ ์ค์นํ๊ณ ์ฌ์ฉํ ์ ์๊ฒ ๋ฉ๋๋ค.
๐ณ ๋์ปค ์ค์น
์ฐ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ฉ EC2 ์๋ฒ์ ์ ์ํ์ฌ ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ฐจ๋ก๋๋ก ์คํํฉ๋๋ค.
(์๋ ๋ด์ฉ์ ๋์ปค ๊ณต์๋ฌธ์์์ ์ ๊ณต๋๋ ๋ด์ฉ์ ๋๋ค.)
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo docker run hello-world
ํด๋น ๋ช ๋ น์ด๊ฐ ์์ ๊ฐ์ด ์คํ๋๋ฉด ๋์ปค ์ค์น์ ์ฑ๊ณตํ ๊ฒ์ ๋๋ค.
๐ช๐ป ์ ํจ์ค ์ค์น
๋ค์ ๋ช ๋ น์ด๋ฅผ ํตํด ์ ํจ์ค ์ด๋ฏธ์ง๋ฅผ ๋ค์ด๋ก๋ํฉ๋๋ค.
sudo docker pull jenkins/jenkins:lts
์ด๋ ๊ฒ ํด์ ๋์ปค๋ฅผ ํตํด ์ ํจ์ค๋ฅผ EC2์ ์ค์นํ์์ต๋๋ค.
๐ง ๋์ปค๋ก ์ ํจ์ค ์คํํ๊ธฐ
์ด์ ์ ํจ์ค ์ปจํ ์ด๋๋ฅผ ์คํํ๋๋ก ํ๊ฒ ์ต๋๋ค.
sudo docker run --rm -d -p [์ธ๋ถํฌํธ]:8080 -v /jenkins:/var/jenkins_home --name [์ปจํ ์ด๋ ์ด๋ฆ] -u root jenkins/jenkins:lts
sudo docker run --rm -d -p 8081:8080 -v /jenkins:/var/jenkins_home --name jenkins -u root jenkins/jenkins:lts
์ด๋ ์ธ๋ถํฌํธ๋ ๋งจ ์ฒ์ ์ธ๋ฐ์ด๋ ๊ท์น์ ์ค์ ํ ์ ํจ์ค์ฉ ํฌํธ๋ฒํธ๋ฅผ ์ ๋ ฅํด์ผ ํฉ๋๋ค.
- docker run : ๋์ปค ์ด๋ฏธ์ง๋ฅผ ์คํํฉ๋๋ค.
- --rm : ์ปจํ ์ด๋๊ฐ ์ข ๋ฃ๋๋ฉด ์ญ์ ํฉ๋๋ค.
- -d : ๋ฐฑ๊ทธ๋ผ์ด๋ ์์ ์ผ๋ก ์คํํฉ๋๋ค.
- -p [์ธ๋ถํฌํธ]:[๋ด๋ถํฌํธ] : ์ปจํ ์ด๋ ์ธ๋ถ์ ๋ด๋ถ ํฌํธ๋ฅผ ํฌ์๋ฉํฉ๋๋ค.
- -v /jenkins:/var/jenkins_home : ์๋ฌด๋ฐ ์ค์ ์ด ์๋ค๋ฉด ๋์ปค ์ปจํ ์ด๋์ ๋ฐ์ดํฐ๋ ์ปจํ ์ด๋๊ฐ ์ข ๋ฃ๋๋ฉด ํ๋ฐ๋ฉ๋๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋์ปค ์ปจํ ์ด๋ ๋ด๋ถ์ ๊ฒฝ๋ก์ ๋์ปค ์ปจํ ์ด๋ ๋ด๋ถ์ ๊ฒฝ๋ก๋ฅผ ์ฐ๊ฒฐํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋ณด์กดํ ์ ์์ต๋๋ค. /jenkins๋ ์ปจํ ์ด๋ ์ธ๋ถ ๊ฒฝ๋ก, /var/jenkins_home์ ์ปจํ ์ด๋ ๋ด๋ถ ๊ฒฝ๋ก์ ๋๋ค.
- --name jenkins: ๋์ปค ์ปจํ ์ด๋์ ์ด๋ฆ์ jenkins๋ก ์ค์ ํฉ๋๋ค.
- -u root : ์ปจํ ์ด๋๊ฐ ์คํ๋ ๋ฆฌ๋ ์ค์ ์ฌ์ฉ์ ๊ณ์ ์ root๋ก ๋ช ์ํฉ๋๋ค.
์ ๋ช ๋ น์ ์กฐ๊ธ ๋ณต์กํ๋ฏ๋ก, ๋์ปค ์ปจํ ์ด๋๋ฅผ ์คํํ ๋๋ง๋ค ์ ๋ ฅํ๋ ๋ฒ๊ฑฐ๋ก์์ ์ค์ด๊ธฐ ์ํด ๋์ปค ์ปดํฌ์ฆ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
(์ ๋ ์ฌ์ฉํ์ง ์์ ๊ฒ์ด์ง๋ง, ํน์ ์ฌ์ฉํ์ค ๋ถ๋ค์ ์ํ ๋ช ๋ น์ด์ ๋๋ค.)
์๋ ๋ช ๋ น์ด๋ฅผ ํตํด ๋์ปค ์ปดํฌ์ฆ๋ฅผ ์ค์นํฉ๋๋ค.
sudo apt install docker-compose
โ๏ธ docker-compose.yml
๋ฐ๋์ ์ด๋ฆ์ docker-compose.yml์ด์ด์ผ ํ๋ฉฐ, ๋ค์๊ณผ ๊ฐ์ด ์์ฑํฉ๋๋ค.
version: "3"
services:
jenkins:
image: jenkins/jenkins:lts
user: root
volumes:
- ./jenkins:/var/jenkins_home
ports:
- 8080:8080
๋์ปค ์ปดํฌ์ฆ๋ฅผ ์คํํ๊ธฐ ์ํด ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํฉ๋๋ค.
sudo docker-compose up -d
๋์ปค ์ปดํฌ์ฆ๋ฅผ ์ข ๋ฃํ๊ธฐ ์ํด์๋ ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํฉ๋๋ค.
sudo docker-compose down
๐ง ์ ํจ์ค ์ค์ ํ๊ธฐ
๋ค์ url๋ก ์ ํจ์ค์ ์ ์ํฉ๋๋ค.
http://[์ ํจ์ค์ฉ EC2 ์ธ์คํด์ค ํผ๋ธ๋ฆญ IPv4 ์ฃผ์]:[์ ํจ์ค ํฌํธ๋ฒํธ]
์ ํจ์ค์ฉ EC2 ํผ๋ธ๋ฆญ IP ์ฃผ์๊ฐ 11.111.111.111 ์ด๊ณ , ํฌํธ๋ฒํธ๊ฐ 8081์ด๋ผ๋ฉด url์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
http://11.111.111.111:8081
์ ์ํ๋ฉด ์์ ๊ฐ์ ํ๋ฉด์ด ๋ณด์ ๋๋ค.
๋น๋ฐ๋ฒํธ๋ ๋ค์ ๋ช ๋ น์ด๋ฅผ ํตํด ์ฐพ์ ์ ์์ต๋๋ค.
sudo docker logs [์ปจํ
์ด๋ ์ด๋ฆ]
ํด๋น ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํด์ ๋ค์ด๊ฐ๋ฉด ๋ฉ๋๋ค.
Install suggested plugins๋ฅผ ํด๋ฆญํฉ๋๋ค.
๋ค์๊ณผ ๊ฐ์ด ์ค์น ํ๋ฉด์ด ๋์ค๋๋ฐ ๊ธฐ๋ค๋ฆฌ๋ฉด ์ค์น๊ฐ ์๋ฃ๋ฉ๋๋ค.
(ํน์๋ผ๋ Intallaton Faulure๊ฐ ๋ฌ๋ค๋ฉด ๊ณ์ retry ํด๋ฆญํด์ฃผ์๋ฉด ๋ฉ๋๋ค.)
์ด๋๋ฏผ ์ ์ ๊ณ์ ์์ฑ์ ์์์ ์ ์ ๋ ฅํด์ค๋๋ค.
Instance Configuration์ ๊ธฐ๋ณธ๊ฐ ๊ทธ๋๋ก ์งํํฉ๋๋ค.
๊ธฐ๋ณธ์ ์ธ ์ค์น๊ฐ ๋๋ฌ์ต๋๋ค.
๐ง ๊นํ๋ธ ์นํ (webhook) ์ค์ ํ๊ธฐ
๊นํ๋ธ ๋ ํฌ์งํ ๋ฆฌ์ ์ ์ํ์ฌ Settings - Webhooks - Add webhook์ ํด๋ฆญํฉ๋๋ค.
- Payload URL - http://[์ ํจ์ค EC2 ํผ๋ธ๋ฆญ IPv4 ์ฃผ์]:[์ ํจ์ค ํฌํธ๋ฒํธ]/github-webhook/
- Content type - application/json
- Secret - ์ค์ ํ์ง ์์
- Just the push event
- Active ์ฒดํฌ
- Add webhook ํด๋ฆญ
๐ง ์ ํจ์ค Credentials ์์ฑ
๋์๋ณด๋์์ Jenkins ๊ด๋ฆฌ๋ฅผ ํด๋ฆญํฉ๋๋ค.
์คํฌ๋กค์ ์กฐ๊ธ ๋ด๋ฆฌ๋ฉด Credentials๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.
์ด๋ฅผ ํด๋ฆญํฉ๋๋ค.
(global)์ ๋ง์ฐ์คํด ๊ฐ์ ธ๊ฐ๋ฉด v ํ์๊ฐ ๋์ค๊ณ , ์ด๋ฅผ ํด๋ฆญํ๋ฉด Add credentials ๊ฐ ๋์ต๋๋ค.
์ด๋ฅผ ํด๋ฆญํฉ๋๋ค.
- Kind - Username with password
- Scope - Global (Jenkins, nodes, items, all child items, etc)
- Username - ๊นํ๋ธ username
- Password - ํด๋น ๊ธ์์ ๋ฐ๊ธํ ๊นํ๋ธ ์ก์ธ์ค ํ ํฐ(์๊ฑฐ๋ ์์ด๋ฒ๋ ธ๋ค๋ฉด repo์ admin:repo_hook ๊ถํ์ ๊ฐ์ง ํ ํฐ์ ์๋ก ์์ฑ ํ ์ ์ด์ฃผ์ธ์)
- ID - ๋ง์๋๋ก ์ ์ด์ฃผ์ธ์
Create ๋ฒํผ์ ๋๋ฌ ์์ฑํด์ค๋๋ค.
๐ง Gradle ์ค์
๋์๋ณด๋ -> Jenkins ๊ด๋ฆฌ -> Tools๋ฅผ ํด๋ฆญํฉ๋๋ค.
Tools์์ ์คํฌ๋กค์ ๋ด๋ฆฌ๋ค ๋ณด๋ฉด Gradle์ด ๋ณด์ ๋๋ค.
Add Gradle ํด๋ฆญ ํ ์์ ๊ฐ์ด ์ค์ ํด์ฃผ์ธ์
Gradle ๋ฒ์ ์ Build์ ์ฌ์ฉ๊ฐ๋ฅํ ๋ฒ์ ์ค ์์ ๋ ๋ฒ์ ์ ์ ํํด์ฃผ์ธ์
์ดํ ๋งจ ์๋ Save ๋ฒํผ์ ๋๋ฌ์ค๋๋ค.
๐ง ์ ํจ์ค CD ์ค์
์ ํจ์ค ๋์๋ณด๋์์ ์๋ก์ด Item์ ํด๋ฆญํฉ๋๋ค.
item ์ด๋ฆ์ ์์๋ก ์ค์ ํด์ฃผ์ธ์
์ดํ Pipeline์ ์ ํํ๊ณ OK๋ฅผ ๋๋ฌ์ค๋๋ค.
Github project๋ฅผ ์ ํํ๊ณ , Project url์ ๊นํ๋ธ ๋ ํฌ์งํ ๋ฆฌ URL์ ์ ์ด์ค๋๋ค.
Build Triggers์์๋ GitHub hook trigger for GITScm polling์ ์ ํํฉ๋๋ค.
์กฐ๊ธ ๋ด๋ ค์ค๋ฉด Pipeline์ด ๋ณด์ ๋๋ค.
์ฌ๊ธฐ์ Pipeline Syntax๋ฅผ ํด๋ฆญํฉ๋๋ค.
- Sample Step - git: Git
- Repository URL - ๊นํ๋ธ ๋ ํฌ์งํ ๋ฆฌ URL
- Branch - ํด๋น ํ์ดํ๋ผ์ธ(CI)์ด ์ ์ฉ๋ ๋ธ๋์น
- Credentials - ์์์ ๋ง๋ค์ด์ค Credentials ์ ํ
- Including in polling? , Including in changelog? ์ ํ
Generate Pipeline Script๋ฅผ ์ ํํ๊ณ ์์ฑ๋ ์คํฌ๋ฆฝํธ๋ฅผ ๋ณต์ฌํด์ฃผ์ธ์.
์ด์ ๋ค์ ์ด์ Pipeline์ผ๋ก ๋์๊ฐ์ ๋ค์ ๋ด์ฉ์ ์์ฑํด์ค๋๋ค.
pipeline {
agent any
tools {
gradle 'gradle'
}
stages {
stage('Github') {
steps {
git branch: 'main', credentialsId: 'github_access_token', url: 'https://github.com/shin-mallang/bapo-test'
}
}
stage('Build') {
steps {
sh "./gradlew clean bootJar"
}
}
}
}
์ด๋ Github Stage์ steps์ ๋ค์ด๊ฐ๋ ๋ด์ฉ์ ์์์ ๋ณต์ฌํ ๋ด์ฉ์ ๋๋ค.
์์๊ฐ์ด ์์ฑํ ํ ์ ์ฅ์ ๋๋ฌ์ค๋๋ค.
์ด์ ํ๋ฒ main ๋ธ๋์น์ ์ปค๋ฐ์ push ํ ๋ค, ์ ํจ์ค์ ์ ์ํ๋๋ก ํ๊ฒ ์ต๋๋ค.
(์ด์ ๊ธ์ ๋ฐ๋ผ ๋ธ๋์น ๋ณดํธ ๊ท์น์ ์์ฑํ์๋ค๋ฉด ๋ฐ๋ก Push๊ฐ ์๋๊ธฐ ๋๋ฌธ์ PR์ ๋ณด๋ด mergeํด์ฃผ์ธ์.)
์๋ง ์์ ๊ฐ์ด ์๋ฌด๊ฒ๋ ์คํ๋์ง ์์์ ๊ฒ์ ๋๋ค.
๐คฌ ์นํ ์ด ์๋ ์ํด์!!!!!
์๋ฌด๋ฆฌ ํด๋ด๋ ์นํ ์ด ์๋์ ์ํ๊ธธ๋ ์ง์ง ์ธ๊ณ ์ถ์๋๋ฐ, ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์์์ต๋๋ค.
ํ์ดํ๋ผ์ธ ์ต์ด ์ค์ ์ดํ์ ์ง๊ธ ๋น๋๋ฅผ ํด๋ฆญํด์ ์คํํด์ฃผ์ด์ผ ๊ทธ ์ดํ๋ถํฐ ์นํ ์ผ๋ก ํธ๋ฆฌ๊ฑฐ๋ฉ๋๋ค.
ํด๋ฆญํ๊ณ ๊ธฐ๋ค๋ฆฌ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ํ์ดํ๋ผ์ธ์ด ์คํ๋ฉ๋๋ค.
๊ทธ๋ฐ๋ฐ ์ ์ ๊ฐ์ด ์ค์ ํ์ จ๋ค๋ฉด, ์๋ง ์ ์ํ์์ ๊ฐ์๊ธฐ ์๋ฒ๊ฐ ์๋ต์ด ์์ด์ง ๊ฒ์ ๋๋ค.
๐คฌ ์ ํจ์ค ์๋ฒ๊ฐ ์ฃฝ์ด์!!
๋น๋ ์ ์๋ฒ๊ฐ ํฐ์ ธ ์๋ตํ์ง ์๋๋ค๋ฉด, Swap ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ค์ ํด ์ฃผ์ด์ผ ํฉ๋๋ค.
์ฐ์ ์ ํจ์ค ์ธ์คํด์ค๋ฅผ ์ค์งํ๊ณ ๋ค์ ์์ํด์ฃผ์ธ์
์ ํจ์ค EC2์ ์ ๊ทผํ์ฌ ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํฉ๋๋ค.
sudo fallocate -l 1.5G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
๋ค์ ์ ํจ์ค๋ฅผ ์คํํฉ๋๋ค.
sudo docker run --rm -d -p 8081:8080 -v /jenkins:/var/jenkins_home --name jenkins -u root jenkins/jenkins:lts
๊ทธ๋ฆฌ๊ณ ์ ํจ์ค์ ์ ์ํฉ๋๋ค.
http://[์ ํจ์ค EC2 ํผ๋ธ๋ฆญ IPv4 ์ฃผ์]:[ํฌํธ๋ฒํธ]
์์์ ์ฒ์ ์ค์ ํ ์ ๋ณด๋ก ๋ก๊ทธ์ธ ํด์ฃผ์ธ์.
ํ์ดํ๋ผ์ธ์ ์ค์ ํฉ๋๋ค.
์์ ๊ฐ์ด ๊ธฐ์กด์ ์คํ์ค์ธ ๋น๋๊ฐ ์กด์ฌํ๋๋ฐ์, ํ์๋ X ํ์๋ฅผ ๋๋ฌ ์ค์งํฉ๋๋ค.
์ธ์คํด์ค๋ฅผ ์ค์ง ํ ์์ํ์๋ค๋ฉด ํผ๋ธ๋ฆญ IPv4 ์ฃผ์๊ฐ ๋ณ๊ฒฝ๋๊ธฐ ๋๋ฌธ์ Webhook ์ค์ ์ ๋ค์ ํด์ฃผ์ด์ผ ํฉ๋๋ค.
Payload URL์ ๋ค์ ์ค์ ํด์ฃผ๊ณ , update ํด์ฃผ์ธ์.
์ด์ main ๋ธ๋์น์ Push ํ ์ ํจ์ค ํ์ดํ๋ผ์ธ์ ํ์ธํฉ๋๋ค.
ํ์ดํ๋ผ์ธ์ด ์นํ ์ผ๋ก ํธ๋ฆฌ๊ฑฐ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
๐ณ SSH Agent ํ๋ฌ๊ทธ์ธ ์ค์น
์ ํจ์ค์์ ์ ํ๋ฆฌ์ผ์ด์ ์ฉ EC2์ ์ ์ํด์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํด์ผ ํ๊ธฐ ๋๋ฌธ์, ์ด๋ฅผ ์ํ ํ๋ฌ๊ทธ์ธ์ ์ค์นํด์ฃผ๋๋ก ํ๊ฒ ์ต๋๋ค.
๋์๋ณด๋ - Jenkins ๊ด๋ฆฌ - Plugins๋ฅผ ํด๋ฆญํฉ๋๋ค.
Avaliable plugins - ssh agent ๊ฒ์ - install without restart๋ฅผ ํด๋ฆญํฉ๋๋ค.
๐ณ ์ ํ๋ฆฌ์ผ์ด์ EC2 ์ ๋ณด ์ค์
์ ํจ์ค์์ ์ ํ๋ฆฌ์ผ์ด์ ์ฉ EC2์ ์ ์ํด์ผ ํ๋ฏ๋ก ํด๋น EC2์ ์ ๋ณด๋ฅผ ์ค์ ํด ์ฃผ์ด์ผ ํฉ๋๋ค.
๋์๋ณด๋ - Jenkins ๊ด๋ฆฌ - Credentials๋ฅผ ํด๋ฆญํฉ๋๋ค.
Stores scoped to Jenkins์ System์ ํด๋ฆญํฉ๋๋ค.
Add credentials๋ฅผ ํด๋ฆญํฉ๋๋ค.
- Kind - SSH Username with private key
- Scope - Global (Jenkins, nodes, items, all child items, etc)
- ID - ์ํ๋๋ฐ๋ก
- Username - ubuntu
- Private Key - Enter directly ์ ํ ํ Add ํด๋ฆญ
Private Key๋ฅผ ์ ๋ ฅํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ฐ์ ์ ํ๋ฆฌ์ผ์ด์ ์ฉ EC2์ ์ ๊ทผํ๊ธฐ ์ํ pem ํค๊ฐ ์๋ ๊ณณ์ผ๋ก ์ด๋ํ ๋ค, ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํฉ๋๋ค.
cat [ํค์ด๋ฆ].pem
์ ๋ด์ฉ์ [-----BEGIN RSA...] ๋ถํฐ [END RSA...] ๊น์ง ์ ๋ถ ๋ค ๋ณต์ฌํด์ค๋๋ค.
(์ด๋ ๋ง์ง๋ง %๋ ๋นผ์ฃผ์ธ์)
์ด์ ํด๋น ๋ด์ฉ์ ์ ๋ ฅํฉ๋๋ค.
์ดํ Create์ ๋๋ฌ ์์ฑ์ ์๋ฃํด์ฃผ์ธ์.
๐ณ ์ ํจ์ค ํ์ดํ๋ผ์ธ ์์
์ด์ ์ ํจ์ค ํ์ดํ๋ผ์ธ์ ์คํฌ๋ฆฝํธ๋ฅผ ์์ ํด์ผ ํฉ๋๋ค.
๋์๋ณด๋์์ ํ์ดํ๋ผ์ธ์ ํด๋ฆญํ์ฌ ์ ์ํฉ๋๋ค.
๊ตฌ์ฑ์ ํด๋ฆญํฉ๋๋ค.
ํ์ดํ๋ผ์ธ ์คํฌ๋ฆฝํธ๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์์ ํฉ๋๋ค.
pipeline {
agent any
tools {
gradle 'gradle'
}
stages {
stage('Github') {
steps {
git branch: 'main', credentialsId: 'github_access_token', url: 'https://github.com/shin-mallang/bapo-test'
}
}
stage('Build') {
steps {
sh "./gradlew clean bootJar"
}
}
stage('Deploy') {
steps {
sshagent(credentials: ['๋ฐฉ๊ธ ์์ฑํ EC2 Credentials ID']) {
sh '''
ssh -o StrictHostKeyChecking=no ubuntu@[์ ํ๋ฆฌ์ผ์ด์
EC2 ํ๋ผ์ด๋น IPv4 ์ฃผ์]
scp build/libs/*.jar ubuntu@[์ ํ๋ฆฌ์ผ์ด์
EC2 ํ๋ผ์ด๋น IPv4 ์ฃผ์]:/home/ubuntu
ssh ubuntu@[์ ํ๋ฆฌ์ผ์ด์
EC2 ํ๋ผ์ด๋น IPv4 ์ฃผ์] "sh [๋ฐฐํฌ ์คํฌ๋ฆฝํธ ์ด๋ฆ].sh" &
'''
}
}
}
}
}
sshagent์ credentials๋ ์์์ ์์ฑํ EC2 Credentials ID์ ๋๋ค.
(์ ์ ๊ฒฝ์ฐ mallang-spring-ec2-key)
๋ ์ฃผ์๊น๊ฒ ์ดํด์ผ ํ ์ ์ด ์ ํ๋ฆฌ์ผ์ด์ ์ฉ EC2์ ํ๋ผ์ด๋น IPv4 ์ฃผ์๋ฅผ ์ ๋ ฅํด์ผ ํ๋ค๋ ๊ฒ์ ๋๋ค.
์ ์ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
pipeline {
agent any
tools {
gradle 'gradle'
}
stages {
stage('Github') {
steps {
git branch: 'main', credentialsId: 'github_access_token', url: 'https://github.com/shin-mallang/bapo-test'
}
}
stage('Build') {
steps {
sh "./gradlew clean bootJar"
}
}
stage('Deploy') {
steps {
sshagent(credentials: ['mallang-spring-ec2-key']) {
sh '''
ssh -o StrictHostKeyChecking=no ubuntu@172.31.25.210
scp build/libs/*.jar ubuntu@172.31.25.210:/home/ubuntu
ssh ubuntu@172.31.25.210 "sh bapo.sh" &
'''
}
}
}
}
}
๐ณ ๋ฐฐํฌ ์คํฌ๋ฆฝํธ ์์
์ด์ ์ ํ๋ฆฌ์ผ์ด์ EC2๋ก ๋์๊ฐ์, ๊ธฐ์กด์ ๋ฐฐํฌ ์คํฌ๋ฆฝํธ๋ฅผ ์์ ํด์ผ ํฉ๋๋ค.
๋์ด์ git pull์ ํตํด ์ต์ ์ ๋ณด๋ฅผ ๋ฐ์์ค๋ ๊ฒ์ด ์๋ ์์ฑ๋ JAR ํ์ผ์ ์ ๋ฌ๋ฐ์ผ๋ฏ๋ก, ๊ทธ์ ๋ง์ถ์ด ๋ฐฐํฌ ์คํฌ๋ฆฝํธ๋ฅผ ์์ ํฉ๋๋ค.
โ๏ธ bapo.sh
#!/bin/sh
PORT=8080
JAR_NAME=jwp-shopping-order.jar
echo " ๐ณ [$PORT] ๋ฒ ํฌํธ๋ฅผ ์ฌ์ฉํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์ฐพ์ต๋๋ค...\n"
PID=$(lsof -i :$PORT -t)
if [ -z $PID ]; then
echo " ๐ ์คํ์ค์ธ ์ ํ๋ฆฌ์ผ์ด์
์ด ์์ด์ ๊ณง๋ฐ๋ก ์คํํฉ๋๋ค.\n"
else
echo " โ ์คํ์ค์ธ ์ ํ๋ฆฌ์ผ์ด์
์ด ์์ด์ ์ด๋ฅผ ์ข
๋ฃํฉ๋๋ค. [PID = $PID]\n"
kill -15 $PID
fi
echo " ๐ณ ์ ํ๋ฆฌ์ผ์ด์
์ ์คํํ๋๋ฐ ํ์ํ ํ๊ฒฝ๋ณ์๋ฅผ ์ธํ
ํฉ๋๋ค.\n"
export FIRST_MALLANG_ENV="mallang1"
export SECOND_MALLANG_ENV=1234
export SPRING_PROFILES_ACTIVE="dev"
export RDS_DRIVER="com.mysql.cj.jdbc.Driver"
export RDS_URL="jdbc:mysql://172.31.40.148:3306/bapo_test"
export RDS_USERNAME="mallang"
export RDS_PASSWORD="1234"
echo " ๐ ์ ํ๋ฆฌ์ผ์ด์
์คํํฉ๋๋ค~ ๐\n"
nohup java -jar $JAR_NAME 1>> build.log 2>> build_error.log &
ํ์ฌ ์ ํจ์ค๋ฅผ ์ํด DB EC2๋ฅผ ์ ๊ฑฐํ๊ธฐ ๋๋ฌธ์ prod๊ฐ ์๋ dev๋ก ์คํํฉ๋๋ค.
๋ํ ๋ก๊ทธ๋ฅผ ํ์ธํ๊ธฐ ์ํด 1>> build.log 2>> build_error.log ๋ฅผ ์ถ๊ฐํ์์ต๋๋ค.
(1๋ฒ์ ํ์ค ์ถ๋ ฅ, 2๋ฒ์ ํ์ค ์๋ฌ ์ถ๋ ฅ์ ๋๋ค.)
์ด์ ๋ค์ ํ๋ฒ main branch์ pushํจ์ผ๋ก์จ, ๋ชจ๋ ๊ณผ์ ์ด ์ ๋์ํ๋์ง ํ์ธํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์ด์ ํฌ์คํ ๋ถํฐ ์ ๋ฅผ ๋ฐ๋ผํ์ จ๋ค๋ฉด Git submodule์ ์ ์ฉํ์ จ์ ํ ๋ฐ์, ๋ง์ฝ ์๋ธ๋ชจ๋์ ์ ์ฉํ๋ค๋ฉด ์๋ธ๋ชจ๋์ ํ์ผ์ด ๋ฐ์๋์ง ์์๊ธฐ ๋๋ฌธ์ ์คํจํ๊ฒ ๋ฉ๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ ์ CD ์คํฌ๋ฆฝํธ์ 'ssh -o StrictHostKeyChecking=no ubuntu@[์ ํ๋ฆฌ์ผ์ด์ EC2 ํ๋ผ์ด๋น IPv4 ์ฃผ์]'๋ฅผ ์ง์์ค๋๋ค.
(๋ฐ๋์ ํ ๋ฒ ์ด์ ์คํํ๊ณ ์คํจํ ๊ฒ์ ํ์ธํ ์ดํ ์ง์์ฃผ์ ์ผ ํฉ๋๋ค.)
์ด๋ known_host ๊ด๋ จํ ๋ด์ฉ์ธ๋ฐ์, SSH ์ต์ด ์๊ฒฉ์ ์ ์ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ๊ตฌ๋ฅผ ํ์ธํด ๋ณด์ จ์๊ฒ๋๋ค.
root@XXXXXXXX:/home# ssh -i key.pem ubuntu@192.168.XXX.XXX
The authenticity of host '192.168.XXX.XXX (192.168.XXX.XXX)' can't be established.
ECDSA key fingerprint is SHA256:XXXXXXXXXXXXXXXX
Are you sure you want to continue connecting (yes/no/[fingerprint])?
์ ํฌ๊ฐ ์ ์ํ ๋์๋ yes๋ฅผ ์ ๋ ฅํ๋ฉด ๋์ง๋ง, ์ ํจ์ค๋ ๊ทธ๊ฒ ์๋๊ธฐ ๋๋ฌธ์ ์ ์ต์ ์ ์ฃผ์ด์ ์ด๋ฅผ ํผํด๊ฐ๋ ๊ฒ์ ๋๋ค.
์ฒซ ssh ์ ์๋ง ์ด๋ฃจ์ด์ง๋ฉด known_hosts์ ํค๊ฐ ๋ฑ๋ก๋๊ธฐ ๋๋ฌธ์, ์ดํ ํด๋น ๋ช ๋ น์ด๋ฅผ ์ญ์ ํด๋ ์ ์์ ์ผ๋ก ์งํํ ์ ์์ต๋๋ค.
๐ง Git Submodule ๋ฐ์ํ๊ธฐ
๋น๋ ์คํฌ๋ฆฝํธ๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋ณ๊ฒฝํฉ๋๋ค.
(Github Stage๊ฐ ๋ณ๊ฒฝ๋์์ต๋๋ค.)
pipeline {
agent any
tools {
gradle 'gradle'
}
stages {
stage('Github') {
steps {
checkout scmGit(
branches: [[name: 'main']],
extensions: [submodule(parentCredentials: true, trackingSubmodules: true)],
userRemoteConfigs: [[credentialsId: 'github_access_token', url: 'https://github.com/shin-mallang/bapo-test']]
)
}
}
stage('Build') {
steps {
sh "./gradlew clean bootJar"
}
}
stage('Deploy') {
steps {
sshagent(credentials: ['๋ฐฉ๊ธ ์์ฑํ EC2 Credentials ID']) {
sh '''
scp build/libs/*.jar ubuntu@[์ ํ๋ฆฌ์ผ์ด์
EC2 ํ๋ผ์ด๋น IPv4 ์ฃผ์]:/home/ubuntu
ssh ubuntu@[์ ํ๋ฆฌ์ผ์ด์
EC2 ํ๋ผ์ด๋น IPv4 ์ฃผ์] "sh [๋ฐฐํฌ ์คํฌ๋ฆฝํธ ์ด๋ฆ].sh" &
'''
}
}
}
}
}
๋ค์ ํ๋ฒ ๋ฉ์ธ ๋ธ๋์น์ Push ํด๋ณด๊ฒ ์ต๋๋ค.
์์ ๊ฐ์ด ์ฑ๊ณตํ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
(๊ทธ ๋ฐ์ ์ฌ๋ฌ ๋น๋ ๊ธฐ๋ก๋ค์ ์ฝ์ง์ ํ์ ์ด๋ ๋์ด๊ฐ์ฃผ์ธ์..)
์์ ๊ฐ์ด ์คํ๋ ์ฑ๊ณตํ๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
๐ง [์ถ๊ฐ] ์ ํจ์ค ์คํฌ๋ฆฝํธ ํ์ผ์ ๊น์ผ๋ก ๊ด๋ฆฌํ๊ธฐ
๋์๋ณด๋ - ํ์ดํ๋ผ์ธ ์ ํ - ๊ตฌ์ฑ์ผ๋ก ์ด๋ํฉ๋๋ค.
Pipeline์ Definition์์ Pipeline script from SCM์ ์ ํํฉ๋๋ค.
์ดํ SCM์ Git์ ์ค์ ํ๊ณ , Repository URL๊ณผ Credentials๋ฅผ ์ค์ ํฉ๋๋ค.
์ดํ ๋น๋ํ ๋ธ๋์น์, ์ ํจ์ค ์คํฌ๋ฆฝํธ(.jenkinsfile)์ ๊ฒฝ๋ก๋ฅผ ์ ์ด์ฃผ๋ฉด ๋ฉ๋๋ค.
์ ๋ script ๋๋ ํ ๋ฆฌ๋ฅผ ๋ง๋ค๊ณ , ๊ทธ ์์ cd.jenkinsfile์ ์์ฑํ ๊ฒ์ด๋ฏ๋ก ์์ ๊ฐ์ด ์ค์ ํด ์ฃผ์์ต๋๋ค.
์ด์ ํ๋ก์ ํธ ํ์ผ๋ก ๋ค์ด๊ฐ์ ์ ํจ์ค ์คํฌ๋ฆฝํธ๋ฅผ ์ถ๊ฐํด์ฃผ๋๋ก ํ๊ฒ ์ต๋๋ค.
์ด๋ฅผ ์ปค๋ฐํ ๋ค main ๋ธ๋์น์ pushํ์ฌ ์ ์ฉํฉ๋๋ค.
์ ์ ์ฉ๋๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
๐ง [์ถ๊ฐ] ์ ํจ์ค ์คํฌ๋ฆฝํธ ํ์ผ์ ๋ณ์ ์ฌ์ฉํ๊ธฐ
์์์ ์ดํด๋ณธ ์คํฌ๋ฆฝํธ ํ์ผ ์ค, ์๋ฒ์ IP ์ฃผ์ ๋ฑ์ ์๋ฒ๊ฐ ๋ณ๊ฒฝ๋๋ฉด ๋ฐ๋์ด์ผ ํ๋ ๋ด์ฉ์ ๋๋ค.
๋ํ ์ํฉ์ ๋ฐ๋ผ ๋ฏผ๊ฐํ ์ ๋ณด๊ฐ ์คํฌ๋ฆฝํธ ํ์ผ์ ๋ ธ์ถ๋ ์ ์๋๋ฐ์, ์ด๋ค์ ๋ณ์๋ฅผ ํตํด ๊ฐ์ถ๋๋ก ํ๊ฒ ์ต๋๋ค.
์ฐ์ ์คํฌ๋ฆฝํธ ํ์ผ์ ๋ค์๊ณผ ๊ฐ์ด ๋ณ๊ฒฝํฉ๋๋ค.
pipeline {
agent any
tools {
gradle 'gradle'
}
stages {
stage('Github') {
steps {
checkout scmGit(
branches: [[name: 'main']],
extensions: [submodule(parentCredentials: true, trackingSubmodules: true)],
userRemoteConfigs: [[credentialsId: "$GIT_CREDENTIAL", url: 'https://github.com/shin-mallang/bapo-test']]
)
}
}
stage('Build') {
steps {
sh "./gradlew clean bootJar"
}
}
stage('Deploy') {
steps {
sshagent(credentials: ["$EC2_CREDENTIAL"]) {
sh '''
scp build/libs/*.jar ubuntu@$EC2_PRIVATE_IP:/home/$EC2_USER
ssh ubuntu@$EC2_PRIVATE_IP "sh $SCRIPT_NAME.sh" &
'''
}
}
}
}
}
์ด์ ๋ณ์๋ฅผ ์ค์ ํด ๋ณด๊ฒ ์ต๋๋ค.
๋์๋ณด๋ - ํ์ดํ๋ผ์ธ ์ ํ - ๊ตฌ์ฑ
General์ ์ด ํ๋๋ ๋งค๊ฐ๋ณ์๊ฐ ์์ต๋๋ค๋ฅผ ํด๋ฆญํฉ๋๋ค.
Credentials Parameter ์ String Parameter ํน์ ์ด ์ธ์ ๊ฒ๋ค์ด ํ์ํ๋ค๋ฉด ์์์ ์ ํํด์ ์ ์ฉํฉ๋๋ค.
๋ฑ๋ฑ..
๐ ๋ง๋ฌด๋ฆฌ
์ด๋ ๊ฒ ํด์ ์ด๋ฒ ๊ธ์์ Jenkin๋ฅผ ํตํ ์๋ ๋ฐฐํฌ๊น์ง ์ค์ ํด ๋ณด์์ต๋๋ค.
์ด์ฐ์ด์ฐ ํด์ ๋ฐฐํฌ์ ๊ฐ๋จํ ๊ณผ์ ์ ๋๋ธ ๊ฒ ๊ฐ๋ค์ ๐
์์ ์ ์๋ ๋๊ฒ ๊ฒ์ด ๋ฌ์๋๋ฐ, ํด๋ณด๊ณ ๋๋ ๋ณ๊ฑฐ๋ค์ :)
์กฐ๋ง๊ฐ HTTPS ์ ์ฉํ๋ ๋ฒ ๊น์ง๋ง ์ดํด๋ณด๊ณ ํ๋์ ๋ฐฐํฌ ๊ด๋ จ ์ถ๊ฐ์ ์ธ ๊ธ์ ์์ ๊ฒ ๊ฐ์ง๋ง, ์ดํ ๋ฌด์ค๋จ ๋ฐฐํฌ์ ๋ํด์๋ ์ ์ฉํด๋ณด๊ณ ์์ฑํด๋ณด๊ณ ์ถ์ต๋๋ค.
ํ์ง๋ง ์ต์ ๋ช๋ฌ์ ๊ฑธ๋ฆด ๊ฒ ๊ฐ๋ค์ ๐
์๋ฌดํผ ๋ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค!๐โ๏ธ
๐ Reference
https://developer-nyong.tistory.com/47
https://dallog.github.io/continuous-deploy-with-jenkins-1-backend/