☰
KubeVela resource-update 策略:为选定资源定制更新行为与重建触发规则
2026/9/28 3:10:28 网站建设 项目流程
  • 云原生
  • DevOps
  • 运维
  • 微服务

【免费下载链接】kubevela

The Modern Application Platform.

项目地址:https://gitcode.com/gh_mirrors/ku/kubevela
点击查看免费下载

KubeVela 的resource-update策略(Policy)允许用户在 Application 级别为选定资源自定义更新行为:既可以通过recreateFields让特定字段变化时触发整资源重建(recreate),也可以将默认的三方合并补丁(patch)升级为整对象替换(replace)。本文以 官方文档 为主体,结合 KubeVela 源码与测试,讲解该策略的完整配置方式、字段语义、底层实现原理与适用场景。

为什么需要 resource-update 策略

KubeVela Application 在每次部署时,会通过 ResourceKeeper 将组件渲染出的资源统一 dispatch 到目标集群(见 pkg/resourcekeeper/resourcekeeper.go)。默认情况下,资源更新走“三方合并补丁”(three-way merge patch):只修改由 KubeVela Application 管理的字段,集群中其他实体(如其他控制器、人工改动)写入的字段会原样保留。

但在实际生产中,这种“温柔”的默认行为并不总是符合需求:

  • 某些资源(例如Secret)字段一旦被修改就可能产生不可预期的行为,KubeVela 需要在其受管字段变化时直接删除并重建该资源;
  • 某些资源需要被整体覆盖,任何未被 Application 管理的字段都应被抹除,而不是保留;
  • 某些资源(例如v1/Service)由系统控制器自动填充 spec 字段,不适合整对象替换。

resource-update策略正是为这类场景而生:它以规则(rule)为单位,通过选择器精准命中目标资源,再为其指定更新策略,实现“资源粒度”的更新行为定制。

策略定义与配置骨架

resource-update是一个内置 PolicyDefinition,其 CUE 模板定义位于 vela-templates/definitions/internal/policy/resource-update.cue,对应的部署产物为 charts/vela-core/templates/defwithtemplate/resource-update.yaml。策略类型常量ResourceUpdatePolicyType = "resource-update"定义在 apis/core.oam.dev/v1alpha1/resource_update_policy_types.go。

一个完整的 Application 配置骨架如下:

apiVersion: core.oam.dev/v1beta1 kind: Application metadata: name: my-app spec: components: # ... 组件定义 policies: - type: resource-update name: resource-update properties: rules: - selector: componentNames: ["my-comp"] # 可选:按组件名选择 componentTypes: ["k8s-objects"] # 可选:按组件类型选择 oamTypes: ["COMPONENT", "TRAIT"] # 可选:按 OAM 类型选择 traitTypes: ["scaler"] # 可选:按 Trait 类型选择 resourceTypes: ["Deployment"] # 可选:按资源类型选择(如 Secret、ConfigMap) resourceNames: ["my-deploy"] # 可选:按资源名称选择 strategy: op: "patch" # 可选,默认 patch,可填 replace recreateFields: ["data.key"] # 可选:字段变化时触发重建

策略的properties.rules是规则列表,每条规则由两部分组成:

selector:规则选择器

选择器支持六种维度,均为可选的字符串数组,语义为“命中任一即匹配”:

字段说明
componentNames按组件名称选择资源
componentTypes按组件类型选择资源
oamTypes按 OAM 类型选择,值为COMPONENT或TRAIT
traitTypes按 Trait 类型选择资源
resourceTypes按资源类型选择(如Deployment、Secret、ConfigMap)
resourceNames按资源名称选择

这些字段对应 Go 类型ResourcePolicyRuleSelector,与 pkg/resourcekeeper/utils.go 中的匹配逻辑一一对应。

strategy:更新策略

字段类型默认值说明
opstringpatch更新操作符:patch(三方合并补丁)或replace(整对象替换)
recreateFields[...string]空指定字段路径(如data.key),字段发生变化时触发资源重建

从 CUE 模板可见op: *"patch" | "replace"使用默认值语法,即未显式指定时默认为patch;recreateFields为可选字段。

