用 client-go 读取 ConfigMap 必须三步:先初始化 *rest.Config,再构造 clientset.Clientset,最后调用 CoreV1().ConfigMaps(namespace).Get();namespace 非空,Get() 第二参数须为 metav1.GetOptions{}。
必须先初始化 *rest.Config,再构造 clientset.Clientset,最后调用 CoreV1().ConfigMaps(namespace).Get()。跳过任一环节都会 panic 或返回 nil。
rest.InClusterConfig() 仅适用于 Pod 内运行;本地调试请用 rest.InClusterConfig() 替换为 clientcmd.BuildConfigFromFlags("", kubeconfigPath)
namespace)不能传空字符串,否则会报错 namespaces "" not found
Get() 第二个参数必须是 metav1.GetOptions{},不能传 nil(v0.28+ 版本已强制要求)cfg, err := rest.InClusterConfig()
if err != nil {
log.Fatal(err)
}
clientset, err := kubernetes.NewForConfig(cfg)
if err != nil {
log.Fatal(err)
}
cm, err := clientset.CoreV1().ConfigMaps("default").Get(context.TODO(), "my-config", metav1.GetOptions{})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Data keys: %v\n", maps.Keys(cm.Data))
常见原因是没传 ResourceVersion,或传了过期的值。Kubernetes 使用乐观并发控制,Update() 要求请求体中 ObjectMeta.ResourceVersion 与服务端当前一致。
cm.Data 后调用 Update() 前,必须保留原始 cm.ResourceVersion
Get() 一次再改再 Update(),不能靠缓存旧对象Apply()(需 v1.22+ + server-side apply)可绕过 ResourceVersion 校验,但需启用 serverSideApply 特性门不要手动遍历 cm.Data 映射赋值,容易漏字段、类型错配。推荐用 mapstructure.Decode() 或 envconfig.Process() 这类库做结构绑定。
mapstructure.Decode() 支持嵌套结构、类型转换、默认值(default:"xxx" tag)mapstructure:"key-name" tag 显式指定 key 名required:"true" tag 或手动校验type Config struct {
TimeoutSeconds int `mapstructure:"timeout-seconds"`
LogLevel string `mapstructure:"log-level" default:"info"`
}
var cfg Config
if err := mapstructure.Decode(cm.Data, &cfg); err != nil {
log.Fatal(err)
}
原生 Watch() 返回的 watch.Interface 不自动重连。一旦网络抖动或 apiserver 重启,watch 就静默终止,后续变更完全收不到。
err != nil 后 sleep + retry,同时记录上次收到的 resourceVers
ion
cache.NewInformer() 或 cache.NewSharedIndexInformer(),它们内置重试、reflector 和本地缓存ResyncPeriod 不是轮询间隔,而是强制触发全量同步的周期,不影响事件实时性