尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Karmada 集群级资源传播暂停与恢复:PropagationPolicy Suspension 设计与实现深度解析

Karmada 集群级资源传播暂停与恢复:PropagationPolicy Suspension 设计与实现深度解析 Karmada 集群级资源传播暂停与恢复PropagationPolicy Suspension 设计与实现深度解析【免费下载链接】karmadaOpen, Multi-Cloud, Multi-Cluster Kubernetes Orchestration项目地址: https://gitcode.com/GitHub_Trending/ka/karmada导读Karmada 的资源传播链路Resource Template → ResourceBinding/ClusterResourceBinding → Work → 成员集群同步在默认情况下是无缝的任何资源模板、传播策略或覆盖策略的变更都会立即同步到成员集群。本篇文章围绕 docs/proposals/dispatch-suspension/README.md 这一官方设计提案深入讲解 Karmada 如何通过扩展PropagationPolicy/ClusterPropagationPolicyAPI 提供集群粒度的资源传播暂停Pause与恢复Resume能力并结合当前仓库源码API 类型定义、binding 控制器、execution 控制器等还原其从提案到落地的实现细节帮助你掌握按集群分批灰度发布、控制面变更留档校验等实战用法。背景为什么需要暂停资源传播Karmada 的资源传播过程主要经历三个阶段资源模板Resource Template被PropagationPolicy/ClusterPropagationPolicy选中生成ResourceBinding/ClusterResourceBinding调度结果载体再由 Binding 生成Work最终同步到成员集群。在提案发布之时这三个阶段几乎是无缝的一旦资源模板、PropagationPolicy/ClusterPropagationPolicy或OverridePolicy/ClusterOverridePolicy发生变化改动会立即同步到成员集群。虽然这在大多数场景下是符合预期的但也带来两个问题用户无法在资源传播过程中主动干预唯一可介入的点是 Binding 生成Work时应用OverridePolicy/ClusterOverridePolicy而这一步还需要用户提前创建好覆盖策略无法根据调度结果动态定制在控制面与成员集群对资源争抢控制权、反复更新的场景下用户希望先暂停同步以快速定位问题。因此该提案提出为 Karmada 增加集群粒度的资源传播暂停与恢复能力把何时同步的控制权交还给用户。设计目标与非目标Goals目标提供暂停资源传播的能力提供恢复资源传播的能力提供集群粒度的暂停/恢复编排能力即可以只暂停部分集群的传播。Non-Goals非目标不提供开箱即用的多集群金丝雀发布Canary、滚动发布Rolling与蓝绿发布Blue-Green完整方案不提供按指定集群序列自动发布工作负载的能力。也就是说该特性提供的是暂停/恢复这一底层编排原语而非完整的发布工具链用户可以基于它自行编排发布节奏。用户故事四大典型场景Story 1控制面与成员集群的资源争抢排障当 Karmada 控制面与成员集群对同一资源竞争控制权导致资源被反复更新时运维人员希望先暂停资源到成员集群的同步以便快速定位问题、避免在排查期间继续扩散变更。Story 2按集群顺序分批发布应用版本发布时发布负责人希望指定集群的发布顺序只有当前集群发布成功并确认无误后才继续向下一个集群发布。这正对应集群粒度暂停 手动恢复的编排方式。Story 3结合 partition 实现控制面侧金丝雀发布在业务部署中通过给 StatefulSet 等工作负载设置partition字段可以实现实例子集更新达到金丝雀发布效果。但在联邦控制面中当用户希望只更新某个 Deployment 的部分实例时必须在分发到不同集群前拆分副本数。此时用户希望在计算各集群拆分数量时暂停该 Deployment 的传播待计算结果应用到系统后再恢复传播从而实现金丝雀发布目标。该场景对应的需求在社区中被追踪为 issue #1567 与 #4421。Story 4控制面变更留档校验业务变更先在联邦控制面中生效但不同步到成员集群而是保留在控制面内。用户可以检查ResourceBinding、Work等资源的内容确认系统按预期执行确认无误后再恢复变更、同步到成员集群。这相当于为控制面增加了一个预演/审查窗口。总体设计思路提案的设计非常克制不引入新的独立 CRD而是扩展现有 API 并沿既有传播链路传递暂停信息。核心思路如下在PropagationPolicy/ClusterPropagationPolicy中新增suspension字段Suspension结构将关键暂停信息透传到ResourceBinding/ClusterResourceBinding资源再由 Binding 透传到Work资源Karmada-controller-manager中的控制器根据Work资源上的暂停信息决定是否将资源同步到目标成员集群。这样暂停信息贯穿整条传播链路且每一层都有对应的持久化表达便于排查与审计。API 变更详解PropagationPolicy / ClusterPropagationPolicy提案中为PropagationSpec增加Suspension字段并定义了Suspension与SuspendClusters两个结构。提案初始设计如下// PropagationSpec represents the desired behavior of PropagationPolicy. type PropagationSpec struct { ... // Suspension declares the policy for suspending different aspects of propagation. // nil means no suspension. no default values. // optional Suspension *Suspension json:suspension,omitempty } // Suspension defines the policy for suspending different aspects of propagation. type Suspension struct { // SuspendScheduling controls whether scheduling should be suspended. // Note: Postpone this until there is a solid use case. // SuspendScheduling *bool json:suspendScheduling,omitempty // SuspendDispatching controls whether dispatching should be suspended. // nil means not suspend. // Note: true means stop propagating to all clusters. Can not co-exist // with DispatchingOnClusters which is used to suspend particular clusters. // optional SuspendDispatching *bool json:suspendDispatching,omitempty // SuspendDispatchingOnClusters declares a list of clusters to which // the dispatching should be suspended. // Note: Can not co-exist with Dispatching which is used to suspend all. // optional SuspendDispatchingOnClusters *SuspendClusters json:suspendDispatchingOnClusters,omitempty } // SuspendClusters represents a group of clusters that should be suspended from propagating. // Note: No plan to introduce the label selector or field selector to select clusters yet, as it // would make the system unpredictable. type SuspendClusters struct { // ClusterNames is the list of clusters to be selected. // optional ClusterNames []string json:clusterNames,omitempty }设计上有三个值得注意的点SuspendScheduling暂停调度被推迟注释中明确等有坚实用例再引入最终没有进入第一期实现SuspendDispatching与SuspendDispatchingOnClusters互斥一个表示全部暂停另一个表示暂停指定集群两者不能共存SuspendClusters只支持按集群名列表选择刻意不引入标签选择器Label Selector或字段选择器Field Selector因为这会让系统变得不可预测。ResourceBinding / ClusterResourceBindingResourceBindingSpec同样增加Suspension字段// ResourceBindingSpec represents the expectation of ResourceBinding. type ResourceBindingSpec struct { ... // Suspension declares the policy for suspending different aspects of propagation. // nil means no suspension. no default values. // optional Suspension *Suspension json:suspension,omitempty }WorkWorkSpec增加SuspendDispatching布尔字段作为最终落到成员集群执行层的暂停标记// WorkSpec defines the desired state of Work. type WorkSpec struct { ... // SuspendDispatching controls whether dispatching should // be suspended, nil means not suspend. // Note: true means stop propagating to all clusters. // optional SuspendDispatching *bool json:suspendDispatching,omitempty }新引入的 ConditionTypeDispatching为描述Work资源的分发暂停状态提案引入新的条件类型DispatchingWorkDispatching。同时系统会通过 Event 记录资源分发的暂停事件方便用户在kubectl describe时直接看到暂停原因。当前仓库中的实际实现与提案的差异需要特别指出提案中的字段命名与最终落地实现存在差异。在 pkg/apis/policy/v1alpha1/propagation_types.go 中Suspension结构最终实现为// Suspension defines the policy for suspending different aspects of propagation. type Suspension struct { // Dispatching controls whether dispatching should be suspended. // nil means not suspend, no default value, only accepts true. // Note: true means stop propagating to all clusters. Can not co-exist // with DispatchingOnClusters which is used to suspend particular clusters. // optional Dispatching *bool json:dispatching,omitempty // DispatchingOnClusters declares a list of clusters to which the dispatching // should be suspended. // Note: Can not co-exist with Dispatching which is used to suspend all. // optional DispatchingOnClusters *SuspendClusters json:dispatchingOnClusters,omitempty } // SuspendClusters represents a group of clusters that should be suspended from propagating. // Note: No plan to introduce the label selector or field selector to select clusters yet, as it // would make the system unpredictable. type SuspendClusters struct { // ClusterNames is the list of clusters to be selected. // optional ClusterNames []string json:clusterNames,omitempty }即JSON 字段名从提案的suspendDispatching/suspendDispatchingOnClusters简化为dispatching/dispatchingOnClusters语义相同均为暂停分发并且注释中明确没有默认值只接受true。因此以当前仓库 API 为准实际编写 PropagationPolicy 时应使用suspension.dispatching与suspension.dispatchingOnClusters.clusterNames。与之对应WorkSpec的字段名则保留了SuspendDispatching见 pkg/apis/work/v1alpha1/work_types.go注释进一步说明true表示停止向对应成员集群传播并且不阻止状态Status采集——即暂停期间成员集群上的工作负载状态仍会回流到控制面这对灰度期间的观测非常关键。此外在 pkg/apis/work/v1alpha2/binding_types.go 中ResourceBinding的Suspension结构内嵌了policyv1alpha1.Suspension并额外提供了Scheduling字段用于第三方系统在ResourceBinding创建时通过准入 Webhook 暂停调度一旦完成调度则无法再暂停否则会失效。实战从暂停全部到按集群分批发布以下示例基于当前仓库的实际 API 字段编写即suspension.dispatching/suspension.dispatchingOnClusters其操作逻辑与提案保持一致。场景一暂停全部集群的传播将Deployment(default/nginx)的分发设为全局暂停。此后无论用户如何修改该 DeploymentKarmada都不会把变更同步到任何目标集群apiVersion: policy.karmada.io/v1alpha1 kind: PropagationPolicy metadata: name: nginx-propagation spec: resourceSelectors: - apiVersion: apps/v1 kind: Deployment name: nginx placement: clusterAffinity: clusterNames: - member1 - member2 - member3 suspension: dispatching: true此时控制面上与该 Deployment 相关的所有Work资源都会进入暂停状态。以对应 member1 集群的 Work 为例其位于karmada-es-member1命名空间apiVersion: work.karmada.io/v1alpha1 kind: Work metadata: name: nginx-xxx namespace: karmada-es-member1 spec: workload: manifests: - xxx suspendDispatching: true status: conditions: - lastTransitionTime: 2024-07-01T08:33:28Z message: Work dispatching is in a suspended state. reason: SuspendDispatching status: True type: Dispatching当用户删除或置空suspension字段后Karmada 会恢复该 Deployment 在所有集群中的资源同步。场景二仅暂停指定集群分批发布假设Deployment(default/nginx)已传播到 member1、member2、member3。现在用户要发布新版本镜像但希望新版本只先同步到 member1apiVersion: policy.karmada.io/v1alpha1 kind: PropagationPolicy metadata: name: nginx-propagation spec: resourceSelectors: - apiVersion: apps/v1 kind: Deployment name: nginx placement: clusterAffinity: clusterNames: - member1 - member2 - member3 suspension: dispatchingOnClusters: clusterNames: - member2 - member3场景三逐步推进发布确认 member1 上的新版本发布成功后将暂停范围收窄到仅 member3此时新版本即可同步到 member2apiVersion: policy.karmada.io/v1alpha1 kind: PropagationPolicy metadata: name: nginx-propagation spec: resourceSelectors: - apiVersion: apps/v1 kind: Deployment name: nginx placement: clusterAffinity: clusterNames: - member1 - member2 - member3 suspension: dispatchingOnClusters: clusterNames: - member3场景四发布失败回滚如果新版本同步到 member1 后发现问题、发布失败用户可以在 Karmada 控制面回滚Deployment 的版本。由于 member2、member3 仍处于暂停状态尚未收到新版本因此这两处集群的业务不会受到波及——这正是集群粒度暂停在发布安全上的核心价值。源码级实现印证1. 暂停决策Binding 控制器在 pkg/controllers/binding/common.go 中shouldSuspendDispatching函数实现了暂停判定逻辑func shouldSuspendDispatching(suspension *workv1alpha2.Suspension, targetCluster workv1alpha2.TargetCluster) bool { if suspension nil { return false } suspendDispatching : ptr.Deref(suspension.Dispatching, false) if !suspendDispatching suspension.DispatchingOnClusters ! nil { if slices.Contains(suspension.DispatchingOnClusters.ClusterNames, targetCluster.Name) { suspendDispatching true } } return suspendDispatching }逻辑清晰suspension为 nil未配置暂停时直接返回 false不暂停Dispatching为 true 时全局暂停否则检查DispatchingOnClusters.ClusterNames是否包含目标集群名命中则对该集群暂停。Binding 控制器在生成Work时通过ctrlutil.WithSuspendDispatching(...)见 pkg/controllers/ctrlutil/workoption.go把该判定结果写入Work.Spec.SuspendDispatching见 pkg/controllers/binding/common.go。2. 暂停判定工具函数pkg/util/work.go 提供了IsWorkSuspendDispatching供各控制器统一判断 Work 是否处于暂停分发状态// IsWorkSuspendDispatching checks if the work is suspended from dispatching. func IsWorkSuspendDispatching(work *workv1alpha1.Work) bool { return ptr.Deref(work.Spec.SuspendDispatching, false) }3. 状态与事件Execution 控制器pkg/controllers/execution/execution_controller.go 是消费暂停标记的最终执行者。它维护Dispatching条件的两种状态暂停时status: False、reason: SuspendDispatching、message: Work dispatching is in a suspended state.恢复时status: True、reason: Dispatching、message: Work is being dispatched to member clusters.。该控制器在同步 Work 前检查util.IsWorkSuspendDispatching(work)见 pkg/controllers/execution/execution_controller.go#L135若命中暂停则跳过资源分发同时通过updateWorkDispatchingConditionIfNeededpkg/controllers/execution/execution_controller.go#L378-L402更新条件并向事件系统上报用户可通过kubectl describe work直接看到暂停原因。4. 相关测试该能力具备完整的单元测试覆盖可参考 pkg/controllers/binding/common_test.go、pkg/controllers/ctrlutil/workoption_test.go、pkg/controllers/execution/execution_controller_test.go、pkg/util/work_test.go 以及 pkg/util/helper/predicate_test.go覆盖暂停判定、Work 选项注入与控制器行为等路径。边界情况与风险边界情况暂停不阻塞删除一个重要的语义保证是分发暂停不会阻塞资源删除。当用户通过 PropagationPolicy 将某个资源设为分发暂停随后执行删除操作时资源仍会被正常删除不会因暂停而滞留成员集群中的遗留资源。这避免了暂停与清理语义互相干扰。风险暂停期间故障迁移被挂起提案明确列出该风险当工作负载处于暂停状态时即使已启用 Failover 特性门控故障迁移也会被暂停直到用户取消暂停。运维人员需要意识到暂停是全链路的它会同时冻结正常分发与故障迁移因此在长暂停窗口内应结合其他手段如人工巡检保障可用性。测试计划UT单元测试为新增功能补充单元测试覆盖暂停判定、Work 生成选项、条件更新等逻辑E2E端到端测试测试资源分发暂停能力测试资源分发恢复能力测试集群级资源分发暂停能力分别在命名空间级PropagationPolicy与集群级ClusterPropagationPolicy各测一遍。备选方案对比独立 RolloutPolicy CRD提案还记录了一个被否定的备选方案新增一个独立的策略配置类型 CRD暂命名为RolloutPolicy用户通过配置该 CRD 的实例来决定是否暂停/恢复指定资源模板到目标成员集群的同步。其 API 草案同样包含SuspensionsuspendDispatching/suspendDispatchingOnClusters结构与Work.Spec.SuspendDispatching字段并引入名为Dispatching的条件类型描述 Work 的分发暂停状态。两种方案的优劣势分析如下方案一最终采纳扩展 PropagationPolicy/ClusterPropagationPolicy优点对用户而言简洁直观易于控制无需学习新 CRD缺点无法针对单个资源单独指定分发暂停只能跟随 PropagationPolicy 的粒度系统侧的ResourceBinding也需要包含分发暂停策略描述并同步到Work。方案二备选独立 RolloutPolicy CRD优点能够针对特定资源单独指定分发暂停缺点对用户增加学习成本API 功能相对单一且需要一个独立的控制器处理该资源增加了资源更新冲突的概率。最终社区选择方案一将暂停能力内聚到既有传播策略体系中这也与 Karmada策略驱动的一贯设计哲学保持一致。总结Karmada 的集群级资源传播暂停/恢复能力为多集群编排提供了关键的刹车与节流阀沿既有链路透传PropagationPolicy/ClusterPropagationPolicy → ResourceBinding/ClusterResourceBinding → Work暂停信息每一层都可观测、可审计双粒度控制dispatching全局暂停 dispatchingOnClusters集群名单暂停二者互斥执行与观测解耦暂停只冻结分发不阻塞删除、不阻断状态采集并以Dispatching条件与事件暴露状态落地实现与提案有命名演进实际 API 使用dispatching/dispatchingOnClusters仅接受true编写 YAML 时需以当前仓库 pkg/apis/policy/v1alpha1/propagation_types.go 为准。基于这一原语你可以自行编排按集群分批灰度发布 失败回滚保护 控制面变更预演等发布流程在保留控制面灵活性的同时把业务风险牢牢锁在暂停范围之外。【免费下载链接】karmadaOpen, Multi-Cloud, Multi-Cluster Kubernetes Orchestration项目地址: https://gitcode.com/GitHub_Trending/ka/karmada创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表