이 포스트는 'Github Actions, Jenkins로 CI/CD를 도전해보자! 1편 (Github Actions 도입하여 CI 테스트)'의 후속편입니다. CI/CD를 도입하게 된 계기, 전체적인 구조도, Github Actions를 통한 CI 테스트 내용을 원하신다면 1편을 참고해주세요.
앞선 포스트인 'Github Actions, Jenkins로 CI/CD를 도전해보자! 1편' 을 보시면 아시겠지만, 프리티어 유형의 EC2에서 빌드를 진행하던 중에 EC2 멈춤 현상이 발생했습니다. 이는 메모리가 너무 적기 때문에 발생하는 현상입니다.
그러므로!! Swap memory를 설정하여 RAM 크기를 늘려주니 해결됐습니다. 설정 방법은 다음과 같습니다.
// aws에서는 count=32로 예제가 써있는데 절반인 16을 적은 이유는 권장 크기가 2GB이기 때문
$ 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 vi /etc/fstab
/swapfile swap swap defaults 0 0
$ free -h
위 명령어로 스왑 메모리 설정이 잘 됐는지 확인합니다.
Swap memory가 2.6GB가 된 걸 볼 수 있습니다. 성공!!!
$ sudo apt-get update
$ sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
$ sudo mkdir -p /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) 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-compose-plugin
$ sudo docker run hello-world
위의 명령어로 테스트를 진행하면 됩니다!
$ sudo docker run -d --name jenkins -p 8080:8080 jenkins/jenkins:jdk17
// 프로젝트에선 jdk17을 사용했기에 jdk17입니다.
Jenkins 설정은 자료가 많으니 스킵하겠습니다..!
이번 프로젝트에서는 빌드, 테스트, 배포(환경 변수 설정, 권한 부여, 프로세스 종료 등) 과정을 서버용 EC2에 사람이 접속해서 설정하는 일 없도록 Jenkins로만 제어하고픈 목표가 있었습니다. 왜냐면 서버용 EC2에 접속해서 이것저것 수정하는 작업들(환경변수, 프로세스 종료 등)이 너무 귀찮았기 때문입니다.
이름 넣고 Pipeline을 선택하면 됩니다.
생성된 Item으로 들어가서 위 구성을 클릭합니다.
General, Advanced~ 부분은 아직은 건드리지 않고 위 사진의 Pipeline script에다가 스크립트를 작성하여 CI/CD를 커스텀할 예정입니다!
스크립트 작성 전에 Jenkins에 gradle을 구성해줘야 합니다. 아래 사진처럼 Item에서 설정을 하는 것이 아닌 전체 설정에서 추가해주면 됩니다.
pipeline {
agent any
tools {
gradle 'gradle'
}
environment {
DB_URL = credentials('db-url-credentials-id')
DB_USER = credentials('db-user-credentials-id')
DB_PASS = credentials('db-password-credentials-id')
}
stages {
stage('Git Clone') {
steps {
git branch: 'develop', url: 'https://github.com/2024-Saphy/BE.git'
}
}
stage('BE-Build') {
steps {
sh "chmod +x ./gradlew"
sh "./gradlew clean build"
}
}
}
}
스크립트를 보면 딱 느낌적인 느낌이 옵니다.
이번 프로젝트에서는 application.yml의 DB 관련 정보를 숨기기 위해 아래 사진처럼 .env 파일을 이용했습니다.
(.env를 쓰려면 꼭 yml에 .env import 부분을 추가해주셔야 합니다!!)
Jenkins EC2에 .env를 직접 생성해줘도 되지만, .env 파일에 수정 사항이 생기면 EC2에 직접 접속해서 수정해줘야하는 점이 귀찮았습니다.
그렇기에 environment를 사용하여 .env에 수정 사항이 생겼을 때 Jenkins 페이지에서 credentials만 수정하는 방식이 훨씬 간편하다고 느껴 이 방식을 택했습니다.
credentials 생성은 아래 사진처럼 하시면 됩니다.
Secret에 숨길 내용을 적으시면 됩니다.
이렇게 USER, URL, PASSWORD를 다 추가해주시고 스크립트에 ID를 넣으시면 됩니다. 참고로 저는 RDS를 사용했기 때문에 Jenkins EC2에 DB 세팅을 할 필요가 없었습니다. 만약 Jenkins EC2내에 로컬 DB를 쓰실 예정이라면 Jenkins EC2 내에서 DB 세팅을 해주셔야 합니다.
그 다음 아래 사진의 '지금 빌드' 를 클릭하면 스크립트대로 Pipeline이 실행됩니다.
그런데 젠킨스에 빌드중 아래 사진처럼 contextLoads() 메서드가 실패가 떴습니다. 분명 로컬에서는 잘 되는데 왜 젠킨스에서만 문제지?!
해결 방법은 아래 사진처럼 코드를 추가해주면 됩니다.
(사실 정확한 원인이 뭔지 잘 모르겠습니다..)
여기까지는 단순히 깃허브 저장소의 develop 브랜치의 코드를 Clone 해오고 Build를 진행하는 과정입니다.
그런데 이 과정에서 궁금증이 생겼습니다.
그러면 Clone한 깃허브 프로젝트 파일은 대체 어떤 디렉토리에 있는거야?!?!?!
(정확히는 Jenkins 스크립트를 실행하는 디렉토리의 위치가 궁금한 것!!)
일단 EC2에 접속해서 아래 명령어를 입력하여 jenkins 컨테이너를 실행시킵니다.
(docker 컨테이너 안에 Jenkins 환경을 구축했습니다. 자세한 내용은 'Github Actions, Jenkins로 CI/CD를 도전해보자! 1편' 을 참고해주세요!)
$ docker exec -it jenkins bash
위 사진처럼 jenkins라는 이름의 도커 컨테이너가 실행됩니다. 참고로 옆에 있는 84da94250d60은 컨테이너의 ID입니다.
구글링도 하고 직접 폴더에 들어가면서 찾아보니 Clone된 깃허브 프로젝트 폴더는 위 경로에 생기는 걸 알 수 있습니다!
정리하자면 Jenkins Item의 이름과 동일한 'Saphy' 라는 폴더가
/var/Jenkins_home/workspace
에 생기고, 'Saphy' 폴더 안에서 스크립트를 실행하게 되는 것입니다. 이전에 테스트용으로 'Saphy-CI-CD'라는 이름의 Item을 생성해서 빌드했기 때문에 위 사진처럼 'Saphy-CI-CD'라는 이름의 폴더가 존재하는 것입니다.
'Saphy' 폴더 안에서 스크립트를 실행한 것을 위 사진에서 볼 수 있습니다.
처음에 Jenkins를 사용할 때는 삐걱대는 경우가 많았는데, 포스트를 작성하면서 리뷰해보니 참 간단한 내용이었구나~ 라고 느껴집니다. 이처럼 포스트를 작성하며 공부했던, 프로젝트에 도입했던 내용을 작성하는 것이 배운 내용들이 정리되는 느낌이라 참 좋은 것 같습니다.
다음 포스트에서는 Jenkins로 CD를 하는 과정을 다루겠습니다.
참고 블로그:
[DevOps] Jenkins를 통한 CI/CD 구축기 1편 (Jenkins 설치)
[DevOps] Jenkins를 통한 CI/CD 구축기 2편 (Backend CI/CD 구축)
ec2 스프링 빌드 시 멈춤 현상 해결법