90일차) 2025-05-09(Jenkins를 통한 CI/CD)
깃허브 액션같은 경우, webhook을 하는데 큰 문제가 없었다.
# 하지만 오픈소스 CI 도구인 젠킨스의 경우, 로컬 환경(private network)에 설치하면 내가 네트워크 관리자여서 포트포워딩을 제어할 수 있는 상황이 아니라면 webhook이 불가능하다. 따라서 우리는 클라우드에 인스턴스를 생성하여 jenkins를 구성할 예정이다.
EKS가 설치된 VPC의 퍼블릭 서브넷에 Jenkins를 설치
- 인스턴스 유형은 최소 small 이상으로 해야한다.
root@ip-10-50-10-213:~# apt update -y
- 레포등록을 위한 키 추가
wget -O /usr/share/keyrings/jenkins-keyring.asc \
https://pkg.jenkins.io/debian/jenkins.io-2023.key
- 젠킨스 레포 추가
echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc]" \
https://pkg.jenkins.io/debian binary/ | sudo tee \
/etc/apt/sources.list.d/jenkins.list > /dev/null
- 젠킨스는 자바로 만든 앱이기 때문에 자바 설치
apt install -y fontconfig openjdk-17-jre
- 레포 업뎃
apt-get update
- 젠킨스 설치
apt-get install jenkins -y
root@ip-10-50-10-213:~# systemctl restart jenkins
root@ip-10-50-10-213:~# systemctl enable jenkins
- 인스턴스의 8080포트로 접속
젠킨스는 플러그인을 통해 원하는 환경을 구성할 수 있다.
ex) 내가 만든 앱은 gradle로 빌드하고 aws에 배포할꺼니까 gradle, aws 플러그인을 설치하는식
# 인증관련된 정보(docker 계정정보, 깃허브계정정보, 필수한 플러그인이나 툴들 설치)
# 메이븐이라는 도구를 정의
----
혹시 나중에 젠킨스 빌드를 많이 하면, 디스크 용량이 부족한 경우가 생긴다. 그럴 땐 EBS를 늘리면 된다.
도커로그인 정보 등록
# 젠킨스홈
https://github.com/oolralra/simple_sb.git
# 이걸 fork하세요!! 간단 스프링부트앱 mvn으로 빌드. 8085번이 타겟포트
# 웹훅.
# 깃에 CI/CD스크립트를 저장.
# 소스코드의 브랜치과 같게.
-----------
앞으로 이 Jenkinsfile이라는 스크립트에서 우리가 해야할것들.
1. 소스코드에 변경사항이 생겼을때 git clone.
2. 앱빌드(maven) => target 폴더에 springbootApp.jar 파일 생성
3. target/springbootApp.jar 을 넣어서 도커 빌드.
4. 컨테이너레지스트리(도커허브)에 push
5. 깃허브레포를 소스레포에서 deploy레포로 변경후 git clone
6. deployment.yml 파일의 이미지 태그를 수정 후 push
------------------------
github 웹훅 환경을 구성.
# http://<본인인스턴스주소>:8080/github-webhook/
pipeline {
agent any
stages {
stage('start') {
steps {
sh "echo hello jenkins!!!"
}
post {
failure {
sh "echo failed"
}
success {
sh "echo success"
}
}
}
}
}
# 스테이지들-스테이지-스텝스...
# post 스텝스를 수행후 성공/실패 여부에 따라서 분기점.
# 레포에서 아무파일이나 생성해서 소스코드에 변화를 줬을때
# 새로운 젠킨스 빌드가 자동으로 수행되는지 확인한다 = webhook 성공
위에서 정리한 절차대로 스크립트를 짜면된다!!
pipeline { agent any tools { maven 'my_maven' } environment { GITNAME = 'oolralra' GITEMAIL = 'oolralra@gmail.com' GITWEBADD = 'https://github.com/<본인>/simple_sb.git' GITSSHADD = 'git@github.com:<본인>/simple_sb.git' GITCREDENTIAL = 'git_cre' DOCKERHUB = '<본인허브>/spring' DOCKERHUBCREDENTIAL = 'docker_cre' } stages { stage('start') { steps { sh "echo hello jenkins!!!" } post { failure { sh "echo failed" } success { sh "echo success" } } } } } |
# 환경변수를 본인에 맞게 수정.
stages { stage('Checkout Github') { steps { checkout([$class: 'GitSCM', branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[credentialsId: GITCREDENTIAL, url: GITWEBADD]]]) } post { failure { sh "echo clone failed" } success { sh "echo clone success" } } } stage('springboot app build') { steps { sh "mvn clean package" } post { failure { sh "echo mvn packaging fail" } success { sh "echo mvn packaging success" } } } stage('docker image build') { steps { sh "docker build -t ${DOCKERHUB}:${currentBuild.number} ." sh "docker build -t ${DOCKERHUB}:latest ." // currentBuild.number 젠킨스가 제공하는 빌드넘버 변수 // oolralra/fast:<빌드넘버> 와 같은 이미지가 만들어질 예정. } post { failure { sh "echo image build failed" } success { sh "echo image build success" } } } stage('docker image push') { steps { withDockerRegistry(credentialsId: DOCKERHUBCREDENTIAL, url: '') { sh "docker push ${DOCKERHUB}:${currentBuild.number}" sh "docker push ${DOCKERHUB}:latest" } } post { failure { sh "docker image rm -f ${DOCKERHUB}:${currentBuild.number}" sh "docker image rm -f ${DOCKERHUB}:latest" sh "echo push failed" // 성공하든 실패하든 로컬에 있는 도커이미지는 삭제 } success { sh "docker image rm -f ${DOCKERHUB}:${currentBuild.number}" sh "docker image rm -f ${DOCKERHUB}:latest" sh "echo push success" // 성공하든 실패하든 로컬에 있는 도커이미지는 삭제 } } } stage('EKS manifest file update') { steps { git credentialsId: GITCREDENTIAL, url: GITSSHADD, branch: 'main' sh "git config --global user.email ${GITEMAIL}" sh "git config --global user.name ${GITNAME}" sh "sed -i 's@${DOCKERHUB}:.*@${DOCKERHUB}:${currentBuild.number}@g' fast.yml" sh "git add ." sh "git branch -M main" sh "git commit -m 'fixed tag ${currentBuild.number}'" sh "git remote remove origin" sh "git remote add origin ${GITSSHADD}" sh "git push origin main" } post { failure { sh "echo manifest update failed" } success { sh "echo manifest update success" } } } } |
# 기존 stages 제거후 복붙.
# 혹시모르니 기존이 빌드되어 나온 jar파일은 삭제.
# 여기까지 성공했는지 확인.
# 인스턴스에 docker가 설치 안되어있음.
인스턴스에서
curl -fsSL https://get.docker.com -o get-docker.sh
# jenkins는 명령을 치는 주체가 jenkins 라는 리눅스 사용자.
# 따라서 jenkins라는 리눅스 사용자에게 권한을 부여.
root@ip-10-50-10-213:~# usermod -aG docker jenkins
# jenkins라는 사용자를 docker라는 그룹에 add해주는 명령.
root@ip-10-50-10-213:~# systemctl restart jenkins
# 젠킨스 재시작후 다시 빌드.
# 우리는 github와 ssh 통신이 실패했다.
# Jenkinsfile을 수정
ssh 통신을 위한 인증
- id/pass 방식
- public key 방식(키페어)
- 클라이언트 = private key = 젠킨스
- 서버 = public key = 깃허브
인스턴스에서 키페어 생성
- 관리자 권한을 취득 후 jenkins라는 사용자로 변경
- 기본값으로 키페어 생성
ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa -N '' -q
- 깃허브에 퍼블릭키 등록
jenkins@ip-10-50-10-213:~$ cat ~/.ssh/id_rsa.pub
# 꼭 처음부터 끝까지
- 젠킨스에 프라이빗키 credential 생성
- 프라이빗키
jenkins@ip-10-50-10-213:~$ cat ~/.ssh/id_rsa
# 프라이빗키값 전체
- 내 known_hosts에 등록시키기 위해 깃허브서버에 ssh 접속을 1회 실시
jenkins@ip-10-50-10-213:~$ ssh git@github.com
실습)
여러분들이 argoCD 설치해서 앱배포가 잘 되게끔 해보세요!!
딸깍 해서 스프링부트앱에 "프로젝트 조 알려주세요!"라는 내용이 뜨는 사이트주소를 저한테 알려주시면 됩니다!"