扫码阅读
手机扫码阅读

没有addon的生态,是个不够开放的生态

262 2023-09-07

Cloud Native

神州数码ESG服务BU云原生交付中心、云基地

在云原生上的尝试、调研与分享

本期作者

肖晟鹏

专业踩坑的 bug工程师

在前不久的一期云原生专栏推文中 神助攻网红项目一线牵:顶级云原生项目 KubeVela 插件仓库支持 GitLab 了! ,我们分享了云原生团队与顶级云原生开源项目 KubeVela 的故事,详细介绍了 KubeVela 的项目背景、应用场景,谈到了云原生团队借由给自己编写 addon (插件)的契机,成功为 KubeVela 做出了在代码仓库方面的开源贡献——实现 KubeVela 插件仓库对 GitLab 的支持。

那么本期推文就来初步探索 KubeVela 中的 addon,谈谈 KubeVela 中为什么需要 addon,并以一个简小的例子来说明如何自定义 addon。


#1 为什么需要addon

我们知道,应用和 模块自定义 都可以自己写 yaml 或者 cue 文件部署,为什么会存在 addon (插件)呢?

这是因为通过自己写 yaml 和 cue 的方式来部署应用一般是用于部署自己写的服务,而如果是部署一些通用的中间件,这种方式就太麻烦了。比如有的应用每个集群只需要部署一次,但是非常复杂,每次部署都要写一大堆配置文件。

并且如果应用需要用到一个复杂的模块定义,那么开发人员在部署应用的时候就会花费大量的时间去研究怎么写 yaml 或者 cue 去扩展 KubeVela。


什么是 cue

cue 是 json 的超集,与 Go 完美集成,还能使用 go 的一些内置依赖包。

使用 cue 的目的就是为了使配置更加灵活。

在 KubeVela 中部署的时候,cue 定义会转变为 yaml 定义。

那么有没有一个很好地解决办法呢?

这就是 Addon了。

Addon 在安装启用之后,会被创建成一个一个的应用,最终由运行在管控集群的 KubeVela 控制器完成对应用中所描述资源的下发。

插件可以给 KubeVela 管理的集群带来:自定义的应用和自定义的组件。

并且,Addon 在 UX 页面上是可以通过 OSS 或者代码仓库引入的,官方有个公共的插件库,并且还能够引入自己的插件库,在页面上点击启用,或者使用 CLI enable,就能给 KubeVela 带来新的功能,在 KubeVela 中扩展 Terraform 功能就是通过 addon 的形式来的。

#2 如何定义addon

addon代码的目录结构

那么插件是如何定义的呢?

官方文档中有简单的说明,其实插件代码中编写的就是一些 yaml 和 cue 文件,addon 代码必须要满足如下目录结构,其中metadata.yamltemplate.yaml是必须的:


目录结构

├── resources/
│   ├── xxx.cue
│   ├── xxx.yaml
│   └── parameter.cue
├── definitions/
├── schemas/
├── README.md
├── metadata.yaml
└── template.yaml

metadata.yaml: 元数据文件 (metadata.yaml)描述了插件的名称、描述等基本描述信息。只有包含这个文件,一个仓库下的目录才会被 UX/CLI 识别为一个插件的资源目录。

template.yaml: 插件目录下面的所有文件最终会渲染成为一个 KubeVela 的 Application 应用,所以template.yaml就是用于组成这个应用的框架。

resources目录: 下的文件可以理解为应用的部署文件,格式为K8S的Manifest,当addon启用的时候,如果resources目录下有定义,就会部署到集群上面去。

definitions目录: 用于存放组件定义、运维特征定义和工作流节点定义等模版定义文件,当addon启用的时候,如果该目录下有定义,那么最终KubeVela会引入新的模块定义,比如新的组件定义,在部署的时候就可以选择不同的type,而不是webservice进行部署。

schema目录: 配合definitions目录中存放的模块定义。在definitions目录下编写模块定义时,在cue中通常会写一些自定义的属性,比如开放什么端口,service的类型等。这些自定义的属性在CLI部署的时候可以供用户使用,如果你希望这些属性也能够在UX界面展示,就需要在该目录下将这些数据写进去。


概念是很抽象的,实践才是检验真理的唯一标准。

我们这里来做一个小实验,从简单的 addon 部署简单应用开始。

一个简单的小实例

Step 1:创建代码仓库

首先创建一个代码仓库,目录结构如下:

