CRD YAML 必须用 apiextensions.k8s.io/v1,Kubernetes 1.22+ 已彻底移除 v1beta1;v1 要求显式设 spec.preserveUnknownFields: false、validation 移至 spec.versions[0].schema.openAPIV3Schema,且推荐用 kubebuilder 自动生成以确保 group/version/kind/Scheme 注册严格一致。

CRD YAML 文件必须用 v1 版本,别写 v1beta1
Kubernetes 1.22+ 已彻底移除 v1beta1 的 CRD API,继续用会报错:no matches for kind "CustomResourceDefinition" in version "apiextensions.k8s.io/v1beta1"。所有新定义必须用 apiVersion: apiextensions.k8s.io/v1。
关键区别在于:v1 要求显式声明 spec.preserveUnknownFields: false(推荐设为 false),且 validation 必须用 schema.openAPIV3Schema,不再支持顶层 validation 字段。
-
spec.version废弃,改用spec.versions数组,至少含一个name、served: true、storage: true的版本 -
spec.validation必须嵌套在spec.versions[0].schema.openAPIV3Schema下 - 如果要用多版本转换(如 v1alpha1 → v1),需额外配置
conversion和 Webhook
Go 结构体字段必须加 kubebuilder 注释生成 CRD
纯手写 YAML 容易漏掉字段校验、默认值、CRD 状态结构等细节。推荐用 kubebuilder 从 Go struct 自动生成 —— 这才是生产级做法。
核心注释包括:// +kubebuilder:object:root=true 标记根资源,// +kubebuilder:subresource:status 启用 status 子资源,// +kubebuilder:printcolumn 控制 kubectl get 输出列。
立即学习“go语言免费学习笔记(深入)”;
- 字段标签必须含
json:"fieldName,omitempty",否则生成的 schema 缺少字段映射 - 必需字段加
// +kubebuilder:validation:Required,否则默认是 optional - 数字范围校验用
// +kubebuilder:validation:Minimum=1,字符串长度用MaxLength/MinLength - 运行
make manifests(kubebuilder 项目)或controller-gen crd:crdVersions=v1 paths="./..." output:crd:dir=deploy/crds
spec.schema.openAPIV3Schema 里不能直接写 map[string]interface{}
Go 中若用 map[string]interface{} 表示动态字段,controller-gen 会生成空 schema 或报错:cannot generate CRD for type map[string]interface{}。Kubernetes 不允许无约束的任意 JSON。
正确做法是:用 runtime.RawExtension(需导入 k8s.io/apimachinery/pkg/runtime),或定义明确的 struct(哪怕只含 map[string]string 字段)。
-
runtime.RawExtension对应 OpenAPI 中的type: object+x-kubernetes-embedded-resource: true - 若字段只是键值对,定义为
map[string]string,它会被正确转成type: object, additionalProperties: { type: string } - 避免
interface{}、any、json.RawMessage(除非配合RawExtension)
apply CRD 后 controller 拿不到对象?检查 group/version/kind 是否匹配
CRD 定义里的 spec.group、spec.names.kind、spec.versions[0].name,必须和 Go controller 中的 SchemeBuilder.Register 类型注册完全一致,大小写、复数形式都不能错。
典型错误:CRD 里写 kind: MyDatabase,但 Go 里注册的是 Mydatabase;或 CRD group: db.example.com,而 controller 用 db.example.org。
- 用
kubectl get crd mydatabases.db.example.com -o yaml确认实际生效的 CRD 内容 - 检查 controller 日志是否出现
no matches for kind "MyDatabase" in version "db.example.com/v1" - 确保
client-go的 Scheme 包含该类型:mydatabasev1.AddToScheme(scheme)


















