spinnaker CD 연동해 보기 (3) - jenkins parameter 사용, kubernetes livenessProbe, readinessProbe 설정
전체 글타래
2022.12.18 - [Study/CI&CD] - 로컬 kubernetes에 Spinnaker 설치해 보기
2022.12.22 - [Study/CI&CD] - spinnaker CD 연동해 보기 - jenkins, kubernetes 연동, pipeline 사용
2022.12.26 - [Study/CI&CD] - spinnaker CD 연동해 보기 (2) - deploy manifest artifact 사용, SpEL 사용
2023.01.10 - [Study/CI&CD] - spinnaker CD 연동해 보기 (4) - pipeline template 사용해 보기
이번 목표
이전 글에서 pipeline으로 template을 만들고 외부 artifact로 호출하 deploy manifest를 공통화하는 과정까지 진행하였다.
이번 글에서는 무중단 배포를 위해 jenkins에서 docker image를 생성할 때 latest가 아닌 빌드 버전으로 tag를 지정하고 빌드하고 이 값을 spinnaker와 연동하여 사용하는 것을 진행해 본다.
jenkins에서 jib:build 시 tag 지정하기
maven에서 jib:build시 tag를 지정하려고 한다
기존에는 latest tag를 사용하였었다.
빌드하려는 tag규칙은 [version].[buildNumber]로 정했다.
예를 들면 "bluesky-cloud-config-server:0.0.1-SNAPSHOT.23"과 같이 docker image를 빌드하려고 한다.
version은 maven에서 관리하는 해당 프로젝트의 버전이고
buildNumber는 jenkins에서 job 수행별로 순차적으로 증가하여 매겨지는 번호이다.
우선 jenkins의 buildNumber를 jib:build 시 넘겨받아야 한다.
jenkins 환경 변수 사용하기
jenkins에서 사용할 수 있는 환경 변수는 build의 execut shell 같은 항목을 선택하면 url을 안내하고 있다.
해당 링크([jenkins주소]/env-vars.html/)를 클릭하면 사용할 수 있는 환경 변수 목록이 나온다.
http://localhost:8080/env-vars.html/
그중 BUILD_NUMBER를 사용하려고 한다.
이 값을 jenkins에서 maven build시 다음과 같이 -D 옵션을 통해 넘긴다.
mvn -Dbuild.number=${BUILD_NUMBER} jib:build
이제 maven에서는 build.number라는 값으로 jenkins의 build number를 가져다 쓸 수 있게 된다.
다음과 같이 jib plugin tag 설정에서 전달된 값을 사용하면 된다.
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>${jib-maven-plugin.version}</version>
<configuration>
<from>
<image>openjdk:17-slim</image>
</from>
<to>
<tags>
<tag>${project.version}.${build.number}</tag>
</tags>
</to>
</configuration>
</plugin>
${project.version}은 maven에서 제공하는 환경 변수이고 ${build.number}는 -D로 넘긴 변수이다.
${build.number}를 넘기지 않은 경우에도 특정 값으로 동작되도록 다음과 같이 properties에 기본값을 정의해주면 좋다.
</properties>
<build.number>LOCAL_BUILD</build.number>
</properties>
이제 jenkins의 buildNumber를 넘겨받아 docker image 빌드 시 사용할 수 있게 되었다.
spinnaker로 빌드 정보 전달하기
jenkins에서 maven의 jib:build를 통해 이미지가 생성되었다.
이제 이 생성된 이미지를 spinnaker에서 가져다가 사용해야 한다.
기존 설정은 단순히 tag를 latest로 사용하였지만 이제 매 빌드 시 tag는 ${project.version}.${build.number}의 형태로 지정되어야 한다.
spinnaker에 소개된 "Triggering pipelines with Jenkins" 문서에서 처럼 jenkins에서 파일을 만들고 값을 전달하는 방법도 있다.
https://spinnaker.io/docs/guides/user/pipeline/triggers/jenkins/
(build=${BUILD_NUMBER}를 가진 build.properties를 만든 예제)
stages {
stage('Generate Kubernetes Manifests') {
steps {
sh '''
npm install
npm run import
npm run build
echo "BUILD=${BUILD_NUMBER}" > build.properties
'''
}
}
}
하지만 jenkins는 maven의 ${project.version} 값을 알지 못한다.
${project.version}도 같이 넘기고 싶은 경우 jenkins가 maven 빌드에 BUILD_NUMBER 값을 넘긴 김에 maven에서 spinnaker로 넘길 정보를 가진 파일을 생성하는 게 좋다.
maven properties-maven-plugin 사용하기
https://www.mojohaus.org/properties-maven-plugin/index.html
maven에서 빌드 정보를 파일로 만드는 방법은 여러 가지가 있을 수 있다.
직접 플러그인을 구현해도 된다.
간단하게 쓸 수 있는 properties-maven-plugin을 사용해 보았다.
다음과 같이 plugin 설정을 추가했다.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>${properties-maven-plugin.version}</version>
<configuration>
<outputFile>
build.properties
</outputFile>
</configuration>
</plugin>
jenkins에서 maven 빌드 시 위 plugin을 실행하면 된다.
mvn properties:write-project-properties
빌드하면 대략 다음처럼 build.properties가 생성된다.
내용 중 build.number가 -D 옵션으로 추가한 파라미터이고 만약 -D 옵션으로 추가하지 않은 경우 properties로 설정한 LOCAL_BUILD란 값이 설정되게 된다.
#Properties
angus-mail.version=1.0.0
artemis.version=2.26.0
asciidoctor-maven-plugin.version=2.2.2
asciidoctor.doctype=book
asciidoctor.outputDirectory=/var/jenkins_home/workspace/bluesky-cloud/bluesky-cloud ci develop/bluesky-cloud-parent/target/generated-docs
asciidoctor.preserveDirectories=true
asciidoctorj-diagram.version=2.2.3
aspectj.version=1.9.19
assertj.version=3.23.1
awaitility.version=4.2.0
bluesky-boot-autoconfigure-devcheck.version=3.0.0-SNAPSHOT
bluesky-boot.version=0.0.1-SNAPSHOT
brave.version=5.14.1
build-helper-maven-plugin.version=3.3.0
build.number=7
#... 이하 생략
jenkins Archive the artifacts 설정 추가하기
위 설정이 추가되면 빌드 시 build.properties가 생성된 것을 확인할 수 있다.
spinnaker에서 jenkins에서 빌드된 build.properties를 가져오기 위해서는 archive를 해야 한다.
빌드 후 조치로 archive the artifacts 설정으로 빌드된 build.properties를 가져가도록 추가한다.
이렇게 추가하면 빌드 시 해당 build.properties가 archive 된고 링크로 호출하여 사용할 수 있게 된다.
http://[젠킨스주소]/job/bluesky-cloud/job/bluesky-cloud%20ci%20develop/7/artifact/bluesky-cloud-parent/build.properties
spinnaker에서 build.properties를 읽도록 설정하기
이 부분은 간단하다.
기존의 pipeline의 jenkins trigger부분에서 build.properties를 읽는다고 설정을 추가하면 된다.
이제 deploy manifest에서 tag를 수정하면 된다.
image: ${parameters.imageHost}/luversof/${execution.application}:${trigger.properties['build.version']}.${trigger.properties['build.number']}
spinnaker에서 delete manifest 삭제하기
기존엔 jenkins trigger -> delete manifest -> deploy manifest로 동작하였다.
새로 반영될 때마다 기존 deployment와 service를 삭제한 후 배포를 하였다.
이제 deploy manifest가 매번 버전이 다르게 반영되기 때문에 삭제를 하는 단계를 제거해도 반영이 진행된다.
다만 새로 띄우자마자 바로 이전 pod를 제거하는 것을 확인할 수 있다.
이에 대해서 새로 띄우는 pod에 대해 모니터링을 한 후 변경이 되도록 설정을 하여야 한다.
deploy manifest에 livenessProbe, readinessProbe 설정하기
새로 배포되는 pod가 잘 떠있는지 체크한 후 기존 pod를 삭제하도록 kubernetes의 deploy manifest에 livenessProbe와 readinessProbe를 설정한다.
livenessProbe는 pod가 비정상 상태이면 재시작 처리를 하고 readinessProbe는 pod가 비정상 상태이면 대상에서 제외한다.
대략 아래처럼 설정해 보았다.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: '${execution.application}'
name: '${execution.application}-deployment'
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: '${execution.application}'
template:
metadata:
labels:
app: '${execution.application}'
spec:
containers:
- args:
- '--spring.profiles.active=${parameters.springProfilesActive}'
image: >-
${parameters.imageHost}/luversof/${execution.application}:${trigger.properties['build.version']}.${trigger.properties['build.number']}
name: spring
ports:
- containerPort: '${#toInt(parameters.nodePort)}'
workingDir: /usr/local/app
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: ${#toInt(parameters.nodePort)}
initialDelaySeconds: 3
periodSeconds: 3
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: ${#toInt(parameters.nodePort)}
initialDelaySeconds: 3
periodSeconds: 3
# ... 이하 생략
위 설정을 추가하고 배포를 테스트해보면 새 pod의 상태를 기다리고 기존 pod를 terminating 하는 것을 확인할 수 있다.
이외에도 startupProbe가 있어서 시작 시 상태에 대한 모니터링도 설정할 수 있다고 한다.