Reconcile 不触发主因是控制器未注册监听:CRD 未 install、SetupWithManager 漏 .For() 或 .Owns()、RBAC 缺 watch 权限;验证需用 kubectl auth can-i watch 并检查日志是否输出 reconciling。

Reconcile 函数不触发,大概率不是代码写错了,而是控制器根本没注册上监听目标资源。
为什么 Reconcile 从不执行
Manager 启动成功 ≠ Controller 开始干活。最常见原因有三个:
-
CRD没提前make install——no matches for kind "MyApp"这类错误会被静默吞掉,日志里只显示 leader election 失败或 watch 初始化失败 -
SetupWithManager里漏了.For(&MyApp{}),或者用了.Owns(&Deployment{})却忘了先.For主资源 -
RBAC缺少watch权限 —— Kubernetes 不报权限错误,而是直接不推送事件,Reconcile就永远不会被调用
验证方法:kubectl auth can-i watch myapps.myscheme.example.com/v1 --list;再确认 config/rbac/role.yaml 中 resources 字段是否包含 myapps(注意是复数形式,和 CRD 的 spec.names.plural 严格一致)。
client.Get 返回 NotFound 却不是真不存在
这不是网络问题,也不是对象没创建,而是权限或作用域错配:
- RABC 没给
get权限,Kubernetes 会伪装成NotFound,而非明确的Forbidden - CRD 是
ClusterScoped,但你用req.NamespacedName去查 —— 正确做法是用types.NamespacedName{Name: req.Name}(去掉 Namespace) - 本地调试时用了
make run,但没加ENABLE_WEBHOOKS=false,导致 admission webhook 启动失败,manager 无法完成初始化,client 实际未就绪
快速排查:在 Reconcile 开头加一行 log.FromContext(ctx).Info("reconciling", "name", req.Name, "namespace", req.Namespace),看这条日志是否出现。不出现,说明根本没进函数;出现了但 Get 报错,再查 RBAC 和 scope。
立即学习“go语言免费学习笔记(深入)”;
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
更新 Status 字段总被拒绝
r.Status().Update(ctx, &myApp) 报错 the server does not allow this method on the requested resource,是因为没走 status 子资源路径。
- 必须用
status.SubResource("status"),不能直接r.Client.Update() - 确保 CRD 定义中启用了 status subresource:
status: {}在openAPIV3Schema下,并且subresources块存在 - Go 类型里必须显式定义
Status MyAppStatus `json:"status,omitempty"`字段,且MyAppStatus结构体要注册进 Scheme(myapp.AddToScheme(scheme))
否则 APIServer 会拒收任何对 /status 路径的请求,错误信息非常不直观。
子资源(如 Deployment)创建后不自动清理
删掉自定义资源后,关联的 Deployment 还留在集群里,说明 OwnerReference 没生效。
- 创建子资源时,必须调用
ctrl.SetControllerReference(&myApp, &dep, r.Scheme),不能只手动填ownerReferences -
&myApp必须是已持久化的对象(即已通过r.Client.Get或事件参数拿到的完整实例),不能是空 struct 或只填了 Name 的壳 - 检查生成的 Deployment YAML,确认
metadata.ownerReferences[0].controller是true,且uid和apiVersion与原 CR 一致
最容易忽略的是:Operator 启动前,必须先 make install 安装 CRD,否则 myApp 对象本身没有 UID,SetControllerReference 会静默失败。

