场景一:字段变化触发资源重建(recreateFields)

最典型的场景是管理 Kubernetes 中不可就地更新的资源,例如带immutable: true的Secret。原始文档给出了如下示例:

apiVersion: core.oam.dev/v1beta1 kind: Application metadata: name: recreate spec: components: - type: k8s-objects name: recreate properties: objects: - apiVersion: v1 kind: Secret metadata: name: recreate data: key: dgo= immutable: true policies: - type: resource-update name: resource-update properties: rules: - selector: resourceTypes: ["Secret"] strategy: recreateFields: ["data.key"]

通过指定recreateFields: ["data.key"],当 Application 渲染出的 Secret 的data.key字段与集群中的现有值不一致时,KubeVela 会先删除、再重建该 Secret;如果字段未变化,则走正常更新(默认 patch)。

重建判定的底层实现

重建判定逻辑位于 pkg/utils/apply/apply.go 的needRecreate函数(apply.go 附近):

  1. 将existing与desired两个对象分别转换为非结构化(unstructured)数据;
  2. 遍历recreateFields中的每个字段路径,用 Kubernetes 的fieldpath.Pave(...).GetValue(field)从现有对象中取出对应值;
  3. 若字段路径取值失败,直接返回错误(说明路径不合法或对象结构不符);
  4. 逐字段比较新旧值,任一字段发生变化即判定需要重建。

触发重建后,apply.go会先删除现有对象(若其DeletionTimestamp为空),再调用Create创建期望对象;同时代码注释明确说明recreate does not support dryrun,即该分支不支持 dry-run 预览。

字段路径语法

recreateFields使用 Kubernetes 标准字段路径语法,例如:

  • data.key:读取data映射下的key;
  • spec.template.spec.containers[0].image:读取首个容器的镜像;
  • 顶层字段直接写字段名,如immutable。

选择器 + 字段路径的组合,使 KubeVela 可以精确到“某个资源的某个字段变化才重建”,极大降低不必要的重建频率。

场景二:整对象替换更新(op: replace)

默认的patch基于三方合并,只修改 Application 管理的字段;而replace会把整个对象当作一个整体提交更新,即使某字段并非由 KubeVela Application 管理,也会一并被期望值覆盖抹除。原始文档的第二个示例:

apiVersion: core.oam.dev/v1beta1 kind: Application metadata: name: recreate spec: components: - type: k8s-objects name: recreate properties: objects: - apiVersion: v1 kind: ConfigMap metadata: name: recreate data: key: val policies: - type: resource-update name: resource-update properties: rules: - selector: resourceTypes: ["ConfigMap"] strategy: op: replace

通过op: replace,KubeVela 对命中的 ConfigMap 采用整对象替换更新。可以将其理解为“Application 级别的ApplyResourceByReplace”——它把原本作为 FeatureGate(见下文)全局生效的替换行为,收敛到单个 Application 内的具体资源上。

replace 与 patch 的执行差异

在 pkg/utils/apply/apply.go 的更新主流程中:

  • replace 分支:将desired的ResourceVersion设置为现有对象的版本号后,直接调用Update提交整个对象,即“以期望对象整体覆盖现有对象”;
  • patch 分支:调用三方 diff 计算补丁(patcher.patch),仅将差异字段打补丁到现有对象;若补丁为空(无差异)则直接返回,不产生任何 API 请求。

与 ApplyResourceByReplace FeatureGate 的关系

如果策略未显式指定op,则 apply 逻辑会检查全局 FeatureGateApplyResourceByReplace(pkg/features/controller_features.go):

  • FeatureGate 开启且目标资源属于可更新类型时,默认行为变为replace;
  • 否则默认回落到patch。

值得注意的是,isUpdatableResource做了特例处理(apply.go):v1/Service的 spec 会被 Service 控制器自动填充 IP 等字段,因此即使开启该 FeatureGate 也不会被替换,以避免破坏系统字段。这一特例同时说明:op: replace并非在所有资源上都安全,使用前需评估目标资源是否存在系统控制器写入的字段。

规则匹配与分发链路

