0
点赞
收藏
分享

微信扫一扫

持续集成CI&CD之CI的完整版最佳实践

本CI实践主要对于有持续集成需求,适用于联调开发环境,可以大大加快开发人员的联调验证速度。主要采用jenkins pipeline脚本实现。

jenkins pipeline

​参考文档​​:https://www.jenkins.io/zh/doc/book/pipeline/jenkinsfile

​编写语法参考 ​​:http://groovy-lang.org/semantics.html

概念

pipeline是用户定义的一个CD流水线模型 。pipeline的代码定义了整个的构建过程, 他通常包括构建, 测试和交付应用程序的阶段 。本质上,Jenkins 是一个自动化引擎,它支持许多自动模式。 pipeline向Jenkins中添加了一组强大的工具, 支持用例 简单的持续集成到全面的CD流水线。通过对一系列的相关任务进行建模, 用户可以利用pipeline的很多特性。

声明式

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any  // (1)
    stages {
        stage('Build') {  // (2)
            steps {
                // (3)
            }
        }
        stage('Test') {  // (4)
            steps {
                // (5)
            }
        }
        stage('Deploy') { // (6)
            steps {
                // (7)
            }
        }
    }
}

(1)在任何可用的代理上,执行流水线或它的任何阶段。 (2)定义 "Build" 阶段。 (3)执行与 "Build" 阶段相关的步骤。 (4)定义"Test" 阶段。 (5)执行与"Test" 阶段相关的步骤。 (6)定义 "Deploy" 阶段。 (7)执行与 "Deploy" 阶段相关的步骤

脚本化

Jenkinsfile (Scripted Pipeline)

node {  // (1)
    stage('Build') { // (2)
        // (3)
    }
    stage('Test') { // (4)
        // (5)
    }
    stage('Deploy') { // (6)
        // (7)
    }
}

(1)在任何可用的代理上,执行流水线或它的任何阶段。 (2)定义 "Build" 阶段。 stage 块 在脚本化流水线语法中是可选的。 然而, 在脚本化流水线中实现 stage 块 ,可以清楚的显示Jenkins UI中的每个 stage 的任务子集。 (3)执行与 "Build" 阶段相关的步骤。 (4)定义 "Test" 阶段。 (5)执行与 "Test" 阶段相关的步骤。 (6)定义 "Deploy" 阶段。 (7)执行与 "Deploy" 阶段相关的步骤

CI集成流程

CI流程架构

持续集成CI&CD之CI的完整版最佳实践_kubernetes

(1)开发人员代码提交 (2)开发人员点击jenkins构建 (3)开发人员使用运维工具查看服务情况

代码部署文件

开发环境部署以k8s为例

spring-cloud-nacos

本案例是将spring-cloud-nacos工程通过jenkins编译打包发布的开发环境,所有部署相关的文件都在docker文件夹中。 采用jenkins-pipeline的声明式部署,所有maven打包、镜像编译方式,部署都使用容器化,不依赖主机。相关的文件都使用jenkins系统变量、凭证配置。

工程结构

父工程
|--- 子模块1  # java子模块
|------ docker文件夹 # 存放部署文件
|--------- Dockerfile
|--------- Jenkinsfile
|--------- k8s.yaml
|------ src
...
|--- 子模块2
|------ docker文件夹
|--------- Dockerfile
|--------- Jenkinsfile
|--------- k8s.yaml
|------ src

部署文件-Dockerfile

用于容器镜像制作。

FROM openjdk:8-jre
MAINTAINER QiMing Mei <meiqiming@talkweb.com.cn>

ARG JAR_FILE
ENV JAVA_OPTS="-server -Xms1024m -Xmx1024m" JAR_FILE="${JAR_FILE}"

ADD target/${JAR_FILE} /usr/share/service/${JAR_FILE}

ENTRYPOINT java ${JAVA_OPTS} -jar /usr/share/service/${JAR_FILE}  --server.port=${CONTAINER_PORT} \
--spring.cloud.nacos.discovery.ip=${DOMAIN_NAME} --spring.cloud.nacos.server-addr=${NACOS_URL}

部署文件-k8s.yaml

用于k8s环境部署。

apiVersion: v1
kind: Namespace
metadata:
  name: __NAME_SPACE__
  labels:
    name: __NAME_SPACE__
---
apiVersion: v1
kind: Service
metadata:
  name: __DOMAIN_NAME__
  namespace: __NAME_SPACE__
spec:
  ports:
  - name: app-port
    port: __CONTAINER_PORT__
    targetPort: __CONTAINER_PORT__
    protocol: TCP
  # 当开启管理端口时,外部服务需要访问时打开此注释
  # - name: manage-port
  #   port: __MANAGE_PORT__
  #   targetPort: __MANAGE_PORT__
  #   protocol: TCP
  selector:
    app: __DOMAIN_NAME__
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: __DOMAIN_NAME__
  namespace: __NAME_SPACE__
spec:
  selector:
    matchLabels:
      app: __DOMAIN_NAME__
  replicas: __REPLICAS_NUM__
  template:
    metadata:
      labels:
        app: __DOMAIN_NAME__
    spec:
      initContainers:
      - name: init-agent-sidecar
        image: ming19871211/skywalking-agent:__SKYWALKING_VESION__
        command:
        - 'sh'
        - '-c'
        - 'set -ex;cp -r /skywalking/agent/* /usr/skywalking/agent;'
        volumeMounts:
        - name: agent
          mountPath: /usr/skywalking/agent
      containers:
      - name: __DOMAIN_NAME__
        image: __DOCKER_IMAGE__
        imagePullPolicy: IfNotPresent #本地存在就不到远程拉取镜像
        env: #环境变量设置
        - name: TZ
          value: Asia/Shanghai
        - name: NACOS_NAMESPACE
          value: __NACOS_NAMESPACE__
        - name: DEPLOY_ENV  # 兼容性配置,后续版本建议删除
          value: __NACOS_NAMESPACE__
        - name: NACOS_GROUP
          value: __NACOS_GROUP__
        - name: JAVA_OPTS
          value: "__JAVA_OPTS__"
        - name: CONTAINER_PORT
          value: "__CONTAINER_PORT__"
        - name: MANAGE_PORT
          value: "__MANAGE_PORT__"
        - name: NACOS_URL
          value: __NACOS_URL__
        - name: DOMAIN_NAME
          value: __DOMAIN_NAME__.__NAME_SPACE__
        # - name: DOMAIN_NAME
        #   valueFrom:
        #     fieldRef:
        #       apiVersion: v1
        #       fieldPath: status.podIP
        envFrom:
        - secretRef:
            name: __NACOS_AUTH__
        resources: #资源限制
          requests:
            memory: "128Mi"
            cpu: "100m" #最低需要 0.1个cpu
          limits:
            memory: "__LIMIT_MEMORY__Mi"
            cpu: "1000m"
        ports:
        - containerPort: __CONTAINER_PORT__
          name: app-port
          protocol: TCP
        - containerPort: __MANAGE_PORT__
          name: manage-port
          protocol: TCP
        readinessProbe: #就绪探针
          httpGet:
          #  path: __APP_MANAGE_PATH__/actuator/health/readiness
          #  port: __MANAGE_PORT__
          tcpSocket:
            port: __CONTAINER_PORT__
          initialDelaySeconds: 60
          periodSeconds: 15
          timeoutSeconds: 5
        livenessProbe: #健康检查
        #  httpGet:
        #    path: __APP_MANAGE_PATH__/actuator/health/liveness
        #    port: __MANAGE_PORT__
          tcpSocket:
            port: __CONTAINER_PORT__
          initialDelaySeconds: 60
          periodSeconds: 15
          timeoutSeconds: 5
        volumeMounts:
        - name: time-config
          mountPath: /etc/localtime
          readOnly: true
        - name: agent
          mountPath: /usr/skywalking/agent
        # 增加挂载
        # - name: [PVC_NAME_ALIAS] # pod挂载别称
        #   mountPath: [POD_MOUNT_PATH] # pods内挂载路径
        #   subPath: [PVC_MOUNT_SUBPATH] #  pvc挂载盘中的子路径,注释这一项标识挂载根路径下
      imagePullSecrets:
      - name: __DOCKER_REGISTRY_SECRET__
      nodeSelector:
        isDev: "true"
      volumes:
      - name: time-config
        hostPath:
          path: /etc/localtime
      - name: agent
        emptyDir: {}
      # 增加挂载
      # - name: [PVC_NAME_ALIAS] # pod挂载别称
      #   persistentVolumeClaim:
      #     claimName: [PVC_NAME] # 对应指定的pvc名称

