分享

Jenkins GitLab Docker SpringCloud Kubernetes构建可持续自动化微服务系统

 也算是读过四书 2021-01-31

  现有混合云平台的场景下,即有线下和线上的环境,又有测试与正式的场景,而且结合了Docker,导致打包内容有所区分,且服务的发布流程复杂起来,手工打包需要在编译阶段就要根据环境到处更改配置,因此纯手工发布增加了实施的难度,需要一个统一的适应各种环境部署的方案。

基于微服务的发布流程

  手动/自动构建 -> Jenkins 调度 K8S API ->动态生成 Jenkins Slave pod - Slave pod 拉取 Git 代码/编译/打包镜像 ->推送到镜像仓库 Harbor - Slave工作完成,Pod 自动销毁 ->部署到测试或生产 KubernetesK8S)平台。

  上面是理想状况下的将服务编译打包成镜像上传到镜像库后部署到Kubernetes平台的一个流程,但问题是:

  1. 我们有线上线下平台,代码在线下GitLab,是出不了外网的,因此线上K8S集群无法拉取代码编译。

  2. Jenkinsmaster所在服务器是CentOS6.5,没有Docker环境,也没有在K8S集群服务器内,因此无法直接执行docker build镜像和 kubectl apply 发布服务到K8S集群。

  3. Jenkinsslave节点都是无法访问外网的,

  4. 线上服务需要Pinpoint而线下环境暂时不需要启用Pinpoint,否则一直报错,因此需要根据选择的环境动态的构建Dockerfile,而且要求整个发布流程可选择。

就上面现实问题,我们将发布流程简化:

关键点:

Docker镜像的打包使用com.spotifydocker-maven-plugin插件结合Dockerfile,调用远程服务器的Docker环境生成镜像。

K8S服务部署采用的是ssh方式,将Deployment文件上传到K8S集群服务器,然后执行部署命令。

如何利用Dockerfile打包镜像

  之前也是用com.spotifydocker-maven-plugin插件来打包镜像并推送到私有镜像仓库,但问题是无法根据环境写条件判断,如动态选择是否需要启动pinpoint,线上线下库地址动态更换,导致镜像名前缀也是要动态变化的,此时直接配置无法满足,需要结合Dockerfile来实现。

先更改pom文件,指定本项目的Dockerfile文件地址,默认是放在项目根目录下:

           <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>1.2.0</version>
                <configuration>
                    <!--覆盖相同标签镜像-->
                    <forceTags>true</forceTags>
                    <!-- 与maven配置文件settings.xml一致 -->
                    <serverId>nexus-releases</serverId>
                    <!--私有仓库地址 -->
                    <registryUrl>https://${docker.repostory}</registryUrl>
                    <!--远程Docker地址 -->
                    <dockerHost>http://10.3.87.210:2375</dockerHost>
                    <!-- 注意imageName一定要是符合正则[a-z0-9-_.]的,否则构建不会成功 -->
                    <!--指定镜像名称 仓库/镜像名:标签-->
<imageName>${docker.repostory}/${project.artifactId}:${project.version}</imageName>
                    <dockerDirectory>${project.basedir}</dockerDirectory>
                    <resources>
                        <resource>
                            <!-- 指定要复制的目录路径,这里是当前目录 -->
                            <!-- 将打包文件放入dockerDirectory指定的位置 -->
                            <targetPath>/app/</targetPath>
                            <!-- 指定要复制的根目录,这里是target目录 -->
                            <directory>${project.build.directory}</directory>
                            <!-- 指定需要拷贝的文件,这里指最后生成的jar包 -->
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>

<registryUrl>https://${docker.repostory}</registryUrl>

指定远程仓库地址,在主项目的<properties>中指定,这里默认线上仓库<docker.repostory>39.95.40.97:5000</docker.repostory>

<dockerHost>http://10.3.87.210:2375</dockerHost>

指定Docker镜像打包服务器,这里指定线下服务器。

<imageName>${docker.repostory}/${project.artifactId}:${project.version}</imageName>

指定镜像名称 仓库/镜像名:标签

<dockerDirectory>${project.basedir}</dockerDirectory>

指定Dockerfile文件地址,此处指定项目根目录

Dockerfile内容

FROM join:0.2
 
MAINTAINER {description} Join
 
ADD /app/{artifactId}-{version}.jar /app/
 
