Jenkins集成Kubernetes实现动态Agent构建机制
之前agent都是运行在k8s node节点上,一般项目更新都是在晚上或者中午,agent只会在更新的时候才会去用,平时一直运行agent也会造成系统的资源浪费,因此可以在Jenkins上集成Kubernetes插件,通过定义Pod模板,当任务开始执行后动态创建一个agent程序,去运行任务,当任务执行完成后,agent也会自动消失。
由于是容器版的agent,肯定有很多工具没有集成在容器里面,因此我们换需要自己制作一个容器,集成丰富的插件
1.Jenkins集成Kubernetes
主要就是安装一个Kubernetes插件,然后配置Kubernetes集群信息,定义agent容器Pod模板,实现创建任务时自动运行一个agent容器
1.1.安装Kubernetes插件
系统管理—>插件管理—>搜索Kubernetes—>直接安装
安装过程很可能会失败,可以尝试多安装几次,最后看到爆黄,重启Jenkins就好了
1.2.进入配置k8s信息以及Pod模板信息页面
1)跳转至Kubernetes插件配置页面
点击系统管理—>cloud—>点击超链接即可调整到配置Kubernetes信息的页面
2)配置集群列表选择Kubernetes
3)点击Kubernetes cloud details进行k8s集群信息配置
1.3.配置Kubernetes集群地址信息
填写kubernetes信息:
kubernetes地址:https://kubernetes.default //访问api的地址,由于Jenkins部署在k8s中可以通过服务发现方式访问api
kubernetes命名空间:jenkins //将来agent运行后存放于哪个命名空间下
填写Jenkins地址信息,声明agent如何连接Jenkins
Jenkins地址:http://jenkins-svc:8080
Jenkins通道:http://jenkins-svc:50000
可以查一下Jenkins的svc资源名称,通过服务发现的方式去连接Jenkins
[root@k8s-master1 ~]# kubectl get svc -n jenkins NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE jenkins-svc NodePort 10.99.113.179 <none> 8080:38080/TCP,50000:50000/TCP 14d
最终样子
1.4.添加pod模板
pod模板就是运行agent pod的模板信息,定义一写agent pod的参数
1)点击Pod Templates
2)点击添加Pod模板
3)填写pod模板名称
名称:jnlp-slave
1.5.配置pod模板信息
这个pod模板其实就是agent容器,无需配置agent镜像地址,他会自己从官方拉取,新版的镜像地址为:jenkins/inbound-agent:4.3-4
1)点击 Pod Template details配置pod模板信息
2)配置pod模板信息
名称:jenkins-slave //jenkins agent pod的名称
命名空间:jenkins //jenkins agent pod所在的命名空间
标签列表:jenkins-slave //jenkins任务可以指定agent的标签,最终运行在这个agent上
用法:尽可能的使用这个节点
指定一个存储卷,持久化agent数据
卷类型选择nfs,填写nfs服务器的地址、提供存储的路径,jenkins会自动生成k8s yaml文件,这个nfs会自动被挂载到agent pod数据存储路径:/home/jenkins/agent,也可以使用pvc存储agent数据
配置完数据卷后,即可点击保存
由于我们将agent的数据持久化了,因此也需要把nfs共享路径的权限调整为agent容器的所属用户,否则无法存储数据
[root@k8s-master2 ~]# cd /data2/k8s/ [root@k8s-master2 /data2/k8s]# mkdir jenkins-agent [root@k8s-master2 /data2/k8s]# chown -R 1000.1000 jenkins-agent
1.6.使用pvc存储agent pod数据(扩展)
1.5中关于agent pod的数据是持久化到nfs中,也可以将agent的数据持久化到pvc里
1.6.1.编写pvc资源yaml文件
apiVersion: v1 kind: PersistentVolume metadata: name: jenkins-agent-pv labels: pv: jenkins-agent-pv spec: capacity: storage: 10Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain nfs: path: /data2/k8s/jenkins-agent-data server: 192.168.16.105 --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: jenkins-agent-pvc namespace: jenkins spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi selector: matchLabels: pv: jenkins-agent-pv
1.6.2.创建pvc资源
[root@k8s-master1 jenkins]# kubectl apply -f jenkins-agent-pvc.yaml
persistentvolume/jenkins-agent-pv create
persistentvolumeclaim/jenkins-agent-pvc create
[root@k8s-master1 jenkins]# kubectl get pv,pvc -n jenkins | grep agent
persistentvolume/jenkins-agent-pv 10Gi RWX Retain Bound jenkins/jenkins-agent-pvc 54m
persistentvolumeclaim/jenkins-agent-pvc Bound jenkins-agent-pv 10Gi RWX 54m
1.6.3.创建pvc存储路径并赋权
[root@k8s-master2 ~]# mkdir /data2/k8s/jenkins-agent-data [root@k8s-master2 ~]# chown -R 1000.1000 /data2/k8s/jenkins-agent-data
1.6.4.配置jenkins pod模板信息使用pvc作为数据存储
jenkins配置k8s集群地址: http://192.168.16.104:38080/configureClouds/
找到pod模板,点击添加卷—>类型为Persistent Volume Claim—>申明值就是pvc的名称—>挂载路径就是要持久化容器的那个路径数据
在找到最下面的工作空间卷,类型选择Persistent Volume Claim Workspace volume,工作空间卷只能添加一个,主要是为agent进行数据持久化的
填写声明值:jenkins-agent-pvc,这个声明值也就是pvc的名称
配置完成后点击保存即可生效
2.调整pipeline脚本使用动态agent去执行任务
2.1.编辑pipeline脚本
仅需要调整使用哪个gaent即可
pipeline { agent { label 'jenkins-slave' } //仅需要调整使用哪个gaent即可 environment { IMAGE_REPO = "harbor.jiangxl.com/project" DINGDING_TOKEN_CREDS = credentials('dingding-token') TAB_STR = "\n \n " } parameters { gitParameter(name: 'VERSION',defaultValue: 'master',type: 'BRANCH',description: '选择要更新的分支') string(name: 'project_namespace',defaultValue: 'know-system',description: '项目所在的命名空间',trim: true) string(name: 'project_kind',defaultValue: 'deployment',description: '项目资源所使用的pod控制器',trim: true) string(name: 'container_name',defaultValue: 'nginx',description: '项目所使用的pod容器名称',trim: true) string(name: 'project',defaultValue: 'know-system',description: '项目名称',trim: true) } stages { stage('运维确认信息') { steps { input message: """ jobname: ${project} branch: ${VERSION}""", ok: "更新" updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success') script { env.BUILD_TASKS = env.STAGE_NAME + " ✅ " + env.TAB_STR } } } stage('拉取项目代码') { steps { checkout([$class: 'GitSCM', branches: [[name: '$VERSION']], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab-root', url: 'http://192.168.16.106:30080/root/know_system.git']]]) updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success') script { env.BUILD_TASKS += env.STAGE_NAME + " ✅ " + env.TAB_STR } } } stage('Dockerfile构建项目镜像') { steps { sh """ echo " FROM harbor.jiangxl.com/project/nginx-project:v1-code RUN mkdir /data/code/know_system COPY ./* /data/code/know_system/ EXPOSE 80 " >Dockerfile """ retry(2) {sh 'docker build -t ${IMAGE_REPO}/${project}:master-v${BUILD_ID} . '} updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success') script { env.BUILD_TASKS += env.STAGE_NAME + " ✅ " + env.TAB_STR } } } stage('推送镜像到Harbor仓库') { steps { sh 'docker push ${IMAGE_REPO}/${project}:master-v${BUILD_ID}' updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success') script { env.BUILD_TASKS += env.STAGE_NAME + " ✅ " + env.TAB_STR } } } stage('更新项目至Kubernetes环境') { steps { sh 'kubectl -n ${project_namespace} set image ${project_kind} ${project} ${container_name}=${IMAGE_REPO}/${project}:master-v${BUILD_ID} --record' updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success') script { env.BUILD_TASKS += env.STAGE_NAME + " ✅ " + env.TAB_STR } } } } post { success { echo "构建成功,发送消息到钉钉" sh """ curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGDING_TOKEN_CREDS_PSW}' \ -H 'Content-Type: application/json' \ -d '{ "msgtype": "markdown", "markdown": { "title":"project", "text": "??构建成功?? \n\n 关键字: jenkins \n\n 项目名称: ${JOB_BASE_NAME} \n\n 更新的分支号: ${VERSION} \n\n 本次构建的镜像版本: ${IMAGE_REPO}/${project}:master-v${BUILD_ID} \n\n 构建地址: ${RUN_DISPLAY_URL} \n\n 阶段任务状态: ${BUILD_TASKS}" } }' """ } failure { echo "构建失败,发送消息到钉钉" sh """ curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGDING_TOKEN_CREDS_PSW}' \ -H 'Content-Type: application/json' \ -d '{ "msgtype": "markdown", "markdown": { "title":"project", "text": "?❌ 构建失败 ❌? \n\n 关键字: jenkins \n\n 项目名称: ${JOB_BASE_NAME} \n\n 更新的分支号: ${VERSION} \n\n 本次构建的镜像版本: ${IMAGE_REPO}/${project}:master-v${BUILD_ID} \n\n 构建地址: ${RUN_DISPLAY_URL} \n\n 阶段任务状态: ${BUILD_TASKS}" } }' """ } always { echo "构建流程结束" } } }
2.2.将pipeline粘贴到jenkins中
2.3.构建任务观察效果
1)填写更新信息点击开始构建
2)观察jenkins输出日志
3)查看k8s中jenkins命名空间是否有agent pod产生
可以看到在jenkins名称空间下多了一个jenkins-slave-s3vh2 pod资源,jenkins任务由这个agent去完成
4)查看jenkins任务的构建状态
我们的agent不再是部署在k8s node节点上,因此不再具备集成docker、k8s的命令
jenkins agent使用的容器是 jenkins/inbound-agent:4.3-4,这个容器仅仅只是与k8s master建立了连接,其内部并没有集成docker命令、k8s命令,因此就会导致我们任务构建失败
2.5.查看agent pod产生的数据
#jenkins数据都存储在workspace里,这个路径是pvc的挂载路径
[root@k8s-master2 ~]# ll /data2/k8s/jenkins-agent-data/ 总用量 0 drwxr-xr-x 3 www www 26 6月 4 14:48 caches drwxr-xr-x 4 www www 34 6月 4 14:47 remoting drwxr-xr-x 4 www www 64 6月 4 14:48 workspace
3.解决agent容器没有集成部署命令的问题
3.1.问题分析
jenkins agent使用的容器是 jenkins/inbound-agent:4.3-4,这个容器仅仅只是与k8s master建立了连接,其内部并没有集成docker命令、k8s命令,因此就会导致我们任务构建失败
我们想要解决此种问题,不光单单针对k8s、docker环境,就要将我们需要用到的命令工具全部集成到pod的容器内
将这些工具全都集成到jnlp容器中显然有些不合理,可以想一下k8s pod的机制,一个pod最多可以有4个容器,我们可以手动制作一个容器放到pod模板中,然后再修改pipeline脚本,哪一个阶段需要用到命令工具了,我们就给他指定这个阶段采用什么容器去执行
将命令工具集成到agent容器内也需要考虑以下因素:
- 是否可以创建一个新的容器,让新的容器来做具体的任务,agent容器只负责连接jenkins服务
- 是否可以针对不同的构建环境(java、python、go、nodejs),制作不同的容器,在pipeline中针对阶段任务构建环境的不同就调用不同的容器去执行任务
制作容器注意的点:
动态Agent机制是靠一个Agent容器与Jenkins服务端建立连接,然后所有的构建操作都由一个专门集成构建环境工具的容器去操作。
关于制作容器要考虑的工具范围和注意点:
1)容器底层系统镜像采用centos7,虽然容器体积大了点但是功能及其丰富;
2)配置阿里云yum镜像源,用于安置环境工具;
3)需要使用docker命令构建镜像,安装docker环境,并挂载节点的docker.sock文件;
4)需要拉取Gitlab上的程序代码,安装Git工具;
5)需要使用Maven编译程序代码,安装Maven、Jdk工具;
6)需要将编译好的war包进行测试,安装tomcat环境,如果不需要测试可以不安装;
7)需要将程序部署在K8S集群,需要将kubectl命令复制到容器里;
8)使用kubectl命令需要kubeconfig认证才可使用,需要将Master节点的.kube目录拷贝至容器;
9)由于本容器还需要连接Harbor推送镜像以及使用kubectl的kubeconfig文件,因此需要在容器的hosts文件中增加Harbor仓库的地址解析以及K8S APIServer的域名地址解析。
由于kubectl命令会去找apiserver的域名,因此还需要配一个hosts,在Dockerfile中无法配置hosts,因此可以自己写一个hosts文件,然后在entrypoint脚本中是由于cat方式再重定向到/etc/hosts
3.2.1.准备软件
准备tomcat、kubectl命令、kubectl证书文件、entryporint、Dockerfile容器启动脚本
[root@k8s-node2 ~/docker-image/docker-jnlp]# ll
总用量 51096
-rw-r--r-- 1 root root 9353658 3月 24 2017 apache-tomcat-8.5.12.tar.gz
-rw------- 1 root root 5583 6月 4 16:59 config
-rw-r--r-- 1 root root 867 6月 7 11:40 Dockerfile
-rwxr-xr-x 1 root root 79 6月 7 11:37 entryporint.sh
-rwxr-xr-x 1 root root 42950656 6月 4 16:59 kubectl
3.2.2.准备entrypoint启动脚本
entrypoint.sh脚本中主要组成包括加载/etc/profile、启动Tomcat、将K8S Apiserver、Harbor仓库的域名地址解析写到hosts文件、追踪Tomcat的日志夯筑容器。
关于如何将解析写到hosts文件的思路:自己手动写一个hosts文件,再Dockerfile中定义COPY,将hosts文件拷贝到/tmp目录中,然后在通过cat+重定向的方式将其输出到/etc/hosts
hosts文件里需要增加harbor的地址解析和k8s api地址的解析
1.准备hosts文件
[root@k8s-node2 ~/docker-image/docker-jnlp]# vim hosts
192.168.16.106 apiserver.cluster.local
192.168.16.106 harbor.jiangxl.com
2.准备entrypoint脚本
[root@k8s-node2 ~/docker-image/docker-jnlp]# vim entrypoint.sh
#!/bin/bash
source /etc/profile
/data/tomcat/bin/startup.sh
cat /tmp/hosts >> /etc/hosts
tail -f /data/tomcat/logs/catalina.out
3.2.3.编写Dockerfile
注意:Dockerfile关于安装docker命令不要使用epel源去安装,要下载docker官方的源,安装docker-ce,安装完docker-ce之后,docker命令的版本就是高版本,低版本的docker命令在使用docker push的时候会报错
FROM centos:centos7.5.1804
#准备yum源,安装docker、jdk、maven等必要软件
RUN rm -rf /etc/yum.repos.d/* && curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo ;curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && yum -y install git curl tar bash vim java net-tools
#安装docker
RUN curl -o /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo && yum -y install --setopt=obsoletes=0 docker-ce-19.03.0-3.el7
#安装maven jdk
COPY jdk1.8.tar.gz /usr/local
COPY apache-maven-3.3.9.tar /usr/local/
RUN tar xf /usr/local/jdk1.8.tar.gz -C /usr/local/ && tar xf /usr/local/apache-maven-3.3.9.tar -C /usr/local/ && echo -e "export JAVA_HOME=/usr/local/jdk1.8.0_131 \nexport MVN_HOME=/usr/local/apache-maven-3.3.9 \nexport PATH=\$PATH:\$JAVA_HOME/bin:\$MVN_HOME/bin" >> /etc/profile && echo "source /etc/profile" >> ~/.bashrc
COPY settings.xml /usr/local/apache-maven-3.3.9/conf/settings.xml
#准备kubectl认证文件目录
RUN mkdir /root/.kube
#将kubectl认证文件上传到容器里对应的目录
COPY .kube /root/.kube
#将kubectl目录上传至容器
COPY kubectl /usr/local/bin
RUN chmod a+x /usr/local/bin/kubectl
#部署tomcat
RUN mkdir /data/soft -p
COPY apache-tomcat-8.5.12.tar.gz /data/soft
RUN tar xf /data/soft/apache-tomcat-8.5.12.tar.gz -C /data && mv /data/apache-tomcat-8.5.12 /data/tomcat && rm -rf /data/tomcat/webapps/*
COPY hosts /tmp/hosts
COPY entrypoint.sh /data/
ENTRYPOINT ["/bin/bash","/data/entrypoint.sh"]
3.2.4.构建容器并启动查看工具是否可用
1.构建镜像
[root@k8s-node2 ~/docker-image/docker-jnlp]# docker build -t harbor.jiangxl.com/jenkins/build-tools:v1 .
2.启动镜像
[root@k8s-node2 ~/docker-image/docker-jnlp]# docker run -itd -v /var/run/docker.sock:/var/run/docker.sock harbor.jiangxl.com/jenkins/build-tools:v1
a2a962d3ead1a7cef29b6ac837a19869c83c609fa953449418b3dbf42bdd01c0
3.进入容器验证工具是否可用
[root@f3adc78e4d3a /]# java -version
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
[root@f3adc78e4d3a /]# mvn -v
ache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-10T16:41:47+00:00)
Maven home: /usr/local/apache-maven-3.3.9
Java version: 1.8.0_131, vendor: Oracle Corporation
Java home: /usr/local/jdk1.8.0_131/jre
Default locale: en_US, platform encoding: ANSI_X3.4-1968
OS name: "linux", version: "3.10.0-862.el7.x86_64", arch: "amd64", family: "unix"
[root@f3adc78e4d3a /]# netstat -lnpt | grep java
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 28/java
tcp 0 0 127.0.0.1:8005 0.0.0.0:* LISTEN 28/java
tcp 0 0 0.0.0.0:8009 0.0.0.0:* LISTEN 28/java
[root@a2a962d3ead1 /]# docker -v
Docker version 20.10.7, build f0df350
[root@a2a962d3ead1 /]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master1 Ready master 30d v1.19.6
k8s-master2 Ready master 30d v1.19.6
k8s-node1 Ready <none> 30d v1.19.6
k8s-node2 Ready <none> 30d v1.19.6
3.2.5.推送镜像到harbor仓库
将工具镜像和agent镜像都推送至harbor仓库
[root@k8s-node2 ~]# docker push harbor.jiangxl.com/jenkins/build-tools:v1
4.重新配置集群中Pod模板添加容器
我们刚刚手动制作了一个集成所有工具的docker镜像,需要把这个镜像添加到pod模板中的容器列表,然后让pipeline脚本调用
jenkins中的k8s集群配置,旧版本
(默认新加了容器列表就会把原来默认的jnlp agent容器给覆盖掉,所以再添加了工具容器之后还需要再把jnlp容器在容器列表中重新添加一下)新版本
(新版本已经没有这个缺陷,只需要增加一个工具容器就可以让pipeline部分阶段任务由指定的工具容器去完成,连接k8s master还是让默认的jnlp agent容器去做)
4.1.添加工具容器
http://192.168.16.104:38080/configureClouds/这个链接下,找到pod模板—>容器列表—>添加容器
名称:jenkins-build
Docker镜像:harbor.jiangxl.com/jenkins/build-tools:v1
工作目录:/home/jenkins/agent #工作目录与agent容器保持一致
运行的命令和命令参数都设置为空,否则会覆盖我们制作的启动命令
4.2.添加agent容器(旧版需要这样做)
老版的jenkins需要再声明一次agent容器,因为工具容器会将pod模板的容器给覆盖,所以需要在容器列表再声明agent容器,新版本2.277则无需再声明agent镜像
还是在容器列表—>添加容器,agent容器就需要配置命令参数了
名称:jenkins-slave
Docker镜像:harbor.jiangxl.com/jenkins/inbound-agent:4.3-4
运行的命令:/bin/sh -c
命令参数:jenkins-slave
4.3.添加卷为数据提供持久化
我们需要把docker.sock文件挂载到pod中,也需要为/home/jenkins/agent路径进行数据持久化
/home/jenkins/agent下的数据使用在1.6中定义的pvc进行存储即可,docker.sock文件通过hostpath的方式挂载本地的文件到pod中
5.优化pipeline脚本指定阶段任务运行在指定的容器
我们在pod模板中定义了容器列表,其中包含一个集成所有构件工具的容器,我们的阶段任务都依赖某些工具,所以要把每个阶段任务让指定的工具容器去运行
5.1.优化pipeline脚本
主要是在stage里增加一个container(‘容器名’){具体的任务},让指定的容器去运行执行的阶段任务
pipeline {
agent { label 'jenkins-slave' }
environment {
IMAGE_REPO = "harbor.jiangxl.com/project"
DINGDING_TOKEN_CREDS = credentials('dingding-token')
TAB_STR = "\n \n "
}
parameters {
gitParameter(name: 'VERSION',defaultValue: 'master',type: 'BRANCH',description: '选择要更新的分支')
string(name: 'project_namespace',defaultValue: 'know-system',description: '项目所在的命名空间',trim: true)
string(name: 'project_kind',defaultValue: 'deployment',description: '项目资源所使用的pod控制器',trim: true)
string(name: 'container_name',defaultValue: 'nginx',description: '项目所使用的pod容器名称',trim: true)
string(name: 'project',defaultValue: 'know-system',description: '项目名称',trim: true)
}
stages {
stage('运维确认信息') {
steps {
input message: """
jobname: ${project}
branch: ${VERSION}""", ok: "更新"
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script {
env.BUILD_TASKS = env.STAGE_NAME + " ✅ " + env.TAB_STR
}
}
}
stage('拉取项目代码') {
steps {
container('jenkins-build'){
checkout([$class: 'GitSCM', branches: [[name: '$VERSION']], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab-root', url: 'http://192.168.16.106:30080/root/know_system.git']]])
} //由pod模板中的jenkins-build这个容器去运行checkout任务
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script {
env.BUILD_TASKS += env.STAGE_NAME + " ✅ " + env.TAB_STR
}
}
}
stage('Dockerfile构建项目镜像') {
steps {
container('jenkins-build'){
sh """
echo "
FROM harbor.jiangxl.com/project/nginx-project:v1-code
RUN mkdir /data/code/know_system
COPY ./* /data/code/know_system/
EXPOSE 80
" >Dockerfile
"""
retry(2) {sh 'docker build -t ${IMAGE_REPO}/${project}:master-v${BUILD_ID} . '}
} //工具镜像里继承了docker命令,由pod模板中的jenkins-build这个容器去运行构建镜像的任务
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script {
env.BUILD_TASKS += env.STAGE_NAME + " ✅ " + env.TAB_STR
}
}
}
stage('推送镜像到Harbor仓库') {
steps {
container('jenkins-build'){
sh 'docker login -u admin -p admin $IMAGE_REPO'
sh 'docker push ${IMAGE_REPO}/${project}:master-v${BUILD_ID}'
} //工具镜像里继承了docker命令,由pod模板中的jenkins-build这个容器去运行推送镜像的任务
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script {
env.BUILD_TASKS += env.STAGE_NAME + " ✅ " + env.TAB_STR
}
}
}
stage('更新项目至Kubernetes环境') {
steps {
container('jenkins-build'){
sh 'kubectl -n ${project_namespace} set image ${project_kind} ${project} ${container_name}=${IMAGE_REPO}/${project}:master-v${BUILD_ID} --record'
} //工具镜像里继承了kubelet命令,由pod模板中的jenkins-build这个容器去运行升级的任务
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script {
env.BUILD_TASKS += env.STAGE_NAME + " ✅ " + env.TAB_STR
}
}
}
}
post {
success {
echo "构建成功,发送消息到钉钉"
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGDING_TOKEN_CREDS_PSW}' \
-H 'Content-Type: application/json' \
-d '{
"msgtype": "markdown",
"markdown": {
"title":"project",
"text": "??构建成功?? \n\n 关键字: jenkins \n\n 项目名称: ${JOB_BASE_NAME} \n\n 更新的分支号: ${VERSION} \n\n 本次构建的镜像版本: ${IMAGE_REPO}/${project}:master-v${BUILD_ID} \n\n 构建地址: ${RUN_DISPLAY_URL} \n\n 阶段任务状态: ${BUILD_TASKS}"
}
}'
"""
}
failure {
echo "构建失败,发送消息到钉钉"
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGDING_TOKEN_CREDS_PSW}' \
-H 'Content-Type: application/json' \
-d '{
"msgtype": "markdown",
"markdown": {
"title":"project",
"text": "?❌ 构建失败 ❌? \n\n 关键字: jenkins \n\n 项目名称: ${JOB_BASE_NAME} \n\n 更新的分支号: ${VERSION} \n\n 本次构建的镜像版本: ${IMAGE_REPO}/${project}:master-v${BUILD_ID} \n\n 构建地址: ${RUN_DISPLAY_URL} \n\n 阶段任务状态: ${BUILD_TASKS}"
}
}'
"""
}
always {
echo "构建流程结束"
}
}
}
5.2.构建任务观察agent pod的状态
1)填写构建信息,然后点击构建任务
2)观察任务构建日志查看agent容器是否启动
看到jenkins在k8s上启动了一个名为jenkins-slave-00nh9的容器
3)agent容器在k8s集群成功启动
只要agent pod成功运行,pod中的build容器就开始构建任务了
4)点击运维确认信息
5)任务构建成功
6)agent pod自动销毁
当jenkins任务构建结束后,agent pod会自动销毁,避免资源浪费
7)钉钉消息发送成功
baron
pipeline里的很多stage都是在一个容器里执行的吧,都是串行的还好,我其实想请教下如何实现并行的几个stage,用同一个容器模板生成多个容器
麦小轮
使用--- 隔开在一个文件里面继续写下一个容器