部署文件-Jenkinsfile

jenkins部署脚本文件,分为三个步骤进行部署(maven编译、docker镜像制作、k8s部署),整个部署运行的节点只需要有docker环境即可部署。

def&nbsp;docker_image&nbsp;=&nbsp;&quot;&quot;&nbsp;//定义全局的镜像变量
pipeline&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;/*
    1.配置maven相关变量 credentials-[Secret file]类型: jenkins-maven-setting[maven setting.xml文件]
    2.配置docker仓库相关变量 系统环境变量:DOCKER_REGISTRY_ADDR [docker仓库地址]
    credentials-[Username with password]类型:jenkins-docker-registry-creds[docker仓库账号/docker仓库密码]
    3.配置nacos相关变量 定义账号密码对应下面的NACOS_URL
    credentials-[Username with password]类型:jenkins-nacos-creds[nacos登录账号/nacos登录密码]
    4.配置k8s相关变量 credentials-[Secret file]类型: jenkins-k8s-config[k8s集群访问凭证文件]
    5.若需要启动skywalking链路跟踪,需要配置环境变量IS_SKYWALKING=true, SKYWALKING_VESION=[skywalking的版本号]

    合计:1个docker仓库地址环境变量,4个credentials为必须配置;2个skywalking环境变量根据需求配置;
    `参考文档`:https://www.jenkins.io/zh/doc/book/pipeline/jenkinsfile
    `编写语法参考 `:http://groovy-lang.org/semantics.html
     */
&nbsp;&nbsp;&nbsp;&nbsp;// 如果指定具体的节点执行,请 agent { label 'docker-slave' }
&nbsp;&nbsp;&nbsp;&nbsp;agent&nbsp;any
&nbsp;&nbsp;&nbsp;&nbsp;options&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//超时一小时
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeout(time:&nbsp;1,&nbsp;unit:&nbsp;&#39;HOURS&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//不允许同时执行
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;disableConcurrentBuilds()
&nbsp;&nbsp;&nbsp;&nbsp;}
// #######################需要修改的区域 开始#################################
&nbsp;&nbsp;&nbsp;&nbsp;/*** 一般情况下只需要修改environment与parameters区域的 ${SERVER_NAME} ${MODULE_NAME}  ${NAME_SPACE}
     * ${NACOS_NAME_SPACE}  没有多层子项目的情况下SERVER_NAME与MODULE_NAME一般是相同的
     * 教育云认证服务 eg: SERVER_NAME=MODULE_NAME=ssop-auth-service, NACOS_NAME_SPACE=NAME_SPACE=talkweb-school-dev
     **/
