jenkins对接k8s集群
先跳过本节操作
- 自由风格
- 流水线
- 多分支流水线
本节学习内容
- Jenkins可以通过Kubernetes插件与Kubernetes集群进行对接。首先,在Jenkins的全局配置中,你需要配置Kubernetes云的相关信息,包括Kubernetes API服务器的地址、凭据、命名空间等。然后,在Jenkins Pipeline中,你可以使用
kubernetes关键字来定义在Kubernetes集群中执行的代理节点。这样,Jenkins将使用Kubernetes插件自动创建和管理这些代理节点,以执行Pipeline中的任务和步骤。 - 使用Kubernetes的
Pod模板作为动态代理节点是一种常见的做法。在Jenkins Pipeline中,你可以使用podTemplate关键字定义一个Pod模板,其中包含了代理节点的配置,如镜像、环境变量、卷挂载等。然后,你可以在Pipeline中使用agent指令来指定使用这个Pod模板作为代理节点,例如agent { kubernetes { label 'mypodtemplate' } }。这样,当Pipeline执行时,Jenkins将根据需要动态创建Pod,并在Pod中运行代理节点来执行任务。 - 要制作不同类型的业务集成的代理容器,你可以创建自定义的Docker镜像。首先,创建一个包含所需工具和依赖的基础镜像。然后,根据不同类型的业务需求,构建定制的镜像,将业务所需的工具、库和配置文件添加到镜像中。你可以使用Dockerfile来定义构建过程,然后使用Docker构建命令将镜像构建出来。在Jenkins中,你可以使用这个定制的代理容器镜像作为Pipeline中的代理节点,以便执行特定类型的业务集成任务。
- 集成代码扫描、Docker镜像自动构建、Kubernetes服务部署和自动化测试是常见的DevOps流程。在Jenkins中,你可以使用各种插件和工具来实现这些集成:
- 代码扫描:可以使用静态代码分析工具的Jenkins插件,如SonarQube插件,将代码扫描集成到Pipeline中,实现自动化的代码质量分析和报告生成。
- Docker镜像自动构建:可以使用Docker插件或者Docker Pipeline插件,在Pipeline中定义Docker构建步骤,自动构建、打标签和推送Docker镜像到镜像仓库。
- Kubernetes服务部署:可以使用Kubernetes插件,在Pipeline中使用Kubernetes资源定义文件(如Deployment、Service等)或kubectl命令,实现Kubernetes服务的自动化部署和更新。
- 自动化测试:可以使用各种测试框架和工具,在Pipeline中定义测试步骤,如单元测试、集成测试、端到端测试等。你可以使用相应的Jenkins插件或命令
kubernetes插件
https://plugins.jenkins.io/kubernetes/
Kubernetes Plugin是Jenkins的一个插件,它提供了与Kubernetes集群进行集成的功能。该插件允许Jenkins与Kubernetes集群交互,以动态地创建和管理Kubernetes Pod作为构建代理节点。
Kubernetes Plugin的主要功能包括:
- 动态代理节点:该插件允许Jenkins自动在Kubernetes集群中创建Pod,作为构建的代理节点。每个构建可以在独立的Pod中运行,以隔离构建环境并提供资源隔离。
- 云配置:插件提供了配置Kubernetes集群的云信息,包括Kubernetes API服务器的地址、凭据、命名空间等。
- Pod模板:可以定义Kubernetes Pod的模板,包括镜像、环境变量、卷挂载等配置。这些模板可以在Pipeline中使用,以指定构建任务在Pod中运行的环境。
- Pod自动伸缩:根据构建的需求,插件可以自动调整Pod的数量,以适应并行构建和资源利用的要求。
- 在构建期间使用Kubernetes命令:插件提供了一组用于在构建期间与Kubernetes集群交互的步骤,例如创建、删除、替换Pod,执行kubectl命令等。
通过Kubernetes Plugin,Jenkins可以与Kubernetes集群紧密集成,以提供可扩展、弹性和资源隔离的构建环境。这样,Jenkins可以利用Kubernetes的强大功能来管理构建代理节点,并在需要时自动创建和销毁节点,实现更高效的构建和部署过程。

图解

