CI/CD 파이프라인 구축
수업에서 Jenkins를 활용해 Spring 어플리케이션을 배포했다.
프로젝트 진행 시 설정 정보가 담겨있는 application.yml
은 보통 git에 올리지 않고 따로 관리한다.
이때 어떻게 배포할지 고민했고, 아래의 과정으로 application.yml
github에 올리지 않고, CI/CD 파이프 라인을 구축해보자.
Docker 설치
sudo apt update
sudo apt-get install ca-certificates curl gnupg
Add Docker’s official GPG key:
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
Use the following command to set up the repository:
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
Docker Engine 설치
sudo apt update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo chmod 006 /var/run/docker.sock
설치 완료
ubuntu@ip-172-31-13-228:~$ docker -v
Docker version 24.0.5, build ced0996
Jenkins 설치
EC2 Free-tier에서 Jenkins를 사용하면 메모리가 부족해 정상 작동이 안될 수 있다.
ubuntu@ip-172-31-13-228:~$ free -h
total used free shared buff/cache available
Mem: 966Mi 218Mi 130Mi 0.0Ki 617Mi 587Mi
Swap: 0B 0B 0B
swap 메모리사용을 통해 이를 해결하자.
sudo dd if=/dev/zero of=/swapfile bs=128M count=16
dd
: 루트파일 시스템에 스왑 파일 생성bs
: Block 크기count
: Block 수- 지정한 블록 크기는 인스턴스에서 사용가능한 메모리보다 작아햐 한다.
sudo chmod 600 /swapfile
sudo mkswap /swapfile
Setting up swapspace version 1, size = 2 GiB (2147479552 bytes)
no label, UUID=43d7dc37-535f-4a81-942d-c9cd46d1a284
스왑영역 설정
sudo swapon /swapfile
- swap 공간에 swap file을 추가하여 swap file 사용하도록 설정
sudo swapon -s
Filename Type Size Used Priority
/swapfile file 2097148 0 -2
- 성공 여부 확인
sudo vi /etc/fstab
LABEL=cloudimg-rootfs / ext4 defaults,discard 0 1
LABEL=UEFI /boot/efi vfat umask=0077 0 1
/swapflie swap swap defaults 0 0
- 부팅 시 swap file 활성화
ubuntu@ip-172-31-13-228:~$ free -h
total used free shared buff/cache available
Mem: 966Mi 197Mi 163Mi 0.0Ki 605Mi 605Mi
Swap: 2.0Gi 0B 2.0Gi
total 2GB로 변경되었다.
Docker에 Jenkins 이미지 설치
docker pull jenkins/jenkins:jdk11
ubuntu@ip-172-31-13-228:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jenkins/jenkins jdk11 1dd84990e937 3 days ago 463MB
Docker에서 Jenkins 실행
ubuntu@ip-172-31-13-228:~$ docker run -d -p 80:8080 --name jenkins jenkins/jenkins:jdk11
e749a14300bb9303a6720df0c46c34c44710bb5b95e31775092025cd850258cb
ubuntu@ip-172-31-13-228:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e749a14300bb jenkins/jenkins:jdk11 "/usr/bin/tini -- /u…" 5 seconds ago Up 2 seconds 50000/tcp, 0.0.0.0:80->8080/tcp, :::80->8080/tcp jenkins
이제 public ip로 접근 가능하다.
jenkins shell 이동
docker exec -it jenkins /bin/bash
로그인 secret 확인
cat /var/jenkins_home/secrets/initialAdminPassword
Install suggested plugins
플러그인 설치 후 skip and countunue as admin
Web Project 생성
private repository 만든 후 깃에 push.
참고로 yml파일은 .gitignore에 추가하지 않고 push 했다.
Jenkins에서 git에 접근을 위한 credential 생성
Developer settings → Personal Access tokens → Tokens(classic) → Genereate new token(classic)
토큰 이름 지정 후 repo
, admin:repo_hook
체크
- ghp_ 로 시작하는 토큰 보관
Jenkins관리 -> System -> Github
- Credential 두 개 생성
secret: 아까 발급받은 ghp_로 시작하는 토큰 Secret에 기입
username: github 이메일
password: 아까 발급받은 ghp_로 시작하는 토큰 Secret에 기입
Test Connection
credential에 secret text
로 만든 토큰 설정 후 test connection
Jenkins Pipeline 생성
pipeline syntax 클릭
아래와 같이 스크립트 입력
지금 빌드
클릭 후 클론 여부 확인
docker exec -it jenkins /bin/bash
cd /var/jenkins_home/workspace/{파이프 라인 이름}
ls
git에 push된 프로젝트가 존재하는지 확인해야 한다.
Jenkins에서 빌드
아까 application.yml
을 제외하고 git에 push 했다.
이 설정 파일을 Jenkins 빌드 시 주입하고자 Jenkins서버에 만들어두자.
docker exec -itu0 jenkins /bin/bash
apt-get update
apt-get upgrade
apt-get install vim
vi /var/jenkins_home/workspace/settings/application.yml
나의 설정파일 내용은 아래와 같다.
spring:
datasource:
url: jdbc:h2:~/test
driverClassName: org.h2.Driver
username: sa
password:
h2:
console:
enabled: true
path: /h2-console
stage('build with gradle') {
steps {
sh 'cp /var/jenkins_home/workspace/settings/application.yml src/main/resources/application.yml'
sh 'chmod +x gradlew'
sh './gradlew clean build'
}
}
.gitignore
설정을 잘못해서 17트 만에 성공했다.
이제 서버에 배포 및 실행만 남았다.
SSH 접근 위한 credential 추가
jenkins관리 -> credentials -> Stores scoped to Jenkins의 system 클릭 -> Global credentials -> add credentials
EC2에 접근하는 pem키 등록
총 3개 credentials
ssh plugin (SSH Agent) 설치 후 jenkins 컨테이너 재시작
docker restart jenkins
spring server 설정
Spring 서버가 동작할 EC2에 들어가 jdk를 설치하고 jar파일을 실행할 쉘 스크립트를 작성하자.
apt-get update
sudo apt install openjdk-11-jdk
cd ~
mkdir mydemo
vi deploy.sh
#!/bin/bash
pid=$(pgrep -f mydemo)
if [ -n "${pid}" ]
then
kill -15 ${pid}
echo kill process ${pid}
else
echo no process
fi
chmod +x ./mydemo/demo-0.0.1-SNAPSHOT.jar
nohup java -jar ./mydemo/demo-0.0.1-SNAPSHOT.jar >> application.log 2> /dev/null &
Jenkins Script for Deploy
stage('deploy') {
steps {
sshagent(credentials: ['jenkins-ssh-key']) {
sh '''
ssh -o StrictHostKeyChecking=no ubuntu@{spring server ip} uptime
scp /var/jenkins_home/workspace/spring-pipeline/build/libs/*.jar ubuntu@{spring server ip}:/home/ubuntu/mydemo
ssh -t ubuntu@{spring server ip} chmod +x ./deploy.sh
ssh -t ubuntu@{spring server ip} ./deploy.sh
'''
}
}
}
배포 결과
github webhook을 통한 CI/CD
payload url: Jenkins Server IP
Content type: application/json
jenkins 구성 -> GitHub hook trigger for GITScm polling 체크
아래 6개 규칙을 Jenkins 서버 EC2 보안그룹에 추가
유형 | 프로토콜 | 포트 범위 | 소스 | IP 주소 | 이름 |
---|---|---|---|---|---|
HTTP | TCP | 80 | 사용자 지정 | 192.30.252.0/22 | github-webhook-1 |
HTTP | TCP | 80 | 사용자 지정 | 185.199.108.0/22 | github-webhook-2 |
HTTP | TCP | 80 | 사용자 지정 | 140.82.112.0/20 | github-webhook-3 |
HTTP | TCP | 80 | 사용자 지정 | 143.55.64.0/20 | github-webhook-4 |
HTTP | TCP | 80 | 사용자 지정 | 2a0a:a440::/29 | github-webhook-5 |
HTTP | TCP | 80 | 사용자 지정 | 2606:50c0::/32 | github-webhook-6 |
ping 확인
webhook을 설정하고 push 하면 아래와 같이 push 태그의 webhook을 보낸다.
Jenkins에서는 이를 감지하여 script에 작성된 내용을 자동으로 수행하게 된다.
완료
위와 같은 process로 CI/CD 파이프라인을 구축해보았다.
프로젝트 시 Docker를 활용할 것 같다. 그냥 서버가 아닌 Docker에 배포하는 방법도 찾아봐야 할 것 같다.
또한, 운영서버와 로컬 서버를 나누면서 application.yml
파일을 따로 관리해야 할 텐데, 설정파일을 더 효율적으로 관리할 수 있는 방법을 고민해봐야할 것 같다.
'우리 FISA' 카테고리의 다른 글
우리FISA 클라우드 서비스 개발 - Spring Boot 어플리케이션에서 RDS MySQL 이중화 (1) | 2023.08.29 |
---|---|
우리FISA 클라우드 서비스 개발 - 프로젝트 시작 전 CI/CD 파이프라인 만들기 (0) | 2023.08.20 |
우리FISA 클라우드 서비스 개발 - 프로젝트 시작과 프로젝트 산출물 (0) | 2023.08.13 |
우리FISA 클라우드 서비스 개발 - Spring Framework에서 테스트 (0) | 2023.08.06 |
댓글