ENTRYPOINT ["java", "-Xmx512m","-Dspring.profiles.active={active}",{jarparam} "-jar", "/app/{artifactId}-{version}.jar"]

  基础镜像用join:0.2,里面包含了pinpoint和监控jvmpromethus客户端包。

  Jarparam会在Jenkins中动态替换运行时参数,active 指定当前运行环境,这里可能有人提议根据项目yml文件中指定内容自动匹配,因为要考虑到如果自动匹配 更换线上线下环境就需要更改yml配置文件后又要上传到gitlab,如此没有必要多做一步,直接在Jenkins中当作参数指定最为便捷。

  此处Dockerfile是通用模板,如果有特殊内容添加,可自行更改,此时的域名交易模板需要在Jenkins运行时替换参数后才有用,如果想直接在本机运行打包,可手动替换参数内容后运行:

clean package -DskipTests docker:build

推送

clean package -DskipTests docker:build -DpushImage

Jenkins发布流程

利用Jenkinspipeline构建流水线

  Pipeline也就是构建流水线,对于程序员来说,最好的解释是:使用代码来控制项目的构建、测试、部署等。使用它的好处有很多,包括但不限于:

使用Pipeline可以非常灵活的控制整个构建过程;

可以清楚的知道每个构建阶段使用的时间,方便构建的优化;

构建出错,使用stageView可以快速定位出错的阶段;

一个job可以搞定整个构建,方便管理和维护等。

  Pipeline 支持两种语法,声明式和脚本式。这两种方法都支持构建持续交付流水线,都可以通过 web UI Jenkinsfile 文件来定义 Pipeline(通常认为创建 Jenkinsfile 文件并上传到源代码控制仓库是最佳实践)

Jenkinsfile 就是一个包含对 Jenkins Pipeline 定义的文本文件,会上传到版本控制中。下面的 Pipeline 实现了基本的 3 段持续交付流水线。

声明式 Pipeline

// Jenkinsfile (Declarative Pipeline)
 
pipeline {
 
    agent any
 
    stages {
 
        stage('Build') {
 
            steps {
 
                echo 'Building..'
 
            }
 
        }
 
        stage('Test') {
 
            steps {
 
                echo 'Testing..'
 
            }
 
        }
 
        stage('Deploy') {
 
            steps {
 
                echo 'Deploying....'
 
            }
 
        }
 
    }
 
}

对应的脚本式 Pipeline

// Jenkinsfile (Scripted Pipeline)
 
node {
 
    stage('Build') {
 
        echo 'Building....'
 
    }
 
    stage('Test') {
 
        echo 'Building....'
 
    }
 
    stage('Deploy') {
 
        echo 'Deploying....'
 
    }
 
}

  注意,所有的 Pipeline 都会有这三个相同的 stage,可以在所有项目的一开始就定义好它们。下面演示在 Jenkins 的测试安装中创建和执行一个简单的 Pipeline

  假设项目已经设置好了源代码控制仓库,并且已经按照入门章节的描述在 Jenkins 中定义好了 Pipeline

  使用文本编辑器(最好支持 Groovy 语法高亮显示),在项目根目录中创建 Jenkinsfile

  上面的声明式 Pipeline 示例包含了实现一个持续交付流水线所需的最少步骤。必选指令 agent 指示 Jenkins Pipeline 分配执行程序和工作空间。没有 agent 指令的话,声明式 Pipeline 无效,无法做任何工作!默认情况下 agent 指令会确保源代码仓库已经检出,并且可用于后续步骤。

  stage step 指令在声明式 Pipeline 中也是必须的,用于指示 Jenkins 执行什么及在哪个 stage 中执行。

  对于脚本式 Pipeline 的更高级用法,上面的示例节点是至关重要的第一步,因为它为 Pipeline 分配了一个执行程序和工作空间。如果没有 nodePipeline 不能做任何工作!在 node 内,业务的第一阶段是检出此项目的源代码。由于 Jenkinsfile 是直接从源代码控制中提取的,因此 Pipeline 提供了一种快速简单的方法来访问源代码的正确版本:

// Jenkinsfile (Scripted Pipeline)

node {

    checkout scm

    /* .. snip .. */

}

这个 checkout 步骤会从源代码控制中检查代码,scm 是特殊变量,它指示运行检出步骤,复制触发了这次 Pipeline 运行的指定版本。

最终的流程样式:

  一般用声明式来构建流水,实际操作过程中还是发现脚本式构建更顺手,而且Groovy语言更方便查资料,因此下面以脚本构建为主演示一个流程。

1.新建任务