部署流程
[系统管理] -> [插件管理] -> [搜索kubernetes]->直接安装
若安装失败,请先更新 bouncycastle API Plugin并重新启动Jenkins
[系统管理] -> [系统配置] -> [Add a new cloud]
配置地址信息
- Kubernetes 地址: https://kubernetes.default
- Kubernetes 命名空间:jenkins
- 服务证书不用写(我们在安装Jenkins的时候已经指定过serviceAccount),均使用默认
- 连接测试,成功会提示:Connection test successful
- Jenkins地址:http://jenkins:8080
- Jenkins 通道 :jenkins:50000
配置Pod Template
名称:jnlp-slave
命名空间:jenkins
标签列表:jnlp-slave,作为agent的label选择用
连接 Jenkins 的超时时间(秒) :300,设置连接jenkins超时时间
工作空间卷:选择hostpath,设置/opt/jenkins,注意需要设置目录权限,否则Pod没有权限
# pod内部,jenkins会使用UID为1000的用户执行命令 $ chown -R 1000:1000 /opt/jenkins-pod $ chmod 777 /opt/jenkins-pod
安装插件

安装成功

Configure clouds
配置k8s节点
http://jenkins.yuchaoit.cn/manage/configureClouds/

选择k8s节点插件
# jenkins 和api-server 在一个集群下,直接走服务发现
[root@k8s-master ~]#kubectl -n jenkins exec -it jenkins-master-75c78b968c-cllc7 -c jenkins -- bash
jenkins@jenkins-master-75c78b968c-cllc7:/$
jenkins@jenkins-master-75c78b968c-cllc7:/$
jenkins@jenkins-master-75c78b968c-cllc7:/$
jenkins@jenkins-master-75c78b968c-cllc7:/$ curl -k -I https://kubernetes.default
HTTP/2 403
audit-id: df0f2ada-bfe1-4dd9-ae0a-8f64a9f3e6c5
cache-control: no-cache, private
content-type: application/json
x-content-type-options: nosniff
x-kubernetes-pf-flowschema-uid: 049f9f11-249c-435d-b02f-2c54c2b012ec
x-kubernetes-pf-prioritylevel-uid: 0b022f79-1724-4434-b059-555efda4bb57
content-length: 218
date: Thu, 11 May 2023 09:16:56 GMT
jenkins@jenkins-master-75c78b968c-cllc7:/$
[root@k8s-master ~]#kubectl -n default get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 62d
测试连接

为何可以直接连接上,不需要配置证书了
因为jenkins安装的时候,创建过serviceAccount
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: jenkins
namespace: jenkins
spec:
accessModes:
- ReadWriteOnce
storageClassName: nfs # 你依然要提前准备好nfs的驱动器
resources:
requests:
storage: 200Gi
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins
namespace: jenkins
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: jenkins-crb
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: jenkins
namespace: jenkins
这段配置可以让Jenkins的Pod直接访问API Server的原因是通过创建了一个具有cluster-admin权限的ServiceAccount并绑定到jenkins-crb的ClusterRole上。
在Kubernetes中,API Server是用于与集群进行交互的主要组件。访问API Server需要适当的身份验证和授权。通过创建具有cluster-admin权限的ServiceAccount并绑定到jenkins-crb的ClusterRole,我们赋予了Jenkins Pod访问API Server的权限。
当Jenkins的Pod使用这个ServiceAccount进行身份验证时,它将被授予拥有cluster-admin级别权限的令牌。这意味着Jenkins的Pod可以通过API Server执行各种操作,例如创建、更新和删除资源对象,监视集群状态等。
k8s过程




jenkins-master根据pod标签选择构建环境(参考agent节点理解)

节点选择器

持久化配置,容器内构建的数据,映射给宿主机这个目录。

测试jenkins(回放job)
作为调试构建任务的一个技巧,而不用反复去构建新的job。
# 给node-selector节点标签加上
[root@k8s-master ~]#kubectl label node k8s-slave1 jnlp-slave=true
node/k8s-slave1 labeled

正常结果是,jenkins-master链接k8s,通过节点选择器,创建pod,创建任务
查看pod创建
# 请看jnlp-slave-lk97z 已经创建了,以及详细变化
[root@k8s-master ~]#kubectl -n jenkins get po -w
NAME READY STATUS RESTARTS AGE
gitlab-5bdddc77ff-qh4b8 1/1 Running 4 (27h ago) 3d3h
jenkins-master-75c78b968c-cllc7 1/1 Running 10 (27h ago) 3d
jnlp-slave-lk97z 0/1 ContainerCreating 0 3s
postgres-78dc4bd6bc-g94nd 1/1 Running 4 (27h ago) 3d3h
redis-56bb5f8cc9-84lb9 1/1 Running 4 (27h ago) 3d3h
jnlp-slave-lk97z 1/1 Running 0 67s
jnlp-slave-lk97z 1/1 Terminating 0 74s
jnlp-slave-lk97z 0/1 Terminating 0 75s
jnlp-slave-lk97z 0/1 Terminating 0 75s
jnlp-slave-lk97z 0/1 Terminating 0 75s
构建为什么失败

