CRD必须先通过YAML注册到API Server,Go结构体仅用于后续操作;YAML需确保group/version/kind大小写一致、kind为PascalCase、spec.versions为数组且仅一个storage: true,字段标签须指针+omitempty+显式json/yaml,validation注释严格匹配OpenAPI v3类型名。

CRD 不能只靠 Go 结构体“定义”出来,必须先用 YAML 注册到 API Server,Go 代码只是后续操作它的工具。
CRD YAML 必须先部署成功,否则 kubectl 和 Go 都不认识这个资源
很多人写完 MyApp 结构体就急着跑控制器,结果 kubectl get myapps 报 no matches for kind "MyApp"。这不是 Go 的问题,是 API Server 根本没加载你的 CRD。
- 检查
spec.group和你实际使用的apiVersion是否一致(比如 CRD YAML 里写group: example.com,那资源实例的apiVersion就得是example.com/v1,不能是example/v1) -
spec.names.kind必须 PascalCase(MyApp✅,myapp❌),Kubernetes 强制校验 - 创建 CRD 后等
STATUS变成Established再创建 CR:kubectl get crd appservices.example.com -o wide - 集群版本低于 v1.16?必须用
apiextensions.k8s.io/v1beta1,字段和验证规则有差异
Go 结构体字段必须带指针 + omitempty + 显式 json/yaml 标签
controller-gen 生成的结构体如果字段没加 json:"field,omitempty",API Server 在解析 CR 实例时会直接拒绝,报错类似 spec.validation.openAPIV3Schema.type is required,不是运行时报错,是注册阶段就失败。
- 所有字段优先用指针:
Name *string `json:"name,omitempty" yaml:"name,omitempty"` - 嵌套结构体要显式加
json:"spec,omitempty"和struct{},不能靠匿名嵌入自动推导 - 切片字段必须写
json:"items,omitempty",比如Items []string `json:"items,omitempty"` - 别用
map[string]interface{}表示动态字段——controller-gen 无法生成合法 OpenAPI schema
validation 注释必须严格匹配 OpenAPI v3 类型名
// +kubebuilder:validation 注释不生效,往往是因为类型名写错了。它不认 Go 类型,只认 OpenAPI v3 规范里的字符串。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
立即学习“go语言免费学习笔记(深入)”;
- 写
// +kubebuilder:validation:Minimum=0,不是Min=0 - 字符串长度限制用
MinLength=1,数组用MinItems=1(不是MinLength) - 类型声明必须是
string、integer、boolean—— 写int或bool会静默失效 - 必填字段加
// +kubebuilder:validation:Required(注意双斜杠+空格)
AddToScheme 调用顺序错,client-go 就会 panic “no kind is registered”
Go 程序要操作 CR,必须让 scheme “认识”这个类型。但注册时机不对,client.Get() 一调就 panic。
- 必须在构建
rest.Config和初始化client.Client之前,调用生成的MyAppV1.AddToScheme(scheme) - 别漏掉基础 Scheme 加载:
clientgoscheme.AddToScheme(scheme)和apiextensionsv1.AddToScheme(scheme),否则连 CRD 自身都解析不了 - 如果用
controller-runtime,记得用schemeBuilder.Register(&MyApp{}, &MyAppList{}),而不是只注册单个类型 - 用动态客户端(
dynamic.Interface)时,传的必须是*unstructured.Unstructured,别把*v1.MyApp塞进去
最常被忽略的是:CRD YAML 中 spec.versions 必须是数组,且仅一个 storage: true;手写成 spec.version 字段,Kubernetes 1.16+ 会直接拒绝,错误信息很明确但容易扫一眼就过。

















