보통 Blue/Green 자동화 배포 파이프라인을 구축할 때 Jenkins를 많이 이용한다.
Aws에서 제공하는 Code Pipeline을 사용해 구축할 수 도 있지만 배포할 때마다 비용이 발생하므로, 자주 배포가 일어난다면 서버 비용만 나오는 Jenkins를 사용하는 것이 이득일 수 있다.
아래 예제는 Bitbucket Repository 안에 있는 소스를 배포해야 하므로 Bitbucket과 연동하는 법으로 정리하였고
젠킨스 서버는 Local에서 Docker 컨테이너를 띄어 진행했다.
간단히 그림으로 표현하자만 아래와 같다.
1. 젠킨스 이미지 다운로드 및 실행
아래 명령어로 젠킨스 도커 이미지를 다운로드해 컨테이너를 실행한다.
docker run -itd --name jenkins -p 8090:8080 jenkins/jenkins:lts
docker ps 명령어를 실행해 돌아가고 있는 컨테이너를 확인해보면 젠킨스 컨테이너를 확인할 수 있다.
설정한 8090 포트번호로 접속해보면 젠킨스 초기 로그인 페이지로 접속할 수 있다.
패스워드는 /var/jenkins_home/secrets/initialAdminPassword 위치에서 확인할 수 있는데 아래 명령어를 실행하면 간단히 정보를 확인할 수 있다.
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
명령어를 사용해 출력된 패스워드를 복사해 Administrator password에 입력해주면 된다.
2. 플러그인 설치
패스워드를 입력해주면 기본 플러그인을 설치할 것인지, 플러그인을 선택해서 설치할 것인지 선택하는 창이 나타난다.
Install suggested plugins를 클릭해 기본 플러그인을 설치해준다.
3. 초기 설정
플러그인이 모두 설치되면 첫번째 관리자 계정을 등록할 수 있다. 본인이 기억할 수 있는 계정으로 설정하면 된다.
Jenkins URL도 설정해준다.
4. 플러그인 설치
위 설정을 모두 정상적으로 마쳤으면 Dashboard가 나타나는데, 사이드 메뉴에 Jenkins 관리 -> 플러그인 관리로 접속한다.
설치 가능 탭을 클릭하고 Bitbucket을 검색해 아래 체크되어있는 Bitbucket 플러그인을 설치한다.(Bitbucket 배포 기준)
그리고 SSH로 EC2에 배포하기 위해 Publish Over SSH 플러그인도 설치해준다.
5. Webhook 등록
플러그인 설치가 완료됬으면 Bitbucket에 접속해 배포하려는 Repository에 Repository setting -> Webhook 설정으로 접속해 Webhook을 등록해준다.
URL은 {젠킨스를 설치한 서버 URL}:{post}/bitbucket-hook/ 으로 등록한다.
현재 젠킨스 서버가 localhost:8090의 URL을 가지고 있는데, localhost로는 webhook 발송이 안된다.
그래서 ngrok을 사용해 8090 포트를 포워딩한 주소로 설정해 테스트해볼 것이다.
$ brew install ngrok/ngrok/ngrok # ngrok 설치
$ ngrok http 8090 # 8090 포트 포워딩
포워딩된 주소를 URL에 등록해준다.
6. SSH Server 등록
Dashboard > Jenkins 관리 > 시스템 설정으로 접속해 제일 하단을 보면 위에서 설치한 Publish over SSH 플러그인의 설정 부분이 있다.
key에 EC2 생성 시에 발급받은 pem키를 복사해 넣어 권한을 부여한다.
SSH 서버도 배포할 EC2로 설정해준다.
7.Item 생성
다시 Jenkins 대시보드로 접속해 새로운 Item 메뉴를 클릭 -> Freestyle project 생성
소스 코드 관리 > Repository URL에 위에서 Webhook을 설정한 Repository URL을 입력하면 아래와 같은 오류가 발생할 것이다.
Bitbucket에서 2022년 3월 1일부터는 Atlassian 계정 암호를 사용하여 Bitbucket API 또는 Git over HTTPS로 인증할 수 없다.
(참고 : https://bitbucket.org/blog/deprecating-atlassian-account-password-for-bitbucket-api-and-git-activity)
이를 해결하려면 Bitbucket 앱 비밀번호를 발급해야 한다.
Bitbucket 아이디와 발급받은 비밀번호로 Credentials를 추가해주면 위 에러가 사라진다.
위에 설정을 모두 마치고 빌드할 브랜치도 설정해준다.
Bitbucket에 Push가 발생할 때 Build 되도록 Build when a change pushed to BitBucket 항목을 체크한다.
빌드 스텝은 쉘 실행을 선택하고 실행될 쉘을 입력해주면 된다.
빌드된 파일을 모두 삭제하고 빌드 후 테스트까지 진행한다.
빌드 후 jar를 EC2로 배포하기 위해 빌드 후 조치를 추가한다. (Send build artifacts over SSH)
위에서 생성한 SSH Server를 선택하고 Transfers 정보를 기입해준다.
- Source files : 배포할 소스 파일
- Remove prefiex : 원격 서버에서 생성되어서는 안 되는 파일 경로의 첫 부분
- Remote directory : 원격 서버에 디렉터리
- Exec command : 실행할 명령어
위 이미지에서는 배포 후 home/ec2-user/start_server.sh 파일의 명령어를 실행하도록 설정 하였다.
아래는 start_server.sh 파일 내용이다. 구동중인 애플리케이션이 있으면 종료시키고 새로 배포된 애플리케이션을 실행시킨다.
REPOSITORY=/home/ec2-user/deploy
echo "> 현재 구동중인 애플리케이션 pid 확인"
CURRENT_PID=$(pgrep -f ${PROJECT_NAME}.*.jar)
echo " 현재 구동중인 애플리케이션pid: $CURRENT_PID"
if [ -z "$CURRENT_PID" ]; then
echo "> 현재구동중인 애플리케이션이 없으므로 종료하지 않습니다."
else
echo "> kill -15 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 5
fi
echo "> 새 애플리케이션 배포"
JAR_NAME=$(ls -tr $REPOSITORY/ | grep jar | tail -n 1)
echo "> JAR Name: $JAR_NAME"
nohup java -jar $REPOSITORY/$JAR_NAME 2>&1 &
배포하려는 원격 서버에서 위에서 설정한 쉘(start_server.sh) 경로에 맞춰 생성하면 된다.
8.Test
이제 해당 Bitbucket branch에 push를 발생시켜보면 자동적으로 빌드가 시작되는 것을 확인할 수 있다.
빌드가 완료되고 해당 EC2에 접속해서 deploy 디렉터리를 보면 jar파일이 정상적으로 배포가 된 것을 확인할 수 있다.
물론! EC2에 버전에 맞는 JDK가 설치되어 있어야 정상작동한다.
이렇게 Jenkins로 자동화 배포를 구축해보았다.
설정해야 될 것은 많지만 어렵지 않아 쉽게 구축은 했지만 아직 무중단 배포는 설정하지 못하였다.
AWS를 사용한다면 Elastic Beanstalk를 같이 사용해서 무중단 자동화 배포가 가능하다.
해당 예제는 추후에 정리해서 올리려고 한다.
로컬 도커에서 젠킨스 이미지를 빌드받아 진행하다 보니 메모리 부족인지 자꾸만 빌드 중에 Jeckins 컨테이너가 꺼지는 상황이 발생한다.
이 부분은 어떤 부분이 문제인지 파악해서 업데이트하도록 하겠다. 아마도 메모리 문제인듯한데 찾아봐야 할 듯싶다.
P.S.
docker stats으로 확인해보면 메모리 Limit가 1.9GB정도 되는데 빌드할때 메모리를 2GB 넘게 잡아먹는다.
그래서 Jenkins 컨테이너에 CPU 최대 사용량을 80% 정도, 메모리를 4G 설정하고 빌드하게되면 조금 느려지지만 컨테이너는 종료되지 않았다. (근데 메모리 설정은 먹히지 않는듯 하다.. docker stats으로 확인해봣지만 여전히 1.9GB다...ㅠ 왜지?)
$ docker update --cpus=0.8 jenkins
$ docker update --memory 4G --memory-swap -1 jenkins
'ETC' 카테고리의 다른 글
Jenkins Pipeline에 Slack 연동하기 (0) | 2022.05.08 |
---|---|
Jenkins를 이용한 Docker 컨테이너 자동 배포하기(Blue Ocean, Bitbucket, NCP) (8) | 2022.05.06 |
H2 Database 사용자 정의 함수 만들기 (0) | 2022.04.19 |
인텔리제이 TODO 기능 활용하기 (0) | 2022.01.06 |
최근 Log4j2 취약점 설명 및 해결 방안 (0) | 2021.12.13 |