/ 代码仓库的目录结构

resources 目录下保存的是一些 k8s 的 Manfest,如下:

redis-deployment.yaml

apiVersion: apps/v1kind: Deploymentmetadata: name: redis-deployment namespace: redis labels: app: redisspec: replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - name: redis image: redis:6.2.6 command: - "sh" - "-c" - "redis-server /usr/local/etc/redis/redis.conf" ports: - containerPort: 6379 volumeMounts: - name: data mountPath: /data - name: config mountPath: /usr/local/etc/redis/redis.conf subPath: redis.conf volumes: - name: data hostPath: path: /home/k8s/redis/data - name: config configMap: name: redisconfig

redis-service.yaml

apiVersion: v1kind: Servicemetadata: name: redis-service labels: app: redisspec: type: NodePort ports: - name: redis port: 6379 selector: app: redis

redis-config.cue

output: { type: "raw" properties: { apiVersion: "v1" kind: "ConfigMap" metadata: { name: "redisconfig" namespace: "redis" } data: input: parameter.redisconfig }}

parameter.cue

apiVersion: apps/v1kind: Deploymentmetadata: name: redis-deployment namespace: redis labels: app: redisspec: replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - name: redis image: redis:6.2.6 command: - "sh" - "-c" - "redis-server /usr/local/etc/redis/redis.conf" ports: - containerPort: 6379 volumeMounts: - name: data mountPath: /data - name: config mountPath: /usr/local/etc/redis/redis.conf subPath: redis.conf volumes: - name: data hostPath: path: /home/k8s/redis/data - name: config configMap: name: redisconfig

ps:这里的 parameter 就是自定义的属性。

如果熟悉 K8S 的读者一眼看过去就明白,这就是 K8S 的 Manifest,在 K8S 上面部署资源的文件。

addon 仓库中必须要有 metadata.yaml 文件,该文件描述了插件的名称、描述等基本描述信息。只有包含这个文件,一个仓库下的目录才会被 UX/CLI 识别为一个插件的资源目录。

metadata.yaml

metadata.yaml:name: my-redisversion: 1.0.0description: Example adddon.icon: icon/niu.jpegurl: example.com tags: - only_example deployTo: runtimeCluster: false

这里就是描述了这个插件的基本信息,这里有一个参数deployTo.runtimeCluster,表示插件是否安装到子集群当中,当该字段被设置为 true,应用中的资源会被下发到子集群当中。

插件目录下面的所有文件最终会渲染成为一个 KubeVela 的 Application 应用,所以 template.yaml 就是用于组成这个应用的框架。

template.yaml

apiVersion: core.oam.dev/v1beta1kind: Applicationmetadata: name: redis namespace: redisspec:

这个文件就是 KubeVela 在部署应用时使用的 yaml 定义,我这里什么都没有写,只是定义了应用的名称和命名空间,插件在启用的时候会走默认的工作流,将 resources 目录中定义的 k8s 资源部署到 KubeVela 的集群中。

Step 2:启用插件

在服务器上克隆代码,使用命令启用插件::

vela addon enable

启用成功之后能通过命令查看刚刚引入的 addon:

这里的 addon 名称就是在 metadata.yaml 定义的name, 使用命令查看 application,可以看到自定义的应用:

使用 kubectl 工具查看 K8S 资源,可以看到部署的情况:

启用这个 addon,KubeVela 就将 addon 代码中定义的一些 k8s 资源 渲染成 KubeVela 应用并创建,这就是 addon 的运行机制。

#3 说在最后

addon 部署应用一般用于给集群带来一些只需要部署一次的应用,比如 KubeVela 的 UX,或者一些通用的中间件等。

但是在实际使用中,通常用户有着不一样的需求,比如在部署服务 A 时,需要一个定制参数的中间件。在部署服务B时,需要不同的工作流节点。在这种场景下,就可以通过 addon 带来模块定义,在部署应用的时候选择不同的组件类型,不同的工作流节点类型。

关于如何使用 addon 扩展 KubeVela 模块,这里留一个悬念,我们下篇文章再见!


原文链接: http://mp.weixin.qq.com/s?__biz=Mzg5MzUyOTgwMQ==&mid=2247500429&idx=1&sn=4b8dda60c01e1305532755caab0b4c6f&chksm=c02ff92bf758703d9720f8e6a520c2eab4fda7359b7738610136ae32fedf45d207211465a65e#rd