2.填写任务名和描述,由于防止构建历史太多,只保留3个。

3.添加构建时全局构建参数,用来构建流程动态选择环境,这里有两种方式,一种是直接在页面上添加,如下图,一种是在Jenkinsfile中添加(第一次构建时不会出现选项,第二次构建才会出现,因此首次构建需要试构建,暂停再刷新页面才会有选择框),两种最张效果一样,这里为了方便采用Jenkinsfile来添加全局参数。

Jenkinsfile中添加

properties([
        parameters([string(name: 'PORT', defaultValue: '7082', description: '程序运行端口'),choice(name: 'ACTIVE_TYPE', choices: ['dev', 'prd', 'local'], description: '程序打包环境'),choice(name: 'ENV_TYPE', choices: ['online', 'offline'], description: '线上、还是线下环境'),booleanParam(name: 'ON_PINPOINT', defaultValue: true, description: '是否添加Pinpoint监控'),booleanParam(name: 'ON_PROMETHEUS', defaultValue: true, description: '是否添加Prometheus监控'),string(name: 'EMAIL', defaultValue: '104@qq.com', description: '打包结果通知')])
])

4.选择源码代码库:

需要添加认证,将Jenkinsssh秘钥添加到GitLab的页面中,且需要将此处gitlabjoint用户添加到需要拉取代码的项目中才有权限拉取代码。

Jenkinsfile位置放在项目的根目录。

5. Jenkinsfile中指定maven目录地址

MVNHOME = '/opt/maven354'

为防止手工填写项目名和版本号等一系列信息,因此直接读取pom文件中要编译项目的这些信息给全局变量:

pom = readMavenPom file: 'pom.xml'
echo "group: ${pom.groupId}, artifactId: ${pom.artifactId}, version: ${pom.version} ,description: ${pom.description}"
artifactId = "${pom.artifactId}"
version = "${pom.version}"
description = "${pom.description}"

根据选择的线上环境还是线下环境,替换镜像仓库ip

if (params.ENV_TYPE == 'offline' || params.ENV_TYPE == null) {
  sh "sed -i 's#39.95.40.97:7806#10.3.87.51:8080#g' pom.xml"
  image = "10.3.87.51:8080/${artifactId}:${version}"
}

6.编译

利用maven构建,利用上面的内容先替换掉DockerfileDeployment中的变量,再根据选择的条件是否启用pinpointpromethus,最后编译。

def jarparam=''
def pinname = artifactId
if( pinname.length() > 23) {
  pinname = artifactId.substring(0,23)
}
//添加pinpoint
if(params.ON_PINPOINT) {
  jarparam = '"-javaagent:/app/pinpoint-agent/pinpoint-bootstrap-1.8.0.jar","-Dpinpoint.agentId={pinname}", "-Dpinpoint.applicationName={pinname}",'
}
//添加prometheus
if(params.ON_PROMETHEUS) {
  jarparam = jarparam + '"-javaagent:/app/prometheus/jmx_prometheus_javaagent-0.11.0.jar=1234:/app/prometheus/jmx.yaml",'
}
 
sh "sed -i 's#{jarparam}#${jarparam}#g' Dockerfile"
 
sh "sed -i 's#{description}#${description}#g;s#{artifactId}#${artifactId}#g;s#{version}#${version}#g;s#{active}#${params.ACTIVE_TYPE}#g;s#{pinname}#${pinname}#g' Dockerfile"
 
sh "sed -i 's#{artifactId}#${artifactId}#g;s#{version}#${version}#g;s#{port}#${params.PORT}#g;s#{image}#${image}#g' Deployment.yaml"
 
sh "'${MVNHOME}/bin/mvn' -DskipTests clean package"

需要注意的是pinpointpinpoint.applicationName不能操作24个字符,否则启用不成功,因此超过的直接截断。

Department文件详情看后文。

跳过测试编译打包 '${MVNHOME}/bin/mvn' -DskipTests clean package 需要在Jenkins服务器安装maven环境,还有指定mavenjar包私有仓库地址。

7. Docker打包

前提是上一步指定pom文件中的镜像仓库和Dockerfile中的内容是替换后的完整内容。

sh "'${MVNHOME}/bin/mvn' docker:build"

8. 推送镜像

sh "'${MVNHOME}/bin/mvn' docker:push"

如何发布服务到K8S集群

  前面几步已经将项目打包并生成了镜像并推送到了私有仓库,下面就是部署服务到K8S集群。

