목차
- 개요
- CD 파이프라인 워크플로우
- Naver Could Container Registry 신청
- Jenkins서버 ↔ 애플리케이션 서버 ssh 키 생성
- Jenkins ↔ Application Server SSH 원격 접속 Credentials 등록
- Jenkins ↔ Docker Registry Credentials 등록
- Dockerfile 생성하기
- 배포 작업하기
- 파이프라인 스크립트 작성
- main 브랜치 Push 및 배포 확인하기
1. 개요
지난 젠킨스를 이용하여 CI를 구성하였고 이번 글에서는 배포를 자동화해주는 CD를 구축해보려한다.
우리는 CI/CD 구축이 되어 있지 않다면 매번 코드를 옮기고 Jar를 빌드해서 서버에 옮기고 서버를 재시작하는 과정을 반복해야 할 것이다.
Jenkins를 이용해 구축할 것이며 아래 과정에서 천천히 살펴보자.
2. CD 파이프라인 워크플로우
![](https://blog.kakaocdn.net/dn/wDIGh/btsFmk6A4AP/S9f4UKlkJSQKanv98T3ejK/img.png)
- Github에 변경사항에 대해 Push후 PR를 올린다.
- Github에서 레포지토리의 main브랜치에 코드가 merge되면 Jenkins에게 webhook을 날린다.
- Jenkins가 빌드, 도커 이미지를 생성한다.
- 생성된 도커 이미지를 Docker Registry에 등록한다.
- auctionHub 서버가 도커 이미지를 받아 실행한다.
3. Naver Could Container Registry 신청
![](https://blog.kakaocdn.net/dn/bhJgFn/btsFm3p8a2o/tqMHKqPxNOGYiVHm47h5rk/img.png)
애플리케이션의 이미지를 저장할 서버로 Container Registry를 신청해준다. Docker Conainer 이미지를 저장하고 관리하는 서버로 사용할 수 있다.
https://guide.ncloud-docs.com/docs/containerregistry-start
4. Jenkins서버 ↔ 애플리케이션 서버 ssh 키 생성
젠킨스에서 애플리케이션 서버간 ssh 통신이 가능하도록 설정이 필요하다.
- Jenkins 서버 ssh 키 생성하기
ssh-kegen -t rsa
![](https://blog.kakaocdn.net/dn/bRawEU/btsFqMubmho/4bQYLGjFUjPMgBWSMxLRaK/img.png)
- Application 서버 ssh 키 생성
ssh-kegen -t rsa -f id_rsa
![](https://blog.kakaocdn.net/dn/3Bzut/btsFs0ZKMFr/eaPZEGrCYeofk5m9gKKKO1/img.png)
- Jenkins서버에서 Application Server를 Known_hosts로 등록하기
ssh-keyscan -H [Application 서버 ip] >> ~/.ssh/known_hosts
- Application 서버의 authorized_keys에 Jenkins 서버의 공개키(id_rsa.pub) 입력하기
![](https://blog.kakaocdn.net/dn/x1GvI/btsFnW5oF2M/3l9GE0EX6KtQzCk8kWUdU0/img.png)
위 나온 key를 vi를 통해 편집하여 저장하고 닫는다.
![](https://blog.kakaocdn.net/dn/bhQLQS/btsFqaIFDXk/RUekfp5nDJrQ1O8LIUK6S1/img.png)
5. Jenkins ↔ Application Server SSH 원격 접속 Credentials 등록
- Jenkins 서버에서
cat ~/.ssh/id_rsa
명령어를 입력하여 출력된 비밀키를 복사한다.- 이때 주의할 점으로는 BEGIN행부터 END행까지 포함해서 넣어주어야 한다.
![](https://blog.kakaocdn.net/dn/sQIbU/btsFqXvz87X/ox3K7HNn9sm16AesA9u2WK/img.png)
- Jenkins로 넘어가 새로운 Credentials를 추가해준다.
![](https://blog.kakaocdn.net/dn/CbgKj/btsFuGUgtUA/iHCbcdK4DSPO727OjnJGx1/img.png)
ID 에는 Jenkins 시스템 내에서 해당 Credentials를 구분할 ID 값을 적어준다.
Username 에는 Application Server에서 사용되는 OS 계정명을 적는다. (ex. root)
복사한 비밀키 값을 Private key 란에 입력한다.
6. Jenkins ↔ Docker Registry Credentials 등록
- 네이버 클라우드 포탈에서 신규 API 인증키를 생성한다.
![](https://blog.kakaocdn.net/dn/m6zEJ/btsFlSCCbtB/OQG142gJLIQoIIbwWJMmE1/img.png)
- 발급받은 API 인증키를 앞선 과정과 똑같이 Jenkins 서버의 Credentials로 등록한다.
- Kind는 Username with password 를 선택한다.
- Username 에는 API 인증키의 Access Key ID 입력한다.
- Password 에는 API 인증키의 Secret Key 입력한다.
- ID에는 Jenkins 시스템 내에서 해당 Credentials를 구분할 ID 값을 적어준다.
![](https://blog.kakaocdn.net/dn/msJRs/btsFs2Dhhiq/ck4jbLsJRV0KYXl4dVmtx0/img.png)
7. Dockerfile 생성하기
도커는 이미지를 빌드할 때, DockerFile이라는 스크립트 파일 기반으로 동작한다.
프로젝트 최상단에 Dokerfile을 아래 공식문서를 보고 참고하길 바란다.
https://docs.docker.com/engine/reference/builder/
8. 배포 작업하기
Github에서 webhook을 이용하여 main브랜치에 push가 된다면, Jenkins 서버의 API가 호출 되도록 하였다.
- Jenkins Generic Webhook Trigger Plugin 설치
![](https://blog.kakaocdn.net/dn/bISjVP/btsFmium0Ih/nQIKav7DLNVQXzSLT4OIK1/img.png)
- Generic Webhook설정을 통해 구체적으로 어떤 상황에서 배포 작업이 유발될지 설정해준다.
- main 브랜치에 코드가 Push 되면 Github에서는 다음과 같은 API를 호출한다.
http://JENKINS_URL/generic-webhook-trigger/invoke
- Github 레포지토리에 돌아가 webhook을 등록해준다.
![](https://blog.kakaocdn.net/dn/bF9sSX/btsFpQp3eC7/kF4ksAg8u8MqfEsJoZKyAk/img.png)
![](https://blog.kakaocdn.net/dn/tWqKc/btsFm0z997p/WkBsugNQvqRgR9H3iUwng0/img.png)
![](https://blog.kakaocdn.net/dn/btL1AO/btsFm6tugRg/EsGnLxTmyGBBT6uFLIp05k/img.png)
이렇게 하고 저장을 해주면 Pushes 이벤트가 발생할 때 마다 해당 Payload URL을 호출한다.
9. 파이프라인 스크립트 작성
webhook 조건을 만족할 경우, 파이프라인 스크립트가 동작해서 배포 자동화 작업을 수행한다.
pipeline {
environment {
IMAGE_NAME = "이미지 이름"
REGISTRY_CONTAINER = "레지스트리 컨테이너 endpoint"
REGISTRY_CREDENTIAL = "젠킨스 <-> 도커 Credentials ID값"
SSH_CONNECTION_IP = "계정명@Application서버IP"
SSH_CONNECTION_CREDENTIAL = "젠킨스 <-> Application Server SSH Credentials ID"
}
agent any
stages {
// Checkout Git repository
stage('Checkout Git') {
steps {
git branch: 'main',
credentialsId: '02247ad5-1f10-471b-ab72-6d95b8d2d293D',
url: 'https://github.com/f-lab-edu/auctionHub.git'
}
}
// Build repository
stage('Build') {
steps {
sh './gradlew clean bootJar'
echo 'Build repository Success!'
}
}
// Test
stage('Test') {
steps {
// sh './gradlew test'
echo 'Test Success!'
}
}
// 도커 이미지 빌드
stage('Build Container Image') {
steps {
script {
image = docker.build("${REGISTRY_CONTAINER}/${IMAGE_NAME}")
}
}
}
// 생성된 도커 이미지를 네이버 클라우드 Docker Registry에 등록
stage('Push Container Image') {
steps {
script {
docker.withRegistry("https://${REGISTRY_CONTAINER}", REGISTRY_CREDENTIAL) {
image.push("${env.BUILD_NUMBER}")
image.push("latest")
image
}
}
}
}
// 애플리케이션 서버가 도커 이미지를 다운받고 실행하도록 제어
stage('Server run') {
steps {
sshagent(credentials: [SSH_CONNECTION_CREDENTIAL]) {
sh "ssh -o StrictHostKeyChecking=no ${SSH_CONNECTION_IP} 'whoami'"
// 최신 컨테이너 삭제
sh "ssh -o StrictHostKeyChecking=no ${SSH_CONNECTION_IP} 'docker rm -f ${IMAGE_NAME}'"
// 최신 이미지 삭제
sh "ssh -o StrictHostKeyChecking=no ${SSH_CONNECTION_IP} 'docker rmi -f ${REGISTRY_CONTAINER}/${IMAGE_NAME}:latest'"
// 최신 이미지 PULL
sh "ssh -o StrictHostKeyChecking=no ${SSH_CONNECTION_IP} 'docker pull ${REGISTRY_CONTAINER}/${IMAGE_NAME}:latest'"
// 이미지 확인
sh "ssh -o StrictHostKeyChecking=no ${SSH_CONNECTION_IP} 'docker images'"
// 최신 이미지 RUN
sh "ssh -o StrictHostKeyChecking=no ${SSH_CONNECTION_IP} 'docker run -d --name ${IMAGE_NAME} -p 8080:8080 ${REGISTRY_CONTAINER}/${IMAGE_NAME}:latest'"
// 컨테이너 확인
sh "ssh -o StrictHostKeyChecking=no ${SSH_CONNECTION_IP} 'docker ps'"
}
}
}
}
}
10. main 브랜치 Push 및 배포 확인하기
![](https://blog.kakaocdn.net/dn/bPvUvp/btsFmiHQWBD/bOgcYQnBpKnp6IrBbe1K9K/img.png)
참고
'Etc.' 카테고리의 다른 글
Redis 캐시 적용으로 성능 개선하기 (0) | 2024.03.15 |
---|---|
Auditing을 고려한 테이블 설계 과정 (0) | 2024.03.02 |
Scale out시 세션불일치 방지를 위한 Redis 선정과정 (1) | 2024.02.23 |
젠킨스를 통한 CI/CD 구성하기 - CI (1) | 2024.02.06 |
라이브러리 vs 프레임워크 (0) | 2023.12.14 |