先记住这个答案
Service 通过 label selector 选定一组 Pod,Endpoints 控制器持续监听,将匹配且就绪的 Pod IP 写入 Endpoints/EndpointSlice。就绪探针决定 Pod 的就绪状态:配置了探针时,只有探针成功的 Pod 才会被纳入 Endpoints;未配置探针时,Running 的 Pod 默认就绪并被纳入。若探针由成功转为失败,则会被移除。kube-proxy 依据 Endpoints 生成转发规则,因此流量只达就绪 Pod。
- Service 流量只转发到 Endpoints 中标记就绪的 Pod
- 就绪探针失败会自动摘除对应 Pod 的 Endpoints 条目
- 未配置就绪探针时 Running 的 Pod 默认就绪并接收流量
从选择器到 Endpoints 的联动更新
Service 定义中的 selector 是入口。Endpoints 控制器(运行在 controller-manager)监听 Service 与 Pod 变化,找出满足标签匹配的 Pod。但匹配标签并不等于直接写入 Endpoints,控制器同时检查 Pod 的 status.conditions 中 Ready 是否为 True。若配置了就绪探针,探针结果决定该条件值:成功则为 True,失败则为 False;若未配置,Pod 在 Running 后默认 Ready 为 True。探针状态变化会触发 Endpoints 更新。因此,Endpoints 是从存活 Pod 中筛掉未就绪 Pod 后的最终转发名单。
转发层面,kube-proxy 监听 Endpoints(或 EndpointSlice)变化并生成 iptables/IPVS 规则。它只将规则指向这些就绪 Pod 的 IP。由于就绪探针失败会摘除对应 Endpoint,新连接便不再分配该 Pod。探针恢复后又重新加入,实现自动摘除和恢复。注意:就绪探针在容器启动后持续执行,与存活探针不同,它不影响进程重启,只影响流量接入。
滚动更新中探针延迟导致的流量中断案例
场景:一个 Deployment 运行 my-app,副本数为 3,Service 通过 app: my-app 选择 Pod。代码部署了新版本,就绪探针改为 HTTP 请求 /ready,服务端在启动前 15 秒内返回 500。由于探针失败,新 Pod 的 Ready 条件为 False,Endpoints 控制器不会把新 Pod IP 加入 Endpoints。旧 Pod 仍正常,流量全部留在旧版本,直到新 Pod 探针成功后替换。
若不配置就绪探针,Pod 一旦容器启动且 Running,Ready 即 True,Endpoints 会立即加入新 Pod。如果新版本启动期间尚未能处理请求,就会出现请求 5xx。因此就绪探针的关键作用是延迟放行流量,失败边界在探针初始延迟和容错设置上。本例中,通过观察 kubectl describe pod 中 Readiness 状态,可确认探针失败原因,并结合日志修复启动逻辑。
探针配置与选择器匹配的易错边界
边界一:Service 的 selector 与 Pod 标签必须精确匹配,但 Endpoints 还依赖 Pod 的 Ready 条件。若 Pod 标签匹配但未运行或处于 Terminating,同样不进入 Endpoints。另外,当 Service 没有 selector,而是手动管理 Endpoints 时,就绪探针就完全失效,因为控制器不参与。手动 Endpoints 需自行监控 Pod 健康。
边界二:就绪探针的 periodSeconds 和 failureThreshold 决定摘除速度。若探针间隔过长或失败阈值过大,Pod 已故障却仍可能接收流量,直到阈值触发。反之,探针过于敏感也会摘除尚可短时处理的 Pod。可运维判断:出现“Pod 出现部分失败但流量仍照常”时,先查看 kubectl get endpoints <svc> 中是否存在该 Pod IP,再核对 kubectl get pod 的就绪状态。
容易答错的地方
- 探针失败不会终止容器
- 就绪探针失败时,kubelet 不会重启容器,只将该 Pod 标记为未就绪,并从 Service Endpoints 摘除。很多人误以为就绪探针用来重启不可用容器,实际重启应由存活探针(livenessProbe)负责。
- 未配置探针就不会有健康检查
- 实际上,只要容器进程启动且未崩溃,Pod 就会变为 Running 并自动 Ready,无需探针。但缺少就绪探针时,容器即使不能处理请求(如依赖未就绪),也会接收流量。所以默认行为是“无探针视为就绪”。
面试官还会怎么问?
Endpoints 和 EndpointSlice 有什么区别?
EndpointSlice 是新一代 API,可表示同一 Service 的部分端点,支持大规模集群。Endpoints 是旧版,限制 1000 个端点,超出会截断。它们分别由 EndpointSlice 控制器和 Endpoints 控制器维护,内容一致,只是分片方式不同。
就绪探针在启动失败时为何不立即摘除?
就绪探针受 initialDelaySeconds 和 periodSeconds 控制,首次检查在延迟后才开始,失败需连续 failureThreshold 次才变为 False。因此短时失败不会立即摘除,避免抖动。
手动创建 Endpoints 时还能用就绪探针吗?
不能。手动定义 Endpoints 后,Endpoints 控制器不会覆盖它,但也不会自动加入就绪 Pod。就绪探针只作用于由 Service 选择器自动生成的 Endpoints。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。