先看看Department.yaml文件:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {artifactId}
  namespace: default
  labels:
    app: {artifactId}
    version: {version}
spec:
  selector:
    matchLabels:
      app: {artifactId}
  replicas: 1
  template:
    metadata:
      labels:
        app: {artifactId}
      annotations:
        prometheus.io.jmx: "true"
        prometheus.io.jmx.port: "1234"
    spec:
      containers:
      - name: {artifactId}
        image: {image}
        # IfNotPresent\Always
        imagePullPolicy: Always
        ports:
        - name: prometheusjmx
          containerPort: 1234
        livenessProbe: #kubernetes认为该pod是存活的,不存活则需要重启
          httpGet:
            path: /health
            port: {port}
            scheme: HTTP
          initialDelaySeconds: 60 ## 设置为系统完全启动起来所需的最大时间+若干秒
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        readinessProbe: #kubernetes认为该pod是启动成功的
          httpGet:
            path: /health
            port: {port}
            scheme: HTTP
          initialDelaySeconds: 40 ## 设置为系统完全启动起来所需的最少时间
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        env:
        - name: eureka-server
          value: "eureka-server.default.svc.cluster.local"
        - name: eureka-server-replica
          value: "eureka-server-replica.default.svc.cluster.local"
        resources:
        # 5%的CPU时间和700MiB的内存
          requests:
#            cpu: 50m
            memory: 700Mi
          # 最多允许它使用
          limits:
#            cpu: 100m
            memory: 1000Mi
        # 指定在容器中挂载路径
        volumeMounts:
        - name: logs-volume
          mountPath: /logs
        - name: host-time
          mountPath: /etc/localtime
          readOnly: true
        - name: host-timezone
          mountPath: /etc/timezone
          readOnly: true
        - name: pinpoint-config
          mountPath: /app/pinpoint-agent/pinpoint.config
      volumes:
      - name: logs-volume
        hostPath:
        # 宿主机上的目录
          path: /logs
      - name: host-time
        hostPath:
          path: /etc/localtime
      - name: host-timezone
        hostPath:
          path: /usr/share/zoneinfo/Asia/Shanghai
      - name: pinpoint-config
        configMap:
          name: pinpoint-config
       # 运行在指定标签的节点,前提是先给节点打标  kubectl label nodes 192.168.0.113 edgenode=flow
#      nodeSelector:
#        edgenode: flow
---
apiVersion: v1
kind: Service
metadata:
  name: {artifactId}
  namespace: default
  labels:
    app: {artifactId}
    version: {version}
spec:
  selector:
    app: {artifactId}
  ports:
  - name: tcp-{port}-{port}
    protocol: TCP
    port: {port}
    targetPort: {port}

里面的变量会在前面几步自动替换掉。

添加了prometheus收集jvm的内容:

prometheus.io.jmx: "true"
prometheus.io.jmx.port: "1234"

containerPort: 1234

pinpoint的配置内容pinpoint.configconfigMap  保存,方便更改内容。

其它内容不在此详解,可自行google

  网上资料一般发布服务都是直接kubectl deploy,这种情况只适用于jenkins的服务器已包含在K8S服务器集群中。第二种情况是在K8S集群服务器里面生成Jenkins的一个slave节点,然后在pipeline里面设置node(“k8s”){ ……} 里面发布,具体方法自行google

        这里为了避免麻烦,采用直接SSHK8S服务器集群的方案发布服务。

配置sshagent

SSH Agent Plugin sshagent方法支持,用于上传构建产物到目标服务器

Jenkins插件库搜索后直接下载安装(需要连外网环境),生产环境已安装,直接使用。

使用:

sshagent(credentials: ['deploy_ssh_key_23']) {
  sh "scp -P 2222 -r Deployment.yaml root@39.95.40.97:/docker/yaml/Deployment-${artifactId}.yaml"
  sh "ssh -p 2222 root@39.95.40.97 'kubectl apply -f /docker/yaml/Deployment-${artifactId}.yaml && kubectl set env deploy/${artifactId} DEPLOY_DATE=${env.BUILD_ID}'"
}

先用ssh远程到K8S集群中的服务器,将Deployment文件上传,然后再远程执行kubectl apply发布服务。

        为了避免误操作,在发布前做了发布确认提示判断。

timeout(time: 10, unit: 'MINUTES') {
   input '
确认要部署吗?'
}

      以上流程已完成整个流程,然后可以去K8S环境去看服务是否有正常运行。

