直接调用create()创建pod后,若未设置spec.nodename则进入pending等待调度器绑定;设为具体节点名可绕过调度器实现静态绑定,但需确保节点存在且无不可容忍污点;非控制器管理的pod应设restartpolicy为never或onfailure。

如何用 Go 创建 Pod 而不触发默认调度器
直接调用 Create() 创建 Pod 后,它会进入 Pending 状态,但不会自动被 kube-scheduler 绑定到节点——除非你显式设置 spec.nodeName 或留空让调度器接管。很多初学者误以为“创建就等于运行”,结果卡在 Pending 且无日志可查。
关键点在于:Pod 的调度行为由 spec.nodeName 字段控制:
- 留空(
"")→ 交给 kube-scheduler,需确保集群有可用节点、资源充足、亲和性/污点匹配 - 填入具体节点名(如
"node-1")→ 绕过调度器,直接绑定(称为“static binding”),但要求该节点存在且未打不可容忍污点 - 填错节点名或节点不可达 → Pod 永远卡在
Pending,kubectl describe pod会显示FailedScheduling或NodeNotReady
示例中常忽略 spec.RestartPolicy,默认是 Always,但对非控制器管理的 Pod(如直接创建的单 Pod),应设为 Never 或 OnFailure,否则容器退出后会被反复重启却无法重建。
为什么 List/Get Pod 时经常拿不到最新状态
List() 和 Get() 返回的是服务端缓存快照,不是实时数据。尤其在高并发或快速变更场景下,你刚 Create() 完一个 Pod,立刻 Get() 可能还看不到 Status.Phase 更新为 Running,因为 status 更新有延迟,且 client-go 默认不强制刷新。
解决办法不是轮询加 sleep,而是用 watch:
- 用
Watch()监听事件流,过滤ADDED/MODIFIED类型,等Status.Phase == "Running"再继续 - Watch 的
ResourceVersion参数决定从哪条变更开始监听;设为""表示从当前最新开始 - 注意 Watch 连接可能断开,需实现重连逻辑,不要依赖单次调用
别用 time.Sleep(2 * time.Second) 硬等——这在 CI 或多租户环境极不可靠,节点负载高时 status 更新可能延迟数秒甚至更久。
Update 和 Patch Pod 时哪些字段允许修改
Pod 是不可变对象,绝大多数字段一旦创建就不能改。Kubernetes API 明确拒绝修改以下字段,返回 422 Unprocessable Entity 错误:
-
spec.containers[*].image(镜像名)——想换镜像?删了重建,或用 Deployment 管理 -
spec.restartPolicy、spec.serviceAccountName、spec.nodeName(已绑定后不可改) -
spec.volumes中已挂载的卷配置(如hostPath路径、configMap名称)
真正能安全 Patch 的字段极少,常见且安全的只有:
-
metadata.labels和metadata.annotations(推荐用StrategicMergePatchType) -
spec.activeDeadlineSeconds(仅限批处理类 Pod) -
spec.tolerations(动态加容忍,配合污点使用)
用 clientset.CoreV1().Pods(ns).Update() 强行提交全量 spec 修改,大概率失败;应优先考虑是否真需要改 Pod,还是该用更高层抽象(如 Deployment)来间接更新。
删除 Pod 时如何避免“删了又自动出来”
直接 Delete() 一个由 Deployment、StatefulSet 等控制器管理的 Pod,它会在几秒内被控制器自动重建——这不是 bug,是 Kubernetes 的设计本意。你看到的“删不掉”,其实是控制器在履行职责。
- 确认 Pod 是否受控制器管理:看
metadata.ownerReferences,若有controller: true的Deployment或ReplicaSet条目,就别直接删 Pod - 要真正停掉实例,应缩容控制器:
clientset.AppsV1().Deployments(ns).Patch(..., types.StrategicMergePatchType, []byte{"spec":{"replicas":2}}) - 如确需绕过控制器临时删 Pod(如调试),加
PropagationPolicy参数:metav1.DeletePropagationBackground或Foreground,但不会影响控制器后续行为
最易被忽略的一点:即使你删掉了所有 Pod,只要控制器的 replicas > 0,它就会立刻拉起新 Pod。真正的“停止服务”,永远发生在控制器层面,而非 Pod 层面。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











