client-go 初始化失败主因是认证凭据缺失或权限不足:本地需检查 kubectl config,pod 中应使用 rest.inclusterconfig() 读取 serviceaccount 凭据,并确保 serviceaccount 绑定含明确 resources/verbs 的 role/clusterrole。

client-go 初始化失败:证书或 Token 权限不足
初始化 rest.Config 时卡住、报 x509: certificate signed by unknown authority 或 Forbidden: User "system:anonymous" cannot list ...,基本是认证没过。不是代码写错了,而是 client-go 没拿到有效凭据。
- 本地用
kubectl config current-context确认当前上下文,再用kubectl config view --minify --flatten检查是否含user和对应client-certificate-data/token - 在 Pod 里运行时,别手动构造 Config——直接用
rest.InClusterConfig(),它会自动读取/var/run/secrets/kubernetes.io/serviceaccount/下的ca.crt和token - 如果用 ServiceAccount,确保它绑了对应 Role/ClusterRole;
rbac.authorization.k8s.io/v1的rules必须显式声明resources(比如["pods"])和verbs(比如["get", "list"]),空数组或*不生效
List/Watch 卡住或漏事件:Informer 启动顺序不对
调用 cache.NewSharedIndexInformer 后没等 HasSynced() 就开始查缓存,或者忘记调 Run(),结果永远拿不到数据。Informer 不是“配置完就自动工作”的黑盒。
- 必须先调
informer.Run(stopCh)启动监听协程,再用cache.WaitForCacheSync(stopCh, informer.HasSynced)等首次同步完成,否则缓存为空 - 不要在
Run()前调informer.GetIndexer().List()——返回空切片,且不报错 - Watch 默认只推增量事件,但 Informer 内部缓存是全量快照;如果需要实时强一致,别依赖缓存,直接走
clientset.CoreV1().Pods(ns).Get(),代价是绕过本地缓存、多一次 API Server 请求
更新资源时版本冲突(409 Conflict):没处理 ResourceVersion
用 clientset.CoreV1().Pods(ns).Update() 直接改对象再提交,大概率遇到 Operation cannot be fulfilled on pods "...": the object has been modified; please apply your changes to the latest version and try again。Kubernetes 要求乐观并发控制。
- 所有 Update 操作必须基于最新
ResourceVersion;从 List/Get 返回的对象自带该字段,直接改完传回去即可 - 如果只是想“确保某字段是 X”,别用 Get→改→Update 三步——改用
Patch(),类型选types.StrategicMergePatchType,发更小 payload,也避开版本竞争 - 注意:Patch 的 JSONPath 或原生 struct 字段名要和 OpenAPI spec 严格一致,比如
spec.containers[0].image,写成spec.container[0].image(少个 s)就静默失败
自定义资源(CRD)操作报 NotFound:Scheme 没注册
用 dynamic.Client 或 typed Client 访问 CRD 时,报 no kind "MyResource" is registered for version "mygroup.example.com/v1",不是 API Server 没装 CRD,而是 client-go 不认识这个类型。
立即学习“go语言免费学习笔记(深入)”;
- 用
dynamic.Client时,不用注册类型,但得确认 GroupVersion 是服务端实际暴露的(kubectl api-resources | grep mygroup查),且命名空间路径拼对:/apis/mygroup.example.com/v1/namespaces/{ns}/myresources - 用 typed client(如 kubebuilder 生成的)时,必须在
scheme.AddToScheme(scheme.Scheme)里显式调用 CRD 的AddToScheme函数,漏掉这句,Scheme 就不知道怎么序列化/反序列化你的结构体 - 如果混用多个 CRD,别反复调
AddToScheme——它不是幂等的,重复注册会 panic
ResourceVersion 和 Scheme 注册这两处,不报编译错、不抛 panic,但一跑就静默失效,最容易拖到上线后才暴露。










