Karmada v0.10 版本新特性解析:Resource Interpreter Webhook、动态权重调度与跨集群观测
【免费下载链接】karmadaOpen, Multi-Cloud, Multi-Cluster Kubernetes Orchestration项目地址: https://gitcode.com/GitHub_Trending/ka/karmada
本文基于 Karmada 官方变更记录 CHANGELOG-0.10.md 展开,系统讲解 v0.10 版本交付的三大核心能力:Resource Interpreter Webhook 框架(让自定义资源获得与原生资源同等的传播能力)、dynamicWeight与Job分片调度增强,以及kubectl karmada get跨集群资源观测命令。读完本文,你可以理解自定义资源接入 Karmada 传播体系的完整机制、动态权重复制分摊的计算原理,并掌握从控制面统一观测成员集群工作负载的方法。
一、Karmada v0.10 交付了哪些能力
Karmada v0.10 的版本记录围绕三个主题组织:新特性(What's New)包括 Resource Interpreter Webhook、调度能力增强、跨集群工作负载观测三大块;其他重要变更(Other Notable Changes)则涵盖 estimator 行为调整、对象标签迁移、Bug 修复与可观测性埋点等内容。
从源码结构看,这几块能力分别落在以下模块:
| 特性 | 仓库中对应的实现位置 |
|---|---|
| Resource Interpreter Webhook | pkg/resourceinterpreter/、pkg/webhook/interpreter/ |
| dynamicWeight / Job 分片调度 | pkg/apis/policy/v1alpha1/propagation_types.go、pkg/scheduler/core/ |
| kubectl karmada get | pkg/karmadactl/get/get.go |
| 事件/状态埋点 | pkg/events/events.go、pkg/apis/work/v1alpha2/binding_types.go |
下面按变更记录的原始脉络逐一展开。
二、Resource Interpreter Webhook:教会 Karmada 理解你的自定义资源
2.1 设计动机
在资源(即 resource template)传播到成员集群的过程中,Karmada 会根据资源定义采取行动。例如在构建ResourceBinding阶段,karmada-controller-manager会解析Deployment等资源的replicas字段,而对没有replicas的资源则不做处理。对于 Kubernetes 原生资源,Karmada 内置了解析知识;但对于自定义资源类型(CRD),由于不了解其结构,Karmada 只能把它当作普通资源处理。
v0.10 引入的Resource Interpreter Webhook框架正是解决这一问题的方案:用户可以实现自己的 CRD 插件,在传播流程的各个环节被 Karmada 咨询。借助该框架,CRD 和 CR 将像 Kubernetes 原生资源一样被传播,也就是说所有调度原语(scheduling primitives)都支持自定义资源。官方提案见 Resource Interpreter Webhook Proposal,仓库同时提供了完整的示例工程与工具,位于 examples/customresourceinterpreter/。
2.2 配置 API:ResourceInterpreterWebhookConfiguration
框架受 Kubernetes Admission Webhook 的启发,由两个 API 构成:一个声明启用哪些 webhook 的配置 APIResourceInterpreterWebhookConfiguration(定义在config.karmada.io组),一个声明 Karmada 与 webhook 之间请求/响应格式的消息 APIResourceInterpreterContext。
配置对象的核心结构(摘自提案文档):
type ResourceInterpreterWebhookConfiguration struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` // Webhooks 是需要启用的 webhook 及其作用资源与操作的列表。 Webhooks []ResourceInterpreterWebhook `json:"webhooks"` } type ResourceInterpreterWebhook struct { // Name 是 webhook 的完全限定名。 Name string `json:"name"` // ClientConfig 定义如何与 webhook 通信。 ClientConfig admissionregistrationv1.WebhookClientConfig `json:"clientConfig"` // Rules 描述该 webhook 关注的操作和资源。 Rules []RuleWithOperations `json:"rules,omitempty"` // TimeoutSeconds 指定 webhook 超时时间(1~30 秒),默认 10 秒。 TimeoutSeconds *int32 `json:"timeoutSeconds,omitempty"` // InterpreterContextVersions 是 Webhook 期望的 ResourceInterpreterContext // 版本有序列表,Karmada 会优先使用列表中它支持的第一个版本。 InterpreterContextVersions []string `json:"interpreterContextVersions"` }其中RuleWithOperations是操作(Operations)与资源(APIGroups/APIVersions/Kinds)的元组,APIGroups、APIVersions、Kinds三个字段都支持*通配(出现*时切片长度必须为 1);核心组的 group 为空,需写成[""]。
2.3 消息 API 与操作集合:InterpreterOperation
InterpreterOperation表示 Karmada 在整个传播过程中可能调用 webhook 的请求类型,这也是本框架的扩展点所在:
| 操作 | 含义 |
|---|---|
*(InterpreterOperationAll) | 匹配所有操作 |
InterpretReplica | 让 webhook 解释资源声明的副本数(仅适用于带副本声明的资源类型) |
ReviseReplica | 请求 webhook 按目标值修改副本数 |
InterpretStatus | 解释如何获取状态(适用于状态不在.status路径的特殊资源) |
Prune | 解释如何将资源模板打包进 Work |
Retain | 请求 webhook 决定期望资源模板中哪些本地变更需要保留(适用于成员集群控制器会回写.spec的资源) |
AggregateStatus | 解释如何把各集群状态聚合回资源模板 |
InterpretHealth | 解释如何判断资源的健康状态 |
InterpretDependency | 解释资源的依赖关系(如 Deployment 依赖 ConfigMap/Secret),使依赖可随资源一起传播 |
对应的请求/响应消息ResourceInterpreterContext包含Request与Response两部分:Request携带UID(用于 Karmada 与 webhook 之间关联日志)、Kind、Name、Namespace、Operation、资源对象Object,以及在特定操作下才填充的ObservedObject(仅Retain操作,来自成员集群的观测对象)、DesiredReplicas(仅ReviseReplica操作)、AggregatedStatus(各集群状态列表)等字段;Response则按需回填Replicas、ReplicaRequirements、Dependencies、RawStatus、Healthy,以及 JSONPatch 格式的Patch(当前仅支持 RFC 6902 的JSONPatch)。
提案中的两条用户故事说明了典型使用场景:
- 让自定义工作负载参与副本调度:你的自定义资源与
Deployment高度相似、带有replica字段,希望通过ReplicaScheduling规则把副本分到多个集群。没有该框架时,Karmada 因不了解结构而无法读取副本数; - 自定义本地值保留(retain)策略:成员集群中的控制器会修改资源(如更新
.spec中的字段),你希望 Karmada 保留这些变更。没有该框架时,Karmada 可能无法正确保留,导致资源在 Karmada 与你的控制器之间被反复来回修改。
2.4 配置示例与请求/响应示例
下面是一个声明了两个 webhook 的配置示例:foo.example.com服务于foo.example.com组的Foo,实现Retain与InterpretHealth;bar.example.com服务于bar.example.com组的Bar,实现InterpretDependency与InterpretHealth:
apiVersion: config.karmada.io/v1alpha1 kind: ResourceInterpreterWebhookConfiguration metadata: name: example webhooks: - name: foo.example.com rules: - operations: ["Retain", "InterpretHealth"] apiGroups: ["foo.example.com"] apiVersions: ["*"] kinds: ["Foo"] clientConfig: url: https://xxx:443/explore-foo caBundle: {{caBundle}} interpreterContextVersions: ["v1alpha1"] timeoutSeconds: 3 - name: bar.example.com rules: - operations: ["InterpretDependency", "InterpretHealth"] apiGroups: ["bar.example.com"] apiVersions: ["*"] kinds: ["Bar"] clientConfig: url: https://xxx:443/explore-bar caBundle: {{caBundle}} interpreterContextVersions: ["v1alpha1"] timeoutSeconds: 3以InterpretHealth为例,Karmada 发送的请求形如:
apiVersion: config.karmada.io/v1alpha1 kind: ResourceInterpreterContext request: uid: xxx kind: group: foo.example.com version: v1alpha1 kind: Foo name: foo namespace: default operation: InterpretHealth object: <资源的原始数据>webhook 响应形如:
apiVersion: config.karmada.io/v1alpha1 kind: ResourceInterpreterContext response: uid: xxx # 与请求中的 uid 相同 successful: true healthy: true2.5 仓库中的实现与示例
从源码结构看,该框架的调用入口在 pkg/resourceinterpreter/interpreter.go,其中:
- Webhook 解释器的具体实现位于 pkg/resourceinterpreter/customized/webhook/,包含 webhook 配置管理(configmanager/)、请求属性解析(request/)与服务端点解析(serviceresolvers.go);
- Karmada 对原生资源的默认解释逻辑位于 pkg/resourceinterpreter/default/native/,按操作拆分为 replica.go、revisereplica.go、retain.go、aggregatestatus.go、healthy.go、dependencies.go 与 prune/ 等文件,可以对照各操作逐一理解默认行为;
- 除了 webhook 方式,仓库还演进出了基于 Lua 声明式的解释器 pkg/resourceinterpreter/customized/declarative/,并对 Argo Workflows、KubeRay、Flux、Volcano 等第三方生态资源内置了定制配置(见 pkg/resourceinterpreter/default/thirdparty/resourcecustomizations/)。
完整的可运行示例见 examples/customresourceinterpreter/:包含示例 CRD 定义 workload.example.io_workloads.yaml、webhook 服务端 examples/customresourceinterpreter/webhook/app/、webhook 配置 karmada-interpreter-webhook-example.yaml 以及配套的资源与 PropagationPolicy,是上手该框架最直接的参考。
三、调度能力显著增强
3.1 dynamicWeight:按可用副本数动态分配权重
v0.10 为PropagationPolicy与ClusterPropagationPolicy引入了dynamicWeight原语(对应上游 PR #841)。开启后,副本可以按一个动态权重列表划分,每个集群的权重在调度时基于其可用副本数(available replicas)实时计算出来,从而显著平衡各集群的利用率。
在类型定义中,dynamicWeight位于ReplicaSchedulingStrategy的WeightPreference(ClusterPreferences)下,源码见 pkg/apis/policy/v1alpha1/propagation_types.go:
// ClusterPreferences describes weight for each cluster or for each group of cluster. type ClusterPreferences struct { // StaticWeightList defines the static cluster weight. StaticWeightList []StaticClusterWeight `json:"staticWeightList,omitempty"` // DynamicWeight specifies the factor to generates dynamic weight list. // If specified, StaticWeightList will be ignored. DynamicWeight DynamicWeightFactor `json:"dynamicWeight,omitempty"` } // DynamicWeightFactor represents the weight factor. // For now only support 'AvailableReplicas'. type DynamicWeightFactor string const ( // DynamicWeightByAvailableReplicas 按可用资源(available replicas)生成集群权重列表。 DynamicWeightByAvailableReplicas DynamicWeightFactor = "AvailableReplicas" )关键行为约束(可直接从源码注释得到):
- 当前仅支持
AvailableReplicas一种因子,后续可按需扩展; - 一旦指定
dynamicWeight,staticWeightList将被忽略——动态权重优先于静态权重。
类型定义中的注释给出了官方计算示例,值得完整保留:
调度器选出了 A/B/C 三个集群,需要分配 12 个副本。集群 A 最多可用 6 个副本、B 最多 12 个、C 最多 18 个,则 A:B:C 的权重为 6:12:18(即 1:2:3),最终分配结果为 A: 2、B: 4、C: 6。
结合ReplicaSchedulingStrategy的语义(propagation_types.go):replicaSchedulingType为Divided时按有效候选集群划分副本;replicaDivisionPreference为Weighted时按WeightPreference中的权重划分;若只声明Weighted而未配置任何权重,则所有集群等权。一个典型的声明写法为:
spec: replicaScheduling: replicaSchedulingType: Divided replicaDivisionPreference: Weighted weightPreference: dynamicWeight: AvailableReplicas3.2 Job 分片调度
v0.10 引入了对Job的调度分片支持(对应上游 PR #898):期望多个副本的Job现在可以像Deployment一样被划分到多个集群,这使得在若干小集群上运行超大型 Job 成为可能。从 examples/nginx/ 等示例使用的PropagationPolicy可见,副本调度原语是策略声明层的一部分,Job接入分片调度后同样由这些原语驱动。
四、从 Karmada 控制面观测工作负载
工作负载(如 Deployment)被传播到成员集群后,用户往往还希望获取跨集群的整体状态,尤其是每个Pod的状态。v0.10 为此在kubectl-karmada中引入了get子命令,可以直接从 Karmada 控制面获取部署在成员集群中的各类资源。
变更记录给出的示例输出:
$ kubectl karmada get deployment NAME CLUSTER READY UP-TO-DATE AVAILABLE AGE ADOPTION nginx member2 1/1 1 1 19m Y nginx member1 1/1 1 1 19m Y $ kubectl karmada get pods NAME CLUSTER READY STATUS RESTARTS AGE nginx-6799fc88d8-vzdvt member1 1/1 Running 0 31m nginx-6799fc88d8-l55kk member2 1/1 Running 0 31m结合源码可以补充两点输出细节。该命令的实现位于 pkg/karmadactl/get/get.go,其输出的ADOPTION列有三个取值(get.go):
| 取值 | 常量 | 含义 |
|---|---|---|
Y | managedByKarmada | 该资源由 Karmada 控制面托管 |
N | notManagedByKaramda | 该资源位于成员集群,但未受 Karmada 控制面管理 |
- | notApplicable | Karmada 控制面自身资源,不适用 |
此外代码中还定义了CLUSTER、ADOPTION以及针对事件的EVENT附加列(get.go),说明该命令对 Pod、Event 等资源有定制化的列渲染逻辑,而不仅是简单拼接原生kubectl get输出。
五、其他重要变更
变更记录的 "Other Notable Changes" 一节列出了以下值得关注的调整,均附带了上游 PR 编号以便追溯:
- karmada-scheduler-estimator(PR #777):集群的 Pod 数量成为计算可用副本数时的重要参考因素。从 pkg/estimator/server/ 的 estimator 服务端实现可见,可用副本估算会结合节点可分配资源与现有工作负载共同计算;
- Work 对象标签迁移(PR #752):此前打在
Work对象上的标签resourcebinding.karmada.io/namespace、resourcebinding.karmada.io/name、clusterresourcebinding.karmada.io/name已全部迁移为注解(annotations)。编写基于标签的选择器逻辑时需注意这一兼容性变化; - Bug 修复(PR #817):修复了集群 unjoin(退出联邦)对资源状态聚合的影响,避免已退出集群的状态残留污染聚合结果;
- Work 对象事件(PR #800):引入
SyncFailed与SyncSucceed事件。在 pkg/events/events.go 中可确认这两个事件原因常量(EventReasonSyncWorkloadFailed = "SyncFailed"、EventReasonSyncWorkloadSucceed = "SyncSucceed"),且 pkg/controllers/binding/cluster_resource_binding_controller_test.go 中对事件触发行为有专门的测试断言; - ResourceBinding / ClusterResourceBinding 条件(PR #823、PR #825):分别引入
Scheduled与FullyApplied条件。FullyApplied在 pkg/apis/work/v1alpha2/binding_types.go 中定义为“资源已被完全应用于所有相关集群”的状态条件,且两个 Binding 类型的 printcolumn 中都有对应的FULLYAPPLIED列,kubectl get时可直接查看; - Cluster 对象事件(PR #749):引入
CreateExecutionNamespaceFailed与RemoveExecutionNamespaceFailed事件,用于观测为成员集群创建/删除执行命名空间时的失败; - 工作队列指标(PR #831):为
karmada-agent与karmada-controller-manager引入workqueue_adds_total、workqueue_depth、workqueue_longest_running_processor_seconds、workqueue_queue_duration_seconds_bucket等指标,便于监控控制器队列健康度; - karmada-scheduler 特性门控(PR #805):调度器引入 feature gates 机制,从 pkg/scheduler/scheduler.go 的调度器组装逻辑可以看出其特性注册入口;
- karmada-controller-manager 删除行为(PR #970):成员集群中删除资源时默认采用
Background删除选项,加快删除速度。
六、小结
Karmada v0.10 是一次围绕"传播能力下沉"与"可观测性补强"的版本:
- Resource Interpreter Webhook通过配置 API(
ResourceInterpreterWebhookConfiguration)与消息 API(ResourceInterpreterContext)把InterpretReplica、Retain、AggregateStatus、InterpretDependency等操作开放给用户,使 CRD 获得与原生资源一致的副本调度、状态聚合与健康判断能力; dynamicWeight: AvailableReplicas让副本按集群实时可用容量加权划分,配合Weighted划分偏好可显著平衡集群利用率;Job 分片则把多副本 Job 纳入了同样的调度原语;kubectl karmada get让成员集群中的 Deployment、Pod 等资源的跨集群状态可以在控制面统一查看,ADOPTION列明确区分了受管与不受管资源;- 事件(
SyncSucceed/SyncFailed)、条件(Scheduled/FullyApplied)与工作队列指标共同补齐了传播链路的观测手段。
如果需要在实际集群中验证这些能力,建议从 examples/customresourceinterpreter/ 的 webhook 示例与 samples/nginx/ 的 PropagationPolicy 示例入手,并配合 docs/command-line-flags/karmadactl_get.md 了解get命令的完整参数。
【免费下载链接】karmadaOpen, Multi-Cloud, Multi-Cluster Kubernetes Orchestration项目地址: https://gitcode.com/GitHub_Trending/ka/karmada
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考