jenkins对接k8s集群

先跳过本节操作

  • 自由风格
  • 流水线
  • 多分支流水线

本节学习内容

  1. Jenkins可以通过Kubernetes插件与Kubernetes集群进行对接。首先,在Jenkins的全局配置中,你需要配置Kubernetes云的相关信息,包括Kubernetes API服务器的地址、凭据、命名空间等。然后,在Jenkins Pipeline中,你可以使用kubernetes关键字来定义在Kubernetes集群中执行的代理节点。这样,Jenkins将使用Kubernetes插件自动创建和管理这些代理节点,以执行Pipeline中的任务和步骤。
  2. 使用Kubernetes的Pod模板作为动态代理节点是一种常见的做法。在Jenkins Pipeline中,你可以使用podTemplate关键字定义一个Pod模板,其中包含了代理节点的配置,如镜像、环境变量、卷挂载等。然后,你可以在Pipeline中使用agent指令来指定使用这个Pod模板作为代理节点,例如agent { kubernetes { label 'mypodtemplate' } }。这样,当Pipeline执行时,Jenkins将根据需要动态创建Pod,并在Pod中运行代理节点来执行任务。
  3. 要制作不同类型的业务集成的代理容器,你可以创建自定义的Docker镜像。首先,创建一个包含所需工具和依赖的基础镜像。然后,根据不同类型的业务需求,构建定制的镜像,将业务所需的工具、库和配置文件添加到镜像中。你可以使用Dockerfile来定义构建过程,然后使用Docker构建命令将镜像构建出来。在Jenkins中,你可以使用这个定制的代理容器镜像作为Pipeline中的代理节点,以便执行特定类型的业务集成任务。
  4. 集成代码扫描、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的主要功能包括:

  1. 动态代理节点:该插件允许Jenkins自动在Kubernetes集群中创建Pod,作为构建的代理节点。每个构建可以在独立的Pod中运行,以隔离构建环境并提供资源隔离。
  2. 云配置:插件提供了配置Kubernetes集群的云信息,包括Kubernetes API服务器的地址、凭据、命名空间等。
  3. Pod模板:可以定义Kubernetes Pod的模板,包括镜像、环境变量、卷挂载等配置。这些模板可以在Pipeline中使用,以指定构建任务在Pod中运行的环境。
  4. Pod自动伸缩:根据构建的需求,插件可以自动调整Pod的数量,以适应并行构建和资源利用的要求。
  5. 在构建期间使用Kubernetes命令:插件提供了一组用于在构建期间与Kubernetes集群交互的步骤,例如创建、删除、替换Pod,执行kubectl命令等。

通过Kubernetes Plugin,Jenkins可以与Kubernetes集群紧密集成,以提供可扩展、弹性和资源隔离的构建环境。这样,Jenkins可以利用Kubernetes的强大功能来管理构建代理节点,并在需要时自动创建和销毁节点,实现更高效的构建和部署过程。

image-20230511165528649

图解

image-20230511170228477

部署流程

  1. [系统管理] -> [插件管理] -> [搜索kubernetes]->直接安装

    若安装失败,请先更新 bouncycastle API Plugin并重新启动Jenkins

  2. [系统管理] -> [系统配置] -> [Add a new cloud]

  3. 配置地址信息

    • Kubernetes 地址: https://kubernetes.default
    • Kubernetes 命名空间:jenkins
    • 服务证书不用写(我们在安装Jenkins的时候已经指定过serviceAccount),均使用默认
    • 连接测试,成功会提示:Connection test successful
    • Jenkins地址:http://jenkins:8080
    • Jenkins 通道 :jenkins:50000
  4. 配置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
      

安装插件

image-20230511171124850

安装成功

image-20230511171300061

Configure clouds

配置k8s节点

http://jenkins.yuchaoit.cn/manage/configureClouds/

image-20230511171421596

选择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

测试连接

image-20230511171926909

为何可以直接连接上,不需要配置证书了
因为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过程

image-20230511172516657


image-20230511172527912


image-20230511172542478


image-20230511172644362


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

image-20230511172853190


节点选择器

image-20230511173003316


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

image-20230511173125397

测试jenkins(回放job)

作为调试构建任务的一个技巧,而不用反复去构建新的job。

# 给node-selector节点标签加上
[root@k8s-master ~]#kubectl label node k8s-slave1 jnlp-slave=true
node/k8s-slave1 labeled

image-20230511173602094

正常结果是,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

构建为什么失败

image-20230512110434808

查看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 >容器列表

image-20230512113344142

tools容器

image-20230512144541970

该容器的作用就是在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下,可以直接调用

image-20230512145558463

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/

image-20230512152622430

以及k8s的secret

image-20230512152714622

创建docker registry全局凭据

image-20230512154150969

告诉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&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
    }

    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
Copyright © www.yuchaoit.cn 2025 all right reserved,powered by Gitbook作者:于超 2024-03-31 19:40:28

results matching ""

    No results matching ""