- 云原生
- DevOps
- 运维
- 微服务
【免费下载链接】kubevela
The Modern Application Platform.
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:更新策略
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
op | string | patch | 更新操作符: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 附近):
- 将
existing与desired两个对象分别转换为非结构化(unstructured)数据; - 遍历
recreateFields中的每个字段路径,用 Kubernetes 的fieldpath.Pave(...).GetValue(field)从现有对象中取出对应值; - 若字段路径取值失败,直接返回错误(说明路径不合法或对象结构不符);
- 逐字段比较新旧值,任一字段发生变化即判定需要重建。
触发重建后,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策略在控制器运行时被解析并注入到每次资源下发中,核心链路如下:
- 解析策略:ResourceKeeper 在创建时调用
parseApplicationResourcePolicy(pkg/resourcekeeper/resourcekeeper.go),通过policy.ParsePolicy[v1alpha1.ResourceUpdatePolicySpec]从 Application 中解析出resourceUpdatePolicy对象; - 命中规则:下发每个 manifest 时,
getUpdateStrategy(pkg/resourcekeeper/utils.go)调用resourceUpdatePolicy.FindStrategy(manifest)——遍历规则列表,返回第一条命中选择器的策略(apis/core.oam.dev/v1alpha1/resource_update_policy_types.go); - 注入 ApplyOption:在 pkg/resourcekeeper/dispatch.go 与 pkg/resourcekeeper/statekeep.go 中,将命中的策略包装为
apply.WithUpdateStrategy(*strategy)的 ApplyOption,随 manifest 一起交给 Applicator; - 执行更新: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 模式会将其抹除——这正是“三方补丁保留外部字段、替换整对象抹除外部字段”语义的直接证据。
使用建议与注意事项
recreateFields适用于不可就地更新的资源:如immutable: true的 Secret、部分 CRD 字段。字段路径必须与现有对象结构匹配,否则 apply 会直接报错,请先用kubectl get确认实际字段结构;op: replace是“强覆盖”语义:它会抹掉非 Application 管理的字段,请勿对v1/Service等系统控制器维护字段的资源使用,也不建议对多控制器共享的 ConfigMap 随意使用;- 规则列表按序匹配:
FindStrategy返回第一条命中的规则策略(resource_update_policy_types.go),如需“通用 patch + 特殊 recreate”的叠加效果,应将更具体的规则放在前面; - 可与其它策略组合:资源下发时 read-only、take-over、apply-once、resource-update 等策略的 ApplyOption 会同时叠加(dispatch.go),可按需组合;
- 版本前提:本策略为 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.
相关推荐
GRBL-Plotter终极指南:如何用免费开源软件控制你的CNC雕刻机
GRBL Plotter终极指南:如何用免费开源软件控制你的CNC雕刻机 GRBL Plotter是一款功能强大的开源G代码发送软件,专为GRBL控制器设计,支
桌面应用智能硬件KubeVela ApplyOnce 策略实战:用 `apply-once` 策略精细控制配置漂移与资源回收行为
KubeVela ApplyOnce 策略实战:用 apply once 策略精细控制配置漂移与资源回收行为 KubeVela 的 Application 控制
云原生DevOps运维微服务terraform-provider-azurerm策略定义:资源合规规则创建
terraform provider azurerm策略定义:资源合规规则创建 策略定义概述 策略定义(Policy Definition)是Azure资源管理
基础设施DevOps云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考