天天看點

使用 Kustomize 幫你管理 kubernetes 應用(三):将 Kustomize 應用于 CI/CD

前言

首先明确軟體版本,我這裡使用的是

Jenkins ver. 2.121.3

,這個版本比較老,其上安裝 Kubernetes 插件所使用

kubectl

版本也比較老,無法使用 Kustomize 的 yaml 檔案需要的

apiVersion: apps/v1

,直接使用生成

deploy.yaml

檔案會報錯,是以這裡選擇了自己建構一個包含

kubectl

kustomize

的鏡像,在鏡像中使用 Kustomize 生成所需 yaml 檔案并在 Kubernetes 上部署。

軟體版本

軟體 版本
Jenkins 2.121.3
kubectl v1.14.1
kustomize v2.0.3

前期準備

  • Jenkins :本篇使用 Jenkins 示範 CI/CD ,安裝 Jenkins 就不在贅述,可以使用多種方法安裝 Jenkins ,詳細方法見 官網 。同時。 CI/CD 的工具有很多,這裡為了省事使用筆者現有的 Jenkins 進行示範,不推薦使用同筆者一樣的版本,請使用較新的版本;同時也可以使用其他 CI/CD 工具,這裡推薦使用 drone 。如果有更好的方案,歡迎交流。
  • kubectl

    &

    kustomize

    :上文中提到了由于 Jenkins 版本比較老,是以這裡筆者自己制作了包含二者的 docker 鏡像,已上傳 dockerhub ,需要自取:

    guoxudongdocker/kubectl

  • Web 應用:這裡使用 flask 寫了一個簡單的 web 應用,用于示範,同樣以上傳 dockerhub

    guoxudongdocker/flask-python

目錄結構

首先看一下目錄結構,目錄中包括

Dockerfile

Jenkinsfile

、 Kustomize 要使用的

deploy

目錄以及 web 應用目錄。

.
├── Dockerfile
├── Jenkinsfile
├── app
│   ├── main.py
│   └── uwsgi.ini
└── deploy
    ├── base
    │   ├── deployment.yaml
    │   ├── kustomization.yaml
    │   └── service.yaml
    └── overlays
        ├── dev
        │   ├── healthcheck_patch.yaml
        │   ├── kustomization.yaml
        │   └── memorylimit_patch.yaml
        └── prod
            ├── healthcheck_patch.yaml
            ├── kustomization.yaml
            └── memorylimit_patch.yaml           

這裡可以看到 overlays 總共有兩個子目錄

dev

prod

,分别代表不同環境,在不同的環境中,應用不同的配置。

Jenkins 配置

Jenkins 的配置相對簡單,隻需要建立一個 pipeline 類型的 job

使用 Kustomize 幫你管理 kubernetes 應用(三):将 Kustomize 應用于 CI/CD

增加參數化建構,注:參數化建構需要安裝 Jenkins 插件

使用 Kustomize 幫你管理 kubernetes 應用(三):将 Kustomize 應用于 CI/CD

然後配置代碼倉庫即可

使用 Kustomize 幫你管理 kubernetes 應用(三):将 Kustomize 應用于 CI/CD

Pipeline

