作者:赵海亮,浙江大学计算机专业四年级在读博士生,研究方向为云计算、边缘计算、分布式系统等。

虽然 KubeSphere 能够将我们从 yaml 文件的编写中解放出来,但是项目上云仍然十分繁琐。 此外,一旦项目源代码发生更替(如发布新功能或去除 bug 等),所有组件都需要重新经历 “源码打包 --> 制作镜像 --> 启动容器” 这个流程。 这意味着,项目运维人员不得不从事大量重复性劳动。为了提高项目发布的效率,工业界引入了 DevOps 的概念。

本文首先将介绍 DevOps 是什么,随后尝试利用 KubeSphere 集成的功能来实现 DevOps。

什么是 DevOps

目前绝大多数互联网公司将开发和系统管理划分成不同的部门。 开发部门的驱动力通常是 “频繁交付新特性”,而运维部门则更关注 IT 服务的可靠性和 IT 成本投入的效率。 两者目标的不匹配,因而存在鸿沟,从而减慢了 IT 交付业务价值的速度。 为了解决这个问题,DevOps(Development 和 Operations 的组合词)被提出。 DevOps 的目的是在企业内部搭建一个自动化 “软件交付” 和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。

实现 DevOps 通常需要多个软件和工具的密切配合。 如图 1 所示,DevOps 将软件的交付流程依次划分为 Plan、Code、Build、Test、Release、Deploy、Operate 以及 Monitor 这些阶段。 当需求变更时,将会从 Monitor 重新平滑过渡至 Plan 阶段。每个阶段都有一系列的软件和工具可供选择。 对于任意项目,我们只需要基于这些软件和工具 搭建一条自动化流水线 ,再设置类似于 “一旦代码变更就自动执行” 这样的钩子函数,整个项目即可自动实现“持续集成 / 持续交付(CI/CD)”,这将大大减少重复劳动。

KubeSphere DevOps 基于 Kubernetes Jenkins Agent 实现。 和传统的 Jenkins Controller-Agent 架构不同的是,在 KubeSphere 中,Jenkins Agent 可以动态扩缩容,从而降低 CI/CD 对集群资源的盲目占用。 KubeSphere 的 DevOps 用户指南参见 https://kubesphere.io/zh/docs/devops-user-guide/。 本文将依照该指南将一个开源项目上云。

基于 DevOps 的项目部署

项目介绍

本次实验要部署的项目叫做尚医通,这是一个基于 Spring-Boot 实现的预约挂号统一平台。 该项目一共包含三个子部分,分别为 yygh-parentyygh-siteyygh-admin。 在架构上,该项目依赖的数据层中间件有 mysql、redis、mongodb 以及 rabbitmq,依赖的流量治理中间件有 sentinel 和 nacos。

接下来,我们约定项目根目录为 his,然后分别从开源地址 https://gitee.com/leifengyang/yygh-parent、https://gitee.com/leifengyang/yygh-site 和 https://gitee.com/leifengyang/yygh-admin 拉取源代码:

(base) ➜  his lsa
total 0
drwxr-xr-x   5 hliangzhao  staff   160B Nov 15 10:33 .
drwxr-xr-x@ 42 hliangzhao  staff   1.3K Nov 15 10:33 ..
drwxr-xr-x  24 hliangzhao  staff   768B Nov 15 10:33 yygh-admin
drwxr-xr-x  15 hliangzhao  staff   480B Nov 15 10:33 yygh-parent
drwxr-xr-x  24 hliangzhao  staff   768B Nov 15 10:34 yygh-site

依次查看三个项目的文件布局:

