파란하늘의 지식창고
article thumbnail
반응형

전체 글타래

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.01 - [Study/CI&CD] - spinnaker CD 연동해 보기 (3) - jenkins parameter 사용, kubernetes livenessProbe, readinessProbe 설정

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를 제거하는 것을 확인할 수 있다.

container를 생성하고
ready가 1로 올라가자 마자 가차없이 바로 이전 pod를 삭제한다.

이에 대해서 새로 띄우는 pod에 대해 모니터링을 한 후 변경이 되도록 설정을 하여야 한다.

deploy manifest에 livenessProbe, readinessProbe 설정하기

https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/

새로 배포되는 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가 있어서 시작 시 상태에 대한 모니터링도 설정할 수 있다고 한다.

 

 

반응형
profile

파란하늘의 지식창고

@Bluesky_

내용이 유익했다면 광고 배너를 클릭 해주세요