podTemplate(label: 'jnlp-slave', cloud: 'kubernetes',
  containers: [
    containerTemplate(
        name: 'jnlp',
        image: 'guoxudongdocker/jenkins-slave',
        alwaysPullImage: true
    ),
    containerTemplate(name: 'kubectl', image: 'guoxudongdocker/kubectl:v1.14.1', command: 'cat', ttyEnabled: true),
  ],
  nodeSelector:'ci=jenkins',
  volumes: [
    hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'),
    hostPathVolume(mountPath: '/usr/bin/docker', hostPath: '/usr/bin/docker'),
    hostPathVolume(mountPath: '/usr/local/jdk', hostPath: '/usr/local/jdk'),
    hostPathVolume(mountPath: '/usr/local/maven', hostPath: '/usr/local/maven'),
    secretVolume(mountPath: '/home/jenkins/.kube', secretName: 'devops-ctl'),
  ],
)
{
    node("jnlp-slave"){
        stage('Git Checkout'){
            git branch: '${branch}', url: 'https://github.com/sunny0826/flask-python.git'
        }
        stage('Build and Push Image'){
            withCredentials([usernamePassword(credentialsId: 'docker-register', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
                sh '''
                docker login -u ${dockerUser} -p ${dockerPassword}
                docker build -t guoxudongdocker/flask-python:${Tag} .
                docker push guoxudongdocker/flask-python:${Tag}
                '''
            }
        }
        stage('Deploy to K8s'){
            if ('true' == "${deploy}") {
                container('kubectl') {
                    sh '''
                    cd deploy/base
                    kustomize edit set image guoxudongdocker/flask-python:${Tag}
                    '''
                    echo "部署到 Kubernetes"
                    if ('prod' == "${ENV}") {
                        sh '''
                        # kustomize build deploy/overlays/prod | kubectl apply -f -
                        kubectl applt -k deploy/overlays/prod
                        '''
                    }else {
                        sh '''
                        # kustomize build deploy/overlays/dev | kubectl apply -f -
                        kubectl applt -k deploy/overlays/dev
                        '''
                    }    
                }
            }else{
                echo "跳過Deploy to K8s"
            }

        }
    }
}

           

這裡要注意幾點:

  • 拉取 git 中的代碼需要在 jenkins 中配置憑據。
  • 筆者的 jenkins 部署在 Kubernetes 上,要操作叢集的話,需要将 kubeconfig 以 Secret 的形式挂載到 jenkins 所在 namespace。
  • jenkins-slave

    需要 Java 環境運作,是以要将主控端的

    jdk

    挂載到

    jenkins-slave

    中。
  • 同樣的,主控端中需要事先安裝

    docker

  • docker-register

    為 dockerhub 的登入憑證,需要在 jenkins 中添加相應的憑證。

示範

開始建構

這裡選擇環境、分支,填入版本即可開始建構,注意:這裡的版本将已 tag 的形式标記 docker 鏡像。

使用 Kustomize 幫你管理 kubernetes 應用(三):将 Kustomize 應用于 CI/CD

這裡就可以看到建構成功了

使用 Kustomize 幫你管理 kubernetes 應用(三):将 Kustomize 應用于 CI/CD

檢視結果

這裡為了友善(其實就是懶),我就不給這個服務添加 ingress 來從外部通路了,這裡使用

KT

打通本地和 k8s 叢集網絡來進行調試。

為了簡化在Kubernetes下進行聯調測試的複雜度,雲效在SSH隧道網絡的基礎上并結合Kubernetes特性建構了一款面向開發者的輔助工具kt

這裡看到這個服務正常啟動了

使用 Kustomize 幫你管理 kubernetes 應用(三):将 Kustomize 應用于 CI/CD

釋出新版本

更新 web 服務并送出

使用 Kustomize 幫你管理 kubernetes 應用(三):将 Kustomize 應用于 CI/CD

按照上面步驟在 jenkins 中重新建構,當然也可以配置鈎子,每次代碼送出後自動建構

檢視檢視新版本

同上面一樣,在建構成功後檢視服務是否更新

使用 Kustomize 幫你管理 kubernetes 應用(三):将 Kustomize 應用于 CI/CD

可以看到,版本已經更新了

釋出生産環境

這裡模拟一下釋出生産環境,假設生産環境是在

devops-prod

的 namespace 中,這裡隻做示範之用,真正的生産環境中,可能存在不止一個 k8s 叢集,這時需要修改 Jenkinsfile 中的

secretVolume

來挂載不同 k8s 的 kubeconfig 來達到釋出到不同叢集的目的。當然,一般釋出生産環境隻需選擇測試通過的鏡像來釋出即可,不需要在進行建構打包。

使用 Kustomize 幫你管理 kubernetes 應用(三):将 Kustomize 應用于 CI/CD

檢視生産版本

使用 Kustomize 幫你管理 kubernetes 應用(三):将 Kustomize 應用于 CI/CD

總結

上面的這些步驟簡單的示範了使用 jenkins 進行 CI/CD 的流程,流程十分簡單,這裡僅供參考

Kustomize 的作用

那麼, Kustomize 在整個流程中又扮演了一個什麼角色呢?

更新鏡像

jenkinsfile

中可以看到, kustomize 更新了基礎配置的鏡像版本,這裡我們之前一直是使用

sed -i "s/#Tag/${Tag}/g" deploy.yaml

來進行替換了,但是不同環境存在比較多的差異,需要替換的越來越多,導緻 Jekninsfile 也越來越臃腫和難以維護。 kustomize 解決了這個問題。

kustomize edit set image guoxudongdocker/flask-python:${Tag}           

環境區分

上面也提到了,不同的環境我們存在這許多差異,雖然看上去大緻類似,但是很多細節都需要修改。這時 kustomize 就起到了很大的作用,不同環境相同的配置都放在

base

中,而差異就可以在

overlays

中實作。

.
├── base
│   ├── deployment.yaml
│   ├── kustomization.yaml
│   └── service.yaml
└── overlays
    ├── dev
    │   ├── healthcheck_patch.yaml
    │   ├── kustomization.yaml
    │   └── memorylimit_patch.yaml
    └── prod
        ├── healthcheck_patch.yaml
        ├── kustomization.yaml
        └── memorylimit_patch.yaml           

可以看到,

base

中維護了項目共同的基礎配置,如果有鏡像版本等基礎配置需要修改,可以使用

kustomize edit set image ...

來直接修改基礎配置,而真正不同環境,或者不同使用情況的配置則在

overlays

中 以 patch 的形式添加配置。這裡我的配置是 prod 環境部署的副本為2,同時給到的資源也更多,詳情可以在

Github

上檢視。

與 kubectl 的內建

在 jenkinsfile 中可以看到

# kustomize build deploy/overlays/dev | kubectl apply -f -
kubectl apply -k deploy/overlays/dev           

這兩條指令的執行效果是一樣的,在

kubectl v1.14.0

以上的版本中,已經內建了 kustomize ,可以直接使用

kubectl

進行部署。

結語

這裡隻是對 kustomize 在 CI/CD 中簡單應用的展示,隻是一種比較簡單和基礎的使用,真正的 CI 流程要比這個複雜的多,這裡隻是為了示範 kustomize 的使用而臨時搭建的。而 kustomize 還有很多黑科技的用法,将會在後續的文章中介紹。