현재 진행 중인 구름톤 풀스택 과정에서 팀 프로젝트의 CI/CD를 구축해 보았습니다.
CI/CD 구축은 처음 해봐서 구글링을 통해 다양한 구축법을 조사한 결과
오성원님의 블로그를 중심으로 추가/변경하여 설계한 CI/CD 파이프라인을 기준으로 구축해 보았습니다!
OS는 Mac 환경입니다!
✦ CI/CD 파이프라인
✦ 프로젝트 배경
우리 홍삼팀에서는 로그인/회원가입 기능 + 게시물 CRUD 기능을 넣은 간단한 SNS를 만드는 프로젝트를 진행했다.
백엔드 개발자 3명은 Spring을 사용하고 프런트엔드 개발자 2명은 React를 사용했다.
각자 맡은 기능을 개인 branch에서 개발하고 develop branch에 merge를 했다.
develop branch에서 모든 코드를 합치고 회의를 통해 develop branch에서 main branch로
merge가 되면 webhook을 통해 main branch로 연결해 둔 CI/CD 파이프라인이 실행되도록 했다.
✦ Backend CI 구축
📌 준비 사항
1. Jenkins용 EC2에 Docker와 Jenkins컨테이너 생성 (추후 포스팅 예정)
2. Backend 배포용 EC2 생성 후 Java 설치 (저는 Java 11을 설치했습니다.)
1. Jenkins Item 생성 + git clone
1.1 Jenkins Item 생성
jenkins 메인 화면에서 Item 생성을 클릭한 후 backend용 파이프라인부터 만들어보자.
Item이름을 적고 Pipeline을 선택 후 OK 버튼을 누른다.
1.2 git clone 스크립트 작성
pipeline {
agent any
stages {
stage('git clone') {
steps {
git branch: 'main', url: 'https://github.com/seoyeoning/2023-hongsamSNS.git'
}
}
}
}
우선 체크하는 부분은 다 넘어가고 Definition은 Pipeline script로 선택한 후 git clone단계까지의 스크립트를 작성한다.
저장을 누르고 지금 빌드를 누르면 Jenkins 컨테이너에 git clone이 진행된다.
혹시 clone이 잘 됐나 확인하고 싶으면 Jenkins용 인스턴스에 접근해서
sudo docker exec -it {컨테이너 이름} /bin/bash
위의 명령어를 입력하면 Jenkins 컨테이너에 접속하게 되고
cd /var/jenkins_home/workspace
위의 파일로 이동해서 ls를 진행하면 Jenkins의 Item 이름으로 파일로 git clone 된 파일을 확인할 수 있다.
2. 빌드
git clone으로 다운받은 우리 팀의 파일 구조는 hongsam_back 파일에서 spring 파일인 backend 파일을 build 해야 하기 때문에
backend 디렉터리로 이동한 후 빌드를 진행하는 스크립트를 추가로 작성해 주었다.
git clone과 build 과정을 진행하는 과정까지 스크립트가 작성되었다.
pipeline {
agent any
tools {
gradle 'gradle'
}
stages {
stage('git clone') {
steps {
sh 'rm -rf hongsam_back hongsam_back@tmp'
git branch: 'main', url: 'https://github.com/seoyeoning/2023-hongsamSNS.git'
}
}
stage('B-build') {
steps {
dir("./backend") {
sh './gradlew clean build'
}
}
}
}
}
sh 'rm -rf hongsam_back hongsam_back@tmp'
이 명령어로 CI를 진행할 때 전에 clone 했던 파일을 모두 지워주었다.
전에 생긴 파일을 지워주지 않으면 CI를 할 때마다 변경된 내용이 업데이트되는데
가끔 코드가 꼬일 때가 있어서 깔끔하게 삭제하고 다시 clone 하는 방법을 선택했다.
tools 설정을 gradle로 설정하는 과정도 추가되었는데 위 과정을 그대로 했는데 gradle 관련 오류가 발생하면
Jenkins 관리의 Tools에 들어가서 본인 프로젝트의 gradle 버전을 등록해 주면 된다.
여기까지 작성한 후 지금 빌드를 누르면 빌드가 잘 되었는지 확인할 수 있다.
✦ Backend CD 구축
CD 배포 과정에서는 Jenkins용 EC2 인스턴스의 jenkins 컨테이너에 빌드된 jar 파일을
백엔드 배포용 EC2 인스턴스에 보내주는 과정이다.
따라서 우선 Jenkins 서버에서 백엔드 운영 서버로 통신을 해야 하므로 SSH 통신 설정을 하고 스크립트를 작성했다.
1. SSH 통신 설정
1.1 SSH Agent Plugin 설치
1.2 credentials 생성
Jenkins 관리의 Credentials에서 새로운 credential을 생성하고 위의 양식처럼 작성한다.
ID : 스크립트에서 식별할 이름
Username : 기본으로 ubuntu
Private Key : 백엔드 운영 서버에 접속할 때 사용하는 백엔드 EC2의 pem 키를 모두 복사해서 넣어준다.
-----BEGIN RSA PRIVATE KEY-----(포함) 부터 -----END RSA PRIVATE KEY-----(포함) 까지 전부 복사한다.
2. CD (배포) 스크립트 작성
위에서 작성한 빌드까지의 스크립트에 CD 스크립트를 추가한 최종 CI/CD 스크립트이다.
pipeline {
agent any
tools {
gradle 'gradle'
}
stages {
stage('git clone') {
steps {
sh 'rm -rf hongsam_back hongsam_back@tmp'
git branch: 'main', url: 'https://github.com/seoyeoning/2023-hongsamSNS.git'
withCredentials([GitUsernamePassword(credentialsId: 'submodule_key', gitToolName: 'Default')]) {
sh 'git submodule update --init --recursive'
}
}
}
stage('B-build') {
steps {
dir("./backend") {
sh './gradlew clean build'
}
}
}
stage('Deploy') {
steps {
sshagent(credentials: ['aws_key']) {
sh '''
ssh -o StrictHostKeyChecking=no ubuntu@{backend ec2 public ip} uptime
scp /var/jenkins_home/workspace/hongsam_back/backend/build/libs/backend-0.0.1-SNAPSHOT.jar ubuntu@{backend ec2 public ip}:/home/ubuntu
ssh -tt ubuntu@{backend ec2 public ip} ./deploy.sh
'''
}
}
}
}
}
❗️git clone 단계에서 추가된 명령어
withCredentials([GitUsernamePassword(credentialsId: 'submodule_key', gitToolName: 'Default')]) {
sh 'git submodule update --init --recursive'
}
이 부분은 보안 관련 github의 서브 모듈을 추가한 부분으로 만약 서브 모듈이 없으면 삭제해 주면 된다.
서브 모듈 관련 포스팅은 추후에 따로 포스팅할 예정이다.
Deploy 단계에서 우선 백엔드 서버에 접속한 후
scp를 사용해서 jar 파일을 백엔드 서버의 /home/ubuntu로 복사해 준다.
마지막으로 백엔드 서버에 원격 접속해서 deploy.sh 파일을 실행시켜 준다.
경로 등은 본인의 프로젝트에 맞게 수정해 주면 된다.
deploy.sh 파일은 백엔드 인스턴스에 미리 생성해 놨다.
deploy.sh의 내용은 다음과 같다.
pid=$(pgrep -f jenkins | pgrep java)
if [ -n "${pid}" ]
then
sudo kill -9 ${pid}
echo kill process ${pid}
sleep 10
else
echo no process
fi
echo "Deployment Start..."
JAR_PATH=$(ls -t /home/ubuntu/*.jar | head -1)
sudo chmod +x ${JAR_PATH}
sudo nohup java -jar -DSpring.profiles.active=prod ${JAR_PATH} >> /home/ubuntu/application.log &
sleep 10
혹시 오류나면 권한문제 확인해보기.
chmod +x deploy.sh
여기까지 완성한 후 지금 빌드를 누르면 CI/CD 구축 성공이다!!
(혹시 오류가 난다면 log를 확인 후 구글링 or GPT를 이용하면 충분히 해결할 수 있다. 대부분 나의 삽질..)
❗️현재는 Jenkins 내에서 지금 빌드를 눌러야 작동이 되는데
github main branch를 트리거로 작동하게 해주는 webhook은 추후 따로 포스팅할 예정이다.
✦ 배운점
처음으로 본격적인 배포 + CI/CD를 통한 지속적 통합 + 지속적 배포는 처음으로 구축해 보았는데..
상당히 어렵고 상당히 복잡했다..
구글링으로 찾아보면 정말 다양한 방법들로 구축할 수 있다는 걸 알았다.
그래도 팀에 민폐는 끼치지 말아야겠다는 생각에 열심히 뚝딱뚝딱 했더니 꽤 그럴듯한 CI/CD 가 완성된 것 같다. 👏
더 자세하게 이해하기 위해서 더 깊게 공부해 봐야겠다!!
(혹시 잘못된 정보가 있다면 댓글 부탁드립니다..🙏)
✦ Reference
[DevOps] Jenkins를 통한 CI/CD 구축기 2편 (Backend CI/CD 구축)
'CI,CD' 카테고리의 다른 글
[CI&CD] EC2, Docker, Jenkins, React 프로젝트 CI/CD 구축 (0) | 2023.08.16 |
---|