Open phosae opened 1 year ago
大佬,您也太牛逼了吧,写的真好,醍醐灌顶
有个比较困惑的点,我的理解不知道是否正确:
通过 RecommandOptions
初始化的自定义 API 会启动 APF 流控,同时会尝试 Patch FlowSchema 和 PriorityLevelConfigurations 对象的 Status。 那么:
所以感觉既然没有必要,后面自定义 API 的流控逻辑是不是可以关闭。不过目前的代码,似乎关闭之后flag上的限流开关会生效,这部分是否存在啥最佳实践呀,比如把值配置的比较大防止被二次限流。
@xuzhenglun
没太理解这个表述,能举个具体例子吗?
在一些情况下,比如自定义 API 和 kube-apiserver 版本存在差异的情况下,可能会因为 FlowControl 对象的版本不兼容导致自定义 API 访问失败,或者对象状态在不同版本 API 之间 Patch 产生抖动。
@phosae
多谢回复,其实这句话其实是来自社区文档:https://kubernetes.io/docs/concepts/cluster-administration/flow-control/#mandatory-configuration-objects
Each kube-apiserver independently maintains the mandatory and suggested configuration objects, using initial and periodic behavior. Thus, in a situation with a mixture of servers of different versions there may be thrashing as long as different servers have different opinions of the proper content of these objects.
这两个问题我前两天仔细看了下代码基本上搞明白了,我自己尝试回答下,有错误的话麻烦指正:
filterChain
只包在了 APIServerHandler
的 FullHandlerChain
上,Director
上并没有被包含 filterChain
。 实际委托的时候是通过 Director -> NonGoRestfulMux
委托出去的,所以后续请求不会走到另外一个 filterChain
里去了。FlowSchema
和 PriorityLevelConfiguration
的 status
,这个行为包括自定义 API 也会。 K8S API 和自定义 API 内 apimachinary 库版本不一样的时候,可能出现读写对象行为不一致的现象。 具体的例子的话,我这边自定义 API 是 1.28 的库写的,跑在 1.24 的 K8S API 上会因为还没有 v1beta3 的对象而报错。workaround 是把 APF 关掉换成旧的限流器, 因为从上面 1 的分析得出,此时 K8S 的 API 内的 APF 还是会生效,为自定义 API 提供限流功能。另外在分析代码的时候,发现似乎博客文章在 API 委托链的图那边有一点微小的不准确。虽然广义上都是委托,但是实际行为实现并不相同:
FilterChain
后,AggratorServer 会负责处理 APIService 对象的 CURD,其他对象统一由 NonGoRestfulMux
处理。AggratorServer 中存在一个叫 APIServiceRegisterController
的控制器,会负责将为所有 APIService
对象生成 ProxyHandler
对象并注册进 NonGoRestfulMux
中。此时,无论是原生对象还是 CRD 对象,都会被通过 local 代理委托交给 KubeAPIService 中 Director 继续处理;GoRestfulContainer
还是 NonGoRestfulMux
都没有匹配到路由的时候,请求会进入 NotFoundHandler
,而注册在其中的就是 APIExtensionServer 的Director
。@xuzhenglun
- APF 会定时 Patch
FlowSchema
和PriorityLevelConfiguration
的status
,这个行为包括自定义 API 也会。 K8S API 和自定义 API 内 apimachinary 库版本不一样的时候,可能出现读写对象行为不一致的现象。 具体的例子的话,我这边自定义 API 是 1.28 的库写的,跑在 1.24 的 K8S API 上会因为还没有 v1beta3 的对象而报错。workaround 是把 APF 关掉换成旧的限流器, 因为从上面 1 的分析得出,此时 K8S 的 API 内的 APF 还是会生效,为自定义 API 提供限流功能。
社区文档说「可能存在不同版本的 kube-apiserver 共同管理存储在 etcd 中的 (FlowSchema| PriorityLevelConfiguration).flowcontrol.apiserver.k8s.io」,这种情况通常发生在集群升级期间。如文档所言,kube-apiserver 在迭代时会尽最大努力保证跨版本兼容(alpha API 和 beta API 保证性一般,正式 API v1 v2 保证很强。
如果升级时,发生 beta 到 v1 之类 API 迁移,kubeadm 之类的集群管理工具会在升级之际一并迁移资源对象。
以上说的是 K8s 自身升级过程中的兼容。
自定义 API 会定时 Patch FlowSchema 和 PriorityLevelConfiguration 的 status
,这点不是很明白。FlowSchema 和 PriorityLevelConfiguration CRUD 应该是在 kube-apiserver 完成。其他进程并不直接管理它们,但可以通过 K8s API 操作对应资源。
如果三方程序使用 client-go 操作 FlowSchema 或 PriorityLevelConfiguration,那么应该根据 kube-apiserver 版本调整 client-go 为对应版本。
委托图谢纠正 🙏,我后续会做修复
https://www.zeng.dev/post/2023-k8s-apiserver-aggregation-internals/