(base) ➜  his cd yygh-parent
(base) ➜  yygh-parent git:(master) tree -L 2
.
├── common                      # 通用模块
│   ├── common-util
│   ├── pom.xml
│   ├── rabbit-util
│   └── service-util
├── data                        # 项目演示数据
│   ├── json
│   └── sql
├── hospital-manage             # 医院后台
│   ├── Dockerfile
│   ├── deploy
│   ├── pom.xml
│   ├── src
├── model                       # 数据模型
│   ├── pom.xml
│   └── src
├── pom.xml
├── server-gateway              # 网关
│   ├── Dockerfile
│   ├── deploy
│   ├── pom.xml
│   └── src
├── service                     # 微服务层
│   ├── pom.xml
│   ├── service-cmn             # 公共服务
│   ├── service-hosp            # 医院数据服务
│   ├── service-order           # 预约下单服务
│   ├── service-oss             # 对象存储服务
│   ├── service-sms             # 短信服务
│   ├── service-statistics      # 统计服务
│   ├── service-task            # 定时服务
│   └── service-user            # 会员服务
└── service-client├── pom.xml├── service-cmn-client├── service-hosp-client├── service-order-client└── service-user-client30 directories, 12 files
(base) ➜  yygh-parent git:(master) cd ../yygh-admin
(base) ➜  yygh-admin git:(master) tree -L 1        # 医院挂号后台(前端 UI)
.
├── Dockerfile
├── LICENSE
├── build
├── config
├── deploy
├── favicon.ico
├── index.html
├── package.json
├── src
└── static5 directories, 9 files
(base) ➜  yygh-site git:(master) tree -L 1        # 用户挂号前台(前端 UI)
.
├── Dockerfile
├── api
├── assets
├── components
├── deploy
├── layouts
├── middleware
├── nuxt.config.js
├── package-lock.json
├── package.json
├── pages
├── plugins
├── static
├── store
└── utils11 directories, 7 files

对于本项目,我们需要部署如下内容:

yygh-parent/hospital-manage         # 医院管理
yygh-parent/server-gateway          # 网关
# 8 个微服务
yygh-parent/service/service-cmn
yygh-parent/service/service-hosp
yygh-parent/service/service-order
yygh-parent/service/service-oss
yygh-parent/service/service-sms
yygh-parent/service/service-statistics
yygh-parent/service/service-task
yygh-parent/service/service-user
# 2 个前端
yygh-admin
yygh-site

以上 12 个待部署的子项目将以独立 Pod 的形式在集群中部署。 每一个子项目根目录需要具有一个 Dockerfile 文件以及一个名为 deploy 的文件夹。 前者是本子项目的镜像制作文件,后者是本子项目的资源清单文件 *.yaml(用于在集群中部署)。 以 service-cmn 为例,其文件布局如下:

(base) ➜  service-cmn git:(master) tree -L 2
.
├── Dockerfile        # 将本子项目构建为镜像的 Dockerfile
├── deploy            # 存放用于部署本子项目的资源清单文件
│   └── deploy.yml
├── pom.xml           # 项目依赖
├── src               # 源代码
│   └── main
└── target            # maven 打包后自动创建

遵循上的一篇文章 使用 KubeSphere 部署 Ruoyi-Cloud · KS 实践 02 中所述的部署流程,我们首先需要将中间件上云。然后,我们将三个项目以流水线的方式上云。

部署中间件

本项目所使用的中间件除了 Sentinel 和 MongoDB,其他均已在前文中部署。 接下里依次部署这两个中间件。

对于 Sentinel,我们直接使用雷丰阳已经制作好的镜像 leifengyang/sentinel:1.8.2,然后暴露一个 NodePort 类型的 Service,端口号为 32636。 访问 http://192.168.23.160:32636,以默认用户 sentinel 和默认密码 sentinel 登录,可以进入 Sentinel 控制台。 如果一切顺利,应该可以看到类似的页面:

对于 MongoDB,我们直接通过应用模版部署它(不勾选登录认证):

为 MongoDB 应用暴露一个 NodePort 类型的 Service,端口号为 31801,然后在本机通过 MongoDB Compass 连接它(192.168.23.160:31801):

如果可以连上,则一切正常。

导入初始数据

使用 DataGrip 将位于 his/yygh-parent/data/sql 目录下的全部演示数据(一共有 5 个 sql 文件需要执行,会创建 5 个 yygh 打头的数据库)导入集群中的 MySQL 实例:

MongoDB 的演示数据将在项目启动后导入。

在 Nacos 中创建微服务的启动配置

观察每一个子项目的 Dockerfile,以 service-cmn 为例:

