kustomize JSON Patch(JSON 补丁)完全指南:用 RFC 6902 精准改造 Ingress 等任意资源

发布时间:2026/9/23 12:44:12
kustomize JSON Patch(JSON 补丁)完全指南:用 RFC 6902 精准改造 Ingress 等任意资源
kustomize JSON PatchJSON 补丁完全指南用 RFC 6902 精准改造 Ingress 等任意资源【免费下载链接】kustomizeCustomization of kubernetes YAML configurations项目地址: https://gitcode.com/gh_mirrors/ku/kustomizeJSON PatchRFC 6902 的完整演示为主线结合仓库源码讲解 patch 的语法、target 定位机制、JSON/YAML 两种写法以及它与其他 patch 方式的取舍读完你可以立刻在自己的 kustomization 项目中落地这套打补丁方案。一、JSON Patch 是什么kustomize 为什么要支持它kustomize 的职责是「Customization of kubernetes YAML configurations」——在不改原始资源的前提下通过叠加规则生成最终 YAML。修改资源的方式有很多种JSON Patch 是其中语法最精确、最贴近标准的一种Strategic Merge PatchSMP把想修改的字段局部重写一份kustomize 按 Kubernetes 特有规则与原资源合并详见 patchstrategicmerge 过滤器。它擅长「改字段」但在「往列表中间插一项」「按精确路径改一个值」等场景下不够直观。JSON Patch由一组显式的操作指令组成每条指令形如{op: replace, path: /spec/rules/0/host, value: foo.bar.io}操作对象、路径、新值一目了然完全遵循 RFC 6902 标准。kustomize 的 JSON Patch 支持体现在两个层面字段层面kustomization.yaml中声明patches新推荐或patchesJson6902已弃用见 kustomization.go每个 patch 带一个target选择器实现层面内置插件 PatchJson6902Transformer 与底层过滤器 patchjson6902.Filter 负责解析和应用。二、完整演示用 JSON Patch 改造一个 Ingress下面完整复现 examples/jsonpatch.md 的官方演示先造一个包含三个路由路径的 Ingress再用一个 JSON Patch 文件同时完成「改值 × 2 指定位置插入 × 1」。2.1 准备资源文件建一个临时工作目录写入 IngressDEMO_HOME$(mktemp -d)cat EOF $DEMO_HOME/ingress.yaml apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: my-ingress spec: rules: - host: foo.bar.com http: paths: - path: / backend: serviceName: homepage servicePort: 8888 - path: /api backend: serviceName: my-api servicePort: 7701 - path: /test backend: serviceName: hello servicePort: 7702 EOF注意示例资源使用的是networking.k8s.io/v1beta1版本的 Ingress这是该演示文档编写时的 API 版本当前 Kubernetes 已演进到networking.k8s.io/v1实际使用时请把apiVersion与target中的version同步替换为你集群支持的版本。2.2 定义三项目标修改我们要做的修改是把host的值从foo.bar.com改为foo.bar.io把/路径的servicePort从8888改为80在paths列表的指定位置/test之前插入一条全新的/healthz服务路径而不是追加到列表末尾或开头。第三条正是 JSON Patch 相对普通字段覆盖的差异化优势路径定位用数组下标/paths/1精确控制插入点。2.3 编写 JSON Patch 文件cat EOF $DEMO_HOME/ingress_patch.json [ {op: replace, path: /spec/rules/0/host, value: foo.bar.io}, {op: replace, path: /spec/rules/0/http/paths/0/backend/servicePort, value: 80}, {op: add, path: /spec/rules/0/http/paths/1, value: { path: /healthz, backend: {servicePort:7700} }} ] EOF该文件是一个 JSON 数组数组中每个元素是一条 RFC 6902 操作指令字段含义本例取值op操作类型add/remove/replace/move/copy/testreplace、addpath用 JSON Pointer 语法/分隔数组用数字下标定位目标字段/spec/rules/0/host等value操作涉及的数值/对象foo.bar.io、80、{...}add在数组路径上的语义是「在指定下标处插入」因此/spec/rules/0/http/paths/1会把新路径插到原下标 1即/api路径之前其余元素自动后移。关于 add 在对象、数组及-通配下标上的行为见 RFC 6902 第 4.1 节。2.4 编写 kustomization 并挂接 patch先声明引用 Ingresscat EOF $DEMO_HOME/kustomization.yaml resources: - ingress.yaml EOF再追加patches字段用target把 patch 指向 Ingress 对象cat EOF $DEMO_HOME/kustomization.yaml patches: - path: ingress_patch.json target: group: networking.k8s.io version: v1beta1 kind: Ingress name: my-ingress EOF2.5 运行并校验输出预期输出$DEMO_HOME/out_expected.yamlapiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: my-ingress spec: rules: - host: foo.bar.io http: paths: - backend: serviceName: homepage servicePort: 80 path: / - backend: servicePort: 7700 path: /healthz - backend: serviceName: my-api servicePort: 7701 path: /api - backend: serviceName: hello servicePort: 7702 path: /test运行构建并与预期比对kustomize build $DEMO_HOME $DEMO_HOME/out_actual.yaml diff $DEMO_HOME/out_actual.yaml $DEMO_HOME/out_expected.yamldiff无输出即说明补丁生效三处修改全部命中host 变为foo.bar.io、/端口变为 80、/healthz被插到/api之前。同时可以看到 patch 后的字段排序如backend与path的顺序可能相对原文件发生变化这与底层实现有关见第四节。三、同样一套补丁也可以写成 YAMLJSON Patch 的规则不变但文件本身可以用 YAML 语法书写YAML 是 JSON 的超集写起来更省标点。追加一条「add」操作到列表末尾/spec/rules/0/http/paths/-中的-表示列表末尾是 RFC 6902 规定的特殊下标cat EOF $DEMO_HOME/ingress_patch.yaml - op: add path: /spec/rules/0/http/paths/- value: path: /canada backend: serviceName: hoser servicePort: 7703 EOF把它加进 kustomization 的 patch 列表cat EOF $DEMO_HOME/kustomization.yaml - path: ingress_patch.yaml target: group: networking.k8s.io version: v1beta1 kind: Ingress name: my-ingress EOF预期输出末尾追加了/canada路径- backend: serviceName: hello servicePort: 7702 path: /test - backend: serviceName: hoser servicePort: 7703 path: /canada验证kustomize build $DEMO_HOME | tail -n 8 |\ diff $DEMO_HOME/out_expected.yaml -tail -n 8截取输出末尾 8 行再与期望片段比对同样无输出即通过。3.1 中文版演示的另一种写法仓库还提供了一份更精简的中文演示 examples/zh/jsonpatch.md它演示的是patchesJson6902旧字段写法patch 中target与path的顺序可以交换用replaceadd两种操作组合把 host 改为foo.bar.io、把 servicePort 改为8080、追加/test路径用grep验证输出例如kustomize build $DEMO_HOME | grep host: foo.bar.io。两份演示互相印证同一个功能既可以写在新字段patches下也可以写在旧字段patchesJson6902下。四、底层原理patch 是如何被解析和应用的4.1 字段定义Patch 与 Selectorkustomization.yaml中的patches字段类型定义在 api/types/kustomization.go每个元素都是types.Patch其结构见 api/types/patch.gopathpatch 文件的相对路径patch直接内联的 patch 内容二选一与path互斥target指向要应用 patch 的资源选择器options可选allowNameChange/allowKindChange两个开关定义见 api/types/patchargs.go。target是types.Selector定义在 api/types/selector.go支持以下条件多个条件取交集AND 关系字段说明groupAPI 组versionAPI 版本kind资源类型name资源名支持正则namespace命名空间labelSelector标签选择器表达式annotationSelector注解选择器表达式从源码可以推断name等字段会被编译为正则表达式见 selector.go 的NewSelectorRegex与anchorRegex非空字段以^(?:pattern)$锚定匹配。这意味着name: my-ingress精确匹配而name: foo.*可以一次命中多个资源。4.2 解析流程从文件到 jsonpatch.Patch内置插件 PatchJson6902Transformer 的Config方法负责解析核心逻辑校验target.name不能为空、path与内联jsonOp不能同时为空若给了path用 Loader 读取文件内容若内容不是以[开头说明是 YAML 格式先yaml.YAMLToJSON转成 JSON——这就是为什么 patch 文件可以用 YAML 书写交给jsonpatch.DecodePatch解码为操作列表空 patch解码后长度为 0直接报错。4.3 应用流程目标选择与逐资源打补丁Transform方法PatchJson6902Transformer.go先按target从资源映射中选出所有匹配资源再对每个资源调用过滤器。最底层的过滤器在 api/filters/patchjson6902/patchjson6902.go把目标资源的 YAML 序列化为 JSON调用jsonpatch库的Apply应用全部操作再把结果反序列化回 YAML。该文件源码注释也坦诚指出一个重要事实这种「YAML → JSON → patch → YAML」的往返方式不保证字段顺序完全保持这正是 2.5 节输出中字段顺序可能重排的根本原因。若对字段顺序敏感应优先考虑 Strategic Merge Patch 或直接检查生成结果。过滤器的行为有完整单测覆盖api/filters/patchjson6902/patchjson6902_test.go 用 4 个用例验证了 JSON/YAML 两种格式下单操作与多操作replace 多个 add的等效性example_test.go 还展示了对多个资源Foo、Bar同时应用同一个 YAML patch 的管道式用法kio.Pipeline与 kustomize 的批处理机制同源。五、一次 patch 打多个资源target 选择器进阶patches字段天然支持「一个 patch 作用于多个资源」因为target是一个选择器而非单一路径。完整演示见 examples/patchMultipleObjects.md核心要点name支持正则name: foo.*可命中多个同类型资源kind: Deployment只按类型筛组合条件更精确例如同时要求kind: Deployment且labelSelector: apphello该演示还展示了用 labelSelector 只 patch 其中一个 DeploymentlabelSelector: keyvalue时仅 deploy2 被修改。需要注意示例中的patches条目既可以放 Strategic Merge Patch 文件也可以放 JSON Patch 文件kustomization.go 注明每个 patch 可以是两者之一kustomize 依据内容自动识别。若想严格指定 JSON Patch 语义可使用旧字段patchesJson6902。六、新旧字段迁移patchesJson6902 已弃用从 kustomization.go 可以看到patchesJson6902已被标记为Deprecated注释明确指出使用patches字段即可它是 JSON Patch 功能的超集。运行时若检测到旧字段kustomize 会给出警告kustomization.go并在内部把patchesJson6902条目合并进patcheskustomization.go。迁移方法很简单把patchesJson6902: - target: group: networking.k8s.io version: v1beta1 kind: Ingress name: my-ingress path: ingress_patch.json改成patches: - path: ingress_patch.json target: group: networking.k8s.io version: v1beta1 kind: Ingress name: my-ingress七、JSON Patch vs Strategic Merge Patch如何选择维度JSON Patch本文Strategic Merge Patch语法RFC 6902 操作数组精确到路径部分重写目标对象按 Kubernetes 合并规则列表操作支持按下标/-精确插入、删除、移动主要靠合并策略行为受 openapi schema 影响适用场景改某个精确字段、列表指定位置插入、跨多个同型资源批量修改覆盖字段、注入 sidecar 等常规合并字段顺序经 JSON 往返不保证完全保持一般保持结构顺序声明位置patches或旧patchesJson6902patches或旧patchesStrategicMerge实际项目中二者可混用都挂在patches下按「精确路径 vs 局部重写」的诉求灵活选择。八、快速上手小结准备要修改的资源本文为ingress.yamlresources引用它写 patch 文件.json或.yaml均可内容为 RFC 6902 操作数组在kustomization.yaml的patches下挂接pathtargetkustomize build生成结果用diff或grep验证需要批量时把target.name写成正则或叠加labelSelector/annotationSelector。更完整的配套示例可继续阅读 examples/jsonpatch.md英文原版、examples/zh/jsonpatch.md中文精简版与 examples/patchMultipleObjects.md多资源补丁。【免费下载链接】kustomizeCustomization of kubernetes YAML configurations项目地址: https://gitcode.com/gh_mirrors/ku/kustomize创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考