crd字段类型错误、json/yaml标签缺失或omitempty未配置会导致kubectl apply失败;status更新须用client.status().update;validation需显式注释;scheme注册顺序必须先clientgoscheme再自定义。

CRD定义里字段类型写错会导致kubectl apply失败
Go结构体字段没加json和yaml标签,或用了指针但没设omitempty,K8s API Server会拒绝创建CRD。这不是校验逻辑问题,是OpenAPI v3 schema生成失败的硬性报错。
- 所有非空字段必须带
json:"fieldName,omitempty",哪怕类型是string或int - 嵌套结构体字段要用
json:"nested,omitempty"+struct{},不能直接用map[string]interface{}(Kubebuilder不生成合法schema) - 切片字段别漏
json:"items,omitempty",否则kubectl get mycrd能查到但describe报错 - 示例:
Replicas *int32 `json:"replicas,omitempty" yaml:"replicas,omitempty"`—— 指针+omitempty是安全写法
controller-runtime的Reconcile函数里不能直接用client.Get更新Status
调用client.Get读取对象后直接改.Status再client.Update,大概率触发“object has been modified”冲突。这不是并发问题,是K8s乐观锁机制在起作用。
- 必须用
client.Status().Update(ctx, obj)单独提交Status变更,这是API Server特许的免版本检查路径 - 如果Status依赖Spec计算,先
client.Get读完整对象,再用DeepCopy()构造新实例,避免修改缓存引用 - 别在Reconcile里反复
Get同一对象——加个if obj.DeletionTimestamp != nil提前return,省掉无谓请求
make manifests生成的CRD YAML缺少validation导致kubebuilder init失败
make manifests默认只生成基础schema,一旦字段有required、minLength等约束,没显式配置就会让kubectl apply -f config/crd/bases/报spec.validation.openAPIV3Schema.type is required。
- 在Go struct字段上加
// +kubebuilder:validation:Required注释(注意是双斜杠+空格) - 字符串长度限制写
// +kubebuilder:validation:MinLength=1,数字范围用Minimum=0,布尔值不用额外注释 - 数组最小长度必须用
MinItems,不是MinLength——这个错网上很多教程都写反了 - 运行
make manifests后立刻检查生成的YAML里openAPIV3Schema.properties.spec.properties.xxx.type是否存在
本地调试controller时scheme注册顺序错乱引发panic
把自定义资源的AddToScheme调用放在clientgoscheme.AddToScheme之前,启动controller会panic:「no kind is registered for the type」。这不是代码bug,是runtime.Scheme内部map覆盖导致的。
立即学习“go语言免费学习笔记(深入)”;
- 必须严格按顺序:先
clientgoscheme.AddToScheme(scheme),再myv1.AddToScheme(scheme) - 如果用了多个API组(如
myv1和myv2),全部AddToScheme都要在clientgoscheme之后 - 测试时用
go run . --leader-elect=false --zap-devel,加上--zap-devel才能看到真实的scheme注册日志
真正卡住人的从来不是CRD怎么写,而是哪一行注释没对齐、哪个标签少了个omitempty、或者scheme注册多了一行换行——这些地方不会报语法错误,但会让kubectl静默失败或controller反复重启。










