KubeSphere DevOps 流水线入门指南

打印 上一主题 下一主题

主题 654|帖子 654|积分 1962

作者:赵海亮,浙江大学计算机专业四年级在读博士生,研究方向为云计算、边沿计算、分布式系统等。
  虽然 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-parent、yygh-site 和 yygh-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 拉取源代码:
  1. (base) ➜  his lsa
  2. total 0
  3. drwxr-xr-x   5 hliangzhao  staff   160B Nov 15 10:33 .
  4. drwxr-xr-x@ 42 hliangzhao  staff   1.3K Nov 15 10:33 ..
  5. drwxr-xr-x  24 hliangzhao  staff   768B Nov 15 10:33 yygh-admin
  6. drwxr-xr-x  15 hliangzhao  staff   480B Nov 15 10:33 yygh-parent
  7. drwxr-xr-x  24 hliangzhao  staff   768B Nov 15 10:34 yygh-site
复制代码
依次查看三个项目的文件布局:
  1. (base) ➜  his cd yygh-parent
  2. (base) ➜  yygh-parent git:(master) tree -L 2
  3. .
  4. ├── common                      # 通用模块
  5. │   ├── common-util
  6. │   ├── pom.xml
  7. │   ├── rabbit-util
  8. │   └── service-util
  9. ├── data                        # 项目演示数据
  10. │   ├── json
  11. │   └── sql
  12. ├── hospital-manage             # 医院后台
  13. │   ├── Dockerfile
  14. │   ├── deploy
  15. │   ├── pom.xml
  16. │   ├── src
  17. ├── model                       # 数据模型
  18. │   ├── pom.xml
  19. │   └── src
  20. ├── pom.xml
  21. ├── server-gateway              # 网关
  22. │   ├── Dockerfile
  23. │   ├── deploy
  24. │   ├── pom.xml
  25. │   └── src
  26. ├── service                     # 微服务层
  27. │   ├── pom.xml
  28. │   ├── service-cmn             # 公共服务
  29. │   ├── service-hosp            # 医院数据服务
  30. │   ├── service-order           # 预约下单服务
  31. │   ├── service-oss             # 对象存储服务
  32. │   ├── service-sms             # 短信服务
  33. │   ├── service-statistics      # 统计服务
  34. │   ├── service-task            # 定时服务
  35. │   └── service-user            # 会员服务
  36. └── service-client
  37.     ├── pom.xml
  38.     ├── service-cmn-client
  39.     ├── service-hosp-client
  40.     ├── service-order-client
  41.     └── service-user-client
  42. 30 directories, 12 files
  43. (base) ➜  yygh-parent git:(master) cd ../yygh-admin
  44. (base) ➜  yygh-admin git:(master) tree -L 1        # 医院挂号后台(前端 UI)
  45. .
  46. ├── Dockerfile
  47. ├── LICENSE
  48. ├── build
  49. ├── config
  50. ├── deploy
  51. ├── favicon.ico
  52. ├── index.html
  53. ├── package.json
  54. ├── src
  55. └── static
  56. 5 directories, 9 files
  57. (base) ➜  yygh-site git:(master) tree -L 1        # 用户挂号前台(前端 UI)
  58. .
  59. ├── Dockerfile
  60. ├── api
  61. ├── assets
  62. ├── components
  63. ├── deploy
  64. ├── layouts
  65. ├── middleware
  66. ├── nuxt.config.js
  67. ├── package-lock.json
  68. ├── package.json
  69. ├── pages
  70. ├── plugins
  71. ├── static
  72. ├── store
  73. └── utils
  74. 11 directories, 7 files
复制代码
对于本项目,我们需要部署如下内容:
  1. yygh-parent/hospital-manage         # 医院管理
  2. yygh-parent/server-gateway          # 网关
  3. # 8 个微服务
  4. yygh-parent/service/service-cmn
  5. yygh-parent/service/service-hosp
  6. yygh-parent/service/service-order
  7. yygh-parent/service/service-oss
  8. yygh-parent/service/service-sms
  9. yygh-parent/service/service-statistics
  10. yygh-parent/service/service-task
  11. yygh-parent/service/service-user
  12. # 2 个前端
  13. yygh-admin
  14. yygh-site
