Jenkins 在 kubernetes 中的 DevOps 流水线最佳实践

微信扫一扫,分享到朋友圈

Jenkins 在 kubernetes 中的 DevOps 流水线最佳实践

前言

kubernetes目前是最为流行的应用运行环境,应用以容器的形态运行在平台之上,可以实现一些动态的策略,保证服务的SLA。因此DevOps也必须适应这种新形态应用的部署的方式。而对DevOps来讲,其实容器化的出现以及容器平台的出现,其实让DevOps更为简单了。在使用Jenkins kubernetes插件的时候,你就会对流水线的认知更加深刻。总结起来具有以下优势:

  • 容器化平台的动态创建slave的方式节约了系统的资源,构建结束后可自行销毁。

  • 容器化配置同一流水线的不同的步骤运行环境,且在一定程度上实现隔离

  • kubernetes Pod的多容器共享volume的机制,让各个流水线共享操作的中间产物。

  • 模块化的配置流水线的方式,可以对流水线不同版本的工具进行统一的配置管理。

传统的kubernetes的操作方式是在一个环境下配置所有的工具,导致对Jenkins master/slave的环境配置要求较大。而到了容器的平台之上,不同的环境的操作可以天然的隔离到不同的容器之中,而且可以像搭积木一样实现流水线分工,还能通过存储共享的方案实现互相之间中间产物的传递,可以说真正的将流水线的设计 体现 的淋漓尽致。

本文就主要围绕Jenkins在kubernetes中的使用方案进行探讨,给大家呈现一个kubernetes下的最佳实践。

准备工作

  • kubernetes环境,可以使用各种商业/免费版本,自行选择。

    我本人使用的是rancher的k3s,因为整体的安装体积小,便于测试。任何一个可用的kubernetes发行版都能满足我们的需求,我们运行应用使用kubernetes最基本的功能即可。

  • helm安装Jenkins到k8s之上(也可以独立安装,Jenkins kubernetes插件不要求Jenkins master必须运行在kubernetes之上)

    请参考我的历史文章: 使用helm在kubernetes环境中安装jenkins

    此外需要安装相应的kubernetes插件,请参见历史文章:

    使用Jenkins kubernetes插件在kubernetes中运行Jenkins流水线

  • 镜像仓库,可以使用Harbor或者Nexus作为镜像仓库。

    镜像仓库可以使用开源的方案,本文不用过多阐述。

  • helm仓库,可以存储已经打包好的helm应用包。

    可以使用harbor存储helm包,也可以使用chartmuseum进行helm包的存储。当然也可以自己搭建web应用服务器进行存储。在kubernetes平台上建议使用helm进行应用部署。方便管理和配置。

    历史文章: 快速搭建Helm 私有仓库Chartmuseum

    历史文章: kubernetes包管理工具 – Helm 3入门到实战(一)

  • Gitlab环境,用于存储代码,用于流水线配置使用。

    官方提供了Gitlab的helm安装部署方式,可以参考。

    https://docs.gitlab.com/charts/

  • Maven仓库,用于存储java的制品,管理jar包依赖,内网存储可以提高构建的速度。

流水线配置

这里把一整段的jenkins流水线配置贴出来供大家参考,另外对其中的一些信息做相应的介绍:

podTemplate(cloud: 'kubernetes',
imagePullSecrets: ['regcred'],
containers: [
containerTemplate(name: 'jnlp', image: '192.168.100.3:5000/jenkins/jnlp-slave:cicd', ttyEnabled: true),
containerTemplate(name: 'maven', image: '192.168.100.3:5000/mavenbuild:cicd', ttyEnabled: true),
containerTemplate(name: 'docker', image: '192.168.100.3:5000/dind:19.03.6', privileged: true, ttyEnabled: true),
containerTemplate(name: 'helm', image: '192.168.100.3:5000/helmcli:v3.1.2', privileged: true, ttyEnabled: true, command: 'cat')
],
volumes: [
persistentVolumeClaim(claimName: 'kubeconfigs', mountPath: '/root/kubeconfigs/', readOnly: true)
]
){
node(POD_LABEL) {
container('maven'){
stage('Pull source code'){
sh "rm -rf ${config.project_name}-pipeline"
git credentialsId: 'test', branch: 'master' , url: 'http://192.168.100.3/gitlab/demo.git'
}
stage('Compile code') {
sh 'mvn clean package'
}
}
container('docker'){
stage('Docker image build & Push') {
withCredentials([usernamePassword(credentialsId: 'nexus-docker', passwordVariable: 'PASSWORD', usernameVariable: 'USERNAME')]) {
sh 'echo "$PASSWORD" | docker login dockerrepo:5000 -u "$USERNAME" --password-stdin'
sh "docker build -t dockerrepo:5000/cicd/app1:v1.${BUILD_NUMBER} \
-f Dockerfile --force-rm --no-cache ."
sh "docker push dockerrepo:5000/cicd/app1:v1.${BUILD_NUMBER}"
}
}
}
container('helm'){
stage('deploy to kubesphere') {
withCredentials([file(credentialsId: 'k3s-kubeconfig', variable: 'KUBECONFIG')]) {
def action
result = sh returnStatus: true, script: "helm status myproject -n default --kubeconfig $KUBECONFIG"
if(result == 0){
action = "upgrade"
}else{
action = "install"
}
sh "helm ${action} myproject \
http://192.168.100.4:9000/helm-repo/springboot-0.1.0.tgz \
--set image.repository=dockerrepo:5000/cicd/app1:v1.${BUILD_NUMBER} \
--set nameOverride=myproject \
--set fullnameOverride=myproject \
--set ingress.enabled=yes \
--set ingress.host=test.cicd.com \
--set ingress.path=/test \
-n default \
--kubeconfig $KUBECONFIG"
}
}
}
}
}