关于测试

  上面的过程没有加入代码测试、代码质量分析SonarQube、发布后服务测试的阶段,后续可以接入。

如何进行多模块如何构建

  很多项目采用的是多模块构成,因此每个项目配置和发布要求不一样,需要单独编译到部署,所以每个模块都需要独立的DockerfileDeployment文件,Jenkinsfile通用一份,然后在发布时自动弹出模块列表,选择需要发布的模块进行编译发布。

//需要处理的项目多项目时先进入子项目
 
projectwk = "."
 
mainpom = readMavenPom file: 'pom.xml'
 
//存在多个模块时,选择其中一个进行编译
 
if(mainpom.modules.size() > 0 ) {
 
  echo "项目拥有模块==${mainpom.modules}"
 
  timeout(time: 10, unit: 'MINUTES') {
 
    def selproj = input message: '请选择需要处理的项目', parameters: [choice(choices: mainpom.modules, description: '请选择需要处理的项目', name: 'selproj')] //, submitterParameter: 'project'
 
    projectwk = selproj
 
    echo "选择项目=${projectwk}"
 
  }
 
}

 读取主项目的pom中的modules判断是否包含多个模块,供用户选择。

然后根据选择的模块进行编译,dir进入选择的模块读取信息并编译。

dir("${projectwk}") {
 
    pom = readMavenPom file: 'pom.xml'
 
    echo "group: ${pom.groupId}, artifactId: ${pom.artifactId}, version: ${pom.version} ,description: ${pom.description}"
 
    artifactId = "${pom.artifactId}"
 
    version = "${pom.version}"
 
    description = "${pom.description}"
 
}

完整的Jenkinsfile

properties([
 
        parameters([string(name: 'PORT', defaultValue: '7082', description: '程序运行端口'),choice(name: 'ACTIVE_TYPE', choices: ['dev', 'prd', 'local'], description: '程序打包环境'),choice(name: 'ENV_TYPE', choices: ['online', 'offline'], description: '线上、还是线下环境'),booleanParam(name: 'ON_PINPOINT', defaultValue: true, description: '是否添加Pinpoint监控'),booleanParam(name: 'ON_PROMETHEUS', defaultValue: true, description: '是否添加Prometheus监控'),string(name: 'EMAIL', defaultValue: '1041126478@qq.com', description: '打包结果通知')])
 
])
 