复制代码
以上 12 个待部署的子项目将以独立 Pod 的形式在集群中部署。 每一个子项目根目次需要具有一个 Dockerfile 文件以及一个名为 deploy 的文件夹。 前者是本子项目的镜像制作文件,后者是本子项目的资源清单文件 *.yaml(用于在集群中部署)。 以 service-cmn 为例,其文件布局如下:
  1. (base) ➜  service-cmn git:(master) tree -L 2
  2. .
  3. ├── Dockerfile        # 将本子项目构建为镜像的 Dockerfile
  4. ├── deploy            # 存放用于部署本子项目的资源清单文件
  5. │   └── deploy.yml
  6. ├── pom.xml           # 项目依赖
  7. ├── src               # 源代码
  8. │   └── main
  9. └── 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 为例:
  1. # service-cmn 的 Dockerfile
  2. FROM openjdk:8-jdk
  3. LABEL maintainer=leifengyang
  4. # 启动 prod 环境,以 service-cmn-prod.yml 作为启动配置
  5. 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"
  6. RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
  7. COPY target/*.jar /app.jar
  8. EXPOSE 8080
  9. 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,其最终内容如下:
  1. # service-cmn-prod.yml
  2. server:
  3.   port: 8080
  4. mybatis-plus:
  5.   configuration:
  6.     log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  7.   mapper-locations: classpath:mapper/*.xml
  8.   global-config:
  9.     db-config:
  10.       logic-delete-value: 1
  11.       logic-not-delete-value: 0
  12. spring:
  13.   cloud:
  14.     sentinel:
  15.       transport:
  16.         # 修改 sentinel 访问地址
  17.         dashboard: http://his-sentinel-nodeport.his:8080
  18.   redis:
  19.     # 修改 redis 访问地址
  20.     host: his-redis-nodeport.his
  21.     port: 6379
  22.     database: 0
  23.     timeout: 1800000
  24.     password:
  25.     lettuce:
  26.       pool:
  27.         max-active: 20      # 最大连接数
  28.         max-wait: -1        # 最大阻塞等待时间 (负数表示没限制)
  29.         max-idle: 5         # 最大空闲
  30.         min-idle: 0         # 最小空闲
  31.   datasource:
  32.     type: com.zaxxer.hikari.HikariDataSource
  33.     driver-class-name: com.mysql.jdbc.Driver
  34.     # 修改 mysql 访问地址和连接凭证
  35.     url: jdbc:mysql://his-mysql-nodeport.his:3306/yygh_cmn?characterEncoding=utf-8&useSSL=false
  36.     username: root
  37.     password: 123456
  38.     hikari:
  39.       connection-test-query: SELECT 1
  40.       connection-timeout: 60000
  41.       idle-timeout: 500000
  42.       max-lifetime: 540000
  43.       maximum-pool-size: 12
  44.       minimum-idle: 10
  45.       pool-name: GuliHikariPool
  46.   jackson:
  47.     date-format: yyyy-MM-dd HH:mm:ss
  48.     time-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 代码片段:
  1. stage('clone code') {
  2.   agent none
  3.   steps {
  4.     // 拉取代码并展示代码文件布局
  5.     container('maven') {
  6.       git(url: 'https://gitee.com/leifengyang/yygh-parent', branch: 'master', changelog: true, poll: false)
  7.       sh 'ls -al'
  8.     }
  9.   }
  10. }
复制代码
流水线的第二个阶段通常是项目的打包与编译。 默认环境下,Maven 从官方堆栈下载项目依靠,如果想要修改默认镜像堆栈,需要修改集群中名为 ks-devops-agent 的 ConfigMap,它拥有一个叫做 MavenSetting 的键:
  1. k8s@ubuntu:~$ k get cm -A | grep devops
  2. his-devopsqxxv7                   istio-ca-root-cert                                           1      24h
  3. his-devopsqxxv7                   kube-root-ca.crt                                             1      24h
  4. kubesphere-devops-system          devops-config                                                1      5d7h
  5. kubesphere-devops-system          devops-jenkins                                               9      5d7h
  6. kubesphere-devops-system          istio-ca-root-cert                                           1      5d7h
  7. kubesphere-devops-system          jenkins-agent-config                                         1      5d7h
  8. kubesphere-devops-system          jenkins-casc-config                                          2      5d7h
  9. kubesphere-devops-system          kube-root-ca.crt                                             1      5d7h
  10. kubesphere-devops-worker          istio-ca-root-cert                                           1      5d7h
  11. kubesphere-devops-worker          ks-devops-agent                                              1      5d7h
  12. kubesphere-devops-worker          kube-root-ca.crt                                             1      5d7h
  13. k8s@ubuntu:~$ k describe cm ks-devops-agent -n kubesphere-devops-worker
  14. Name:         ks-devops-agent
  15. Namespace:    kubesphere-devops-worker
  16. Labels:       app.kubernetes.io/managed-by=Helm
  17. Annotations:  meta.helm.sh/release-name: devops
  18.               meta.helm.sh/release-namespace: kubesphere-devops-system
  19. Data
  20. ====
  21. MavenSetting:
  22. ----
  23. <?xml version="1.0" encoding="UTF-8"?>
  24. ...
  25. <!--
  26. | This is the configuration file for Maven. It can be specified at two levels:
  27. ...
  28. <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  29.           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  30.           xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
  31. ...
复制代码
我们需要修改 MavenSetting 文件,在其中添加国内镜像堆栈地址:

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

相应地,在 Jenkinsfile 中也会自动天生第二步的代码:
  1. stage('project compilation') {
  2.   agent none
  3.   steps {
  4.     container('maven') {
  5.       sh 'mvn clean package -Dmaven.test.skip=true'
  6.     }
  7.   }
  8. }
复制代码
流水线的第三个阶段是制作镜像。我们在章节 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 中增加了如下内容:
  1. stage('default-2') {
  2.   parallel {    // 并行构建 10 个镜像
  3.     stage('build hospital-manage') {
  4.       agent none
  5.       steps {
  6.         container('maven') {
  7.           sh 'docker build -t hospital-manage -f hospital-manage/Dockerfile hospital-manage/'
  8.         }
  9.       }
  10.     }
  11.     stage('build server-gateway') {
  12.       ...
  13.     }
  14.     stage('build service-cmn') {
  15.       ...
  16.     }
  17.     ...
  18.   }
  19. }
复制代码
流水线的第四个阶段是镜像推送。在企业内部,构建好的镜像通常会被推送到企业的私有堆栈中。 笔者接纳阿里云给个人开发者免费提供的镜像堆栈作为推送目标。因为目标堆栈是一个私有堆栈,因此需要提供账户和暗码作为凭证(credential)。 怎样在 KubeSphere 中为镜像推送下令提供凭证呢? 我们可以在 DevOps 的项目设置中创建:

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

基于该凭证,我们在 Jenkinsfile 中编写镜像推送的代码如下:
  1. steps {
  2.   container('maven') {
  3.     // 使用'aliyun-docker-registry'这个凭证登录私有仓库并将镜像推送至其中
  4.     withCredentials([usernamePassword(credentialsId: 'aliyun-docker-registry', passwordVariable: 'ALIYUN_REG_PWD', usernameVariable : 'ALIYUN_REG_USER' ,)]) {
  5.       sh 'echo"$ALIYUN_REG_PWD"| docker login $REGISTRY -u"$ALIYUN_REG_USER"--password-stdin'
  6.       sh 'docker tag hospital-manage:latest $REGISTRY/$DOCKERHUB_NAMESPACE/hospital-manage:SNAPSHOT-$BUILD_NUMBER'
  7.       sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/hospital-manage:SNAPSHOT-$BUILD_NUMBER'
  8.     }
  9.   }
  10. }
  11. ...
  12. environment {
  13.   ...
  14.   REGISTRY = 'registry.cn-hangzhou.aliyuncs.com'
  15.   DOCKERHUB_NAMESPACE = 'hliangzhao-private'
  16.   ...
  17. }
复制代码
同样地,上述过程也以并行的方式执行。最终,Jenkinsfile 中被添加了如下代码:
  1. stage('default-3') {
  2.   parallel {   // 并行推送 10 个镜像
  3.     stage('push hospital-manage') {
  4.       agent none
  5.       steps {
  6.         container('maven') {
  7.           withCredentials([usernamePassword(credentialsId : 'aliyun-docker-registry' ,passwordVariable : 'ALIYUN_REG_PWD' ,usernameVariable : 'ALIYUN_REG_USER' ,)]) {
  8.             sh 'echo"$ALIYUN_REG_PWD"| docker login $REGISTRY -u"$ALIYUN_REG_USER"--password-stdin'
  9.             sh 'docker tag hospital-manage:latest $REGISTRY/$DOCKERHUB_NAMESPACE/hospital-manage:SNAPSHOT-$BUILD_NUMBER'
  10.             sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/hospital-manage:SNAPSHOT-$BUILD_NUMBER'
  11.           }
  12.         }
  13.       }
  14.     }
  15.     stage('push server-gateway') {
  16.       ...
  17.     }
  18.     stage('push service-cmn') {
  19.       ...
  20.     }
  21.     ...
  22.   }
  23. }
复制代码
测试一下到现在为止的流水线,一切运行顺利:

流水线的最后阶段是部署到开发环境和生产环境。因为这一阶段需要和 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 代码为
  1. stage('deploy hospital-manage to dev') {
  2.   agent none
  3.   steps {
  4.     container('maven') {
  5.       kubernetesDeploy(enableConfigSubstitution: true,
  6.         deleteResource: false,
  7.         kubeconfigId: 'demo-kubeconfig',          // 存储了 kubeconfig 上下文信息的文件
  8.         configs: 'hospital-manage/deploy/**'      // 资源清单文件所在位置
  9.       )
  10.     }
  11.   }
  12. }
复制代码
我们尝试运行一下现在的流水线,诡异的事变却发生了。在项目部署阶段产生了如下错误:
  1. Starting Kubernetes deployment
  2. Loading configuration: /home/jenkins/agent/workspace/his-devopsqxxv7/yygh-parent-devops/hospital-manage/deploy/deploy.yml
  3. ERROR: ERROR: java.lang.RuntimeException: io.kubernetes.client.openapi.ApiException: Bad Request
  4. hudson.remoting.ProxyException: java.lang.RuntimeException: io.kubernetes.client.openapi.ApiException: Bad Request
  5.   at com.microsoft.jenkins.kubernetes.wrapper.ResourceManager.handleApiExceptionExceptNotFound(ResourceManager.java:180)
  6.   ...
  7. Api call failed with code 400, detailed message: {
  8.   "kind": "Status",
  9.   "apiVersion": "v1",
  10.   "metadata": {
  11.   },
  12.   "status": "Failure",
  13.   "message": "the export parameter, deprecated since v1.14, is no longer supported",
  14.   "reason": "BadRequest",
  15.   "code": 400
  16. }
  17. 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 验证的写法:
  1. stage('deploy hospital-manage to dev') {
  2.   agent none
  3.   steps {
  4.     container('maven') {
  5.       // 如果不提供 kubeconfigFile,则 kubectl 上下文找不到
  6.       withCredentials([kubeconfigFile(credentialsId: env.KUBECONFIG_CREDENTIAL_ID, variable: 'KUBECONFIG')]) {
  7.         sh 'kubectl apply -f hospital-manage/deploy/**'
  8.       }
  9.     }
  10.   }
  11. }
复制代码
实行证明,该方法有用。同样地,10 个子项目可以并行化部署到 dev 环境。相应的 Jenkins 代码就不再展示了。 部署到 prod 环境的操作雷同。别的,还可以添加部署条件,比方,只有获得相关管理员授权之后部署操作才会启动。
创建前端项目部署流水线

接下来,还剩两个前端项目 yygh-site 和 yygh-admin 需要部署。 前端项目的部署服从相似的步骤:起首下载源码,然后需要通过 Node.js 之类的工具为项目安装依靠并构建(产生 dist 目次),最后是镜像构建、推送和部署。 以 yygh-site 为例,它最终的 Jenkinsfile 如下所示:
  1. pipeline {
  2.     agent {
  3.         node {
  4.             label 'nodejs'
  5.         }
  6.     }
  7.     stages {
  8.         stage('拉取代码') {
  9.             agent none
  10.             steps {
  11.                 container('nodejs') {
  12.                   git(url: 'https://gitee.com/leifengyang/yygh-site', branch: 'master', changelog: true, poll: false)
  13.                   sh 'ls -al'
  14.                 }
  15.             }
  16.         }
  17.         stage('项目编译') {
  18.             agent none
  19.             steps {
  20.                 container('nodejs') {
  21.                     sh 'ls'
  22.                     sh 'npm install --registry=https://registry.npm.taobao.org'
  23.                     sh 'npm run build'
  24.                 }
  25.             }
  26.         }
  27.         stage('构建镜像') {
  28.             agent none
  29.             steps {
  30.                 container('nodejs') {
  31.                     sh 'ls'
  32.                     sh 'docker build -t yygh-site:latest -f Dockerfile  .'
  33.                 }
  34.             }
  35.         }
  36.         stage('推送镜像') {
  37.             agent none
  38.             steps {
  39.                 container('nodejs') {
  40.                     withCredentials([usernamePassword(credentialsId: 'aliyun-docker-registry', usernameVariable: 'DOCKER_USER_VAR', passwordVariable: 'DOCKER_PWD_VAR',)]) {
  41.                         sh 'echo"$DOCKER_PWD_VAR"| docker login $REGISTRY -u"$DOCKER_USER_VAR"--password-stdin'
  42.                         sh 'docker tag yygh-site:latest $REGISTRY/$DOCKERHUB_NAMESPACE/yygh-site:SNAPSHOT-$BUILD_NUMBER'
  43.                         sh 'docker push  $REGISTRY/$DOCKERHUB_NAMESPACE/yygh-site:SNAPSHOT-$BUILD_NUMBER'
  44.                     }
  45.                 }
  46.             }
  47.         }
  48.         stage('部署到 dev 环境') {
  49.             agent none
  50.             steps {
  51.                 kubernetesDeploy(configs: 'deploy/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
  52.             }
  53.         }
  54.         // 1、配置全系统的邮件:                   全系统的监控
  55.         // 2、修改 ks-jenkins 的配置,里面的邮件;   流水线发邮件
  56.         stage('发送确认邮件') {
  57.             agent none
  58.             steps {
  59.                 mail(to: 'someone@test.com', subject: 'yygh-site 构建结果', body: "成功构建 $BUILD_NUMBER")
  60.             }
  61.         }
  62.     }
  63.     environment {
  64.       ...
  65.     }
  66. }
复制代码
此处不再展示更多细节。
总结

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

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

温锦文欧普厨电及净水器总代理

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表