Go是编写Kubernetes Operator的事实标准,因controller-runtime和operator-sdk深度绑定Go;init需指定--domain与--repo确保包路径正确;CRD字段须导出且带json标签;Reconcile中禁止直接修改入参对象,应使用Get+Patch;需覆盖边缘场景并配置完整RBAC权限。

Go语言是编写Kubernetes Operator的事实标准,因为官方SDK(controller-runtime)和生态工具(operator-sdk)深度绑定Go,且Kubernetes本身用Go编写,类型系统与API一致性强——换其他语言不仅绕路,还会在CRD验证、Webhook、OwnerReference处理等环节频繁踩坑。
用 operator-sdk init 初始化项目时必须指定 Go 模块路径
不设 --domain 和 --repo 会导致后续生成的控制器代码引用错误包路径,进而让 make install 或 kubectl apply -f config/ 失败,报错类似 no matches for kind "MyApp" in version "example.com/v1"。
operator-sdk init --domain example.com --repo github.com/yourname/myapp-operator- 确保
go.mod中模块名与--repo完全一致,大小写敏感 - 若已初始化错,别改
go.mod后硬推——要删掉config/crd/bases/和api/目录,再重跑init
定义 CRD 时,Spec 字段必须导出且带 json 标签
否则 controller-runtime 无法序列化/反序列化资源,kubectl create 会静默失败,或报 invalid character '}' looking for beginning of value;更隐蔽的是:字段看似存在,但值始终为零值(如空字符串、0、nil)。
- 正确写法:
Replicas int32 `json:"replicas,omitempty"` - 错误写法:
replicas int32(未导出)或Replicas int32(缺json标签) - 嵌套结构体也需同样处理,比如
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
Reconcile 函数里不能直接修改传入的 req.NamespacedName 对应的对象
传入的 ctx 和 req 是只读快照。直接改 myapp.Spec.Replicas++ 再 Update 会触发无限循环(因为变更触发下一次 Reconcile),还可能因对象版本冲突(ResourceVersion 不匹配)导致 Update 失败并卡住。
立即学习“go语言免费学习笔记(深入)”;
- 正确做法:用
Get重新拉取最新对象,深拷贝后修改,再用Update或Patch - 更安全推荐用
Patch(client.Patch+client.MergeFrom),避免读-改-写竞争 - 注意:不要在 Reconcile 中调用
time.Sleep做“等待”,应改用requeueAfter返回,否则阻塞整个 controller 线程
Operator 的核心复杂度不在代码量,而在于状态收敛逻辑是否覆盖所有边缘场景:节点宕机、etcd 网络分区、finalizer 阻塞、多 replica 下 leader 选举冲突……这些不会在本地 make run 里暴露,必须上真实集群跑 chaos 测试。别跳过 config/default/manager_auth_proxy_patch.yaml 这类权限配置,少一个 verbs: ["patch"] 就会让 Patch 操作静默失败。


