resource-update策略在控制器运行时被解析并注入到每次资源下发中,核心链路如下:

  1. 解析策略:ResourceKeeper 在创建时调用parseApplicationResourcePolicy(pkg/resourcekeeper/resourcekeeper.go),通过policy.ParsePolicy[v1alpha1.ResourceUpdatePolicySpec]从 Application 中解析出resourceUpdatePolicy对象;
  2. 命中规则:下发每个 manifest 时,getUpdateStrategy(pkg/resourcekeeper/utils.go)调用resourceUpdatePolicy.FindStrategy(manifest)——遍历规则列表,返回第一条命中选择器的策略(apis/core.oam.dev/v1alpha1/resource_update_policy_types.go);
  3. 注入 ApplyOption:在 pkg/resourcekeeper/dispatch.go 与 pkg/resourcekeeper/statekeep.go 中,将命中的策略包装为apply.WithUpdateStrategy(*strategy)的 ApplyOption,随 manifest 一起交给 Applicator;
  4. 执行更新:Applicator 依据策略执行 recreate / replace / patch 三种路径(上文所述)。

从源码结构可以看出,该策略与read-only、take-over、apply-once等策略共享同一套 dispatch 扩展机制:isReadOnly、canTakeOver、getUpdateStrategy等检查在 dispatch.go 中依次叠加 ApplyOption,互不冲突、可组合使用。

端到端验证:e2e 测试用例

仓库在 test/e2e-multicluster-test 中提供了完整的端到端验证:

  • 测试数据 app-recreate-test.yaml 同时演示了recreateFields(Secret 的data.key)与op: replace(ConfigMap)两条规则,且两条规则作用于同一个 Application 的不同资源,证明规则列表可以并行生效;
  • 测试用例Test application with resource-update policy(test/e2e-multicluster-test/multicluster_test.go)将该 YAML 解析后创建 Application,验证策略在真实控制器链路中的行为。

此外,pkg/utils/apply/apply_resource_test.go 从单元测试层面对比了 patch 与 replace 的差异:在外部修改 Deployment 增加一个容器后,patch 模式会保留该外部新增容器,而 replace 模式会将其抹除——这正是“三方补丁保留外部字段、替换整对象抹除外部字段”语义的直接证据。

使用建议与注意事项

  1. recreateFields适用于不可就地更新的资源:如immutable: true的 Secret、部分 CRD 字段。字段路径必须与现有对象结构匹配,否则 apply 会直接报错,请先用kubectl get确认实际字段结构;
  2. op: replace是“强覆盖”语义:它会抹掉非 Application 管理的字段,请勿对v1/Service等系统控制器维护字段的资源使用,也不建议对多控制器共享的 ConfigMap 随意使用;
  3. 规则列表按序匹配:FindStrategy返回第一条命中的规则策略(resource_update_policy_types.go),如需“通用 patch + 特殊 recreate”的叠加效果,应将更具体的规则放在前面;
  4. 可与其它策略组合:资源下发时 read-only、take-over、apply-once、resource-update 等策略的 ApplyOption 会同时叠加(dispatch.go),可按需组合;
  5. 版本前提:本策略为 KubeVela 内置 PolicyDefinition,随 vela-core 一起安装(见 charts/vela-core/templates/defwithtemplate/resource-update.yaml),使用kubectl apply部署 Application 即可,无需额外安装组件。

小结

resource-update策略将资源更新行为从“全局统一”升级为“资源粒度可控”:recreateFields解决字段变化需重建的场景,op: replace提供整对象强覆盖的语义,同时默认的patch依旧保留对非受管字段的友好性。理解其选择器、字段路径与底层 apply 三路分支,能帮助你在 KubeVela 中精准编排各类资源的更新策略。

  • 云原生
  • DevOps
  • 运维
  • 微服务

【免费下载链接】kubevela

The Modern Application Platform.

项目地址:https://gitcode.com/gh_mirrors/ku/kubevela
点击查看免费下载
上一篇:如何通过ALFWorld实现跨模态智能交互?从零开始的五大实践维度
下一篇:serverless-ml-course实战:信用卡欺诈检测系统开发全流程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询