查看jenkins-pod详细
可以分析,jenkins是怎么创建pod去执行构建任务的
并且都是我们在jenkins的插件页面里配置的参数,转化为的pod配置。
[root@k8s-master ~]#kubectl -n jenkins get po jnlp-slave-5l6jz -oyaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2023-05-11T10:04:39Z"
labels:
jenkins: slave
jenkins/label: jnlp-slave
jenkins/label-digest: bb74484d3d8cfdd5465f289d1fe175836bf9e531
name: jnlp-slave-5l6jz
namespace: jenkins
resourceVersion: "7104750"
uid: 0c490904-61b6-490f-ab91-1dafda33659c
spec:
containers:
- env:
- name: JENKINS_SECRET
value: 31c15777b59cc1db8f8c260d71bd23c3b6142ead5667a7066f74a33237c92fa9
- name: JENKINS_TUNNEL
value: jenkins:50000
- name: JENKINS_AGENT_NAME
value: jnlp-slave-5l6jz
- name: JENKINS_NAME
value: jnlp-slave-5l6jz
- name: JENKINS_AGENT_WORKDIR
value: /home/jenkins/agent
- name: JENKINS_URL
value: http://jenkins:8080/
image: jenkins/inbound-agent:3107.v665000b_51092-5 # 这就是agent进程镜像去连接master
imagePullPolicy: IfNotPresent
name: jnlp
resources:
requests:
cpu: 100m
memory: 256Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /home/jenkins/agent
name: workspace-volume
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-5tpt9
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
imagePullSecrets:
- {}
nodeName: k8s-slave1
nodeSelector:
jnlp-slave: "true"
preemptionPolicy: PreemptLowerPriority
priority: 0
restartPolicy: Never
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- hostPath:
path: /opt/jenkins-pod/
type: ""
name: workspace-volume
- name: kube-api-access-5tpt9
projected:
defaultMode: 420
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
- downwardAPI:
items:
- fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
path: namespace
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2023-05-11T10:04:39Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2023-05-11T10:04:40Z"
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2023-05-11T10:04:40Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2023-05-11T10:04:39Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: containerd://46aef4400d9708fbb43f1e7798b9402d990072f5c592550d083e6c4961ba375f
image: docker.io/jenkins/inbound-agent:3107.v665000b_51092-5
imageID: docker.io/jenkins/inbound-agent@sha256:8587505e9f5d2e5a77ea8bd85afb3981fb3891adfc8070693b0239dc1e2266be
lastState: {}
name: jnlp
ready: true
restartCount: 0
started: true
state:
running:
startedAt: "2023-05-11T10:04:39Z"
hostIP: 10.0.0.81
phase: Running
podIP: 10.244.2.182
podIPs:
- ip: 10.244.2.182
qosClass: Burstable
startTime: "2023-05-11T10:04:39Z"
[root@k8s-master ~]#
试试这个agent容器
# 获取到jenkins创建的pod,执行任务用的什么镜像
[root@k8s-slave1 ~]#nerdctl run -it docker.io/jenkins/inbound-agent bash
jenkins@29e1984afa78:~$
jenkins@29e1984afa78:~$ java -version
openjdk version "11.0.13" 2021-10-19
OpenJDK Runtime Environment Temurin-11.0.13+8 (build 11.0.13+8)
OpenJDK 64-Bit Server VM Temurin-11.0.13+8 (build 11.0.13+8, mixed mode)
jenkins@29e1984afa78:~$
jenkins@29e1984afa78:~$ mvn
bash: mvn: command not found
jenkins@29e1984afa78:~$
很明显,这个构建容器里,缺少mvn导致失败。
优化pod
因此我们需要将用到的命令行工具集成到Pod的容器内,但是思考如下问题:
- 目前是用的jnlp的容器,是java的环境,我们在此基础上需要集成很多工具,能不能创建一个新的容器,让新容器来做具体的任务,jnlp-slave容器只用来负责连接jenkins-master
- 针对不同的构建环境(java、python、go、nodejs),可以制作不同的容器,来执行对应的任务
Pod-Template中容器镜像的制作
为解决上述问题,我们制作一个tools镜像,集成常用的工具,来完成常见的构建任务,需要注意的几点:
- 使用alpine基础镜像,自身体积比较小
- 替换国内安装源
- 为了使用docker,安装了docker
- 为了克隆代码,安装git
- 为了后续做java的测试等任务,安装jdk环境
- 为了在容器中调用kubectl的命令,拷贝了kubectl的二进制文件
- 为了认证kubectl,需要在容器内部生成.kube目录及config文件
[root@k8s-slave1 ~]#mkdir tools
[root@k8s-slave1 ~]#cp apache-maven-3.6.3-bin.tar.gz tools/
[root@k8s-slave1 ~]#
[root@k8s-slave1 ~]#cp /bin/kubectl tools/
[root@k8s-slave1 ~]#
[root@k8s-slave1 ~]#cd tools/
[root@k8s-slave1 ~/tools]#vim Dockerfile
[root@k8s-slave1 ~/tools]#ls
apache-maven-3.6.3 apache-maven-3.6.3-bin.tar.gz Dockerfile kubectl
[root@k8s-slave1 ~/tools]#
Dockerfile解释
[root@k8s-slave1 ~/tools]#cat Dockerfile
FROM alpine:3.13.4
LABEL maintainer="yc_uuu@163.com"
USER root
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories && \
apk update && \
apk add --no-cache openrc docker git curl tar gcc g++ make \
bash shadow openjdk8 py-pip python3-dev openssl-dev libffi-dev \
libstdc++ harfbuzz nss freetype ttf-freefont && \
mkdir -p /root/.kube && \
usermod -a -G docker root
RUN rm -rf /var/cache/apk/*
#-----------------安装 kubectl--------------------#
COPY kubectl /usr/local/bin/
RUN chmod +x /usr/local/bin/kubectl
# ------------------------------------------------#
#-----------------安装 maven--------------------#
COPY apache-maven-3.6.3 /usr/lib/apache-maven-3.6.3
RUN ln -s /usr/lib/apache-maven-3.6.3/bin/mvn /usr/local/bin/mvn && chmod +x /usr/local/bin/mvn
ENV MAVEN_HOME=/usr/lib/apache-maven-3.6.3
#------------------------------------------------#
[root@k8s-slave1 ~/tools]#
所以这就是一个工具箱容器,专门用于如docker镜像构建,mvn构建的容器。
[root@k8s-slave1 ~/tools]#docker build . -t 10.0.0.66:5000/devops/tools:v1
$ docker push 10.0.0.66:5000/devops/tools:v1
# 检查镜像
[root@k8s-slave1 ~/tools]#curl -u admin:admin -X GET http://10.0.0.66:5000/v2/_catalog
{"repositories":["devops/tools","eladmin","eladmin/eladmin-api","eladmin/eladmin-web","eladmin-web","jenkins","last-eladmin-web","mysql","new_eladmin-web","zabbix-agent","zabbix-server-mysql","zabbix-web-nginx-mysql"]}
[root@k8s-slave1 ~/tools]#
再次修改jenkins配置集群(重要)
kubernetes detail > pod templates >容器列表

tools容器

该容器的作用就是在pod中能运行,接收master的任务。
注意,这是自己构建的私有仓库的镜像,pod想要去拉取镜像,得加入docker-registry,这个凭证。
[root@k8s-master ~]#kubectl -n yuchao get secrets registry-10.0.0.66 -oyaml > registry-10.0.0.66.yml
[root@k8s-master ~]#
# 修改如下
[root@k8s-master ~]#cat registry-10.0.0.66.yml
apiVersion: v1
data:
.dockerconfigjson: eyJhdXRocyI6eyIxMC4wLjAuNjY6NTAwMCI6eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJhZG1pbiIsImVtYWlsIjoieWNfdXV1QDE2My5jb20iLCJhdXRoIjoiWVdSdGFXNDZZV1J0YVc0PSJ9fX0=
kind: Secret
metadata:
name: registry-10.0.0.66
namespace: jenkins
type: kubernetes.io/dockerconfigjson
[root@k8s-master ~]#
# 创建
[root@k8s-master ~]#kubectl apply -f registry-10.0.0.66.yml
secret/registry-10.0.0.66 created
[root@k8s-master ~]#
[root@k8s-master ~]#kubectl -n jenkins get secrets
NAME TYPE DATA AGE
gitlab-secret Opaque 2 4d
registry-10.0.0.66 kubernetes.io/dockerconfigjson 1 4s
[root@k8s-master ~]#
image pull secret
同一个jenkins namespace下,可以直接调用

tools容器还得修改权限
[root@k8s-slave1 ~/tools]#docker run -it 10.0.0.66:5000/devops/tools:v1 bash
bash-5.1# mvn -version
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: /usr/lib/apache-maven-3.6.3
Java version: 1.8.0_275, vendor: IcedTea, runtime: /usr/lib/jvm/java-1.8-openjdk/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "3.10.0-862.el7.x86_64", arch: "amd64", family: "unix"
bash-5.1# git -v
unknown option: -v
usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
[-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
<command> [<args>]
bash-5.1#
bash-5.1# docker version
Client:
Version: 20.10.3
API version: 1.41
Go version: go1.15.10
Git commit: 48d30b5b32e99c932b4ea3edca74353feddd83ff
Built: Sat Mar 20 18:44:30 2021
OS/Arch: linux/amd64
Context: default
Experimental: true
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
bash-5.1#
# 但是k8s、docker都还没连接上
bash-5.1# kubectl get no
The connection to the server localhost:8080 was refused - did you specify the right host or port?
bash-5.1#
bash-5.1# docker ps
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
bash-5.1#
所以很明显要添加docker、k8s的连接信息
docker连接
# 挂载宿主机的docker.socket到容器内
[root@k8s-slave1 ~/tools]#docker run -v /var/run/docker.sock:/var/run/docker.sock --rm -ti 10.0.0.66:5000/devops/tools:v1 bash
bash-5.1#
bash-5.1# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8819365def4f 10.0.0.66:5000/devops/tools:v1 "bash" 2 seconds ago Up 1 second interesting_gates
bash-5.1#
k8s连接
# 给pod挂载一个configmap即可,挂载k8s的证书到容器内 /root/.kube/
# 获取kube_config
# 创建secret,存储敏感信息,jenkins的插件也支持secret
kubectl -n jenkins create secret generic kubeconfig --from-file=/root/.kube/config
jenkins修改volume
/opt/maven-repo/

以及k8s的secret

创建docker registry全局凭据

告诉jenkins去使用tools容器
还得修改jenkinsfile,让jenkins去tools容器里执行构建等命令
pipeline {
agent { label 'jnlp-slave'}
options {
buildDiscarder(logRotator(numToKeepStr: '10'))
disableConcurrentBuilds()
timeout(time: 20, unit: 'MINUTES')
gitLabConnection('gitlab')
}
environment {
REGISTRY = "10.0.0.66:5000"
IMAGE_REPO = "10.0.0.66:5000/eladmin/eladmin-api"
DINGTALK_CREDS = credentials('dingtalk')
REGISTRY_CREDS = credentials('registry')
TAB_STR = "\n \n "
}
stages {
stage('gitlog') {
steps {
script{
sh "git log --oneline -n 1 > gitlog.file"
env.GIT_LOG = readFile("gitlog.file").trim()
}
sh 'printenv'
}
}
stage('checkout') {
steps {
checkout scm
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script{
env.BUILD_TASKS = env.STAGE_NAME + "√..." + env.TAB_STR
}
}
}
stage('mvn package') {
steps {
container('tools') {
sh 'mvn clean package'
}
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script{
env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
}
}
}
stage('build-image') {
steps {
container('tools') {
retry(2) { sh 'docker build . -t ${IMAGE_REPO}:${GIT_COMMIT}'}
}
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script{
env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
}
}
}
stage('push-image') {
steps {
container('tools') {
retry(2) {
sh """
docker logout ${REGISTRY};
docker login ${REGISTRY} -u ${REGISTRY_CREDS_USR} -p ${REGISTRY_CREDS_PSW}
docker push ${IMAGE_REPO}:${GIT_COMMIT}
"""
}
}
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script{
env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
}
}
}
stage('deploy') {
steps {
container('tools') {
timeout(time: 1, unit: 'MINUTES') {
sh "sed -i 's##${IMAGE_REPO}:${GIT_COMMIT}#g' manifests/*"
sh "kubectl apply -f manifests/"
}
}
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script{
env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
}
}
}
}
post {
success {
container('tools') {
echo 'Congratulations!'
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
-H 'Content-Type: application/json' \
-d '{
"msgtype": "markdown",
"markdown": {
"title":"eladmin-api",
"text": "😄👍 构建成功 👍😄 \n**项目名称**: www.yuchaoit.cn \n**Git log**: ${GIT_LOG} \n**构建分支**: ${GIT_BRANCH} \n**构建地址**: ${RUN_DISPLAY_URL} \n**构建任务**: ${BUILD_TASKS}"
}
}'
"""
}
}
failure {
container('tools') {
echo 'Oh no!'
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
-H 'Content-Type: application/json' \
-d '{
"msgtype": "markdown",
"markdown": {
"title":"eladmin-api",
"text": "😖❌ 构建失败 ❌😖 \n**项目名称**: www.yuchaoit.cn \n**Git log**: ${GIT_LOG} \n**构建分支**: ${GIT_BRANCH} \n**构建地址**: ${RUN_DISPLAY_URL} \n**构建任务**: ${BUILD_TASKS}"
}
}'
"""
}
}
always {
echo 'I will always say Hello again!'
}
}
}
提交、查看构建
git push