阿里云Kubernetes服务上搭建jenkins环境并完成应用构建到部署的流水线作业-阿里云开发者社区

开发者社区> 阿里云容器服务 ACK> 正文
登录阅读全文

阿里云Kubernetes服务上搭建jenkins环境并完成应用构建到部署的流水线作业

简介: 本文主要演示如何在阿里云Kubernetes服务上快速搭建jenkins持续集成环境,并基于提供的示例应用快速完成应用源码编译、镜像构建和推送以及应用部署的流水线。

本文主要演示如何在阿里云Kubernetes服务上快速搭建jenkins持续集成环境,并基于提供的示例应用快速完成应用源码编译、镜像构建和推送以及应用部署的流水线。

先决条件:
阿里云Kubernetes集群。

建议: 建议用户先按照以下文档安装部署ack-jenkins应用, 然后成功运行构建任务示例demo-pipeline, 再依照此构建任务示例改造自己的构建任务配置。

1. 快速部署ack-jenkins

容器服务-Kubernetes -> 市场 -> 应用目录 -> ack-jenkins:

image

点击 参数 菜单修改 AdminPassword 字段, 选择Kubernetes集群、填写命名空间发布名称并点击 创建

image

访问jenkins服务并登陆:
image

image

ps:如未设置登陆密码,则可在部署完毕后使用如下命名查看:

