Create()必须同时指定Name和Namespace,Name需符合DNS-1123标准,Namespace不可为空或"";Update()必须基于Get获取的ResourceVersion进行乐观并发更新。

Create() 必须同时指定 Name 和 Namespace
client-go 的 Create() 方法对 Service、Deployment、StatefulSet 等资源校验严格:如果 ObjectMeta.Name 或 ObjectMeta.Namespace 为空,会直接报错 Service "xxx" is invalid: metadata.name: Required value 或类似提示。
常见错误是传入空字符串 "" 作为 Namespace —— 这不等价于 default,Kubernetes 不会自动 fallback。显式写 "default" 或从环境变量读取才是安全做法。
- Namespace 字段不能省略,也不能为
"";clientset.CoreV1().Services("").Create()一定失败 - Name 必须符合 DNS-1123 标准(小写字母、数字、连字符,且不能以连字符开头或结尾)
- 若在集群内运行(如 Pod 中),用
rest.InClusterConfig();本地调试务必用clientcmd.BuildConfigFromFlags("", "/path/to/kubeconfig")并确认 kubeconfig 有效
Update() 必须带 ResourceVersion,否则 409 Conflict
Update() 不是“覆盖式更新”,而是乐观并发控制:API Server 会比对请求体中的 ResourceVersion 和当前对象的版本。不带或版本过期,就返回 409 Conflict。
正确做法永远是先 Get() 拿到最新对象(含 ResourceVersion),再修改字段,最后 Update()。不要自己构造新对象并硬编码 ResourceVersion: "0" —— 那只会让第一次 Update 就失败。
立即学习“go语言免费学习笔记(深入)”;
- 仅想改
spec.ports或spec.selector?直接改原对象字段即可,别重置整个spec,否则可能意外清空clusterIP或type - 批量更新多个字段时,注意
metadata.labels和metadata.annotations是 map 类型,需判空再赋值,避免 nil pointer panic - 如果只是打 patch(比如只增删 annotation),用
Patch()+types.StrategicMergePatchType更轻量、更安全
StatefulSet 创建时 ServiceName 字段不可省略
StatefulSet 的 Spec.ServiceName 是强制字段,哪怕你后续手动创建同名 Service,也必须在 StatefulSet 对象里显式声明。漏写会导致 Pod 启动失败,事件中出现 failed to find Headless Service。
这个字段不是用来“创建” Service 的,而是告诉 StatefulSet:“请把 Pod 的 DNS 记录挂在这个 Service 下”。它必须指向一个已存在的、ClusterIP: None 的 Headless Service。
- Service 必须提前存在,且
spec.clusterIP设为"None",否则 StatefulSet 控制器拒绝绑定 - Service 的
selector必须精确匹配 StatefulSet 的spec.selector.matchLabels,否则 Endpoint 不会注入 - Pod 名称格式为
${statefulset-name}-${index},DNS 可解析为${pod-name}.${service-name}.${namespace}.svc.cluster.local
Watch endpoints 要处理 clusterIP 延迟就绪问题
新建 Service 后立刻 Watch() 其 Endpoints,常发现 Subsets 为空——这不是代码 bug,而是 kube-proxy 规则同步有延迟(尤其在大规模集群或低配节点上)。
不要在 Watch 回调里假设 Endpoints.Subsets 立即非空;更稳妥的做法是结合 List() + 轮询,或监听 Service 的 Status 变化(但 Status.LoadBalancer.Ingress 对 ClusterIP 类型无意义)。
- 若依赖 Endpoints 做服务发现,建议加 1–3 秒初始等待,再开始 Watch
- Watch 的
context.Context必须可控超时或取消,避免 goroutine 泄漏 - Endpoints 不是 CRD,不能用 DynamicClient;必须用
clientset.CoreV1().Endpoints(namespace)


















