KubeSphere DevOps 包含 S2I 和 Pipeline 两部分。在社区中,openshift 提供了一个打包应用的工具 S2I,具体请参考 使用 S2I 构建云原生应用
。KubeSphere 将其做成了服务,采用 CRD 使用一个单独的 Operator 对其进行管理,功能比较独立。而在 3.0 中 Pipeline 与 KubeShere Core 耦合依然十分紧密,在搭建环境和调试上略显复杂。本篇主要提供开发者维护和二次开发 KubeSphere DevOps 3.0 指引。
1. DevOps 流水线架构
下图是流水线的整体架构:
1.1 存储模型
产品概念 | Kubernetes 对象 | Jenkins 对象 |
---|---|---|
DevOps 工程 | DevopsProject | 文件夹 |
流水线 | Pipeline | 流水线/多分支流水线 |
凭证 | Credential | 文件夹下的凭据 |
1.2 数据流
主要涉及两类,一类是创建类型的操作,另一类是触发类型的操作。
创建类型的操作,主要包括三种 CRD 类型的创建,DevopsProject、Pipeline、Credential 。用户通过前端,调用 ks-apiserver 接口,创建对应资源存储在 Etcd 中,然后 ks-controller-manager 不断地将这些对象同步到 Jenkins 。
触发类型的操作,主要是执行、审核流水线等瞬时动作。用户通过前端,调用 ks-apiserver 经过数据转换,直接调用 Jenkins API 。
2. DevOps 流水线相关的组件
2.1 系统核心组件
- ks-apiserver
ks-apiserver 是访问服务的 API 入口。在 3.0 中,ks-apigateway、ks-account 被合并到了 ks-apiserver。因此,ks-apiserver 承载了这两个组件的功能。
- ks-controller-manager
在 3.0 中,DevOps 依然与 KubeSphere Core 代码紧密耦合,没有运行单独的 Operator 处理相关的 CRD 资源。DevOps 所有 CRD 资源的处理都在 ks-controller-manager 中进行。
2.2 Jenkins 流水线
- ks-jenkins
Jenkins 采用的是 Helm 进行安装和维护,相关的配置可以查看 GitHub 上 ks-installer 仓库 。
其中 Jenkins 镜像使用的是官方的,没有进行任何定制。
- uc-jenkins-update-center
uc 是提供给 Jenkins 下载插件的服务。有两方面的原因需要 uc: 一方面是适配离线环境,同时线上官方地址下载慢;另一方面是有自行开发的插件需要集成。
uc 提供的只是一个 Nginx 下载服务,相关的镜像内容也只是为了存储 Jenkins 插件而已。
3. 如何搭建流水线的开发环境
3.1 本地安装 Git、Go、Kubebuilder 基础环境
在此不会详细描述,仅以 OS X 为例。
- 安装 Git
|
|
查看版本
|
|
- 安装 Golang
|
|
查看版本
|
|
- 安装 Kubebuilder
|
|
查看版本
|
|
3.2 安装并配置本地访问
- 安装 Kubernetes 集群
推荐安装工具 Kubekey。现在主流的集群安装工具是基于 Kubeadm 的二次封装。Kubekey 的优势是国内安装快,配置简单。使用 Kubeadm 半小时的工作量,Kubekey 两分钟解决,还集成了不少插件。这也符合我提倡的,技能文档化,文档工具化,工具产品化,产品服务化 的想法。
在安装时,需要注意一个参数。
|
|
由于 kube-apiserver 采用的是 https 通信,这里的 domain 会被设置到 certSANs 中生成证书。通过 certSANs 中地址进行地访问才是合法的。
- 开发环境配置 hosts
完成安装 Kubernetes 集群之后,在开发环境配置 hosts ,即可直接通过 domain 进行远程访问 kube-apiserver 。下面是我本地的 /etc/hosts
配置,一共有三个集群:
|
|
- 开发环境配置 kubeconfig
简单一点,可以直接拷贝服务器的文件到本地保存。这里提供一份脚本,可以快速切换多个环境。注意,替换 your_password
为你的远程登陆密码。
|
|
使用时,执行 on_k8s k1
切换到 k1 环境,执行 on_k8s k2
切换到 k2 环境。
- 验证配置是否成功
|
|
3.3 克隆 KubeSphere 仓库代码
star & fork GitHub 项目 kubesphere/kubesphere 。Git 的提交流程可以参考文档: 一个完整的 Git 提交流程 。
- 克隆代码
|
|
- 进入项目目录
|
|
3.4 配置 Webhook 证书
执行如下命令,在 $TMPDIR
目录下生成证书。
|
|
|
|
3.5 配置 kubesphere.yaml
- 在项目根目录下,新增 kubesphere.yaml 文件。
|
|
这里我直接使用远程环境的访问地址,比使用 telepresence 通过集群服务地址访问效率更高。kubesphere.yaml 中相关的配置值,可以从 kubectl get cm kubesphere-config -n kubesphere-system -o yaml
的输出中获取,粘贴到开发环境中即可。
值得注意的是 3.0 中,采用外置的 Sonarqube ,因此,需要根据官方文档进行单独配置。kubeconfig
字段指向的是开发环境 kubeconfig 文件地址,而线上使用的是 serviceaccount 。S2I 依赖于 S3 服务存储二进制文件,流水线不需要 S3。
3.6 本地运行测试服务
- 运行 ks-apiserver
|
|
服务启动之后,会打印 Start listening on :9090
表示,ks-apiserver 监听在 9090 端口,可以访问。
通过 Postman 进行访问时,需要带上集群前端的 Token,也可以使用 kubesphere-config 中的永久 Token,还可以将 mode 改为 AlwaysAllow
关掉鉴权。
在 Postman 中,可以设置一下变量,通过 {{ VAR_NAME }}
的形式可以引用,十分方便。下面有两类 API 的调用示例:
一种是 CRD 资源的增删改查,带上 Token 即可。
另一种是透传 Jenkins API ,不仅需要带上 Token,还需要带上 Jenkins Crumb 。这些参数通过页面访问时,在 Cookies 中都可以拿到。
- 运行 ks-controller-manager
为了避免干扰,需要先暂停集群中的 ks-controller-manager 。
|
|
运行本地的 ks-controller-manager
|
|
4. 如何发布到集群环境
建议将相关服务的 imagePullPolicy
改为 Always
,确保每次使用的都是最新的镜像。
4.1 更新插件
建立如下目录结构:
|
|
Dockerfile 内容
FROM busybox:1.29.3
COPY webroot/ /webroot/
webroot 中的内容,可以先运行 docker run -it -d kubesphere/jenkins-uc:v3.0.0
获取到容器 ID ,然后使用 docker cp {UC_ContainerID}:/webroot ./
命令拷贝插件,自由替换、增删其中的离线插件。
最后使用 docker build . -t shaowenchen/jenkins-uc:latest
命令打包,推送镜像。然后执行命令 kubectl -n kubesphere-devops-system edit deploy uc-jenkins-update-center
,修改 uc 的服务镜像为 shaowenchen/jenkins-uc:latest
,重启 deploy 即可。
这里需要注意的是 Jenkins 只有在首次初始化时,访问 uc 获取插件。初始化插件列表在 kubectl -n kubesphere-devops-system get cm ks-jenkins -o yaml
中可以查看。
4.2 更新 ks-apiserver 或 ks-controller-manger
- 编译 ks-apiserver
|
|
- 编译并推送 ks-apiserver 镜像
docker build -f build/ks-apiserver/Dockerfile -t shaowenchen/ks-apiserver:latest .
docker push shaowenchen/ks-apiserver:latest
- 更新 ks-apiserver 服务
执行命令,更新镜像为 shaowenchen/ks-apiserver:latest 即可。
|
|
- 编译 ks-controller-manager
|
|
- 编译并推送 ks-controller-manager 镜像
docker build -f build/ks-controller-manager/Dockerfile -t shaowenchen/ks-controller-manager:latest .
docker push shaowenchen/ks-controller-manager:latest
- 更新 ks-controller-manger 服务
执行命令,更新镜像为 shaowenchen/ks-controller-manager:latest 即可。
|
|
5. 关于鉴权插件
kubesphere-token-auth-plugin 插件主要是为了集成 KubeSphere 的权限体系,使 Jenkins 与之保持一致。如下图,无论是 CRD 资源类型,还是触发动作类型,在调用 Jenkins 时,都需要经过 ks-apiserver 进行 token 的 review。
在 KubeSphere 中 Token 是 bearer 类型,但是插件是基于 Basic 鉴权进行的扩展,所以需要转换。代码如下:
|
|
插件中的逻辑主要是,调用 ks-apiserver 鉴权接口,返回合法用户。
6. 后端代码结构及逻辑
6.1 代码目录
代码路径以 https://github.com/kubesphere/kubesphere/tree/release-3.0 为例。
- pkg/apiserver/apiserver.go
通过 ks-apiserver 对外提供的接口,都需要在这里进行注册,配置 GVR 等。
- pkg/kapis/devops
KubeSphere 以 /kapis
为前缀提供 API, 在这里还需要对每个 URL 进行更详细的描述和处理,通常会调用到很多 models 中的函数方法。API 文档也是在这里进行描述的。
- pkg/models/devops
对于数据层的操作,被聚合在 models 中。这里提供了很多对数据的操作方法。
- pkg/controller/devopscredential
credential 的 controller 处理部分。
- pkg/controller/devopsproject
devopsproject 的 controller 处理部分。
- pkg/controller/pipeline
pipeline 的 controller 处理部分。
- pkg/simple/client/devops
上面的代码理解起来相对容易,这部分会有些难度。这里的主要功能是提供对 Jenkins 的操作函数方法。在实现时,抽象了一个 Interface ,希望能够对接不同的编排工具。
简单说了下代码目录,可能还是不够清晰。下面一起通过调用逻辑看看代码。
6.2 关于 CRD 类型的代码逻辑
以创建 DevOps 工程为例。
前端调用 /kapis/devops.kubesphere.io/v1alpha3/workspaces/liuxin-test/devops/ ,传递参数
后端处理 https://github.com/kubesphere/kubesphere/blob/release-3.0/pkg/kapis/devops/v1alpha3/register.go#L154 ,通过生成的 client 写入 Etcd
ks-controller-manager 处理 https://github.com/kubesphere/kubesphere/blob/release-3.0/pkg/controller/devopsproject/devopsproject_controller.go#L205 ,这里单步运行,可以缕清整个链路。最终是调用 pkg/simple/client/devops 中的接口,在 Jenkins 中,创建一个文件夹。
6.3 关于触发类型的代码逻辑
以触发代码扫描为例。
前端调用 kapis/devops.kubesphere.io/v1alpha2/devops/test2-projectwvb2n/pipelines/test1-pipeline/scan/ , 传递参数
后端处理 https://github.com/kubesphere/kubesphere/blob/release-3.0/pkg/kapis/devops/v1alpha2/register.go#L479 ,这是就不需要经过 ks-controller-manager,单步运行调试会发现,依然会进入 pkg/simple/client/devops 然后组装 xml 调用 Jenkins API 。
7. 前端代码结构和逻辑
前端的代码结构清晰,非常直观,文件名能与页面对应上。下面以仓库地址 https://github.com/kubesphere/console/tree/release-3.0 为例进行说明。另外,前端采用的是 React 框架。
7.1 代码目录
主要的逻辑都在 src/pages/devops 目录。
- components
流水线相关的组件。而 src/components 中是整个项目公共的组件。
- containers
对应流水线相关的页面。如下图,左侧选项卡与文件夹中文件名一一对应,包括流水线图形化编辑页面。
- routes
单页面应用的路由配置。