개요
저번 포스팅에서는 Jenkins 서버를 구축하고 Git과 연동하여 Build 하는 단계까지 진행했었습니다.
이번 포스팅에서는 Jenkins 서버에서 ssh로 애플리케이션 서버 접근하여 배포하는 과정을 진행해 보겠습니다.
Jenkins + SpringBoot로 CI/CD 구축해보기(1) - Jenkins SSH 플러그인 설치
위에서 언급한 대로 Jenkins 서버에서 ssh로 애플리케이션 서버에 접근하려면 Jenkins 서버에 SSH 설정이 필요합니다.
SSH 설정을 하기 위해 Jenkins에 Publish Over SSH 플러그인이 필요합니다.
Jenkins 관리 페이지에서 Plugins에 들어가 Publish Over SSH 플러그인을 다운로드 받아 줍니다.
sudo systemctl restart jenkins
설치를 완료했다면 Jenkins를 재시작해 줍니다.
Jenkins + SpringBoot로 CI/CD 구축해보기(2) - Publish over SSH 설정
Jenkins 서버에서 애플리케이션 서버로 접근하려면 Public Key가 필요합니다.
저는 .pem이 아닌 .ppk 키로 ssh 접속을 하고있기 때문에 따로 ssh key를 추가해 줘야 합니다.
우선 Jenkins 서버에서 ssh key를 생성해 줍니다.
ssh-keygen -t rsa
위 커맨드를 입력하여 ssh key를 생성해 줍니다.
# ssh key가 생성된 경로로 이동
cd /home/ec2-user/.ssh/
# 목록 확인
ls
# 결과
>> authorized_keys id_rsa id_rsa.pub
이후 ssh key가 생성된 경로로 이동하여 ls로 목록을 확인해 봅니다.
그러면 authorized_keys, id_rsa, id_rsa.pub가 생성된 것을 확인할 수 있습니다.
cat id_rsa
이후 cat으로 id_rsa(개인키)를 뿌려보면 -----BEGIN OPENSSH PRIVATE KEY----- << 로 시작하는 내용이 나오는데 이것을 복사해 줍니다.
이후 Publish Over SSH의 Key 항목에 복사한 내용을 그대로 입력해 줍니다.
잘 등록해 줬다면 저장해 줍니다.
cat id_rsa.pub
다시 Jenkins 서버에서 위 명령어를 입력하여 공캐키의 내용을 복사해 줍니다.
이후 애플리케이션 서버에 SSH로 접속할 수 있도록 합니다.
# ssh 경로로 이동
cd .ssh
# 목록 확인
ls
# authorized_keys 파일이 있는지 확인
>> authorized_keys
# authorized_keys 파일 편집
vi authorized_keys
애플리케이션 서버에 Jenkins에서 생성한 ssh key의 공개키를 애플리케이션 서버에 authorized_keys에 등록해 줄 것입니다.
vi로 authorized_keys 편집기를 열고 위에서 복사한 Jenkins 서버의 공개키를 붙여넣기 해줍니다.
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
이후 ssh 디렉토리와 authorized_keys 파일에 권한을 설정해 줍니다.
다시 Jenkins의 Publish Over SSH 설정하는 곳으로 돌아와 SSH Server를 등록해 줍니다.
- Name : 원격 서버 이름
- Hostname : 원격 서버의 Private IP
- Username : 원격 서버로 접근할 Username
위 내용들을 입력하고 Test Configuration 버튼을 눌러 애플리케이션 서버로의 연결이 잘 되는지 확인해 봅니다.
사진처럼 Success가 나와야 연결이 성공한 것입니다.
Jenkins + SpringBoot로 CI/CD 구축해보기(3) - 빌드 환경 설정
다시 Jenkins Item으로 돌아와 빌드 환경 설정 항목에 Jar 파일을 Deploy 할 수 있도록 추가해 줄 것입니다.
Send files or execute commands over SSH after the build runs << 이 항목을 체크하고 위 내용들을 입력해 줍니다.
말 그대로 빌드 이후에 ssh를 통해 파일을 보내거나 커맨드를 실행한다는 뜻입니다.
우리는 애플리케이션 서버에 빌드 된 Jar 파일을 보내고 deploy.sh을 실행시켜 Deploy 하면 되겠죠?
- SSH Server Name : 위에서 등록했던 Application 서버를 등록해 줍니다.
- Remove prefix : Source files에서 지정한 경로의 하위 폴더를 지운다는 뜻입니다. => Jar 파일만 전송
- Source files : Gradle Build시 Jar파일이 생성되는 디렉토리입니다.
- Remote Directory : 배포 타겟 서버의 디렉토리입니다.
- Exec command : 원격 서버에서 실행될 스크립트 실행 커맨드입니다.
Jenkins + SpringBoot로 CI/CD 구축해보기(4) - 배포 환경 설정
Jenkins에서 관련 설정들을 마쳤으니 이제 애플리케이션 서버에서 잘 배포가 될 수 있도록 디렉토리 및 권한 설정 그리고 Deploy.sh 스크립트를 작성해 줍시다.
# deploy 폴더 생성
mkdir /deploy
# deploy/jar 폴더 생성
mkdir /deploy/jar/
# deploy/sh 폴더 생성
mkdir /deploy/sh/
# deploy.sh 파일 생성
touch deploy.sh
# deploy.sh 작성
vi deploy.sh
이렇게 배포가 될 수 있도록 디렉토리 및 Shell 스크립트를 만들어 줍니다.
# 8080 포트 종료
fuser -k -n tcp 80
# jar 실행
sudo nohup java -jar /deploy/jar/docker-app-0.0.1-SNAPSHOT.jar > /dev/null 2>&1 &
이후 vi로 deploy.sh에 위 내용을 입력해 줍니다.
기존에 서비스 중인 8080 포트를 종료하고 신규 Jar 파일을 실행할 수 있도록 합니다.
# 디렉토리 소유자 설정
chown -R ec2-user /deploy
# 디렉토리 권한 설정
chmod -R 750 /deploy
이후에 Jenkins에서 ssh로 접속할 user에 대해 권한을 설정해 줍니다.
Jenkins + SpringBoot로 CI/CD 구축해보기(5) - CI/CD Pipeline 확인
이제 모든 구성을 마쳤으니 첫 번째 포스팅에서 구상했던 대로 CI/CD Pipeline이 동작하는지 확인해 봅시다.
@RestController
public class MainController {
@GetMapping("/github-webhook")
public ResponseEntity<?> webhook() {
return new ResponseEntity<>("---- Jenkins CI & CD With Github Webhook ----", HttpStatus.OK);
}
}
이렇게 API를 작성하고 Webhook 설정했던 브랜치에 푸쉬합니다.
그럼 Webhook으로 인해 Jenkins에서 정상적으로 빌드를 실행하는 것을 확인할 수 있습니다.
BUILD SUCCESSFUL in 30s
8 actionable tasks: 8 executed
Build step 'Invoke Gradle script' changed build result to SUCCESS
SSH: Connecting from host [ip-{your-ec2-private-ip}.ec2.internal]
SSH: Connecting with configuration [Spring-Application-Server] ...
SSH: EXEC: completed after 202 ms
SSH: Disconnecting configuration [Spring-Application-Server] ...
SSH: Transferred 2 file(s)
Finished: SUCCESS
최종적으로 Jenkins에서 Build 및 Deploy가 성공한 것을 확인할 수 있습니다.
이렇게 UI와 콘솔로만 보면 모르겠으니 애플리케이션 서버에 8080 포트가 떠있는지 확인해 보겠습니다.
netstat -tnlp
위 명령어를 입력하여 어떤 포트가 떠있는지 확인해 봅시다.
기본적으로 ssh(22 port)와 우리가 Jar로 실행했던 서비스 포트(8080 port)가 정상적으로 잘 살아있는 것을 확인할 수 있습니다.
8080 포트가 실행 중인 것을 확인했으니 애플리케이션 서버의 8080 포트 인바운드 규칙을 추가해줍니다.
이제 Postman으로 API 요청을 해보면 main 브랜치에 푸쉬된 내용이 빌드/배포되어 반영된 것을 확인할 수 있습니다.
Jenkins + SpringBoot로 CI/CD 구축해보기(6) - 아쉬운 점
이렇게 SpringBoot와 Jenkins를 이용하여 CI/CD Pipeline을 구상하고 직접 구축해 봤습니다.
최소한의 스펙으로 간단하게 구현한 것이라 구조에 문제점이 아주 많습니다.
현재는 푸시만 하면 아무렇게나 빌드 & 배포가 이루어지기 때문에 히스토리가 관리되지 않고 성공 유무에 대한 푸시 알림 같은 것도 Jenkins에 직접 들어가야만 확인할 수 있습니다.
또한 현재는 애플리케이션 서버가 1대지만 2대, 3대... 100대가 넘어가는 환경에 대한 설계가 전혀 없고 Auto Scaling 또한 적용할 수 없습니다.
deploy.sh을 보시면 알겠지만 8080 Port Kill => 업데이트된 Jar를 실행하는 프로세스이다 보니 배포 중에 서비스가 중단되는 것도 문제이기도 합니다.
이러한 문제점들을 해결하기 위한 기술적 과제들이 존재하고 이미 여러 가지 방법들로 풀어내서 서비스하고 있는 기업들도 많습니다.
차후에 숙지되면 이러한 문제점들을 보완한 아키텍쳐를 한 번 구현해 보도록 하겠습니다.
'Jenkins' 카테고리의 다른 글
[Jenkins] Jenkins + SpringBoot로 CI/CD 구축해보기(2) (0) | 2023.09.21 |
---|---|
[Jenkins] Jenkins + SpringBoot로 CI/CD 구축해보기(1) (0) | 2023.09.20 |