慎重选用 Runtime 类框架开发 K8s apiserver
本文为 K8s API 和控制器 系列文章之一
- K8s CustomResourceDefinitions (CRD) 原理
- K8s 多版本 API 转换最佳实践
- 实现一个极简 K8s apiserver
- 搞懂 K8s apiserver aggregation
- 最不厌其烦的 K8s 代码生成教程
- 使用 library 实现 K8s apiserver
- 慎重选用 Runtime 类框架开发 K8s apiserver(本文)
- K8s API Admission Control and Policy
sigs.k8s.io/apiserver-runtime 试图用 kubebuilder 构建控制器的理念提供一套快速构建 apiserver 框架,它做了如下事情
引入了 resource.Object interface resourcestrategy interfaces 等各种接口集合
- 尝试聚合存储层策略到 API 层:鼓励将 k8s.io/apiserver 各种 REST storage interfaces 直接放到 API structs 中实现
- 抛弃 Kubernetes 官方项目中较为复杂的 conversion 和 default funcs 代码生成,提供新协议 Defaulter interface 和 Converter interface,以及它们之上的 runtime.Scheme 注册实现
- 基于 k8s.io/apiserver RESTOptionsGetter interface 提供各种存储实现
有了以上三种抽象,sigs.k8s.io/apiserver-runtime 就支持一行代码创建 k8s apiserver
|
|
框架内部会根据 API structs 所实现接口,自动完成 runtime.Scheme 注册,而且会照顾好 k8s.io/apiserver 各层
- 生成 APIGroupInfo struct,完成 HTTP API 层 install
- 完成 pkg/registry/generic/registry.Store 初始化,设置好存储层
一切看着很美好,但在使用时有各种各样的弊端。
首先是存储层策略到 API 层之后,有耦合过紧的问题
- API package/module 必须依赖 sigs.k8s.io/apiserver-runtime 接口(显式/隐式均可)。如果使用者打算对外公开 API,那么会造成语义不清晰
- 如果想在 apiserver 中引入其他项目的 Public API 呢?由于 Golang 只支持在 struct package 提供 interface 实现,而其他 API 不可能会实现框架接口。
x-kubernetes apiserver-using-runtime 只能通过 nested struct 方式,包装外部 API 实现 sigs.k8s.io/apiserver-runtime 接口们
var _ resource.Object = &Foo{}
var _ resource.MultiVersionObject = &Foo{}
var _ resource.ObjectList = &FooList{}
type Foo struct {
hellov1.Foo
}
然后遇到了第二个问题,sigs.k8s.io/apiserver-runtime 社区不活跃,上次更新还是 2022 年底,只适配到 Kubernetes v1.26,且框架本身有一些 bug
- 没有支持 shortname
- 多版本 conversion, default 问题
- …
所以变成需要这样就 bypass 框架
|
|
所以显而易见的问题来了:sigs.k8s.io/apiserver-runtime 本身也是基于 k8s.io/apiserver 提供增强。当项目需要灵活定制策略时,就不可避免需要直接使用底层库。结果是,开发者除了要熟悉 k8s.io/apiserver,还需要再学一套框架。
那为什么不从一开始直接使用 k8s.io/apiserver 呢?
而且随着 k8s.io/apiserver 提供的功能越来越多,框架更新便必然滞后。这也会增加维护成本。
使用框架时需要格外警惕,除非你确定项目的生命周期不长,只打算做一锤子买卖。 欢迎 clone x-kubernetes apiserver-using-runtime 代码查看崩溃过程。
最后 sigs.k8s.io/apiserver-runtime 的一些设计思路,比如降低 default conversion 复杂度,比如简化策略配置,非常适合实现为辅助 library,而非框架。
Author Zeng Xu
LastMod 2023-06-18 18:42
License 本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可,转载时请注明原文链接。