说明:

  1. 在containerTemplate中根据功能的不同配置了多个不同的环境,例如docker,maven等。我们需要自己配置自己的运行环境的容器。例如,我自己打包的maven镜像中已经包含了连接到nexus制品库的信息。

    示例,我的maven镜像的Dockerfile,其中包含maven的配置以及证书等信息。仅供参考。

    [aiops@3 mavenimage]$ ls
    cert.pem  Dockerfile  entrypoint.sh  README.txt  settings.xml
    [aiops@3 mavenimage]$ cat entrypoint.sh
    #!/bin/bash
    /usr/local/bin/mvn-entrypoint.sh && cat
    [aiops@3 mavenimage]$ cat Dockerfile
    FROM maven:3.6.2-jdk-8
    COPY settings.xml /usr/share/maven/ref/
    COPY cert.pem /usr/share/maven/ref/
    COPY entrypoint.sh /usr/local/bin/
    RUN chmod 777 /usr/local/bin/entrypoint.sh
    RUN keytool -importcert -file /usr/share/maven/ref/cert.pem -alias nexus -storepass changeit -keystore $JAVA_HOME/jre/lib/security/cacerts -trustcacerts -noprompt
    RUN git config --global http.sslverify false
    ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
    [aiops@3 mavenimage]$

    示例:我的docker in docker 镜像的内容, 可以将证书,credential等配置提前预置好。仅供参考

    [aiops@3 dind]$ ls
    CA  ca.crt  config.json  daemon.json  Dockerfile
    [aiops@3 dind]$ cat Dockerfile
    FROM 192.168.100.3:5000/docker:19.03.6-dind
    RUN mkdir -p /etc/docker/certs.d/192.168.100.3:5000/ && mkdir -p /root/.docker/
    COPY ca.crt /etc/docker/certs.d/192.168.100.3:5000
    COPY config.json /root/.docker/
    COPY daemon.json /etc/docker/

    示例:helm镜像

    [aiops@3 helm]$ cat Dockerfile
    FROM 192.168.100.3:5000/alpine:3.10
    WORKDIR ~
    RUN apk add curl
    RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.18.0/bin/linux/amd64/kubectl
    RUN chmod +x ./kubectl
    RUN mv ./kubectl /usr/local/bin/kubectl
    RUN wget https://get.helm.sh/helm-v3.1.2-linux-amd64.tar.gz
    RUN tar -zxvf helm-v3.1.2-linux-amd64.tar.gz
    RUN mv ./linux-amd64/helm /usr/local/bin/helm

    jnlp的镜像就是官方提供的镜像,如果自己需要添加自定义的工具可以自行构建Dockerfile

    以上四个容器,就作为流水线中的不同的部分对共有的jenkins workspace进行相应的操作。

  1. 使用Jenkins 的credential的机制,存储敏感数据,避免明文配置和运行。这里我们用到的是用户名密码以及SecretFile的方式。存储的是docker仓库的用户名密码以及kubeconfig文件。建议不要使用明文进行配置。

    withCredentials([usernamePassword(credentialsId: 'nexus-docker', passwordVariable: 'PASSWORD', usernameVariable: 'USERNAME')])
    withCredentials([file(credentialsId: 'k3s-kubeconfig', variable: 'KUBECONFIG')])
  2. 使用helm部署的方式部署应用,可以根据自己的需要打包成helm包,然后上传到helm仓库中,在jenkinsfile中指定相应的helm包即可。同时在声明式语法中也可以使用脚本的语言,例如例子中使用脚本判断是否有helm release已经部署,来决定是否使用helm install命令,否则使用upgrade命令。

    def action
    result = sh returnStatus: true, script: "helm status myproject -n default --kubeconfig $KUBECONFIG"
    if(result == 0){
    action = "upgrade"
    }else{
    action = "install"
    }

总结

本文提供了Jenkins在kubernetes环境中的使用方案,该方案是利用Jenkins kubernetes插件的方式运行流水线,并可以自己动态构建所需要的流水线运行环境。helm对应用进行封装,并暴露出相应的配置用于Jenkins中helm命令的调用。使用withcredential的方式使用Jenkins凭据,减少敏感信息的明文存储。并可以使用groovy脚本配合声明式配置来进行更加复杂的操作。

微信扫一扫,分享到朋友圈

Jenkins 在 kubernetes 中的 DevOps 流水线最佳实践

苹果组装合作伙伴将受益于印度政府的66亿美元生产激励政策

上一篇

研究:地中海饮食+间歇性禁食或是对健康大有益处的饮食组合

下一篇

你也可能喜欢

Jenkins 在 kubernetes 中的 DevOps 流水线最佳实践

长按储存图像,分享给朋友