&nbsp;&nbsp;&nbsp;&nbsp;environment&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 服务的域名,一般与项目名称相同
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DOMAIN_NAME=&#39;${SERVER_NAME}&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// docker容器内部端口,不建议修改
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONTAINER_PORT=80
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// spring boot中设置了管理端口 eg: management.server.port:${MANAGE_PORT:18085} 必须设置 MANAGE_PORT=XXX, 建议直接打开下面注释
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// MANAGE_PORT=90
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// spring boot中没有设置管理端口,但是设置了server.servlet.context-path,并且在非根目录时需要增加环境变量APP_MANAGE_PATH其值与server.servlet.context-path相同
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// APP_MANAGE_PATH="/"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 服务的的实例数量
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;REPLICAS_NUM=1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 表示限制内存大小,单位为M,只能为数字;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LIMIT_MEMORY=2048
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// maven配置文件setting路径
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MAVEN_SETTING=credentials(&#39;jenkins-maven-setting&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// docker仓库地址,一般与系统环境变量相同,若相同时手动修改
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DOCKER_REGISTRY_ADDR=&quot;${env.DOCKER_REGISTRY_ADDR}&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// docker仓库账号密码--对应系统环境变量DOCKER_REGISTRY_ADDR
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DOCKER_REGISTRY=credentials(&#39;jenkins-docker-registry-creds&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 注册中心域名,默认是nacos 一般不需要修改
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NACOS_URL=&#39;nacos-headless.talkweb:8848&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// nacos凭证-对应NACOS_URL
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NACOS_CREDS=credentials(&#39;jenkins-nacos-creds&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// k8s版本号
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;K8S_VERSION=&#39;v1.19.16&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// K8s配置文件路径
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;K8S_CONFIG=credentials(&#39;jenkins-k8s-config&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// k8s中nacos账号密码存储的secret名称
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;K8S_NACOS_AUTH=&quot;nacos-auth&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// k8s中docker仓库信息存储的secret名称
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;K8S_DOCKER_REGISTRY=&quot;hub-local&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 根据需求,xms、xmm已经自动添加 此处不用添加
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//JAVA_OPTS="-Dspring.XXX=XXX "
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;parameters&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 修改部署的域名空间
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string(name:&#39;name_space&#39;,&nbsp;defaultValue:&nbsp;&quot;${NAME_SPACE}&quot;,&nbsp;description:&nbsp;&#39;&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 修改为子项目名称 多层情况,合同产品eg: soeasy-clm-message/soeasy-clm-message-server
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string(name:&#39;module&#39;,&nbsp;defaultValue:&nbsp;&quot;${MODULE_NAME}&quot;,&nbsp;description:&nbsp;&#39;&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// nacos空间
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;choice(name:&nbsp;&#39;nacos_namespace&#39;,&nbsp;choices:&nbsp;[&#39;${NACOS_NAME_SPACE}&#39;],&nbsp;description:&nbsp;&#39;nacos&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// nacos组
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;choice(name:&nbsp;&#39;nacos_group&#39;,&nbsp;choices:&nbsp;[&#39;DEFAULT_GROUP&#39;],&nbsp;description:&nbsp;&#39;nacos&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 配置Tag的git参数,参数类型 设置为 分支或标签
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 配置git地址:在流水线 -> 定义[Pipeline script from SCM] -> SCM[git] -> Repository URL[git地址]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// -> Credentials[git账号] -> 指定分支(为空时代表any)[${Tag}] --> 脚本路径[Jenkinsfile文件的工程路径]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// -> 轻量级检出[去掉√ ]
&nbsp;&nbsp;&nbsp;&nbsp;}
// ########################需要修改的区域 结束################################
&nbsp;&nbsp;&nbsp;&nbsp;stages&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stage(&#39;Run&nbsp;maven&#39;)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;agent&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;docker&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;image&nbsp;&#39;maven:3.5-jdk-8-alpine&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;args&nbsp;&#39;-v&nbsp;$HOME/.m2:$HOME/.m2&nbsp;&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reuseNode&nbsp;true
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;environment&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 设置maven本地仓库地址
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MAVEN_OPTS=&quot;&nbsp;-Dmaven.repo.local=$HOME/.m2/repository&nbsp;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;steps&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;mvn&nbsp;-version&nbsp;&amp;&amp;&nbsp;mvn&nbsp;clean&nbsp;package&nbsp;-pl&nbsp;${params.module}&nbsp;-am&nbsp;&nbsp;&nbsp;-Dmaven.test.skip=true&nbsp;-s&nbsp;$MAVEN_SETTING&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stage(&#39;Build&nbsp;And&nbsp;Push&nbsp;Docker&nbsp;Image&#39;){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;steps&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;script&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 获取标签版本或者分支的commitId
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!params.Tag&nbsp;||&nbsp;params.Tag.contains(&#39;origin/&#39;))&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;git&nbsp;rev-parse&nbsp;--short&nbsp;HEAD&nbsp;&gt;&nbsp;commit-id&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tag&nbsp;=&nbsp;readFile(&#39;commit-id&#39;).replace(&quot;\n&quot;,&nbsp;&quot;&quot;).replace(&quot;\r&quot;,&nbsp;&quot;&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tag&nbsp;=&nbsp;&quot;$params.Tag&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 如果符合条件的tag指向最新提交则只是显示tag的名字,否则会有相关的后缀来描述该tag之后有多少次提交以及最新的提交commit-id
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//git_tag = sh(returnStdout: true,script: 'git describe --tags --always').trim()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 获取jar的名称
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target_jar_name&nbsp;=&nbsp;sh(returnStdout:&nbsp;true,script:&nbsp;&quot;target_jar_name=\$(ls&nbsp;${params.module}/target/*.jar) && echo \${target_jar_name##*/}&quot;).trim()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module_std&nbsp;=&nbsp;sh(returnStdout:&nbsp;true,script:&nbsp;&quot;module_std=${target_jar_name.replace(&#39;.jar&#39;,&#39;&#39;)}&nbsp;&amp;&amp;&nbsp;echo&nbsp;\${module_std%-[0-9].[0-9]*}&quot;).trim()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 解决打包名称不按正规方式命名, 保证模块代号相同
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;project_prefix=env.DOMAIN_NAME.split(&quot;-&quot;)[0]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module_std&nbsp;=&nbsp;module_std.contains(&quot;$project_prefix&quot;)&nbsp;?&nbsp;module_std&nbsp;:&nbsp;params.module.split(&quot;/")[-1]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module_std&nbsp;=&nbsp;module_std.contains(&quot;$project_prefix&quot;)&nbsp;?&nbsp;module_std&nbsp;:&nbsp;&quot;$project_prefix-$module_std&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 赋值镜像名称
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;docker_image&nbsp;=&nbsp;&quot;${env.DOCKER_REGISTRY_ADDR}/${params.name_space}/${module_std}:$tag&quot;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 编译镜像
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;rm&nbsp;-rf&nbsp;${params.module}/docker/target&nbsp;&amp;&amp;&nbsp;mv&nbsp;${params.module}/target&nbsp;&nbsp;${params.module}/docker&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;docker&nbsp;build&nbsp;-t&nbsp;$docker_image&nbsp;--build-arg&nbsp;JAR_FILE=$target_jar_name&nbsp;&nbsp;${params.module}/docker&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&quot;成DOCKER......&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;docker&nbsp;login&nbsp;${DOCKER_REGISTRY_ADDR}&nbsp;--username=${DOCKER_REGISTRY_USR}&nbsp;--password=${DOCKER_REGISTRY_PSW}&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;docker&nbsp;push&nbsp;$docker_image&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;docker&nbsp;rmi&nbsp;$docker_image&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stage(&#39;Deploy&nbsp;to&nbsp;k8s&#39;){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;agent&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;docker&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;image&nbsp;&quot;ming19871211/kubectl:${K8S_VERSION}&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reuseNode&nbsp;true
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;environment&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 定义k8s访问凭证的环境变量
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KUBECONFIG=&#39;.kube/config&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;steps{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;mkdir&nbsp;-p&nbsp;.kube&nbsp;&amp;&amp;&nbsp;cp&nbsp;$K8S_CONFIG&nbsp;.kube/config&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;script&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java_opts&nbsp;=&nbsp;env.JAVA_OPTS&nbsp;?&nbsp;env.JAVA_OPTS&nbsp;:&nbsp;&quot;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java_opts=&quot;${java_opts}&nbsp;-server&nbsp;-Xms${LIMIT_MEMORY.toInteger()&nbsp;/ 2 }m -Xmx${LIMIT_MEMORY.toInteger() /&nbsp;2}m&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 若有大并发随机数场景 java_opts增加 -Djava.security.egd=file:/dev/./urandom 参数
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(env.IS_SKYWALKING&nbsp;&amp;&amp;&nbsp;env.IS_SKYWALKING&nbsp;==&nbsp;&quot;true&quot;)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java_opts=&quot;${java_opts}&nbsp;-javaagent:/usr/skywalking/agent/skywalking-agent.jar=collector.backend_service=&#39;${SKYWALKING_BACKEND_SERVICE}&#39;,agent.namespace=${params.name_space},agent.service_name=${DOMAIN_NAME}&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;skywalking_vesion&nbsp;=&nbsp;env.SKYWALKING_VESION&nbsp;?&nbsp;env.SKYWALKING_VESION&nbsp;:&nbsp;&quot;7.0.0&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//判断k8s部署空间是否存在,若不存在,则直接创建
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;k8s_namespaces&nbsp;=&nbsp;sh(script:&nbsp;&quot;kubectl&nbsp;get&nbsp;namespaces&nbsp;${params.name_space}&quot;,&nbsp;returnStatus:&nbsp;true)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(k8s_namespaces&nbsp;!=&nbsp;0){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;kubectl&nbsp;create&nbsp;namespace&nbsp;${params.name_space}&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//查看nacos认证密钥是否存在,若不存在则创建
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;nacos_auth_name&nbsp;=&nbsp;sh(script:&nbsp;&quot;kubectl&nbsp;-n&nbsp;${params.name_space}&nbsp;get&nbsp;secret&nbsp;${K8S_NACOS_AUTH}&nbsp;&quot;,&nbsp;returnStatus:&nbsp;true)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(nacos_auth_name&nbsp;!=&nbsp;0){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;kubectl&nbsp;-n&nbsp;${params.name_space}&nbsp;create&nbsp;secret&nbsp;generic&nbsp;${K8S_NACOS_AUTH}&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--from-literal=NACOS_USR=$NACOS_CREDS_USR&nbsp;--from-literal=NACOS_PWD=$NACOS_CREDS_PSW&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//查看docker仓库认证密钥是否存在,若不存在则创建
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;docker_registry_name&nbsp;=&nbsp;sh(script:&nbsp;&quot;kubectl&nbsp;-n&nbsp;${params.name_space}&nbsp;get&nbsp;secret&nbsp;${K8S_DOCKER_REGISTRY}&nbsp;&quot;,&nbsp;returnStatus:&nbsp;true)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(docker_registry_name&nbsp;!=&nbsp;0){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;kubectl&nbsp;-n&nbsp;${params.name_space}&nbsp;create&nbsp;secret&nbsp;docker-registry&nbsp;${K8S_DOCKER_REGISTRY}&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--docker-server=${DOCKER_REGISTRY_ADDR}&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--docker-username=${DOCKER_REGISTRY_USR}&nbsp;--docker-password=${DOCKER_REGISTRY_PSW}&nbsp;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//管理端口
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//manage_port = env.MANAGE_PORT ?  env.MANAGE_PORT : "${CONTAINER_PORT.toInteger() + 10}"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;manage_port&nbsp;=&nbsp;env.MANAGE_PORT&nbsp;?&nbsp;&nbsp;env.MANAGE_PORT&nbsp;:&nbsp;env.CONTAINER_PORT
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 应用上下文件访问根路径
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;app_manage_path&nbsp;=&nbsp;(&nbsp;env.APP_MANAGE_PATH&nbsp;&amp;&amp;&nbsp;env.APP_MANAGE_PATH&nbsp;!=&nbsp;&quot;/" ) ? env.APP_MANAGE_PATH : ""
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//部署服务
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;sed&nbsp;-e&nbsp;&#39;s#__DOCKER_IMAGE__#&#39;$docker_image&#39;#&#39;&nbsp;&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;&#39;s#__DOMAIN_NAME__#&#39;${env.DOMAIN_NAME}&#39;#&#39;&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;&#39;s#__NAME_SPACE__#&#39;${params.name_space}&#39;#&#39;&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;&#39;s#__REPLICAS_NUM__#&#39;${env.REPLICAS_NUM}&#39;#&#39;&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;&#39;s#__CONTAINER_PORT__#&#39;${env.CONTAINER_PORT}&#39;#&#39;&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;&#39;s#__MANAGE_PORT__#&#39;${manage_port}&#39;#&#39;&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;&#39;s#__APP_MANAGE_PATH__#&#39;${app_manage_path}&#39;#&#39;&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;&#39;s#__DOCKER_REGISTRY_SECRET__#&#39;${env.K8S_DOCKER_REGISTRY}&#39;#&#39;&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;&#39;s#__LIMIT_MEMORY__#&#39;${env.LIMIT_MEMORY}&#39;#&#39;&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;\&quot;s#__JAVA_OPTS__#${java_opts}#\&quot;&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;&#39;s#__NACOS_NAMESPACE__#&#39;${params.nacos_namespace}&#39;#&#39;&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;&#39;s#__NACOS_GROUP__#&#39;${params.nacos_group}&#39;#&#39;&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;&#39;s#__NACOS_URL__#&#39;${env.NACOS_URL}&#39;#&#39;&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;&#39;s#__NACOS_AUTH__#&#39;${env.K8S_NACOS_AUTH}&#39;#&#39;&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;&#39;s#__SKYWALKING_VESION__#&#39;${skywalking_vesion}&#39;#&#39;&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;${params.module}/docker/k8s.yaml&nbsp;|&nbsp;kubectl&nbsp;apply&nbsp;-f&nbsp;-&quot;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//查看部署服务的状态
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeout(time:&nbsp;30,&nbsp;unit:&nbsp;&#39;SECONDS&#39;)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;3;&nbsp;i++)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep&nbsp;5
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;kubectl&nbsp;&nbsp;-n&nbsp;${params.name_space}&nbsp;&nbsp;get&nbsp;pods&nbsp;|grep&nbsp;^${env.DOMAIN_NAME}&nbsp;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(&nbsp;i&nbsp;==&nbsp;2&nbsp;){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;no_run_num=&nbsp;sh(returnStdout:&nbsp;true,script:&nbsp;&quot;kubectl&nbsp;get&nbsp;pods&nbsp;-n&nbsp;${params.name_space}&nbsp;|grep&nbsp;^${env.DOMAIN_NAME}&nbsp;|grep&nbsp;-v&nbsp;Running&nbsp;|wc&nbsp;-l&quot;).trim()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&quot;成pods目:&nbsp;$no_run_num&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;post&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;always&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&#39;&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&#39;rm&nbsp;-rf&nbsp;.kube&nbsp;&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;success&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&#39;!&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unstable&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&#39;...&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;failure&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&#39;&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;changed&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&#39;...&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}

vue-nacos

工程结构(vue)

|--- docker文件夹 # 存放部署文件
|------ Dockerfile
|------ Jenkinsfile
|------ k8s.yaml
|------ default.conf
|------ entrypoint.sh
|------ init.js
|--- public
|--- src
|--- vue相关文件
...
|--- .gitlab-ci.yml

配置文件-init.js

类似结构

/* 全局静态初始化环境配置 */
var&nbsp;ENV_API&nbsp;=&nbsp;{
&nbsp;&nbsp;AUTH2_URL:&nbsp;&quot;${AUTH2_URL}&quot;,
&nbsp;&nbsp;SERVICE_API_URL:&nbsp;&quot;${SERVICE_API_URL}&quot;
};

替换变量脚本-entrypoint.sh

该脚本主要用于初始化配置文件占(${ENV_XX})位参数的替换

#!/bin/bash
#配置文件路径,默认是static/js/config.js
__config_file="/usr/share/nginx/html/static/js/config.js"
if [ -n "$VUE_CONFIG_FILE_PATH" ]; then
  ;__config_file="/usr/share/nginx/html/${VUE_CONFIG_FILE_PATH}"
fi;

if [  -f "/init-env/env.conf" ]; then
grep -v "^#" /init-env/env.conf |grep -v ^$  |while read LINE
do
  ;A=`echo $LINE |awk -F "=" '{print $1}'`
  ;B=`echo $LINE |awk -F "$A=" '{print $2}'`
  ;result=$(echo $A | grep "\.")
  if [[ "$result" != "" ]]; then
    echo "#$A=\"$B\"" >>  /init-env/env1.conf
  elif [[ -z "$B" ]]; then
    echo "空行,不需转换舍弃";
  else
    ;B=${B//\"/\\\"}#处理特殊字符
    echo "$A=\"${B/\`/\\\`}\"" >>  /init-env/env1.conf
  fi
done
sed -i &#39;s/\r//' /init-env/env1.conf
#sed -e 's#\&#\\&#g' env.conf > env1.conf
eval "$(cat /init-env/env1.conf)"
rm -f /init-env/env1.conf
else
    echo "/init-env/env.conf文件不存在,注意需要引入外部环境变量哦!";
fi;

#备份配置文件,存在就不备份,不存在就备份
if [ ! -f  "${__config_file}.env" ]; then
  cp ${__config_file} ${__config_file}.env
fi

# 变量替换方式直接会将${}的变量替换掉
if [ -f "/init-env/env.conf" -o "$IS_ENV_REPLACE= "true" ]; then
  #替换${}中的环境变量
eval "cat <<EOF
$(<${__config_file}.env)
EOF
" > ${__config_file}
  #删除环境变量文件
  rm -rf /init-env/env.conf
  #赋予可读权限
  chmod -R +r /usr/share/nginx/html
fi

nginx -g &#39;daemon off;'

部署文件-default.conf

容器内nginx的配置

# 隐藏nginx版本
server_tokens ;off;
# 在某些浏览器上禁用内容类型嗅探。
add_header ;X-Content-Type-Options ;nosniff;
# 此标头启用跨站点脚本 (XSS) 过滤器
add_header ;X-XSS-Protection ;";1; ;mode=block";;
# X-Frame-Options 是为了防止clickJacking 
# DENY:不允许在 frame 中展示#
# SAMEORIGIN:允许在相同域名下frame展示
# ALLOW-FROM https://example.com/ :指定来源的 frame 中展示
# add_header X-Frame-Options SAMEORIGIN;
# 开启gzip
gzip ;on;
# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length ;1k;
# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
gzip_comp_level ;5;
# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
gzip_types ;text/plain ;application/javascript ;application/x-javascript ;text/css ;application/xml ;text/javascript ;application/x-httpd-php ;image/jpeg ;image/gif ;image/png ;application/vnd.ms-fontobject ;font/ttf ;font/opentype ;font/x-woff ;image/svg+xml;
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary ;on;
# 禁用IE 6 gzip
gzip_disable ;";MSIE ;[1-6]\.";;
# 设置压缩所需要的缓冲区大小
gzip_buffers ;32 ;4k;
# 设置gzip压缩针对的HTTP协议版本
gzip_http_version ;1.0;
server ;{
 ; ; ; ;listen ; ; ; ; ; ; ;80;
 ; ; ; ;server_name ; ;localhost;
 ; ; ; ;#charset koi8-r;
 ; ; ; ;#access_log  /var/log/nginx/host.access.log  main;
 ; ; ; ;# 带前缀方式的将 ${SERVER_NAME}替换为对应前缀名称即可,若访问直接在根目录下去掉${SERVER_NAME},去掉多余的/
 ; ; ; ;location ;/${SERVER_NAME} ;{
 ; ; ; ; ; ; ; ;alias ;/usr/share/nginx/html;
 ; ; ; ; ; ; ; ;try_files ;$uri ;$uri/ ;/${SERVER_NAME}/index.html;#根据官网这规则配置
 ; ; ; ; ; ; ; ;expires ;5m;
 ; ; ; ;}
 ; ; ; ;# 若访问直接在根目录下,注释下面三行
 ; ; ; ;location ;= ;/ ;{
 ; ; ; ; ; ; ; ;return ;301 ;$scheme://$host/${SERVER_NAME};
 ; ; ; ;}
 ; ; ; ;error_page ; ; ;500 ;502 ;503 ;504 ; ;/50x.html;
 ; ; ; ;location ;= ;/50x.html ;{
 ; ; ; ; ; ; ; ;root ; ; ;/usr/share/nginx/html;
 ; ; ; ;}
}

部署文件-Dockerfile(vue)

用于容器镜像制作,

FROM nginx:stable
MAINTAINER Qiming Mei <meiqiming@talkweb.com.cn>

ADD default.conf /etc/nginx/conf.d/default.conf
COPY dist/ /usr/share/nginx/html/
COPY init.js /usr/share/nginx/html/static/js/config.js
COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh
#CMD ["/bin/bash","-c", "/entrypoint.sh" ]
ENTRYPOINT ["/entrypoint.sh"]

部署文件-k8s.yaml(vue)

apiVersion: v1
kind: Namespace
metadata:
  name: __NAME_SPACE__
  labels:
    name: __NAME_SPACE__
---
apiVersion: v1
kind: Service
metadata:
  name: __DOMAIN_NAME__
  namespace: __NAME_SPACE__
spec:
  ports:
  - name: app-port
    port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: __DOMAIN_NAME__
---
apiVersion: apps/v1  
kind: Deployment
metadata:
  name: __DOMAIN_NAME__
  namespace: __NAME_SPACE__
spec:
  selector:
    matchLabels:
      app: __DOMAIN_NAME__
  replicas: __REPLICAS_NUM__ 
  template: 
    metadata:
      labels:
        app: __DOMAIN_NAME__
    spec:
      initContainers:
      - name: init-env-sidecar
        image: busybox:latest
        command: [ "sh", "-c"]
        args:
        - set -ex;
          CONFIG_FILE=${CONFIG_FILE:-"vue-comm.properties"};
          SYS_GLOBAL_CONFIG=${SYS_GLOBAL_CONFIG:-"sys-global-config.properties"};
          wget --post-data="username=${NACOS_USR}&password=${NACOS_PWD}" -S "${NACOS_URL}/nacos/v1/auth/users/login" -O login-token;
          access_token=$(grep  -Eo '"accessToken":"([^"]*)"' login-token |awk -F \":\" '{print $2}');
          access_token=${access_token/\"/};
          rm -f /init-env/env.conf;
          rm -f /init-env/env-sys.conf;
          wget "${NACOS_URL}/nacos/v1/cs/configs?dataId=${CONFIG_FILE}&group=${NACOS_GROUP}&tenant=${NACOS_NAMESPACE}&accessToken=$access_token" -O  /init-env/env.conf;
          wget "${NACOS_URL}/nacos/v1/cs/configs?dataId=${SYS_GLOBAL_CONFIG}&group=${NACOS_GROUP}&tenant=${NACOS_NAMESPACE}&accessToken=$access_token" -O  /init-env/env-sys.conf || return 0;
          if [  $? -eq 0 -a -f "/init-env/env-sys.conf" ]; then
            echo -e  "\n" >>  /init-env/env.conf;
            cat /init-env/env-sys.conf >> /init-env/env.conf;
          fi
        env: #环境变量设置
        - name: NACOS_NAMESPACE
          value: __NACOS_NAMESPACE__
        - name: NACOS_GROUP
          value: __NACOS_GROUP__
        - name: SYS_GLOBAL_CONFIG
          value: __SYS_GLOBAL_CONFIG__
        - name: CONFIG_FILE
          value: __CONFIG_FILE__
        - name: NACOS_URL
          value: __NACOS_URL__
        envFrom:
        - secretRef:
            name: __NACOS_AUTH__
        volumeMounts:
        - name: init-env
          mountPath: /init-env/
      containers:
      - name: __DOMAIN_NAME__
        image: __DOCKER_IMAGE__
        imagePullPolicy: IfNotPresent #本地存在就不到远程拉取镜像
        env: #环境变量设置
        - name: TZ
          value: Asia/Shanghai
        - name: DOMAIN_NAME
          value: __DOMAIN_NAME__.__NAME_SPACE__
        resources: #资源限制
          requests:
            memory: "128Mi"
            cpu: "100m" #最低需要 0.1个cpu
          limits:
            memory: "__LIMIT_MEMORY__Mi"
            cpu: "1000m"
        ports:
        - containerPort: 80
        readinessProbe: #就绪探针
        #  httpGet:
        #    path: /index.html
        #    port: 80
          tcpSocket:
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 15
          timeoutSeconds: 5
        livenessProbe: #健康检查
        #  httpGet:
        #    path: /index.html
        #    port: 80
          tcpSocket:
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 15
          timeoutSeconds: 5
        volumeMounts:
        - name: time-config
          mountPath: /etc/localtime
          readOnly: true
        - name: init-env
          mountPath: /init-env/
      imagePullSecrets:
      - name: __DOCKER_REGISTRY_SECRET__
      nodeSelector:
        isDev: "true"
      volumes:
      - name: time-config
        hostPath:
          path: /etc/localtime
      - name: init-env
        emptyDir: {}

部署文件-Jenkinsfile(vue)

def docker_image = "" //定义全局的镜像变量
pipeline {
    /*
    1.配置docker仓库相关变量 系统环境变量:DOCKER_REGISTRY_ADDR [docker仓库地址]
    credentials-[Username with password]类型:jenkins-docker-registry-creds[docker仓库账号/docker仓库密码]
    2.配置nacos相关变量 定义账号密码对应下面的NACOS_URL
    credentials-[Username with password]类型:jenkins-nacos-creds[nacos登录账号/nacos登录密码]
    3.配置k8s相关变量 credentials-[Secret file]类型: jenkins-k8s-config[k8s集群访问凭证文件]

    合计:1个docker仓库地址环境变量,3个credentials为必须配置;
    `参考文档`:https://www.jenkins.io/zh/doc/book/pipeline/jenkinsfile
    `编写语法参考 `:http://groovy-lang.org/semantics.html
     */
    // 如果指定具体的节点执行,请 agent { label 'docker-slave' }
    agent any
    options {
        //超时一小时
        timeout(time: 1, unit: 'HOURS')
        //不允许同时执行
        disableConcurrentBuilds()
    }
// #######################需要修改的区域 开始#################################
    /*** 一般情况下只需要修改environment与parameters区域的 
    * 修改以下值即可 ${SERVER_NAME} ${NAME_SPACE} ${NACOS_NAMESPACE} 
    * 一般情况建议把nacos空间与部署空间值设置相同,容易理解
    * nacos配置文件非默认值,eg:vue-comm.properties的,修改为指定名称的属性即可
    */
    environment {
        // 服务的域名,一般与项目名称相同
        DOMAIN_NAME='${SERVER_NAME}'
        // 注册中心的实例数量
        REPLICAS_NUM=1
        // 表示限制内存大小,单位为M,只能为数字;
        LIMIT_MEMORY=2048
        // docker仓库地址,一般与系统环境变量相同,若相同时手动修改
        DOCKER_REGISTRY_ADDR="${env.DOCKER_REGISTRY_ADDR}"
        // docker仓库账号密码--对应系统环境变量DOCKER_REGISTRY_ADDR
        DOCKER_REGISTRY=credentials('jenkins-docker-registry-creds')
        // 注册中心域名,默认是nacos 一般不需要修改
        NACOS_URL='nacos-headless.talkweb:8848'
        // nacos凭证-对应NACOS_URL
        NACOS_CREDS=credentials('jenkins-nacos-creds')
        // nacos配置中心配置文件名称(dataId)
        CONFIG_FILE="vue-comm.properties"
        // nacos配置中心配置文件名称(dataId) 系统全局配置
        SYS_GLOBAL_CONFIG="sys-global-config.properties"
        // k8s版本号
        K8S_VERSION='v1.19.16'
        // K8s配置文件路径
        K8S_CONFIG=credentials('jenkins-k8s-config')
        // k8s中nacos账号密码存储的secret名称
        K8S_NACOS_AUTH="nacos-auth"
        // k8s中docker仓库信息存储的secret名称
        K8S_DOCKER_REGISTRY="hub-local"
    }
    parameters {
        // 修改部署的域名空间
        string(name:'name_space', defaultValue: "${NAME_SPACE}", description: '发布的命名空间')
        // 项目名称
        string(name:'module', defaultValue: "${SERVER_NAME}", description: '发布的项目')
        // nacos空间
        choice(name: 'nacos_namespace', choices: ['${NACOS_NAMESPACE}'], description: 'nacos命名空间')
        // nacos组
        choice(name: 'nacos_group', choices: ['DEFAULT_GROUP'], description: 'nacos组名称')
        // 配置Tag的git参数,参数类型 设置为 分支或标签
        // 配置git地址:在流水线 -> 定义[Pipeline script from SCM] -> SCM[git] -> Repository URL[git地址]
        // -> Credentials[git账号] -> 指定分支(为空时代表any)[${Tag}] --> 脚本路径[Jenkinsfile文件的工程路径]
        // -> 轻量级检出[去掉√ ]
    }
// ########################需要修改的区域 结束################################
    stages {
        stage('Run node') {
            agent {
                docker {
                    image 'node:12'
                    reuseNode true
                }
            }
            steps {
                sh "npm -v && node -v && npm config set registry https://registry.npm.taobao.org && npm install && npm run build "
            }
        }
        stage('Build And Push Docker Image'){
            steps {
                script {
                    // 获取标签版本或者分支的commitId
                    if (!params.Tag || params.Tag.contains('origin/')) {
                        sh "git rev-parse --short HEAD > commit-id"
                        tag = readFile('commit-id').replace("\n", "").replace("\r", "")
                    } else {
                        tag = "$params.Tag"
                    }
                    // 如果符合条件的tag指向最新提交则只是显示tag的名字,否则会有相关的后缀来描述该tag之后有多少次提交以及最新的提交commit-id
                    //git_tag = sh(returnStdout: true,script: 'git describe --tags --always').trim()
                    // 赋值镜像名称
                    docker_image = "${env.DOCKER_REGISTRY_ADDR}/${params.name_space}/${params.module}:$tag"

                    // 编译镜像
                    sh "rm -rf docker/dist && mv dist docker/"
                    sh "docker build -t $docker_image docker"
                }
                echo "完成DOCKER镜像打包......"
                sh "docker login ${DOCKER_REGISTRY_ADDR} --username=${DOCKER_REGISTRY_USR} --password=${DOCKER_REGISTRY_PSW}"
                sh "docker push $docker_image"
                sh "docker rmi $docker_image"
            }
        }
        stage('Deploy to k8s'){
            agent {
                docker {
                    image "ming19871211/kubectl:${K8S_VERSION}"
                    reuseNode true
                }
            }
            environment {
                // 定义k8s访问凭证的环境变量
                KUBECONFIG='.kube/config'
            }
            steps{
                sh "mkdir -p .kube && cp $K8S_CONFIG .kube/config"
                script {
                    //判断k8s部署空间是否存在,若不存在,则直接创建
                    def k8s_namespaces = sh(script: "kubectl get namespaces ${params.name_space}", returnStatus: true)
                    if (k8s_namespaces != 0){
                        sh "kubectl create namespace ${params.name_space}"
                    }
                    //查看nacos认证密钥是否存在,若不存在则创建
                    def nacos_auth_name = sh(script: "kubectl -n ${params.name_space} get secret ${K8S_NACOS_AUTH} ", returnStatus: true)
                    if (nacos_auth_name != 0){
                        sh "kubectl -n ${params.name_space} create secret generic ${K8S_NACOS_AUTH} \
                        --from-literal=NACOS_USR=$NACOS_CREDS_USR --from-literal=NACOS_PWD=$NACOS_CREDS_PSW"
                    }
                    //查看docker仓库认证密钥是否存在,若不存在则创建
                    def docker_registry_name = sh(script: "kubectl -n ${params.name_space} get secret ${K8S_DOCKER_REGISTRY} ", returnStatus: true)
                    if (docker_registry_name != 0){
                        sh "kubectl -n ${params.name_space} create secret docker-registry ${K8S_DOCKER_REGISTRY} \
                        --docker-server=${DOCKER_REGISTRY_ADDR} \
                        --docker-username=${DOCKER_REGISTRY_USR} --docker-password=${DOCKER_REGISTRY_PSW} "
                    }
                    //部署服务
                    sh "sed -e 's#__DOCKER_IMAGE__#'$docker_image'#'  \
                    -e 's#__DOMAIN_NAME__#'${env.DOMAIN_NAME}'#' \
                    -e 's#__NAME_SPACE__#'${params.name_space}'#' \
                    -e 's#__REPLICAS_NUM__#'${env.REPLICAS_NUM}'#' \
                    -e 's#__DOCKER_REGISTRY_SECRET__#'${env.K8S_DOCKER_REGISTRY}'#' \
                    -e 's#__LIMIT_MEMORY__#'${env.LIMIT_MEMORY}'#' \
                    -e 's#__NACOS_NAMESPACE__#'${params.nacos_namespace}'#' \
                    -e 's#__NACOS_GROUP__#'${params.nacos_group}'#' \
                    -e 's#__CONFIG_FILE__#'${env.CONFIG_FILE}'#' \
                    -e 's#__SYS_GLOBAL_CONFIG__#'${env.SYS_GLOBAL_CONFIG}'#' \
                    -e 's#__NACOS_URL__#'${env.NACOS_URL}'#' \
                    -e 's#__NACOS_AUTH__#'${env.K8S_NACOS_AUTH}'#' \
                    docker/k8s.yaml | kubectl apply -f -"

                    //查看部署服务的状态
                    timeout(time: 30, unit: 'SECONDS') {
                        for (int i = 0; i < 3; i++) {
                            sleep 5
                            sh "kubectl  -n ${params.name_space}  get pods |grep ^${env.DOMAIN_NAME} "
                            if ( i == 2 ){
                                no_run_num= sh(returnStdout: true,script: "kubectl get pods -n ${params.name_space} |grep ^${env.DOMAIN_NAME} |grep -v Running |wc -l").trim()
                                echo "还未部署完成pods数目: $no_run_num"
                            }
                        }
                    }
                }
            }
        }
    }
    post {
        always {
            echo '执行完成。'
            sh 'rm -rf .kube '
        }
        success {
            echo '恭喜你,发布成功了!'
        }
        unstable {
            echo '发布不稳定哦...'
        }
        failure {
            echo '发布失败啦,请查明原因哦!'
        }
        changed {
            echo '与之前信息有所不同哦...'
        }
    }
}

jenkins任务创建-发布服务

  1. 选择新建任务
  2. 输入一个任务名称:[工程名称或工程子模块名称,eg:子模块1] -->选择流水线-->确定

持续集成CI&CD之CI的完整版最佳实践_git_02

  1. 丢弃旧的构建-->保持构建的天数:[7]-->保持构建的最大个数:[7]

持续集成CI&CD之CI的完整版最佳实践_java_03

  1. 选择参数化构建-->添加git参数-->名称:[Tag] -->参数分支:[分支或标签]-->默认值[origin/dev]

持续集成CI&CD之CI的完整版最佳实践_kubernetes_04

  1. 流水线-->定义:[pipeline script from SCM] -->SCM:[git]-->Repository URL:[工程的git地址]-->Credentials:[访问git的账号密码] --> 指定分支(为空时代表any):[${Tag}] --> 脚本路径:[Jenkinsfile文件路径,eg:子模块1/docker/Jenkinsfile] -->轻量级检出:去掉√

持续集成CI&CD之CI的完整版最佳实践_kubernetes_05

注意:新建任务前,需要将Jenkinsfile文件注释的前4点,在jenkins系统中配置好。

扩展标准的docker部署

为了不与上面k8s的jenkinsfile冲突,docker部署我们jenkinsfile名称为​​Jenkinsfile-docker​​文件(不会使用上面的jenkinsfile与k8s.yaml文件)


def&nbsp;docker_image&nbsp;=&nbsp;&quot;&quot;&nbsp;//定义全局的镜像变量
pipeline&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;/*
    1.配置maven相关变量 credentials-[Secret file]类型: jenkins-maven-setting[maven setting.xml文件]
    2.配置docker仓库相关变量 系统环境变量:DOCKER_REGISTRY_ADDR [docker仓库地址]
    credentials-[Username with password]类型:jenkins-docker-registry-creds[docker仓库账号/docker仓库密码]
    3.配置nacos相关变量 系统环境变量:NACOS_URL[nacos地址]
    credentials-[Username with password]类型:jenkins-nacos-creds[nacos登录账号/nacos登录密码
    4.配置docker客户端访问的证书
    credentials-[X.509 Client Certificate]类型:jenkins-docker-client-creds[docker客户端凭证]
    5.若需要启动skywalking链路跟踪,需要配置环境变量IS_SKYWALKING=true, SKYWALKING_VESION=[skywalking的版本号]

    合计:1个docker仓库地址环境变量,4个credentials为必须配置;2个skywalking环境变量根据需求配置;
    `参考文档`:https://www.jenkins.io/zh/doc/book/pipeline/jenkinsfile
    `编写语法参考 `:http://groovy-lang.org/semantics.html
     */
&nbsp;&nbsp;&nbsp;&nbsp;// 如果指定具体的节点执行,请 agent { label 'docker-slave' }
&nbsp;&nbsp;&nbsp;&nbsp;agent&nbsp;any
&nbsp;&nbsp;&nbsp;&nbsp;options&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//超时一小时
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeout(time:&nbsp;1,&nbsp;unit:&nbsp;&#39;HOURS&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//不允许同时执行
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;disableConcurrentBuilds()
&nbsp;&nbsp;&nbsp;&nbsp;}
// #######################需要修改的区域 开始#################################
&nbsp;&nbsp;&nbsp;&nbsp;/*** 一般情况下只需要修改environment与parameters区域的 ${SERVER_NAME} ${MODULE_NAME}  ${NAME_SPACE}
     * ${NACOS_NAME_SPACE}  没有多层子项目的情况下SERVER_NAME与MODULE_NAME一般是相同的
     **/
&nbsp;&nbsp;&nbsp;&nbsp;environment&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 服务的域名,一般与项目名称相同
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DOMAIN_NAME=&#39;${SERVER_NAME}&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 表示限制内存大小,单位为M,只能为数字;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LIMIT_MEMORY=2048
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// maven配置文件setting路径
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MAVEN_SETTING=credentials(&#39;jenkins-maven-setting&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// docker仓库地址,一般与系统环境变量相同,若不相同时手动修改
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DOCKER_REGISTRY_ADDR=&quot;${env.DOCKER_REGISTRY_ADDR}&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// docker仓库账号密码--对应系统环境变量DOCKER_REGISTRY_ADDR
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DOCKER_REGISTRY=credentials(&#39;jenkins-docker-registry-creds&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 注册中心域名,默认是nacos 一般与系统环境变量相同,若不相同时手动修改
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NACOS_URL=&quot;${env.NACOS_URL}&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// nacos凭证-对应NACOS_URL
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NACOS_CREDS=credentials(&#39;jenkins-nacos-creds&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 根据需求,xms、xmm已经自动添加 此处不用添加
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//JAVA_OPTS="-Dspring.XXX=XXX "
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;parameters&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 修改部署的域名空间
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string(name:&#39;name_space&#39;,&nbsp;defaultValue:&nbsp;&quot;${NAME_SPACE}&quot;,&nbsp;description:&nbsp;&#39;&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 修改为子项目名称 多层情况,eg: soeasy-clm-message/soeasy-clm-message-server
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string(name:&#39;module&#39;,&nbsp;defaultValue:&nbsp;&quot;${MODULE_NAME}&quot;,&nbsp;description:&nbsp;&#39;&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// nacos空间
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;choice(name:&nbsp;&#39;nacos_namespace&#39;,&nbsp;choices:&nbsp;[&#39;${NACOS_NAME_SPACE}&#39;],&nbsp;description:&nbsp;&#39;nacos&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// nacos组
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;choice(name:&nbsp;&#39;nacos_group&#39;,&nbsp;choices:&nbsp;[&#39;DEFAULT_GROUP&#39;],&nbsp;description:&nbsp;&#39;nacos&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 以下4项参数需要配置到jenkins工程的参数中 */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// string(name:'container_port', defaultValue: "", description: '容器端口')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// string(name:'docker_remotes', defaultValue: "", description: '远程docker的api地址列表,以“,”隔开')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// string(name:'is_tls', defaultValue: "true", description: 'docker的api访问是否开启tls认证')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 服务部署扩展的环境变量,eg
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// choice(name: 'init_env', choices: ['-e ACTIVE_PROFILES=dev -e SENTINEL_DASHBOARD=10.154.142.19:8718'], description: '服务部署扩展的环境变量')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 以下配置为jenkins工程必须设置 */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 配置Tag的git参数,参数类型 设置为 分支或标签
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 配置git地址:在流水线 -> 定义[Pipeline script from SCM] -> SCM[git] -> Repository URL[git地址]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// -> Credentials[git账号] -> 指定分支(为空时代表any)[${Tag}] --> 脚本路径[Jenkinsfile文件的工程路径]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// -> 轻量级检出[去掉√ ]
&nbsp;&nbsp;&nbsp;&nbsp;}
// ########################需要修改的区域 结束################################
&nbsp;&nbsp;&nbsp;&nbsp;stages&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stage(&#39;Run&nbsp;maven&#39;)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;agent&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;docker&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;image&nbsp;&#39;maven:3.5-jdk-8-alpine&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;args&nbsp;&#39;-v&nbsp;$HOME/.m2:$HOME/.m2&nbsp;&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reuseNode&nbsp;true
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;environment&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 设置maven本地仓库地址
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MAVEN_OPTS=&quot;&nbsp;-Dmaven.repo.local=$HOME/.m2/repository&nbsp;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;steps&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;mvn&nbsp;-version&nbsp;&amp;&amp;&nbsp;mvn&nbsp;clean&nbsp;package&nbsp;-pl&nbsp;${params.module}&nbsp;-am&nbsp;-Dmaven.test.skip=true&nbsp;-s&nbsp;$MAVEN_SETTING&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stage(&#39;Build&nbsp;And&nbsp;Push&nbsp;Docker&nbsp;Image&#39;){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;steps&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;script&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 获取标签版本或者分支的commitId
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!params.Tag&nbsp;||&nbsp;params.Tag.contains(&#39;origin/&#39;))&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;git&nbsp;rev-parse&nbsp;--short&nbsp;HEAD&nbsp;&gt;&nbsp;commit-id&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tag&nbsp;=&nbsp;readFile(&#39;commit-id&#39;).replace(&quot;\n&quot;,&nbsp;&quot;&quot;).replace(&quot;\r&quot;,&nbsp;&quot;&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tag&nbsp;=&nbsp;&quot;$params.Tag&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 如果符合条件的tag指向最新提交则只是显示tag的名字,否则会有相关的后缀来描述该tag之后有多少次提交以及最新的提交commit-id
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//git_tag = sh(returnStdout: true,script: 'git describe --tags --always').trim()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 获取jar的名称
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target_jar_name&nbsp;=&nbsp;sh(returnStdout:&nbsp;true,script:&nbsp;&quot;target_jar_name=\$(ls&nbsp;${params.module}/target/*.jar) && echo \${target_jar_name##*/}&quot;).trim()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module_std&nbsp;=&nbsp;sh(returnStdout:&nbsp;true,script:&nbsp;&quot;module_std=${target_jar_name.replace(&#39;.jar&#39;,&#39;&#39;)}&nbsp;&amp;&amp;&nbsp;echo&nbsp;\${module_std%-[0-9].[0-9]*}&quot;).trim()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 解决打包名称不按正规方式命名, 保证模块代号相同
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;project_prefix=env.DOMAIN_NAME.split(&quot;-&quot;)[0]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module_std&nbsp;=&nbsp;module_std.contains(&quot;$project_prefix&quot;)&nbsp;?&nbsp;module_std&nbsp;:&nbsp;params.module.split(&quot;/")[-1]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module_std&nbsp;=&nbsp;module_std.contains(&quot;$project_prefix&quot;)&nbsp;?&nbsp;module_std&nbsp;:&nbsp;&quot;$project_prefix-$module_std&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 赋值镜像名称
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;docker_image&nbsp;=&nbsp;&quot;${env.DOCKER_REGISTRY_ADDR}/${params.name_space}/${module_std}:$tag&quot;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 编译镜像
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;rm&nbsp;-rf&nbsp;${params.module}/docker/target&nbsp;&amp;&amp;&nbsp;mv&nbsp;${params.module}/target&nbsp;&nbsp;${params.module}/docker&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;docker&nbsp;build&nbsp;-t&nbsp;$docker_image&nbsp;--build-arg&nbsp;JAR_FILE=$target_jar_name&nbsp;&nbsp;${params.module}/docker&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&quot;成DOCKER......&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;docker&nbsp;login&nbsp;${DOCKER_REGISTRY_ADDR}&nbsp;--username=${DOCKER_REGISTRY_USR}&nbsp;--password=${DOCKER_REGISTRY_PSW}&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;docker&nbsp;push&nbsp;$docker_image&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;docker&nbsp;rmi&nbsp;$docker_image&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stage(&#39;Deploy&nbsp;to&nbsp;docker&#39;){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;environment&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// docker客户端证书凭证,若不需要ssl访问则注释
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DOCKER_CERT_PATH&nbsp;=&nbsp;credentials(&#39;jenkins-docker-client-creds&#39;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;steps{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;script&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 确定端口
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;container_port=80&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;container_port_map&nbsp;=&nbsp;&quot;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;skywalking_volume_map&nbsp;=&nbsp;&quot;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;docker_client_env=&quot;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(params.container_port)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;container_port=&quot;${params.container_port}&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;container_port_map&nbsp;=&nbsp;&quot;&nbsp;-p&nbsp;${params.container_port}:${params.container_port}&nbsp;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 确定部署机器
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;docker_remote_arr&nbsp;=&nbsp;&quot;${params.docker_remotes}&quot;.split(&quot;,&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;docker_remote_arr.size();&nbsp;++i)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;docker_remote&nbsp;=&nbsp;&quot;${docker_remote_arr[i]}&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(params.docker_remotes)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;docker_client_env=&quot;export&nbsp;DOCKER_TLS_VERIFY=1;&nbsp;export&nbsp;DOCKER_HOST=tcp://${docker_remote}; docker_remote=${docker_remote} ;"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(params.is_tls&nbsp;&amp;&amp;&nbsp;params.is_tls&nbsp;==&nbsp;&quot;false&quot;)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;docker_client_env=&quot;export&nbsp;-n&nbsp;DOCKER_TLS_VERIFY;&nbsp;export&nbsp;DOCKER_HOST=tcp://${docker_remote}; docker_remote=${docker_remote} ;"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//部署服务
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;$docker_client_env&nbsp;docker&nbsp;rm&nbsp;-f&nbsp;$DOMAIN_NAME&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 确定java_opts参数
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java_opts&nbsp;=&nbsp;env.JAVA_OPTS&nbsp;?&nbsp;env.JAVA_OPTS&nbsp;:&nbsp;&quot;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java_opts=&quot;${java_opts}&nbsp;-server&nbsp;-Xms${LIMIT_MEMORY.toInteger()&nbsp;/ 2 }m -Xmx${LIMIT_MEMORY.toInteger() /&nbsp;2}m&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 若有大并发随机数场景 java_opts增加 -Djava.security.egd=file:/dev/./urandom 参数
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(env.IS_SKYWALKING&nbsp;&amp;&amp;&nbsp;env.IS_SKYWALKING&nbsp;==&nbsp;&quot;true&quot;)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;skywalking_vesion&nbsp;=&nbsp;env.SKYWALKING_VESION&nbsp;?&nbsp;env.SKYWALKING_VESION&nbsp;:&nbsp;&quot;7.0.0&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java_opts&nbsp;=&nbsp;&quot;${java_opts}&nbsp;-javaagent:/usr/skywalking/agent/skywalking-agent.jar=collector.backend_service=&#39;${SKYWALKING_BACKEND_SERVICE}&#39;,agent.namespace=${params.name_space},agent.service_name=${DOMAIN_NAME}&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;skywalking_volume_name&nbsp;=&nbsp;&quot;$DOMAIN_NAME-skywalking-vol&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;skywalking_volume_map&nbsp;=&nbsp;&quot;-v&nbsp;${skywalking_volume_name}:/usr/skywalking&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//创建一个配置卷
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;$docker_client_env&nbsp;docker&nbsp;volume&nbsp;rm&nbsp;-f&nbsp;$skywalking_volume_name&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;$docker_client_env&nbsp;docker&nbsp;volume&nbsp;create&nbsp;$skywalking_volume_name&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//创建一个初始化配置卷的容器容器
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;$docker_client_env&nbsp;docker&nbsp;run&nbsp;--rm&nbsp;--name=${skywalking_volume_name}&nbsp;&nbsp;-d&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-v&nbsp;$skywalking_volume_name:/data ming19871211/skywalking-agent:${skywalking_vesion}&nbsp;mv&nbsp;/skywalking/agent&nbsp;/data/&nbsp;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;env_params=&quot;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(params.init_env)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;env_params&nbsp;=&nbsp;&quot;${params.init_env}&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&quot;$docker_client_env&nbsp;docker&nbsp;run&nbsp;-d&nbsp;--name&nbsp;${DOMAIN_NAME}&nbsp;--hostname&nbsp;${DOMAIN_NAME}&nbsp;--restart=always&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;TZ=&#39;Asia/Shanghai&#39;&nbsp;-e&nbsp;CONTAINER_PORT=${container_port}&nbsp;-e&nbsp;DOMAIN_NAME=\${docker_remote%:*}&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;NACOS_URL=&#39;${NACOS_URL}&#39;&nbsp;-e&nbsp;NACOS_USR=${NACOS_CREDS_USR}&nbsp;-e&nbsp;NACOS_PWD=${NACOS_CREDS_PSW}&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;NACOS_NAMESPACE=&#39;${params.nacos_namespace}&#39;&nbsp;-e&nbsp;NACOS_GROUP=&#39;${params.nacos_group}&#39;&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-e&nbsp;DEPLOY_ENV=&#39;${params.nacos_namespace}&#39;&nbsp;-e&nbsp;JAVA_OPTS=&#39;${java_opts}&#39;&nbsp;${env_params}&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$container_port_map&nbsp;-v&nbsp;/etc/localtime:/etc/localtime:ro&nbsp;&nbsp;$skywalking_volume_map&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-m&nbsp;${LIMIT_MEMORY}M&nbsp;$docker_image&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;post&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;always&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&#39;&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;success&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&#39;!&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unstable&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&#39;...&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;failure&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&#39;&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;changed&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&#39;...&#39;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}

标准doker的jenkins部署任务创建

  1. 选择新建任务
  2. 输入一个任务名称:[工程名称或工程子模块名称,eg: 子模块1] -->选择流水线-->确定
  3. 丢弃旧的构建-->保持构建的天数:[7]-->保持构建的最大个数:[7]
  4. 选择参数化构建-->添加字符参数-->名称:[container_port] -->默认值[容器端口,eg: 10000]
  5. 选择参数化构建-->添加字符参数-->名称:[docker_remotes] -->默认值[远程docker的api地址列表 , eg: 192.168.146.91:2378]

持续集成CI&CD之CI的完整版最佳实践_git_06

  1. 选择参数化构建-->添加git参数-->名称:[Tag] -->默认值[origin/dev]
  2. 流水线-->定义:[pipeline script from SCM] -->SCM:[git]-->Repository URL:[工程的git地址]-->Credentials:[访问git的账号密码] --> 指定分支(为空时代表any):[${Tag}] --> 脚本路径:[Jenkinsfile文件路径,eg: 子模块1/docker/Jenkinsfile-docker] -->轻量级检出:去掉√

持续集成CI&CD之CI的完整版最佳实践_kubernetes_07

注意:新建任务前,需要将Jenkinsfile-docker文件注释的前4点,在jenkins系统中配置好。

部署环境运维操作

操作部署相关见下一章节: 持续集成CI&CD之CD的完整版最佳实践​​​​

举报

相关推荐

0 条评论