# service-cmn 的 Dockerfile
FROM openjdk:8-jdk
LABEL maintainer=leifengyang# 启动 prod 环境,以 service-cmn-prod.yml 作为启动配置
ENV PARAMS="--server.port=8080 --spring.profiles.active=prod --spring.cloud.nacos.server-addr=his-nacos.his:8848 --spring.cloud.nacos.config.file-extension=yml"
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezoneCOPY target/*.jar /app.jar
EXPOSE 8080
ENTRYPOINT ["/bin/sh","-c","java -Dfile.encoding=utf8  -Djava.security.egd=file:/dev/./urandom -jar /app.jar ${PARAMS}"]

这意味着该子项目在启动时,会激活 prod 环境,并从 Nacos 中读取 service-cmn-prod.yml 文件作为启动配置。 因此,我们首先需要在 Nacos 中创建其生产环境配置文件 service-cmn-prod.yml,然后将 子项目路径 / src/main/resources/application-dev.yml 的内容复制进去,在其基础上修改。 需要修改的内容主要是中间件的访问地址。 以 service-cmn 为例,它的配置文件被命名为 service-cmn-prod.yml,其最终内容如下:

# service-cmn-prod.yml
server:port: 8080
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplmapper-locations: classpath:mapper/*.xmlglobal-config:db-config:logic-delete-value: 1logic-not-delete-value: 0
spring:cloud:sentinel:transport:# 修改 sentinel 访问地址dashboard: http://his-sentinel-nodeport.his:8080redis:# 修改 redis 访问地址host: his-redis-nodeport.hisport: 6379database: 0timeout: 1800000password:lettuce:pool:max-active: 20      # 最大连接数max-wait: -1        # 最大阻塞等待时间 (负数表示没限制)max-idle: 5         # 最大空闲min-idle: 0         # 最小空闲datasource:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.jdbc.Driver# 修改 mysql 访问地址和连接凭证url: jdbc:mysql://his-mysql-nodeport.his:3306/yygh_cmn?characterEncoding=utf-8&useSSL=falseusername: rootpassword: 123456hikari:connection-test-query: SELECT 1connection-timeout: 60000idle-timeout: 500000max-lifetime: 540000maximum-pool-size: 12minimum-idle: 10pool-name: GuliHikariPooljackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT+8

如图 6 所示,除了 hospitla-manage,其余所有 9 个 Spring-Boot 子项目均需要按照上述规则编写对应的配置文件。 hospitla-manage 的启动不依赖 Nacos,因此不需要。

创建微服务部署流水线

流水线表示应用从代码编译、测试、打包和部署的过程,KubeSphere 的流水线管理使用了业界常用的 Jenkinsfile 来表述一组 CI/CD 流程。 Jenkinsfile 是一个文本文件,使用了 Jenkins 提供的 DSL(Domain-Specific Language)语法。 KubeSphere 提供了可视化编辑器,用户只需在页面上输入少量配置信息,接口自动组装完成 Jenkinsfile。 当然,也可直接编辑 Jenkinsfile。

流水线涉及如下几个概念:

  • Stage:阶段,一个 Pipeline 可以划分为若干个 Stage,每个 Stage 代表一组操作。Stage 是一个逻辑分组的概念,可以跨多个 Node。
  • Node:节点,一个 Node 就是一个 Jenkins 节点,或者是 Master,或者是 Agent,是执行 Step 的具体运行时环境。
  • Step:步骤,Step 是最基本的操作单元,小到创建一个目录,大到构建一个 Docker 镜像,由各类 Jenkins Plugin 提供。

KubeSphere 默认提供的 Agent 有 base、go、maven 和 nodejs。它们分别适用于不同编程语言开发的项目的打包构建。 因为我们即将部署的 10 个子项目均是 Spring-Boot 应用,因此我们选择 maven 作为启动流水线的 agent。

我们可以直接编写流水线的 Jenkinsfile,也可以通过 KubeSphere 提供的可视化页面编辑流水线。 通常,流水线的第一步是下载项目源代码 4,我们在 UI 上直接添加相关命令:

KubeSphere 会自动生成这次编辑的 Jenkinsfile 代码片段:

stage('clone code') {agent nonesteps {// 拉取代码并展示代码文件布局container('maven') {git(url: 'https://gitee.com/leifengyang/yygh-parent', branch: 'master', changelog: true, poll: false)sh 'ls -al'}}
}

流水线的第二个阶段通常是项目的打包与编译。 默认情况下,Maven 从官方仓库下载项目依赖,如果想要修改默认镜像仓库,需要修改集群中名为 ks-devops-agent 的 ConfigMap,它拥有一个叫做 MavenSetting 的键:

k8s@ubuntu:~$ k get cm -A | grep devops
his-devopsqxxv7                   istio-ca-root-cert                                           1      24h
his-devopsqxxv7                   kube-root-ca.crt                                             1      24h
kubesphere-devops-system          devops-config                                                1      5d7h
kubesphere-devops-system          devops-jenkins                                               9      5d7h
kubesphere-devops-system          istio-ca-root-cert                                           1      5d7h
kubesphere-devops-system          jenkins-agent-config                                         1      5d7h
kubesphere-devops-system          jenkins-casc-config                                          2      5d7h
kubesphere-devops-system          kube-root-ca.crt                                             1      5d7h
kubesphere-devops-worker          istio-ca-root-cert                                           1      5d7h
kubesphere-devops-worker          ks-devops-agent                                              1      5d7h
kubesphere-devops-worker          kube-root-ca.crt                                             1      5d7h
k8s@ubuntu:~$ k describe cm ks-devops-agent -n kubesphere-devops-worker
Name:         ks-devops-agent
Namespace:    kubesphere-devops-worker
Labels:       app.kubernetes.io/managed-by=Helm
Annotations:  meta.helm.sh/release-name: devopsmeta.helm.sh/release-namespace: kubesphere-devops-systemData
====
MavenSetting:
----
<?xml version="1.0" encoding="UTF-8"?>
...
<!--| This is the configuration file for Maven. It can be specified at two levels:
...
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
...

我们需要修改 MavenSetting 文件,在其中添加国内镜像仓库地址:

我们通过命令 mvn clean package -Dmaven.test.skip=true 进行项目打包编译。由此,流水线的第二阶段需要执行的命令如下:

相应地,在 Jenkinsfile 中也会自动生成第二步的代码:

stage('project compilation') {agent nonesteps {container('maven') {sh 'mvn clean package -Dmaven.test.skip=true'}}
}

流水线的第三个阶段是制作镜像。我们在章节 2.1 说过,每个子项目的根目录有一个 Dockerfile,并且在章节 2.4 展示过 Dockerfile 的内容。 因此,对于单体应用 hospitla-manage,它的镜像构建命令为 docker build -t hospital-manage -f hospital-manage/Dockerfile hospital-manage/;对于网关子项目 server-gateway,它的镜像构建命令为 docker build -t server-gateway/Dockerfile server-gateway/;其余 8 个微服务的构建命令则是 docker build -t service/service-xxx service/service-xxx/。这里的 xxx 被替换为具体的微服务名称。 在上述构建命令中,尤其需要注意的是 Dockerfile 相对于项目根目录 yygh-parent 所在的位置以及镜像构建上下文的相对位置。

因为上述 10 个镜像的构建相互之间独立,因此可以并行化执行。我们可以很轻易地在 KubeSphere 中做到这一点:

相应地,Jenkinsfile 中增加了如下内容:

stage('default-2') {parallel {    // 并行构建 10 个镜像stage('build hospital-manage') {agent nonesteps {container('maven') {sh 'docker build -t hospital-manage -f hospital-manage/Dockerfile hospital-manage/'}}}stage('build server-gateway') {...}stage('build service-cmn') {...}...}
}

流水线的第四个阶段是镜像推送。在企业内部,构建好的镜像通常会被推送到企业的私有仓库中。 笔者采用阿里云给个人开发者免费提供的镜像仓库作为推送目标。因为目标仓库是一个私有仓库,因此需要提供账户和密码作为凭证(credential)。 如何在 KubeSphere 中为镜像推送命令提供凭证呢? 我们可以在 DevOps 的项目设置中创建:

上图中,笔者创建一个名为 aliyun-docker-hub 的凭证,用户名是我的阿里云账户名,密码则是申请容器镜像服务所创建的密码。 读者需要替换成自己的账户密码:

基于该凭证,我们在 Jenkinsfile 中编写镜像推送的代码如下:

steps {container('maven') {// 使用'aliyun-docker-registry'这个凭证登录私有仓库并将镜像推送至其中withCredentials([usernamePassword(credentialsId: 'aliyun-docker-registry', passwordVariable: 'ALIYUN_REG_PWD', usernameVariable : 'ALIYUN_REG_USER' ,)]) {sh 'echo"$ALIYUN_REG_PWD"| docker login $REGISTRY -u"$ALIYUN_REG_USER"--password-stdin'sh 'docker tag hospital-manage:latest $REGISTRY/$DOCKERHUB_NAMESPACE/hospital-manage:SNAPSHOT-$BUILD_NUMBER'sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/hospital-manage:SNAPSHOT-$BUILD_NUMBER'}}
}
...
environment {...REGISTRY = 'registry.cn-hangzhou.aliyuncs.com'DOCKERHUB_NAMESPACE = 'hliangzhao-private'...
}

同样地,上述过程也以并行的方式执行。最终,Jenkinsfile 中被添加了如下代码:

stage('default-3') {parallel {   // 并行推送 10 个镜像stage('push hospital-manage') {agent nonesteps {container('maven') {withCredentials([usernamePassword(credentialsId : 'aliyun-docker-registry' ,passwordVariable : 'ALIYUN_REG_PWD' ,usernameVariable : 'ALIYUN_REG_USER' ,)]) {sh 'echo"$ALIYUN_REG_PWD"| docker login $REGISTRY -u"$ALIYUN_REG_USER"--password-stdin'sh 'docker tag hospital-manage:latest $REGISTRY/$DOCKERHUB_NAMESPACE/hospital-manage:SNAPSHOT-$BUILD_NUMBER'sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/hospital-manage:SNAPSHOT-$BUILD_NUMBER'}}}}stage('push server-gateway') {...}stage('push service-cmn') {...}...}
}

测试一下到目前为止的流水线,一切运行顺利:

流水线的最后阶段是部署到开发环境和生产环境。因为这一阶段需要和 Kubernetes API Server 打交道,所以需要指定 Kubernetes 上下文 5。 KubeSphere 自动为我们创建了名为 demo-kubeconfig 的凭证,该凭证提供了形如 .kube/config 的文件,使得我们可以根据凭证发起 kubectl apply 命令。 与此同时,我们还需要指定待部署的资源清单文件的位置。 以子项目 hospital-manage 为例,它的资源清单文件在 yygh-parent/hospital-manage/deploy/ 目录下。 观察该目录下的 deploy.yaml 文件,可以发现它要求集群从阿里云私有镜像仓库拉取镜像,需要我们提供 imagePullSecrets 字段:

这意味着我们需要在 his 项目中创建名为 aliyun-docker-hub 的 Secret。 注意,这里是在为 his 项目创建 Secret,而先前是在 DevOps 的项目设置中创建 Credential。二者的服务对象是不同的。 对于部署这个操作,我们可以直接在 UI 上选择 “添加 kubernetesDeploy”:

由此生成的 Jenkinsfile 代码为

stage('deploy hospital-manage to dev') {agent nonesteps {container('maven') {kubernetesDeploy(enableConfigSubstitution: true,deleteResource: false,kubeconfigId: 'demo-kubeconfig',          // 存储了 kubeconfig 上下文信息的文件configs: 'hospital-manage/deploy/**'      // 资源清单文件所在位置)}}
}

我们尝试运行一下现在的流水线,诡异的事情却发生了。在项目部署阶段产生了如下错误:

Starting Kubernetes deployment
Loading configuration: /home/jenkins/agent/workspace/his-devopsqxxv7/yygh-parent-devops/hospital-manage/deploy/deploy.yml
ERROR: ERROR: java.lang.RuntimeException: io.kubernetes.client.openapi.ApiException: Bad Request
hudson.remoting.ProxyException: java.lang.RuntimeException: io.kubernetes.client.openapi.ApiException: Bad Requestat com.microsoft.jenkins.kubernetes.wrapper.ResourceManager.handleApiExceptionExceptNotFound(ResourceManager.java:180)...
Api call failed with code 400, detailed message: {"kind": "Status","apiVersion": "v1","metadata": {},"status": "Failure","message": "the export parameter, deprecated since v1.14, is no longer supported","reason": "BadRequest","code": 400
}
Kubernetes deployment ended with HasError

观察报错内容,似乎是负责执行流水线的 Jenkins Agent 版本太老所导致的。 经过查阅,笔者发现 KubeSphere 的官方维护人员已经提交了相关 issue(https://github.com/kubesphere/website/issues/2096)来说明此事。根据说明,报错的根源在于 Jenkins 的官方插件 kubernetes-cd-plugin “年久失修”,我所安装的 Kubernetes 的 API 版本是 v1.22,而 Jenkins 的 kubernetes-cd-plugin 却已经停摆两年。 对于这个问题,KubeSphere 官方提供的解决方案是以 shell 命令 kubectl apply -f your-crd-file.yaml 的方式进行部署,而非在 UI 上添加 kubernetesDeploy

幸运的是,在笔者撰写此文的 40 分钟前,KubeSphere 官方发起了一个针对此问题的临时解决方案:https://github.com/kubesphere/website/pull/2098。 在该 Pull request 中,贡献者提供了一种提供 kubeconfig 验证的写法:

stage('deploy hospital-manage to dev') {agent nonesteps {container('maven') {// 如果不提供 kubeconfigFile,则 kubectl 上下文找不到withCredentials([kubeconfigFile(credentialsId: env.KUBECONFIG_CREDENTIAL_ID, variable: 'KUBECONFIG')]) {sh 'kubectl apply -f hospital-manage/deploy/**'}}}
}

实验证明,该方法有效。同样地,10 个子项目可以并行化部署到 dev 环境。相应的 Jenkins 代码就不再展示了。 部署到 prod 环境的操作类似。此外,还可以添加部署条件,例如,只有获得相关管理员授权之后部署操作才会启动。

创建前端项目部署流水线

接下来,还剩两个前端项目 yygh-siteyygh-admin 需要部署。 前端项目的部署服从相似的步骤:首先下载源码,然后需要通过 Node.js 之类的工具为项目安装依赖并构建(产生 dist 目录),最后是镜像构建、推送和部署。 以 yygh-site 为例,它最终的 Jenkinsfile 如下所示:

pipeline {agent {node {label 'nodejs'}}stages {stage('拉取代码') {agent nonesteps {container('nodejs') {git(url: 'https://gitee.com/leifengyang/yygh-site', branch: 'master', changelog: true, poll: false)sh 'ls -al'}}}stage('项目编译') {agent nonesteps {container('nodejs') {sh 'ls'sh 'npm install --registry=https://registry.npm.taobao.org'sh 'npm run build'}}}stage('构建镜像') {agent nonesteps {container('nodejs') {sh 'ls'sh 'docker build -t yygh-site:latest -f Dockerfile  .'}}}stage('推送镜像') {agent nonesteps {container('nodejs') {withCredentials([usernamePassword(credentialsId: 'aliyun-docker-registry', usernameVariable: 'DOCKER_USER_VAR', passwordVariable: 'DOCKER_PWD_VAR',)]) {sh 'echo"$DOCKER_PWD_VAR"| docker login $REGISTRY -u"$DOCKER_USER_VAR"--password-stdin'sh 'docker tag yygh-site:latest $REGISTRY/$DOCKERHUB_NAMESPACE/yygh-site:SNAPSHOT-$BUILD_NUMBER'sh 'docker push  $REGISTRY/$DOCKERHUB_NAMESPACE/yygh-site:SNAPSHOT-$BUILD_NUMBER'}}}}stage('部署到 dev 环境') {agent nonesteps {kubernetesDeploy(configs: 'deploy/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")}}// 1、配置全系统的邮件:                   全系统的监控// 2、修改 ks-jenkins 的配置,里面的邮件;   流水线发邮件stage('发送确认邮件') {agent nonesteps {mail(to: 'someone@test.com', subject: 'yygh-site 构建结果', body: "成功构建 $BUILD_NUMBER")}}}environment {...}
}

此处不再展示更多细节。

总结

KubeSphere 为我们提供了 Jenkins 流水线的编辑页面,在一定程度上可以简化操作。

参考

本文参考了雷丰阳的视频课程 云原生 Java 架构师的第一课 K8s+Docker+KubeSphere+DevOps。 如果想全面而深入地自主实践,推荐观看原视频。

本文由博客一文多发平台 OpenWrite 发布!

KubeSphere DevOps 流水线入门指南相关推荐

  1. 云原生Java架构师——KubeSphere DevOps流水线部署RuoyiCloud

    目录 一.简介 二.代码 三.monitor监控服务流水线(先推送一个服务把整个流程走完) 3.1 创建流水线 3.2 拉取代码 3.3 项目编译 3.4 构建镜像 3.5 推送镜像仓库 3.6 mo ...

  2. KubeSphere DevOps流水线部署

    文章目录 一. 安装 1.1 下载yaml 1.2 设置默认StorageClass 1.3 安装 1.4 配置 1.5 查看 1.6 页面 二. 流水线部署 2.1 开启流水线设置 2.1.1 未安 ...

  3. Terraform实战 | 实用云部署编程入门指南,DevOps软件开发运维必备

    Terraform是一种部署技术,任何想要通过基础设施即代码(Infrastructure as Code,IaC)方法来置备和管理基础设施的人,都可以使用这种技术.基础设施指的主要是基于云的基础设施 ...

  4. 如何基于Kubernetes构建完整的DevOps流水线

    前言 关于DevOps是一个很大的话题,它可能既涉及到公司的技术文化构建,也包括开发者技术能力的支持,这次技术干货分享主要是侧重于技术方面,就是如何用Kubernetes来服务好DevOps的流水线. ...

  5. 如何基于 Kubernetes 构建完整的 DevOps 流水线

    前言 关于 DevOps 是一个很大的话题,它可能既涉及到公司的技术文化构建,也包括开发者技术能力的支持,这次技术干货分享主要是侧重于技术方面,就是如何用 Kubernetes 来服务好 DevOps ...

  6. aws python库_适用于Alexa的新AWS Python SDK入门指南

    aws python库 by Ralu Bolovan 由Ralu Bolovan 适用于Alexa的新AWS Python SDK入门指南 (A Beginner's guide to the ne ...

  7. Nginx 入门指南

    Nginx 入门指南 简介: Nginx 是一款轻量级的 Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,其特点是占有内存少,并发能力强.本教程根据淘宝核心系统服务器平台组的 ...

  8. CI Weekly #21 | iOS 持续集成快速入门指南

    搭建 iOS 持续集成环境要多久?每个 iOSer 都有不同的答案.这次我们整理了 flow.ci 的 iOS 持续集成的相关文档和最佳实践,希望帮你更快地完成构建.更新文档见: flow.ci iO ...

  9. 测试开发成长学习路线--如何做一个DevOps流水线上的开发测试

    大家知道,测试开发或者开发测试范围很大,一个人的精力和你当前的项目经历,决定了你属于某一个领域的具体的测试开发的工作.在这里,我不纠结测试开发和开发测试有何不同,有一个叫法罢了.今天这里要讨论的是如何 ...

最新文章

  1. WAIC汇聚全球顶级科学家,畅谈人工智能的未来挑战与突破
  2. 永恒传奇三服务器维护中,仙境传说ro3月3日5点-10点停服维护
  3. boost::filesystem目录相关的测试程序
  4. lua cocos 动画回调
  5. Sublime Text插件的离线安装-使用htmlprettify美化您的HTML代码 1
  6. 一行代码蒸发了 ¥6,447,277,680 人民币!
  7. wxpython安装linux_Ubuntu中安装wxPython
  8. linux 创建文件夹快捷方式
  9. linux耳机的检测原理,耳机检测原理介绍
  10. 经验正交函数分析(EOF)或主成分分析(PCA)在matlab上的实现及实例
  11. 像中文的罗马音字体复制_帮我把日语的罗马音弄成汉字!
  12. Mac读写ntfs磁盘工具:Paragon NTFS for Mac
  13. Word 去除页眉横线
  14. 双11有哪些好用的降噪蓝牙耳机值得推荐?降噪蓝牙耳机性价比排行
  15. Elasticsearch聚合学习之二:区间聚合
  16. python绘制笛卡尔直角坐标系
  17. 超详细讲解!在字节跳动我是如何当面试官的,附大厂真题面经
  18. Python:enumerate函数
  19. IIC通信协议(STM32学习笔记 一)
  20. Vue 下 ESLint 的 error 解决办法

热门文章

  1. 让51单片机进行上网
  2. 易飞9安装和授权视频
  3. django踩坑关于django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty.
  4. android app 目标版本,android – 在gradle中使用目标sdk版本23时,ZBA...
  5. Espresso Idling Resource 使用
  6. 第五届蓝桥杯——java c组 1/a 的分数称为单位分数
  7. 一篇文章,读懂品牌广告与效果广告的相同和不同
  8. CTF-SQL注入入门题型
  9. 关于 CVE-2021-44228 Log4j2 漏洞的相关应对汇总说明(包含中英文客户公告)
  10. 高速接口中的PRBS的设计