大家好,很高兴来到“GO 开源说” 跟大家分享开源项目背后的一些故事、设计思想以及使用方法,今天分享的项目是 KubeVela,一个标准化的云原生平台构建引擎。我是来自阿里云云原生应用平台团队的孙健波(花名:天元),也是 KubeVela 这个项目的核心作者之一。
KubeVela :https://github.com/oam-dev/kubevela
KubeVela 的背景
KubeVela 是一个基于 Go 语言开发的云原生平台级开源项目,这个项目是去年 11 月中旬(详见https://mp.weixin.qq.com/s/LauydAy1ngcDuZ3lhqrL6Q)正式发布的。虽然发布到现在不足两个月时间,但是 KubeVela 作为"阿里巴巴统一云原生应用平台内核”背后的核心依赖,其实已经在阿里多个产品背后运行了比较长的一段时间,我本人目前也在大量参与这些产品和项目的内核建设工作。
这套内核系统诞生自 2019 年年底阿里云联合微软共同推出的 Open Application Model(简称 OAM:https://oam.dev/)模型基于 Kubernetes 的实现,在不断演进和迭代中融合了大量来自开源社区(尤其是微软、字节跳动、第四范式、腾讯和满帮集团的社区参与者们)的反馈与贡献,最终在 2020 年 KubeCon 北美峰会(详见https://medium.com/@alibaba-cloud/kubevela-the-extensible-app-platform-based-on-open-application-model-and-kubernetes-581b7f419e5e)上以“KubeVela”的名字正式与开源社区见面。KubeVela 项目在官宣后得到了整个云原生生态的持续关注,在发布后的第四天就登上了 Go 语言的开源趋势榜榜首。
图 1 KubeVela 的 GitHub Star 快速增长
KubeVela 的 github 地址:https://github.com/oam-dev/kubevela/
KubeVela 是什么?
一言以蔽之,KubeVela 是一个面向平台构建者的、简单易用但又高度可扩展的云原生平台构建引擎。
具体来说,KubeVela 的目标是让任何平台团队都能够以 Kubernetes 原生的方式,快速、高效的打造出适合不同业务场景的、能够直面用户的云原生平台出来。比如:构建应用 PaaS、数据库 PaaS、AI PaaS 或者持续交付系统等等。
图 2 KubeVela “关注点分离”的工作流
在设计上,KubeVela 对平台团队暴露了两大核心 API,包括:
能力模板:“能力”在 KubeVela 中,指能够组成一个完整应用的原子化功能,比如 StatefulSet 和 Ingress 就属于两种不同的“能力”。KubeVela 允许平台团队通过定义各种能力“模板”的方式,在 Kubernetes 中预置各种各样的能力。
部署环境模板:与“能力”类似,应用的部署环境在 KubeVela 中通过“环境”模板来进行预定义和初始化,比如“测试集群”和“生产集群”,就属于两种“环境”。
而作为平台的用户,比如业务团队,他们只需要通过平台团队提供的环境模板来“一键”初始化自己预期的部署集群,然后把自己需要的能力模板“组装”成一个完整的应用,就可以直接向任何 Kubernetes 集群进行应用交付和运维了。
由于上述这些能力和环境,都通过“模板”的方式进行了抽象,所以对于业务团队来说,它们并不需要学习完整的 Kubernetes 概念与细节,只需要了解上述模板暴露出来的参数,就可以无缝的使用 Kubernetes 来完成自己要做的事情。而具体通过模板暴露出哪些可配置项、背后的模板怎么渲染、渲染成什么样 Kubernetes 对象,则完全全在平台团队的掌控之中,并且可以随时调节和修改。
上述“平台团队提供能力模板”结合“业务团队组装模板声明应用”的工作流,也正是阿里和微软共同发布的 OAM 项目提倡的“关注点分离”思想的集中体现。在具体的模板支持上,KubeVela 第一期支持的是 Google 开源的 CUELang 模板语言,第二期则会支持 Helm Chart 包直接作为能力模板。
KubeVela 能为你做什么?
在了解了 KubeVela 是个什么项目以后,我们再来回答第二个大家一直都很关心的问题:作为一个平台构建者,KubeVela 能够帮助你做什么?
一、快速构建抽象
构建“抽象”,是任何一个云原生平台的最基础、也必然会提供的功能。
我们知道,Kubernetes 暴露出来的是一套声明式 API,而所谓抽象,其实就是一个平台在这些声明式 API 的基础上,为用户暴露出来的可操作项和可配置项。作为平台团队,我们之所以要提供“抽象”,其最终目的都是为了简化用户的使用心智,让业务团队只关注他们关心的事情,避免引入大量与业务无关的平台层细节让用户“望而却步”。可以说,提供“抽象”,是任何一个平台团队落地 Kubernetes 等系统级开源项目的第一步。
业界最常见的抽象方式,是给用户提供一个图形界面来进行操作(比如 Console 或者 Dashboard),这些图形界面的共同点,就是仅允许用户填写某些特定的字段参数,从而实现简化用户心智的目的,比如下图所示的某开源 K8s PaaS 项目的 Console:
图 3 某开源 K8s PaaS 项目的 Console
还有一些项目(比如 Racher Rio)选择给用户提供一个命令行工具,其实它的作用跟图形界面完全类似,只不过允许填写的参数变成了 CLI 的参数而已。
当然,对于一些技术水位更高的团队,他们会基于 Kubernetes 再开发上层的 CRD + Operator 来作为“抽象”。比如 Knative 其实就是一种面向 Serverless 场景的抽象,Pinterest 公司则有自己的 Application CRD 抽象等。
那么,作为平台团队,我们又是怎么来决定给用户暴露哪些可配置参数呢?这就涉及到了“抽象”的三种基础模式(更复杂的情况都是对这三种模式的进一步组合):
组合抽象,这种模式常见于我们把 2 个原子能力组合成为一个能力提供,比如我们在实际开发 Console 时,经常会把 K8s Deployment 和 Service 进行“组合”,暴露出一个 Web Service 的概念来让用户可以在一个表单里同时定义容器镜像和暴露端口。
拆分抽象,这种模式常见于我们希望在使用流程上把一个对象上的字段分开成几个表单来进行分步骤填写,从而解耦部署时与运维时的配置。比如一个 Pod 里面的多个容器, 我希望在第一个表单里让用户填写业务容器,在另一个表单让运维填写 Sidecar 容器。再比如 ArgoRollout 这个对象,我会希望一个表单让用户填写容器镜像,另一个表单让运维填写灰度策略。
转换抽象,这种模式通常用于改个名字,或者说去掉一些无关的概念,比如 Knative Revision 跟 Deployment 本质上是一一对应的,但是里面类似 LabelSelector 这种用户不需要关心的字段在 Knative 就会直接去掉了。
图 4 常见抽象模式
上述几种抽象的模式,在业界的很多平台级项目和产品中都有体现。但另一方面,如何正确的设计抽象,以及如何确保抽象能够满足业务方用户的使用需求和习惯,其实是一个非常具备挑战性的问题。这里的关键点在于,无论是图形化界面,还是 CRD Operator,这些“抽象”一旦上线,对它的修改就非常困难。可是另一方面,业务方用户的需求,又几乎不可能是一成不变的(实际情况甚至是“一天一个样”)。
KubeVela 对于“抽象”的设计与实现
作为阿里巴巴的平台团队,我们在进行大规模云原生应用基础设施的实践中,同样也遇到了如何设计“抽象”的难题与挑战。经过大量的尝试与总结,我们最终和研发效能团队一起选择了 GitOps + IaC(Infrastructure as Code)的技术组合来解决这个问题(具体大家可以看这篇文章:https://developer.aliyun.com/article/776786)。
其中,GitOps 更多是对交付流水线的创新,而 IaC 的存在,就是为了解决“抽象”这个问题。具体来说,IaC 的强大之处在于,它对“抽象”的定义是通过“模板”来表达的。这意味着一个“抽象”背后,并不需要 CRD Operator 这样复杂的服务器端编程工作,作为平台团队我们只需要提交一个模板,用户就“自动”有了抽象后的字段;而如果要修改这些抽象字段,我们只需要将对应模板更新,用户那边的抽象也就“自动”改变了。这种抽象机制的调整和更新,不需要任何重新编译和上线的环节,所以我们把它也称为“客户端抽象”。
图 5 用户、抽象、模板和原始 K8s API 之间的关系
在具体的实现上,阿里巴巴是通过 CUELang(https://cuelang.org/) 这个 Google 开发的模板语言来定义抽象模板的,这也是为何 KubeVela 第一期先开源了基于 CUE 的抽象机制。在具体使用上,平台团队只需要将 CUE 模板按照 OAM 规范(即:WorkloadDefinition 和 TraitDefinition 对象)注册(kubectl apply)到 Kubernetes 集群当中,业务用户就可以立刻使用这个抽象(具体的使用方式我们后面会详细说明)。
另一方面,CUE 之所以受到 Google 和阿里的青睐,还在于它比较完善的抽象层实现能力。比如前面我们总结了抽象的三种模式,其中 “转换抽象”和“组合抽象”在模板渲染的时候很容易做,无非就是模板渲染的时候换个字段名称,生成的内容变成多个对象而已。但是拆分抽象其实是有很大难度的,这涉及到拆分后能力的独立运行以及最终两个能力又重新组合到一起(patch-merge)的过程。
而借助 KubeVela,这个拆分就比较简单了。以前面提到解耦业务容器与 Sidecar 容器的定义流程为例,我们希望把“定义业务容器”和“定义 Sidecar 容器”在用户侧拆到两个不同的表单上去。在具体执行上,平台团队只需要注册一个 WorkloadDefinition 对象(名叫 worker),里面携带业务容器的 Deployment 模板,然后再注册一个 TraitDefinition 对象(名叫 sidecar),里面只携带 Sidecar 容器的模板,那么 KubeVela 就会对用户侧暴露出 worker 和 sidecar 两套完全独立的可配置项,使得用户可以在部署时只需要填写 worker 中的业务容器参数,运维则可以在后续的运维时独立填写 sidecar 的配置参数,而完全不需要对用户的 worker 部分进行任何修改。
图 6 KubeVela 对 Kubernetes API 进行“拆分”的例子
当然,除了 CUE 之外,上述抽象机制也可以通过 Helm 来实现,并且同 GitOps 流水线无缝集成。这个功能会作为 KubeVela 下一个重要特性发布,届时我们会分享基于 KubeVela 构建持续交付系统的案例与最佳实践。
二、快速构建用户使用界面
在有了上述“抽象”之后,作为平台的最终用户,业务团队就可以通过某种方式使用这些抽象来交付和管理应用了。在这一层,KubeVela 不会做任何约束,相反,它的目标是让抽象能够被直接透出在用户的使用界面上,这样,当平台团队对这些抽象进行了调整之后,业务用户就可以立即使用到最新的抽象,不需要对系统做任何更新或者升级。
在具体执行上,KubeVela 会给上述抽象自动生成 JSON schema,这个 JSON schema 的内容,就是该抽象允许用户填写的参数列表和类型。所以无论是图形界面,还是其他用户界面,就可以直接使用这个 JSON schema 渲染出用户表单,甚至生成使用文档(https://kubevela.io/#/en/developers/references/workload-types/webservice )。
比如前面解耦 Sidecar 容器定义的例子,KubeVela 就会为用户暴露出两份 JSON schema:一个用来定义业务容器的参数列表,一个用来 Sidecar 容器的参数列表,前端就可以渲染成两个独立的表单来供用户填写。
正是上述 IaC 抽象 + 自动生成 Schema 的机制,让基于 KubeVela 构建面向用户的使用界面不仅变得非常简单,而且还高度可扩展:这些抽象背后的模板只要被平台管理员修改,就会立刻体现在用户的图形界面表单上,根本不需要进行系统升级和重新上线。
在 KubeVela 中,它内置了一个简化版的图形界面,叫做 Appfile,它其实就是把上述抽象的 schema 以 YAML 的方式展示了出来,从而允许用户进行修改和配置,在下面的例子中,我们可以形象的看到每一个“能力抽象”(route,autoscaler 等等)在 Appfile 如何体现为一个个可配置项的。
图 7 在 Appfile 使用 KubeVela 中的抽象
图 8 使用 vela traits 查看已经注册的能力
图 9 使用 vela show 查看能力的使用文档(自动生成)
目前,Appfile 是 KubeVela 内置的使用“抽象”的主要用户界面。与此同时,相同机制的 Dashboard 和 Restful API (https://github.com/oam-dev/kubevela/blob/master/design/vela-core/APIServer-Catalog.md)则计划在 2021 Q2 在 KubeVela 中发布出来,从而让用户通过图形界面和 API 的方式来定义和使用这套抽象机制。
值得一提的是,作为 Kubernetes 原生的平台构建引擎,KubeVela 的上述抽象机制和 Appfile 本身,全部都以声明式 API 的方式实现在 Kubernetes 当中,其中 Appfile 对应的 CRD 就叫做 Application 对象(https://github.com/oam-dev/kubevela/blob/master/config/samples/application/application-sample.yaml)。
所以作为平台团队,他们通过 Definition CRD 来注册抽象模板,作为平台的用户,他们实际上则是通过这个 Application CRD 来使用抽象模板,整套机制完全以 Kubernetes 插件的方式运行,提供了最原生的被集成和可扩展能力。
三、借助 Terraform 统一定义和管理云资源
而有了 Definition + Application 这套体系(这也正是 OAM 规范的核心内容)之后,KubeVela 就可以在一套统一的使用体验和 API 下,集成更多的能力提供方,比如:Terraform(https://www.terraform.io/)。
Terraform 是业内知名的创建云资源的工具,它丰富的生态几乎包含了所有主流云厂商的大部分云资源,是对 Kubernetes 云资源管理能力不足最好的补充。
在 KubeVela 中使用 Terraform 定义和拉起云资源非常简单,如下图所示:
图 10 KubeVela 使用 Terraform 拉起云资源
平台团队:注册云资源模板和抽象
平台团队的工作是定义一个名为"aliyun-rds"的 WorkloadDefinition 对象,并且在里面定义好 Terraform 阿里云 RDS 云资源的模板。在上述例子中我们同样是通过 CUE 来编写的 Terraform 配置, 这是因为 Terraform 云资源本身支持使用 JSON 格式描述,而 CUE 又是 JSON 的超集,所以可以自然的使用 Terraform 所有的能力。
当然,另一方面我们也在计划支持 Terraform 的 HCL (https://www.terraform.io/docs/configuration/syntax.html)语法来作为 KubeVela 的另一种模板语言。在 CUE 模板中我们引用了阿里云的 RDS 定义,并抽象成 user、password 等少量用户字段(parameter)。
用户:定义和使用云资源
这样,用户只需要在 Appfile 中,填写一个新的 Service,命名为 sample-db 而其类型就是我们上面定义的 aliyun-rds,就可以在这个部分定义模板中提供的 user,password 等参数。
除此之外,用户还可以在上面的 express-server 这个业务应用中定义数据绑定,填写名为 sample-db 的配置及其映射的环境变量名称。
最后,用户只需要一句 vela up 命令,KubeVela 就会拉起业务容器,然后自动把 Terraform 创建的阿里云 RDS 返回的链接信息传递到业务的容器中,我们可以在最后一部分看到这个应用已经成功启动,并获得了数据库的连接信息。当然,这个流程中的数据传递和编排功能,也是 KubeVela 内置的核心能力。
总结
作为 Kubernetes 上第一个云原生平台构建引擎以及 OAM 模型的完整实现,KubeVela 为平台构建者提供的能力远不止这些,比如后续即将开源的统一应用灰度框架、多集群多环境的交付组件、CRD Controller 的生命周期管理等等,都是 KubeVela 重点打造的的核心能力。限于篇幅就不再一一展开,非常欢迎大家到社区(https://kubevela.io/)中使用和反馈,了解更多的细节。
本文转载自:阿里巴巴中间件(ID:Aliware_2018)
评论