controller-gen 生成 crd openapi v3 schema 需同时满足:字段含有效 json: tag、结构体含完整 //+kubebuilder:validation 注释、make manifests 启用 crd:trivialversions=true 等参数,缺一则 openapiv3schema 为空或字段缺失。

controller-gen 生成 CRD OpenAPI v3 schema 的前提条件
CRD 的 OpenAPI v3 schema 不是手写的,必须由 controller-gen 从 Go struct 的注释和字段 tag 自动推导生成。它依赖三个关键要素同时满足:结构体字段有 json: tag(如 json:"replicas,omitempty")、类型定义文件里包含完整 //+kubebuilder:validation 注释、且 make manifests 调用时启用了 crd:trivialVersions=true 等正确参数。缺任何一个,生成的 YAML 中 openAPIV3Schema 就会为空或字段缺失,导致 kubectl apply 失败并报错 spec.validation.openAPIV3Schema.type is required。
常见 OpenAPI schema 生成失败的错误现象
运行 make manifests 后,打开 config/crd/bases/xxx.yaml,发现 openAPIV3Schema 下只有空对象 {},或字段全被忽略——这不是 controller-gen 崩溃,而是它“安静地跳过”了无效字段。典型原因包括:
-
api/v1alpha1/mydatabase_types.go中Spec或Status字段没加json:tag,比如写成Replicas int `json:""`(空字符串)或直接漏掉 - 用了嵌套匿名结构体但没加
json:",inline",导致 controller-gen 无法展开校验规则 -
//+kubebuilder:validation注释写在字段上却漏了type,例如//+kubebuilder:validation:Minimum=1却没配//+kubebuilder:validation:type=integer -
Makefile里的manifests目标调用controller-gen时没传crd:generateEmbeddedObjectMeta=true,导致metadata字段不被纳入校验范围
更新 OpenAPI schema 时必须同步修改 Go 类型
CRD 的 OpenAPI schema 完全由 Go 类型驱动,config/crd/bases/ 下的 YAML 是只读产物,每次 make manifests 都会覆盖。因此:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 新增字段?在
MyDatabaseSpec结构体中添加带json:tag 的导出字段,并补全//+kubebuilder:validation注释 - 改字段类型?比如把
string改成*string,必须同时更新json:tag(加omitempty)和 validation 注释(如type=string→type=string,nullable=true) - 删字段?不能只删 YAML;必须先从 Go 类型中移除字段,再跑
make manifests,否则旧字段仍会出现在 schema 中,造成 API Server 拒绝新对象 - 升级 CRD 版本(如 v1alpha1 → v1)?仅靠
create api不够,必须手动实现ConvertTo/ConvertFrom方法,并在config/crd/kustomization.yaml中启用 conversion webhook 补丁,否则老对象解码失败
验证生成的 OpenAPI 是否生效
生成后别急着 kubectl apply,先本地检查:
- 用
yq e '.spec.versions[0].schema.openAPIV3Schema.properties.spec.properties' config/crd/bases/xxx.yaml看字段是否出现且含type和description - 执行
kubectl apply -f config/crd/bases/xxx.yaml,若报错invalid value: object has no field "openAPIV3Schema",说明controller-gen版本太低(需 ≥ v0.12.0)或没启用crd:参数 - 创建一个 CR 实例,故意填错字段(如给
replicas写字符串),观察kubectl create是否立刻报Invalid value: "abc": spec.replicas in body must be of type integer—— 这才是 OpenAPI 校验真正生效
最易被忽略的是:OpenAPI schema 只校验提交到 API Server 的 JSON,不校验控制器内部逻辑;字段加了 required: 但 Reconcile 函数里没做空值保护,照样会 panic。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