node {
 
    stage('Prepare') {
 
        echo "1.Prepare Stage"
 
        MVNHOME = '/opt/maven354'
 
        //echo "UUID=${UUID.randomUUID().toString()}"
 
        checkout scm
 
        //需要处理的项目多项目时先进入子项目
 
        projectwk = "."
 
        mainpom = readMavenPom file: 'pom.xml'
 
        repostory = "${mainpom.properties['docker.repostory']}"
 
        //存在多个模块时,选择其中一个进行编译
 
        if(mainpom.modules.size() > 0 ) {
 
          echo "项目拥有模块==${mainpom.modules}"
 
          timeout(time: 10, unit: 'MINUTES') {
 
            def selproj = input message: '请选择需要处理的项目', parameters: [choice(choices: mainpom.modules, description: '请选择需要处理的项目', name: 'selproj')] //, submitterParameter: 'project'
 
            projectwk = selproj
 
            echo "选择项目=${projectwk}"
 
          }
 
        }
 
 
        dir("${projectwk}") {
 
            pom = readMavenPom file: 'pom.xml'
 
            echo "group: ${pom.groupId}, artifactId: ${pom.artifactId}, version: ${pom.version} ,description: ${pom.description}"
 
            artifactId = "${pom.artifactId}"
 
            version = "${pom.version}"
 
            description = "${pom.description}"
 
        }
 
        script {
 
            GIT_TAG = sh(returnStdout: true, script: '/usr/local/git/bin/git rev-parse --short HEAD').trim()
 
            echo "GIT_TAG== ${GIT_TAG}"
 
        }
 
        image = "192.168.4.2:5000/${artifactId}:${version}"
 
      if (params.ENV_TYPE == 'offline' || params.ENV_TYPE == null) {
 
        sh "sed -i 's#39.95.40.97:5000#10.3.80.50:5000#g' pom.xml"
 
        image = "10.3.80.50:5000/${artifactId}:${version}"
 
      }
 
    }
 
    if(mainpom.modules.size() > 0 ) {
 
       stage('编译总项目') {
 
          sh "'${MVNHOME}/bin/mvn' -DskipTests clean install"
 
       }
 
    }
 
    dir("${projectwk}") {
 
        stage('编译模块') {
 
            echo "2.编译模块 ${artifactId}"
 
            def jarparam=''
 
            def pinname = artifactId
 
            if( pinname.length() > 23) {
 
              pinname = artifactId.substring(0,23)
 
            }
 
            //添加pinpoint
 
            if(params.ON_PINPOINT) {
 
              jarparam = '"-javaagent:/app/pinpoint-agent/pinpoint-bootstrap-1.8.0.jar","-Dpinpoint.agentId={pinname}", "-Dpinpoint.applicationName={pinname}",'
 
            }
 
            //添加prometheus
 
            if(params.ON_PROMETHEUS) {
 
              jarparam = jarparam + '"-javaagent:/app/prometheus/jmx_prometheus_javaagent-0.11.0.jar=1234:/app/prometheus/jmx.yaml",'
 
            }
 
            sh "sed -i 's#{jarparam}#${jarparam}#g' Dockerfile"
 
            sh "sed -i 's#{description}#${description}#g;s#{artifactId}#${artifactId}#g;s#{version}#${version}#g;s#{active}#${params.ACTIVE_TYPE}#g;s#{pinname}#${pinname}#g' Dockerfile"
 
            sh "sed -i 's#{artifactId}#${artifactId}#g;s#{version}#${version}#g;s#{port}#${params.PORT}#g;s#{image}#${image}#g' Deployment.yaml"
 
            sh "'${MVNHOME}/bin/mvn' -DskipTests clean package"
 
            stash includes: 'target/*.jar', name: 'app'
 
        }
 
        stage('Docker打包') {
 
            echo "3.Docker打包"
 
            unstash 'app'
 
            sh "'${MVNHOME}/bin/mvn' docker:build"
 
        }
 
        stage('推送镜像') {
 
            echo "4.Push Docker Image Stage"
 
            sh "'${MVNHOME}/bin/mvn' docker:push"
 
        }
 
         timeout(time: 10, unit: 'MINUTES') {
 
            input '确认要部署吗?'
 
         }
 
        stage('发布') {
 
        if (params.ENV_TYPE == 'offline' || params.ENV_TYPE == null) {
 
              sshagent(credentials: ['deploy_ssh_key_34']) {
 
                sh "scp -r Deployment.yaml root@10.2.85.30:/docker/yaml/Deployment-${artifactId}.yaml"
 
                sh "ssh root@10.2.85.30 'kubectl apply -f /docker/yaml/Deployment-${artifactId}.yaml && kubectl set env deploy/${artifactId} DEPLOY_DATE=${env.BUILD_ID}'"
 
              }
 
           } else {
 
              sshagent(credentials: ['deploy_ssh_key_238']) {
 
                sh "scp -P 22 -r Deployment.yaml root@39.95.40.97:/docker/yaml/Deployment-${artifactId}.yaml"
 
                sh "ssh -p 22 root@39.95.40.97 'kubectl apply -f /docker/yaml/Deployment-${artifactId}.yaml && kubectl set env deploy/${artifactId} DEPLOY_DATE=${env.BUILD_ID}'"
 
              }
 
           }
 
            echo "发布完成"
 
        }
 
    }
 
   stage('通知负责人'){
 
//    emailext body: "构建项目:${description}\r\n构建完成", subject: '构建结果通知【成功】', to: "${EMAIL}"
 
        echo "构建项目:${description}\r\n构建完成"
 
   }
 
}

Jenkinsfile文件放在项目根目录,然后将源码都上传到GitLab

打开BlueOcean,这是Jenkins新出的美化页面。

选择自己的项目。

进入后点击运行,其中会弹出框选择发布参数(这里需要手工填写发布的端口,由于采用配置中心化,端口无法自动读取)。

进入查看流程状态,失败会有相应的提示:

显示发布服务

K8S内查看部署的服务启动情况

Jenkinsfile Pipeline

Jenkinsfile Pipeline语法内容可参考官网:

还可以进入项目后,有个流水线语法:

选择想要的功能,生成:

  Jenkins还可用作发布Vue前端项目,具体内容可参考 Jenkins自动化构建vue项目然后发布到远程服务器 文档。

  Jenkins要发布Net服务需要有一台windowsJenkins slave,还需要在此节点上安装编译器MSBuild框架,Git框架、更改服务器上的IIS权限等功能,最后文件分发到其它windows服务器,过程比较繁琐,若无发布审核建议直接通过VS自带发布功能发布程序。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多