CI/CD란 각각의 개발자들이 개발을 하는 개발환경을 사용자가 사용 가능한 서비스로 전달하는 모든 과정을 지속 가능한 형태로 또 가능하다면 자동으로 해서 개발자와 사용자 사이의 격차를 없애는 것이다. 이러한 과정에는 코드를 빌드하고, 테스트하고 배포하는 활동이 있다.
이런 CI/CD 툴에는 여러 종류가 있지만 내가 접해본 CI/CD 툴은 Github Action 만 사용해보았고 이번에 신규 프로젝트를 들어가며 Jenkins를 사용해보고자 한다.
코드의 빌드를 자동화 해주는 툴로서. 대표적인 기능으로 다음과 같습니다.
그리고 이번 프로젝트에선 서버뿐만 아니라 프론트도 CI/CD를 담당할 예정이라 젠킨스로 선택하게 되었다.
먼저 우리 프로젝트는 총 4대의 서버를 운영하고 있다.
Oracle cloud 4코어 24기가 메인 서버
EC2 t3.micro 2대 (RabbitMQ, Jenkins)
Lightsail 2코어 2기가 1대 (Frontend)
로 사용예정이다.
EC2 t3.micro(프리티어) 에서 젠킨스를 사용할 예정이기 때문에 스왑 메모리 설정을 해줘야 한다 (안하면 서버가 죽는다..)
코드
순서이다
sudo dd if=/dev/zero of=/swapfile bs=128M count=16
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo swapon -s
sudo nano /etc/fstab
/swapfile swap swap defaults 0 0
free
다음과 같이 나온다면 성공한거다
다음 명령을 터미널에서 실행한다.
sudo apt update
sudo apt upgrade
sudo apt install openjdk-xx-jdk
xx에는 사용할 jdk 버전을 입력한다.
프로젝트 jdk 버전이 21을 사용중이라 맞출겸 21을 사용하였다
다음 명령을 터미널에서 실행한다.
sudo sh -c 'echo deb https://pkg.jenkins.io/debian-stable binary/> /etc/apt/sources.list.d/jenkins.list'
sudo apt-get update
sudo apt-get install jenkins
systemctl status jenkins 을 입력하면 설치 여부를 확인할 수 있다.
sudo vi /etc/default/jenkins 을 사용하면 포트 등의 젠킨스 설정을 변경할 수 있다. (근데 난 그냥 기본포트를 사용하였다)
이후 sudo service jenkins restart 를 입력해 젠킨스를 재실행한다.
그리고 EC2 인스턴스에서 젠킨스가 실행된 포트의 인바운드 규칙을 추가해준다.
public ip: 설정한 포트(기본 8080)을 브라우저에 입력하면 젠킨스에 접속할 수 있다.
아래 명령어를 사용하면 비밀번호가 나온다 그걸 치고 들어가면 된다
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
그럼 본인 계정 회원가입창이 뜨고
앞으로 사용할 계정을 생성해주면 된다
sudo apt update
sudo apt install docker.io
세팅끝🔥
젠킨스를 접속하면 아래와 같은 화면일 것이다.
저기 Item은 내가 미리 만들어둔거라 뜨는거고 원래는 아무것도 없어야 정상이다
Jenkins 관리를 누른뒤
Credentials 에서 환경변수를 설정 할 수 있다.
(예시 깃허브 or yml 파일등)
클릭해서 들어가준다
들어가면 원래는 아무것도 없을껀데 미리 만든것 때문에 난 존재하는거다.
걍무시하삼
Add credentials
Username with password
순서대로 설명하자면
Scope : 이 환경변수를 사용할 범위를 지정한다
Username : 유저 이름을 넣으면 된다.
(지금은 깃허브 세팅중이니 깃허브유저 이름을 넣으면 된다.)
Password : github access token 을 넣으면 된다.
(참고로 github access token 권한에 비공개 레포 권한이 있어야한다.)
ID : 이 환경변수를 부를때 사용할 ID 지정한다.
(github라고 적어두자)
Description : 이 환경변수에 대한 설명이다.
(알아서 잘 적길 바란다)
다 세팅했으면 create 누르자.
같은 방법으로 docker 도 세팅해준다
Username : docker hub 이름
Password : docker hub access token
ID : docker
Description : 설명
완료했음 도커와 깃허브 세팅은 완료된거다
깃허브 private Repo 에 yml or properties 파일이 올라가있다면 안해도 된다.
똑같이 credentials 에 글로벌에서 Add credentials을 누른다
Kind에서 Secret file 선택하면 아래와 같이 나올것이다.
File 은 yml 파일 혹은 properties 파일을 선택하면 되고
ID는 이 환경변수 파일을 부를 명칭을 적으면 되고
Description은 그냥 설명 적음 된다.
난 ID를 application 으로 하였다.
젠킨스 서버 말고 난 메인서버가 따로 있기때문에 그 서버 접속 세팅을 해줘야한다.
먼저 젠킨스 Dashboard -> jenkins 관리 -> Plugins 에 가서
Available plugins를 눌러 아래 처럼 Publish Over SSH 를 다운받는다.
다운받은뒤 Dashboard -> jenkins 관리 System Configuration 에서 System 클릭한다.
내리다보면 Publish over SSH가 있다
.pem 파일 혹은 SSH파일을 cat 명령어로 확인하여 Key 부분에 입력해주고
키 암호화 해서 넣는법은 잘 모르겠다.. 혹시 아시는분 있으면 댓글로 알려주세요
이부분은 각자 설정에 맞게 입력해주자.
Name : 서버 이름 (나중에 configName으로 사용됨)
Hostname : 서버 ip 주소
Username : 서버 접속 유저 이름
정도만 설정하면 된다.
새로운 아이템 생성을 누른 다음
Item 이름 설정과 파이프라인 선택하고 OK를 클릭한다.
설명은 대충 알아볼 수 있도록 적어주고
GitHub project 를 클릭해서 CI/CD를 적용할 레포 링크를 가져오자
그 다음 GitHub hook trigger GITScm polling 을 클릭하자
(이건 깃허브 후크를 통하여 이벤트가 발생 [푸시] 했을때 빌드를 하겠단 소리다)
클릭한 뒤 깃허브로 돌아가서 젠킨스와 연동할 프로젝트를 켜준다.
그 뒤 Settings 클릭 -> Webhooks 클릭
Add webhook 클릭
아래와 같은 화면이 나오면
참고로 update webhook 이 아닌 addWebhook 만 나올것이다. 절대로 다시 만들기 귀찮아서 기존꺼 킨거 아님!!
Payload URL : 당신의 젠킨스서버 URL : 포트 / github-webhook / 를 적어주면 된다.
Ex : http://127.0.0.0:8080/github-webhook/
뒤에 / 꼭 넣어주자
나머진 사진과 같이 설정하면 된다.
(Just the push event 꼭 하자)
안하면 모든 이벤트마다 빌드가 되는 머리아픈일이 발생한다...
다시 젠킨스로 돌아가서 파이프라인 스크립트만 작성하면 거의 다한거다.
여기에 아래 코드를 붙혀넣어주자
pipeline {
agent any
stages {
stage('Clone Repository') {
steps {
git branch: '자신의 브랜치', url: "젠킨스 빌드할 레포나 플젝 깃허브 주소"
}
}
//이건 아까 yml 파일 설정한 사람만 사용하자
stage('Add Env') {
steps {
script {
sh 'ls -R admin'
sh 'chmod -R 777 src/main/resources/'
withCredentials([file(credentialsId: 'application', variable: 'application')]) {
sh 'cp $application src/main/resources/application.yml'
}
}
}
}
stage('Build Project') {
steps {
sh './gradlew clean build -x test'
}
}
stage('Docker Login') {
steps {
withCredentials([usernamePassword(credentialsId: 'docker', usernameVariable: 'DOCKER_USERNAME', passwordVariable: 'DOCKER_PASSWORD')]) {
sh "echo \$DOCKER_PASSWORD | docker login -u \$DOCKER_USERNAME --password-stdin"
}
}
}
stage('Build Docker Image') {
steps {
// 아래 빌드 플랫폼은 각자 알맞는 플랫폼으로 설정하자
sh 'docker build --platform linux/arm64/v8 -t 도커 유저이름/이미지이름 .'
}
}
stage('Push Docker Image') {
steps {
sh 'docker push 도커 유저이름/이미지이름'
}
}
stage('SSH Connection') {
steps {
script {
sshPublisher(
continueOnError: true,
failOnError: true,
publishers: [
sshPublisherDesc(
configName: 'server',
verbose: true,
transfers: [
sshTransfer(
execCommand: '''
if docker ps -a | grep -q server; then
docker stop 이미지 이름
docker rm 이미지 이름
fi
docker pull 도커 유저이름/이미지이름
docker run -d --name 이미지이름 -p 80:80 도커 유저이름/이미지이름
''',
execTimeout: 120000 // Adjust as needed
)
]
)
]
)
}
}
}
}
post {
always {
sh 'docker image prune -f'
script {
sshPublisher(
continueOnError: true,
failOnError: true,
publishers: [
sshPublisherDesc(
configName: 'ssh publish over 에서 설정한 이름 기입',
verbose: true,
transfers: [
sshTransfer(
execCommand: 'docker image prune -f',
execTimeout: 60000 // Adjust timeout as needed
)
]
)
]
)
}
}
}
}
깃허브 액션을 사용해보았음 비슷하다 느낄수도 있다.
각 stage 별로 작업을 분리해 뒀고
순서대로 보자면
Clone Repository : 레포를 클론해온다.
Add Env : yml or properties 파일을 resources 아래 넣는다.
(아까 설정 안한사람은 빼도 상관없음)
Build Project : 클론해온 파일을 바탕으로 .jar 파일을 빌드한다.
Docker Login : 도커에 로그인 한다.
Build Docker Image : 도커파일을 빌드한다.
Push Docker Image : 도커허브에 도커파일을 푸시한다.
SSH Connection : 도커파일을 돌릴 원격 서버에 접속한다.
POST : 부분이 도커를 실행할 서버에서 도커 파일을 받고 돌리는 과정이 들어있다.
저렇게 설정을 완료하였음 저장을 누르고 빠져나오자.
근데 아무 작동이 안되는데요??
지금 빌드를 누르면 빌드가 시작될 것이다.
아래와 같이 빨간게 하나도 없다면 성공한 것이다.
다음과 같이 실패한 경우 마우스를 호버하면 로그를 볼 수 있다.
로그를 바탕으로 오류를 고치면 정상 작동 할 것이다.
이로서 나도 jenkins를 활용한 CI/CD 유경험자가 되었다!!!
젠킨스 디코 플러그인으로 빌드 성공/실패에 대하여 알람을 받을 수 있다.
Dashboard -> jenkins 관리 -> plugins 에서
Discord Notifier 를 다운받는다.
다음 디코로 넘어가 웹훅 URL을 발급받는다.
디코 접속 -> 서버설정 -> 연동 -> 새 웹후크 -> 메시지 보낼 위치 설정 및 URL 복사
다시 젠킨스로 돌아와 아이템 -> 구성 -> 파이프 라인 스크립트에서 아래 코드를 추가하자
아래 코드는 Post {} 범위 안에 넣어야한다.
success {
discordSend description: "빌드 성공시 나올 상단 제목",
footer: "빌드 성공시 나올 내용",
link: env.BUILD_URL, result: currentBuild.currentResult,
title: "빌드 성공시 제목",
webhookURL: "웹후크 URL"
}
failure {
discordSend description: "빌드 실패시 나올 상단 제목 ",
footer: "빌드 실페시 나올 내용",
link: env.BUILD_URL, result: currentBuild.currentResult,
title: "빌드 실패시 제목",
webhookURL: "웹후크 URL"
}
설정을 다했음 빌드를 해보자
잘 작동한다면 디코로 알람이 갈 것이다.
이로서 당신도 Jenkins 를 활용한 CI/CD 유경험자로 거듭났다!
여담
작동이 안 되거나 문제가 있다면 댓글 달아줘요.. 만들면서 정리한 게 아니라 프로젝트 일정 쳐내랴 학교 생활하랴 바빠서.. 시간 날 때마다 만든 거라 틀린 정보가 있을 수도 있어요
깃헙 액션이 세팅 부분이나 러닝커브 부분에선 압도적이지만
젠킨스를 잘 활용한다면 깃헙 액션보다 훨씬 좋을 것 같다 생각합니다.
일주일전에 젠킨스 세팅을 마쳤는데 벌써 66번이나 작동하였는데
과연 프로젝트 끝날 때까지 얼마나 작동할지 궁금하네요
잘 봤습니day