Operator 以控制器 Pod 形式运行,需先 apply CRD 并确保其处于 Established 状态,再配置 RBAC、构建镜像、部署 Deployment;跳过 CRD 或权限不足将导致启动失败或 Reconcile 静默失效。

Operator 不是“部署”出来的,而是以控制器 Pod 的形式运行在集群中;你真正要做的,是构建镜像、安装 CRD、配置 RBAC、然后用 kubectl apply 启动它 —— 任何试图跳过 CRD 或绕过 RBAC 直接跑二进制的行为,都会在启动时 panic 报 no matches for kind 或 forbidden。
CRD 必须先 apply,否则 Operator 启动就失败
Controller-runtime 在启动时会尝试 List 你定义的 CR 类型,如果集群里还没注册 CRD,就会直接 crash。这不是可重试错误,而是初始化阶段致命失败。
- 生成 CRD YAML 后(通常由
make manifests或controller-gen输出),必须先kubectl apply -f config/crd/bases/xxx.yaml - 别依赖 Operator 启动时自动创建 CRD —— 官方不支持,kubebuilder 也不做这事
- 检查是否成功:
kubectl get crd | grep myapp,看到 Established 状态才算就绪 - 如果用 Helm chart 打包 Operator,CRD 必须放在
crds/目录下,且 chart values 中禁用crds.enabled: false会导致漏装
RBAC 权限不能靠 guess,得按实际 client 操作反推
Operator 的 client.Client 默认走缓存,但某些操作(如 Patch、Status Update、Watch 子资源)需要显式授权。权限不足的表现不是报错,而是 Reconcile 静默跳过或卡住。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 用
make manifests生成的 RBAC YAML 只覆盖基础 CRUD,漏掉patch和updatestatus是常见原因 - 如果你在 Reconcile 里调用了
r.Status().Update(),RBAC 必须含verbs: [update] resourceNames: [myapps/status] - 如果用
OwnerReference绑定 Deployment,Operator 需要对deployments/finalizers有 patch 权限(清理 finalizer 时用) - 本地调试时用
make run可绕过 RBAC,但一上集群就暴露问题 —— 别信本地能跑就等于线上 OK
镜像构建和 Deployment 配置容易忽略三件事
Operator 本身是个 Go 程序,最终打包成容器运行。很多团队卡在 ImagePullBackOff 或 CrashLoopBackOff,根源不在代码,而在构建和部署环节。
立即学习“go语言免费学习笔记(深入)”;
- 镜像必须用
CGO_ENABLED=0 GOOS=linux go build,否则 Alpine 基础镜像跑不起来 - Deployment 的
spec.template.spec.serviceAccountName必须和 RBAC 中的ServiceAccount名字一致,大小写敏感 - 环境变量
POD_NAMESPACE要注入(用于 controller-runtime 自动识别 namespace scope),没它可能导致跨 namespace 资源查不到 - 别把
manager容器的command写成["./manager"]却忘了args—— 比如缺失--leader-elect会导致多副本竞争崩溃
最常被跳过的一步:Operator 启动后,kubectl get myapps 返回空不是因为没资源,而是因为没创建任何 CR 实例 —— CRD 和 Controller 都就位了,但没人告诉 Operator “该干活了”。这个边界很薄,却决定了整个自动化链条是否真正闭合。

















