목차
0. 포스팅 계기
1. CI/CD 개념
2. OverView : GitLab + Jenkins + Nginx + AWS EC2
3. EC2에 Jenkins 설치 후 초기 설정
4. GitLab - Jenkins 설정
5. Jenkins - EC2 연결
6. 방화벽 설정
7. Nginx로 reverse_proxy 설정
오늘은 5번 Jenkins - EC2 연결부터 7번 Nginx로 reverse proxy 설정하는 방법에 대해서 다루려고 한다.
전반적인 OverView나 EC2에 Jenkins 설치 후 초기 설정하는 과정이 궁금하다면 이전편을 참고하기 바란다.
https://aeeazip.tistory.com/39
[CI/CD] GitLab + Jenkins를 활용한 SpringBoot CI/CD 구축 (1) - EC2에 Jenkins 설치부터 초기 설정까지
목차 0. 포스팅 계기 1. CI/CD 개념 2. OverView : GitLab + Jenkins + Nginx + AWS EC2 3. EC2에 Jenkins 설치 후 초기 설정 4. GitLab - Jenkins 설정 5. Jenkins - EC2 연결 6. 방화벽 설정 7. Nginx로 reverse_proxy 설정 8. 빌드 스크
aeeazip.tistory.com
5. Jenkins - EC2 연결
해당 파트에서는 젠킨스가 프로젝트 빌드가 끝나고 만들어진 jar 파일을 EC2로 전송한다. EC2는 jar 파일을 받아 스크립트를 실행시켜 프로젝트를 배포한다.
1. EC2 - SSH 연결
- SSH 플러그인을 설치
- Jenkins 관리 > Manage Credentials에서 SSH를 위한 새로운 Credential 추가
- 이때 EC2로 Ubuntu를 사용하는 경우 Ubuntu 22.04는 버전 문제로 젠킨스 연결이 불가능 한 이슈가 발생할 수 있으므로 Ubuntu 20.04 언더 버전을 사용하는 것을 추천한다! (필자 또한 Ubuntu 20.04 사용)
Kind | SSH Username with private key |
Scope | Global |
ID | 원하는 ID |
Username | EC2 사용자 이름 (Ubuntu를 사용하는 경우 ubuntu라고 작성) |
Private Key | Enter directly 체크 → .ppk 내용 |
- Jenkins 관리 > System > SSH Remote hosts
- check connection으로 테스트 가능
Hostname | EC2 public IP |
Port | 22 (SSH 포트번호는 22) |
Credentials | 앞서 생성한 Credential |
2. 빌드 설정
- item > Configure > Build Step
- Add bulid step > Execute shell 추가 : jar 파일을 전송하는 코드를 입력
jar 파일 전송 명령어는 아래와 같은 형식으로 작성해주어야 한다.
$ scp -v -o StrictHostKeyChecking=no -i [젠킨스 pem 파일 경로] [젠킨스 jar 파일 경로] [ec2 사용자]@[ec2 public ip]:[ec2 경로]
그런데 기본적으로 EC2에는 /var/jenkins_home 디렉토리가 없다!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
그래서 💣 /var/lib/jenkins 💣로 접근해야 한다... 경로 때문에 하루종일 삽질했다 언버블리버블~
아무튼 나는 .pem을 EC2 내부에 직접 만들어주었다.
ppk를 pem으로 변환해서 생성했고 chmod 777로 .pem 파일에 권한도 부여해주었다.
- Build > Add build step에서 Execute shell script on remote host using ssh 추가
- 빌드 후 jar 파일을 EC2로 보낸 다음, 실행할 스크립트를 지정할 수 있다.
- 나는 EC2 내부에 배포 스크립트 파일을 만들어두고, EC2로 jar 파일이 전달되면 해당 스크립트가 수행될 수 있도록 설정해주었다.
SSH Site | 앞서 설정한 EC2 |
Command | /home/ubuntu/app-server/deploy.sh |
이때 화면에 빨간 글씨로 SSH Site not specified 라고 뜨는데 이렇게 뜨는 것이 맞다.
3. Nginx 설정
Nginx를 웹서버이자 프록시 서버로 사용하기 위해 EC2에 nginx를 설치해주었다.
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install nginx
$ sudo service nginx start
$ sudo service nginx status
먼저 설정 파일을 연다.
$ sudo vi /etc/nginx/sites-enabled/default
위치에 유의하며 아래의 2 줄을 추가한다.
include /etc/nginx/conf.d/service-url.inc;
proxy_pass $service_url;
+ proxy_pass 위에 try files는 주석 처리!!
다음으로 service-url.inc 파일을 추가해준다.
- memotion 서버는 9000 포트를 사용
- proxy 서버 적용 시 ) 기본 포트(80)으로 접속 시 자동으로 9000 포트에 연결
$ sudo vi /etc/nginx/conf.d/service-url.inc
파일 내용을 작성한다.
set $service_url http://127.0.0.1:9000;
nginx 서버를 재시작한다.
$ sudo service nginx restart
4. 배포 스크립트 작성
배포 스크립트는 /home/ubuntu/app-server 디렉토리 밑에 deploy.sh 라는 이름으로 생성해준다.
필자는 /home/ubuntu/memotion_server/deploy.sh 경로로 작성했으며
deploy.sh 내용은 다음과 같다.
#!/bin/bash
REPOSITORY=/home/ubuntu/memotion_server
PROJECT_NAME=Memotion
echo ">>> 현재 구동중인 애플리케이션 pid 확인"
CURRENT_PID=$(pgrep -fl Memotion | grep java | awk '{print $1}')
echo ">> PID : " $CURRENT_PID
if [ -z "$CURRENT_PID" ]; then
echo "구동중인 애플리케이션 없음."
else
echo ">>> kill -15 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 10
fi
echo ">>> 애플리케이션 배포"
JAR_NAME=$(ls -tr $REPOSITORY/*.jar | tail -n 1)
echo ">>> JAR NAME : $JAR_NAME"
chmod +x $JAR_NAME
echo ">>> $JAR_NAME 실행"
nohup java -jar \
-Dspring.profiles.active=prod \
$JAR_NAME > $REPOSITORY/nohup.out 2>&1 &
지금은 테스트 단계이므로 .jar가 없기 때문에 ~/app_server 밑에 jar 파일을 복사해서 넣어주고
~/app_server 밑에 있는 jar 파일과 deploy.sh 파일 모두 chmod 755로 권한을 부여한다.
그런데 build에 성공해도 자꾸 deploy.sh를 못 찾고 실행할 권한이 없다고 떴다!!!!!!!!!!!!!
경로도 문제 없고 실행 권한도 줬잖아;;
sudo: ./deploy.sh: command not found
chmod: changing permissions of 'deploy.sh': Operation not permitted
삽질 끝에 다른 사용자의 파일을 실행하려는 경우
즉 deploy.sh의 소유자가 Jenkins 사용자가 아니라면 해당 파일을 실행할 수 없다는 것을 알았다.
그래서 deploy.hs 파일 소유자를 그냥 Jenkins로 바꿔주었다 ^.^
# 실제로 사용중인 Jenkins 사용자와 그룹을 확인
$ id jenkins
# jenkins-user:jenkins-group은 id값을 넣어줌
$ sudo chown jenkins-user:jenkins-group /home/ubuntu/memotion_server/deploy.sh
그런데 또 똑같은 오류가 발생했다~
GPT의 도움을 얻었는데 Jenkins에서 스크립트를 실행 시 절대경로를 사용하는게 좋다고 해서 절대 경로로 수정해주었다.
+ Jenkins 빌드는 일반적으로 Jenkins 서버 작업 공간 (/var/lib/jenkins/workspace) 에서 실행돼서 상대경로로 작성하면 찾을 수 없던 것!
다시 Jenkins 웹페이지로 돌아가
Execute shell script on remote host using ssh를 아래와 같이 절대경로로 수정해주었고
deploy.sh는 mv 명령어를 사용해 /home/ubuntu/memotion_server/deploy.sh에서 /var/lib/jenins/workspace/deploy.sh로 이동시켜주었고 파일 내용도 아래와 같이 수정해주었다.
#!/bin/bash
REPOSITORY=/var/lib/jenkins/workspace/CICD-Memotion/build/libs
PROJECT_NAME=Memotion
echo ">>> 현재 구동중인 애플리케이션 pid 확인"
CURRENT_PID=$(pgrep -fl Memotion | grep java | awk '{print $1}')
echo ">> PID : " $CURRENT_PID
if [ -z "$CURRENT_PID" ]; then
echo "구동중인 애플리케이션 없음."
else
echo ">>> kill -15 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 10
fi
echo ">>> 애플리케이션 배포"
JAR_NAME=$(ls -tr $REPOSITORY/*.jar | tail -n 1)
echo ">>> JAR NAME : $JAR_NAME"
chmod +x $JAR_NAME
echo ">>> $JAR_NAME 실행"
nohup java -jar \
-Dspring.profiles.active=prod \
$JAR_NAME > /var/lib/jenkins/workspace/nohup.out 2>&1 &
echo ">>> 스크립트 종료"
exit 0
6. 방화벽 설정
EC2의 보안설정 > 인바운드 규칙을 편집해주어도 되지만 EC2 내부에서 직접 방화벽을 설정해주어도 된다!
EC2에서 인바운드 규칙을 편집하는 쪽이 더 간편하지만, 리눅스와 친해지기 위해서... 직접 방화벽을 설정해주었다.
memotion 서버는 9000 포트를 사용하기 때문에 방화벽으로 80, 8080, 9000 등등의 포트를 열어주었다.
이제 실제 API 요청을 보냈을 때 잘 동작하는 것을 확인할 수 있다!
아쉬운점
처음에는 Docker와 Jenkins를 활용해 CI/CD를 구축하려고 했다.
이때, 나는 EC2 내부에 Docker를 설치해서 Jenkins가 빌드 후 생성한 jar를 EC2로 넘겨주면deploy.sh에 jar 파일을 Docker Hub에 업로드하고 이미지를 실행시키는...
위와 같은 로직을 생각하고 실제로 EC2에 docker, docker-compose도 설치 + DockerFile까지 작성했는데 deploy.sh 작성할 때쯤 시간이 부족하기도 하고 Docker를 사용했을 때의 장점도 살리지 못하는 것 같다는 생각에 스크립트 내용을 jar 파일을 실행하는 내용으로 변경했다.
Gitlab + Jenkins + Docker + EC2를 활용한 배포 조합이 흔하지 않은지(?) 리소스가 부족했는데
보통 docker 안에 jenkins를 내려받고 jenkins 이미지를 컨테이너로 실행하는 방식 = docker 활용하는 일반적 방식 인 것 같아서 다음에 기회가 된다면 요런 방식으로도 도전해보고 싶다!
근데 스크립트 내부에서 docker 허브에 플젝을 올려 이미지를 실행시키는게 결코 나쁜 배포 방식이라고 말할 수 없고
세상엔 정말 다양한 방식의 CI/CD 로직이 존재하니까 프로젝트 상황, 규모, 자금에 맞는 방식을 채택하는게 베스트라고 생각한다.
.
.
.
Gitlab + Jenkins + Nginx + EC2를 활용한 배포 完
'Server > CI&CD' 카테고리의 다른 글
[CI/CD] Github Actions + Elastic Beanstalk를 활용한 Node.js CI/CD 구축 (2) (0) | 2024.03.11 |
---|---|
[CI/CD] Github Actions + Elastic Beanstalk를 활용한 Node.js CI/CD 구축 (1) (2) | 2024.02.18 |
[CI/CD] GitLab + Jenkins를 활용한 SpringBoot CI/CD 구축 (2) (0) | 2023.10.20 |
[CI/CD] GitLab + Jenkins를 활용한 SpringBoot CI/CD 구축 (1) (0) | 2023.08.18 |
[CI/CD] Github Action을 활용한 SpringBoot CI/CD 구축 (0) | 2023.08.16 |