[ezfarm] CI/CD 서버 구축과 배포
해당 글의 프로젝트는 다음 URL에서 확인할 수 있다.
CI/CD 적용 이유
서버 개발이 어느정도 완성되었고 프론트와 기능 연결을 위해 배포의 필요성을 느꼈다. 이전의 프로젝트에서는 EC2에 접속해 프로젝트를 clone 받은 후 jar 파일을 실행해 배포를 진행하였다. 하지만 이 방법은배포 후 추가적인 기능 개발, 버그 수정 등을 위해 위와 같은 과정을 반복해야해 매우 번거로웠다. 이러한 이유로Docker/Jenkins Pipeline을 사용해 CI/CD 서버를 구축하게 되었다.
CI/CD 설계
ezfarm 프로젝트의 CI/CD 흐름을 다음과 같이 설계했다.
- 깃허브의 release 브랜치에 배포할 코드를 push한다.
- 깃허브는 해당 레포지토리와 연결된 Jenkins에 webhook을 보낸다.(EC2 서버에 Jenkins 서버 컨테이너가 실행되고 있다.)
- Jenkinsfile이 실행된다. Jenkinsfile의 Pipeline은 다음과 같이 설계했다.
- ezfarm 레포지토리의 release 브랜치를 clone한다.
- 프로젝트를 빌드한다.
- 기존에 띄운 ezfarm 서버 컨테이너와 이미지를 삭제한다.
- dockerfile을 기반으로 새로운 이미지를 생성한 후 컨테이너를 실행시킨다.
- 배포가 완료되면 배포 완료 메일을 발송한다.
- 만약 빌드 또는 배포가 실패하면 실패 메일을 발송한다.
CI/CD 구현
1. Amazon EC2 서버 생성
- Amazon Machine Image(AMI) : Amazon Linux 2 AMI
- 인스턴스 유형 선택 : t2.micro
- 인스턴스 세부 정보 구성 : 1대의 서버만 사용하므로 VPC, 서브넷 설정은 건너뛴다.
- 스토리지 추가 : 서버의 용량은 프리티어 최대 크기인 30GB로 설정한다.
- 보안 그룹
- SSH/TCP/22/내 IP 추가(EC2 접속)
- 사용자 지정 TCP/TCP/8085/내 IP 추가(Jenkins 접속)
- 사용자 지정 TCP/TCP/8085/192.30.252.0/22, 185.199.108.0/22, 140.82.112.0/20, 143.55.64.0/20 추가(Github의 webhook)
- TCP/TCP/8080/위치 무관 추가(ezfarm 프로젝트)
- 고정 아이피(EIP) 할당
2. EC2에 Docker 설치
#도커 설치
sudo yum install docker
#도커 서비스 실행
sudo service docker start
#부팅 시 도커 자동 실행 설정
sudo chkconfig docker on
3. Jenkins 도커 이미지 생성 후 컨테이너 실행
#Jenkins 도커 이미지 생성
sudo docker pull jenkins/jenkins:jdk11
#Jenkins 도커 컨테이너 생성
sudo docker run -d -p 8080:8080 --name jenkins -v /home/jenkins:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock -u root [이미지 id]
4. Jenkins 컨테이너 접속 후 docker 설치
#Jenkins 도커 컨테이너 접속
sudo docker exec -it [컨테이너 id] /bin/bash
#도커 설치 후 압축 해제
curl -fsSLO https://get.docker.com/builds/Linux/x86_64/docker-17.04.0-ce.tgz
tar xzvf docker-17.04.0-ce.tgz
#bash에서 사용 가능하도록 도커 파일 이동
mv docker/docker /usr/local/bin
5. Github Webhook 설정
Repository -> Setting -> Webhooks -> Add Webhook
Payload URL : http://[퍼블릭 IPv4 DNS]/github-webhook/
Content type : application/json
Jenkins 연결 완료
6. Jenkins Pipeline 생성과 Github Repository연결
#Jenkins 서버 주소
[퍼블릭 IPv4 DNS]:[Jenkins 포트 번호]
#Jenkins 초기 비밀번호
Jenkins 컨테이너 접속 후 다음 명령어 실행
cat /var/jenkins_home/secrets/initialAdminPassword
Jenkins 메인 홈 -> 새로운 Item 선택 -> Pipeline 선택
Do not allow concurrent builds : 동시에 빌드가 안되도록 설정
GitHub Project : 깃허브 레포지토리 URL
Build Triggers -> Github hook trigger for GITScm polling : 깃허브 hook 트리거 설정
SCM : Git으로 설정
Repository URL : 레포지토리 URL
Branch Specifier : release 브랜치에 push되면 빌드하도록 트리거 설정
Script Path : 프로젝트 내의 Jenkinsfile이 실행되도록 설정
7. Dockerfile, Jenkinsfile 생성
Dockerfile
FROM adoptopenjdk/openjdk11:alpine-jre
MAINTAINER [이름] <[이메일]>
VOLUME /tmp
EXPOSE 9090
ARG JAR_FILE=build/libs/ezfarm-back-0.0.1-SNAPSHOT.jar
ADD ${JAR_FILE} ezfarm-back.jar
ENTRYPOINT ["java", "-Dspring.profiles.active=dev", "-jar", "/ezfarm-back.jar"]
Jenkinsfile
pipeline {
agent any
environment {
CONTAINER_NAME = 'ezfarm-con'
IMAGE_NAME = 'ezfarm-img'
}
stages {
stage('git pull'){
steps {
echo 'Git Pull - Start'
sh """
git fetch
git pull origin master
"""
}
post {
success {
echo 'Git Pull - Success'
}
failure {
error 'Git Pull - Failure'
}
}
}
stage('build'){
steps {
echo 'Build Start'
sh """
chmod 755 ./gradlew
./gradlew clean build
"""
}
post {
success {
echo 'Build Success'
}
failure {
error 'Build Failure -> Stop'
mail to: 'highright96@gmail.com',
subject: "Jenkins Failure Build",
body: "Build Failed."
}
}
}
stage('deploy'){
steps {
echo 'Deploy Start'
sh """
docker stop ${CONTAINER_NAME}
docker rm ${CONTAINER_NAME}
docker rmi ${IMAGE_NAME}
docker build -t ${IMAGE_NAME} .
docker run -d --name ${CONTAINER_NAME} -p 9090:9090 -v /home/jenkins:/var/jenkins_home ${IMAGE_NAME}
"""
}
post {
success {
mail to: 'highright96@gmail.com',
subject: "Jenkins Success Deploy",
body: "Deploy Success"
}
failure {
error 'Deploy Failure -> Stop'
mail to: 'highright96@gmail.com',
subject: "Jenkins Failure Deploy",
body: "Deploy Failed."
}
}
}
}
}
8. 배포 성공
성공적으로 CI/CD 서버를 구축해 배포에 낭비되는 시간을 줄일 수 있었다.
'Private' 카테고리의 다른 글
[ezfarm] 차집합을 이용해 쿼리 수정하기 (2) | 2021.07.30 |
---|---|
[ezfarm] 도메인 등록 및 HTTPS 설정 (0) | 2021.07.24 |
[ezfarm] Spring Security를 추가한 뒤 단위 테스트(Controller)에서 생기는 문제 해결하기 (0) | 2021.06.18 |
댓글