$ printf $(kubectl get secret --namespace ci jenkins-ci-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo

2. 配置 Kubernetes Cloud

2.1 配置 Kubernetes Cloud

Jenkins使用Kubernetes Plugin连接Kubernetes集群并动态生成和释放slave pod,关于slave pod的模板配置需要在 系统管理 -> 系统配置 -> 云 中进行配置

  • 名称:kubernetes;
  • Kubernetes 地址:https://kubernetes.default.svc.cluster.local:443;jenkins 系统安装在当前集群中,可以使用内部服务端点访问集群的 API Server
  • Kubernetes 命名空间:jenkins;动态 slave pod 会在命名空间 jenkins 下生成和销毁
    点击 测试 按钮验证连接无误:

image.png

  • Jenkins 地址:http://ack-jenkins-default:8080;slave pod连接jenkins master使用的服务端点
  • Jenkins 通道:ack-jenkins-default-agent:50000;slave pod使用jnlp连接jenkins master
    image.png
  • Pod Templates -> 名称: slave-pipeline; slave pod名称
  • Pod Templates -> 命名空间:jenkins
  • Pod Templates -> 标签列表:slave-pipeline;jenkins 构建任务通过此标签选择使用哪个模板生成slave pod
    image.png
  • Pod Templates -> 容器列表 -> jnlp;用于jnlp连接jenkins master
    image.png
  • Pod Templates -> 容器列表 -> kaniko;用于构建和推送容器镜像
    image.png
  • Pod Templates -> 容器列表 -> maven:用于maven构建和打包应用
    image.png
  • Pod Templates -> 容器列表 -> kubectl:用于kubectl命令行部署应用
    image.png
  • Pod Templates -> 环境变量;为kaniko设置DOCKER_CONFIG指定docker.json文件路径
    创建jenkins-docker-cfg secret用于镜像仓库权限设置

本示例中使用了阿里云镜像服务提供的杭州区域镜像仓库:

$ docker login -u xxx -p xxx registry-vpc.cn-beijing.aliyuncs.com
Login Succeeded
$ kubectl create secret generic jenkins-docker-cfg -n ci --from-file=/root/.docker/config.json

配置slave pod启动时挂载 secret jenkins-docker-cfg:
image.png

如果需要设置maven缓存目录,可以挂载hostPath volume 或者共享存储卷到/root/.m2/repository:
image.png

如果需要更改 settings.xml,先创建 ConfigMap:

kubectl create configmap maven-config --from-file=settings.xml -n jenkins

再配置挂载到slave pod:
image.png

如果需要部署应用到本集群,可以在slave pod中使用ServiceAccount通过kubectl部署,配置ServiceAccount:
image.png

2.2 创建构建任务

创建构建任务cicd-pipeline,拉取源码项目https://github.com/haoshuwei/jenkins-demo.git,分支master;maven打包构建,kaniko构建和推送容器镜像;kubectl部署到本集群。
在本示例中,需要打包容器镜像为:registry-vpc.cn-beijing.aliyuncs.com/haoshuwei24/application-demo:20200915
则配置构建参数如下:
image.png
构建任务配置如下:
image.png
执行构建:
image.png
可以在 https://github.com/haoshuwei/jenkins-demo.git 中查看Jenkinsfile内容。

3 连接外部集群

连接外部集群需要创建和使用证书
示例:创建k8sCertAuth证书
在此步骤中,我们需要先创建和配置一个名称为k8sCertAuth的集群证书, 点击 凭证 添加证书:
image
image
image
保存。

3. 详解构建任务示例demo-pipeline

demo-pipeline 构建任务完成的持续集成/持续交付任务为:拉取源码、构建应用war包、打包和推送容器镜像以及部署应用到k8s集群。示例源码项目地址为https://github.com/AliyunContainerService/jenkins-demo.git , 整个构建流程会按照示例项目中Jenkinsfile声明的内容执行构建。

3.1 demo-pipeline的任务配置

demo-pipeline设置了4个构建参数,分别为origin_repo repo image_tagbranchbranch 用于指定本次构建拉取应用源码仓库的哪个分支, 另外3个变量用于构建和推送应用容器镜像的地址,例如示例应用的容器镜像要推送到 registry.cn-hangzhou.aliyuncs.com/ack-cicd/ack-jenkins-demo:latest, 则origin_reporegistry.cn-hangzhou.aliyuncs.com/ack-cicd, repoack-cicd,image_taglatest
image

构建任务中配置从Git仓库拉取源码并指定Jenkinsfile路径:
image

3.2 Jenkinsfile解析

我们在示例源码项目的Jenkinsfilejenkins-demo/Jenkinsfile中定义了以下内容:

pipeline{
      // 定义groovy脚本中使用的环境变量
      environment{
        // 将构建任务中的构建参数转换为环境变量
        IMAGE_TAG =  sh(returnStdout: true,script: 'echo $image_tag').trim()
        ORIGIN_REPO =  sh(returnStdout: true,script: 'echo $origin_repo').trim()
        REPO =  sh(returnStdout: true,script: 'echo $repo').trim()
        BRANCH =  sh(returnStdout: true,script: 'echo $branch').trim()
      }

      // 定义本次构建使用哪个标签的构建环境,本示例中为 “slave-pipeline”
      agent{
        node{
          label 'slave-pipeline'
        }
      }

      // "stages"定义项目构建的多个模块,可以添加多个 “stage”, 可以多个 “stage” 串行或者并行执行
      stages{
        // 定义第一个stage, 完成克隆源码的任务
        stage('Git'){
          steps{
            git branch: '${BRANCH}', credentialsId: '', url: 'https://github.com/AliyunContainerService/jenkins-demo.git'
          }
        }

        // 添加第二个stage, 运行源码打包命令
        stage('Package'){
          steps{
              container("maven") {
                  sh "mvn package -B -DskipTests"
              }
          }
        }


        // 添加第三个stage, 运行容器镜像构建和推送命令, 用到了environment中定义的groovy环境变量
        stage('Image Build And Publish'){
          steps{
              container("kaniko") {
                  sh "kaniko -f `pwd`/Dockerfile -c `pwd` --destination=${ORIGIN_REPO}/${REPO}:${IMAGE_TAG} --skip-tls-verify"
              }
          }
        }

        // 添加第四个stage, 部署应用到指定k8s集群
        stage('Deploy to Kubernetes') {
            parallel {
                    steps {
                        container('kubectl') {
                            step([$class: 'KubernetesDeploy', authMethod: 'certs', apiServerUrl: 'https://kubernetes.default.svc.cluster.local:443', credentialsId:'k8sCertAuth', config: 'deployment.yaml',variableState: 'ORIGIN_REPO,REPO,IMAGE_TAG'])
                        }
                    }
            }
        }
      }
}
3.2.1 environment{} 代码块

用于获取构建参数并转换为Jenkinsfile中使用的环境变量。

3.2.2 agent{} 代码块

用于指定本次构建使用的构建节点标签为slave-pipeline。 进入 系统管理 -> 系统设置 -> 云 可以看到Kubernetes云的配置, 此配置用于定义如何动态创建构建节点:
image
image
image
image

我们可以从上图的Kubernetes云配置中看到, 当我们执行构建任务时,jenkins会动态连接本集群的api server url:https://kubernetes.default.svc.cluster.local:443jenkins 命名空间下创建 slave pod slave-pipeline-xxx, 此slave pod包含4个containers, 分别为用于slave连接master的jnlp、用于maven编译打包java源码的maven、用于容器镜像构建和部署的kaniko以及用于部署k8s应用的kubectl

当使用kaniko容器进行容器镜像构建和推送时, 我们需要获取镜像推送到仓库的权限, 这个权限是以k8s secret的方式挂载到slave-pipeline-xxx的pod里的,环境变量DOCKER_CONFIG则定义了kaniko获取镜像仓库推送权限文件的默认路径。 在此我们需要创建名为jenkins-docker-cfg的secret:

在一台linux机器上执行以下命令:

$ docker login -u xxx -p xxx registry.cn-hangzhou.aliyuncs.com
$ kubectl create secret generic jenkins-docker-cfg -n ci --from-file=/root/.docker/config.json
3.2.3 stages{}代码块

stages{}代码块定义了多个stage,分别完成持续集成/持续部署过程中的不同步骤。

3.2.3.1 源码拉取

源码仓库中一般包含Jenkinsfile Dockerfile deployment.yaml等文件

stage('Git'){
  steps{
    git branch: '${BRANCH}', credentialsId: '', url: 'https://github.com/AliyunContainerService/jenkins-demo.git'
  }
}
3.2.3.2 maven编译和打包源码

maven编译的时候,用户通常会想使用缓存功能, maven缓存需要使用NAS共享存储,创建nas volume并挂载到Kubernetes云的slave-pipeline模板上, 类似jenkins-docker-cfg的挂载。

stage('Package'){
  steps{
    container("maven") {
      sh "mvn package -B -DskipTests"
    }
  }
}
3.2.3.3 kaniko构建和推送镜像

kaniko工具构建容器镜像可以不依赖docker daemon进程,在用户态空间完成镜像构建和推送, 更安全可靠。

stage('Image Build And Publish'){
  steps{
    container("kaniko") {
      sh "kaniko -f `pwd`/Dockerfile -c `pwd` --destination=${ORIGIN_REPO}/${REPO}:${IMAGE_TAG} --skip-tls-verify"
    }
  }
}
3.2.3.4 kubectl部署k8s应用
stage('Deploy to Kubernetes') {
  steps {
    container('kubectl') {
      step([$class: 'KubernetesDeploy', authMethod: 'certs', apiServerUrl: 'https://kubernetes.default.svc.cluster.local:443', credentialsId:'k8sCertAuth', config: 'deployment.yaml',variableState: 'ORIGIN_REPO,REPO,IMAGE_TAG'])
    }
  }
}

在此步骤中,我们需要先创建和配置一个名称为k8sCertAuth的集群证书, 点击 凭证 添加证书:
image
image
image
保存。

variableState: 'ORIGIN_REPO,REPO,IMAGE_TAG' 字段声明需要替换deployment.yaml文件中的哪些环境变量。

4. 系统配置详解

4.1 构建环境配置说明

(1)kubernetes集群动态分配构建pod的配置;
image

(2)slave-pipeline 使用了4个container分别完成流水线中各个stage的构建,Kubernetes Pod Templates配置

container jnlp:
image
container kaniko:
image
container kubectl:
image
container maven:
image

(3) 使用到的构建镜像:

  • jnlp 用于构建节点jnlp连接master:

    jenkinsci/jnlp-slave:3.35-5
  • maven 用于mvn打包构建:

     maven:3.6.2-jdk-14
  • kaniko 用于镜像构建和推送:

    registry.cn-hangzhou.aliyuncs.com/acs/kaniko:v0.14.0
  • kubectl 用于kubectl部署应用:

    registry.cn-hangzhou.aliyuncs.com/acs/kubectl:1.14.8

    (4) kaniko配置镜像仓库权限:

image

4.2 示例项目说明

(1)示例项目中使用的源码仓库

https://github.com/AliyunContainerService/jenkins-demo.git

(2)kaniko 构建和推送docker镜像说明

kaniko可以不依赖docker daemon并在用户空间执行完成Dockerfile中的每一行命令,最终完成docker镜像的构建和推送。

kaniko -f `pwd`/Dockerfile -c `pwd` --destination=${origin_repo}/${repo}:${image_tag}

(3)部署应用到Kubernetes集群插件说明

插件配置如下:
image

对应的Pipeline语法为:

step([$class: 'KubernetesDeploy', authMethod: 'certs', apiServerUrl: 'https://kubernetes.default.svc.cluster.local:443', credentialsId:'k8sCertAuth', config: 'deployment.yaml',variableState: 'ORIGIN_REPO,REPO,IMAGE_TAG'])

声明的变量ORIGIN_REPO,REPO,IMAGE_TAG可在构建执行时把deployment.yaml文件中对应的变量值替换为实际值:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: jenkins-java-demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: jenkins-java-demo
  template:
    metadata:
      labels:
        app: jenkins-java-demo
    spec:
      containers:
      - name: jenkins-java-demo
        image: ${ORIGIN_REPO}/${REPO}:${IMAGE_TAG}
        imagePullPolicy: Always
        ports:
        - containerPort: 8080

---
apiVersion: v1
kind: Service
metadata:
  name: jenkins-java-demo
spec:
  ports:
  - port: 80
    targetPort: 8080
    name: jenkins-java-demo
  selector:
    app: jenkins-java-demo
  type: LoadBalancer

(4)Jenkinsfile说明

pipeline{
      // 定义groovy脚本中使用的环境变量
      environment{
        // 本示例中使用DEPLOY_TO_K8S变量来决定把应用部署到哪套容器集群环境中,如“Production Environment”, “Staging001 Environment”等
        IMAGE_TAG =  sh(returnStdout: true,script: 'echo $image_tag').trim()
        ORIGIN_REPO =  sh(returnStdout: true,script: 'echo $origin_repo').trim()
        REPO =  sh(returnStdout: true,script: 'echo $repo').trim()
        BRANCH =  sh(returnStdout: true,script: 'echo $branch').trim()
      }

      // 定义本次构建使用哪个标签的构建环境,本示例中为 “slave-pipeline”
      agent{
        node{
          label 'slave-pipeline'
        }
      }

      // "stages"定义项目构建的多个模块,可以添加多个 “stage”, 可以多个 “stage” 串行或者并行执行
      stages{
        // 定义第一个stage, 完成克隆源码的任务
        stage('Git'){
          steps{
            git branch: '${BRANCH}', credentialsId: '', url: 'https://github.com/AliyunContainerService/jenkins-demo.git'
          }
        }

        // 添加第二个stage, 运行源码打包命令
        stage('Package'){
          steps{
              container("maven") {
                  sh "mvn package -B -DskipTests"
              }
          }
        }


        // 添加第四个stage, 运行容器镜像构建和推送命令, 用到了environment中定义的groovy环境变量
        stage('Image Build And Publish'){
          steps{
              container("kaniko") {
                  sh "kaniko -f `pwd`/Dockerfile -c `pwd` --destination=${ORIGIN_REPO}/${REPO}:${IMAGE_TAG}"
              }
          }
        }


        stage('Deploy to Kubernetes') {
            parallel {
                stage('Deploy to Production Environment') {
                    when {
                        expression {
                            "$BRANCH" == "master"
                        }
                    }
                    steps {
                        container('kubectl') {
                            step([$class: 'KubernetesDeploy', authMethod: 'certs', apiServerUrl: 'https://kubernetes.default.svc.cluster.local:443', credentialsId:'k8sCertAuth', config: 'deployment.yaml',variableState: 'ORIGIN_REPO,REPO,IMAGE_TAG'])
                        }
                    }
                }
                stage('Deploy to Staging001 Environment') {
                    when {
                        expression {
                            "$BRANCH" == "latest"
                        }
                    }
                    steps {
                        container('kubectl') {
                            step([$class: 'KubernetesDeploy', authMethod: 'certs', apiServerUrl: 'https://kubernetes.default.svc.cluster.local:443', credentialsId:'k8sCertAuth', config: 'deployment.yaml',variableState: 'ORIGIN_REPO,REPO,IMAGE_TAG'])
                        }
                    }
                }
            }
        }
      }
    }

了解更多阿里云容器服务内容,请访问 https://www.aliyun.com/product/containerservice
了解更多kaniko内容请参考:
https://github.com/GoogleContainerTools/kaniko

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
阿里云容器服务 ACK
使用钉钉扫一扫加入圈子
+ 订阅

云端最佳容器应用运行环境,安全、稳定、极致弹性

官方博客
官网链接