crd多版本转换核心是hub-spoke模型:指定唯一storageversion为hub,各spoke版本须实现convertto/convertfrom双向无损转换,且conversion webhook必须正确配置tls与固定路径/convert。

CRD 字段做版本兼容转换,核心不是“手动写 JSON 转换”,而是让 controller-runtime 通过 ConvertTo 和 ConvertFrom 方法,在 Hub-Spoke 模型下完成结构化双向转换。不实现这两个方法,kubectl get v2 就会直接报错 error unmarshaling JSON。
必须指定 storage version 并标记 +kubebuilder:storageversion
Storage 版本是 Hub,所有 Spoke 版本都必须能和它往返转换。Kubebuilder 不会自动选哪个是 Hub —— 你得显式标出来:
- 在目标版本(比如
v2)的类型定义顶部加注释://+kubebuilder:storageversion - 确保该类型所在包的
types.go文件里没有其他//+kubebuilder:storageversion标记,否则生成 CRD 时会报错 - 运行
make manifests后,生成的 CRD YAML 中spec.versions[].storage字段必须为true且仅出现在一个版本上
ConvertTo/ConvertFrom 方法必须成对实现且无损
假设 v1 是 Spoke、v2 是 Hub,那么 v1 类型必须实现:
-
func (src *CronWork) ConvertTo(dst *v2.CronWork) error:v1 → v2,把旧字段映射到新结构(例如把schedule: "0 0/1 * * *"拆进Schedule2.Minute等字段) -
func (dst *CronWork) ConvertFrom(src *v2.CronWork) error:v2 → v1,反向拼回字符串(注意保留默认值、空指针处理,否则 round-trip 会丢信息) - 两个方法里不能用
json.Marshal/Unmarshal做粗暴转换 —— 这会绕过类型安全,且无法处理指针字段、omitempty、默认值等语义
conversion webhook 必须监听 /convert 且 TLS 配置正确
Kubernetes API Server 只认固定路径 /convert,且只信任由它签发或明确信任的证书:
-
kubebuilder create webhook --conversion --spoke会生成骨架,但不会自动启用;需确认config/webhook/kustomization.yaml中已取消注释patchesStrategicMerge行,并包含webhookcainjection_patch.yaml - Webhook server 的 TLS 证书必须由 apiserver 所信任的 CA 签发 —— 推荐用 kubebuilder 自动生成的 cert-manager 流程,不要手动生成自签名证书后硬塞
- CRD 的
spec.conversion.webhook.clientConfig.service.path必须是/convert,这个值不能改,也不支持通过 marker 自定义
最容易被忽略的是:哪怕只加了一个新字段、改了一个字段名,只要没配 conversion webhook,老对象读取新版本时就会卡在解码阶段,连日志都打不出来 —— 因为错误发生在 APIServer 层,根本没走到你的 controller 代码里。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











