Kubernetes Service 没有可用后端:核对 Pod 标签与 EndpointSlice 就绪状态
Service 端口没错却没有可用后端,先对照实际 Pod 标签与 namespace,再检查 EndpointSlice 就绪条件和目标监听端口。
Pod 看起来在运行,Service 却没有可用后端,访问失败,旧版 kube-proxy 日志还可能出现 Couldn't find an endpoint。端口号相同,并不能让 Service 自动找到一个 Pod;对带选择器的 Service,应先检查标签匹配,再检查匹配 Pod 是否就绪。
本文针对通过 .spec.selector 自动选择 Pod 的普通 Service。没有选择器、ExternalName 或手动管理端点的 Service 有自己的连接方式,不应按“选择器缺了标签”处理。
名称相同不等于标签相同
以下命令为只读检查示例。替换命名空间、Service 名称与实际选择条件:
kubectl get service example-api -n team-app -o yaml
kubectl get pods -n team-app --show-labels
kubectl get pods -n team-app -l 'app=example-api,component=api'
最后一条应复现 Service 中的全部选择条件。没有结果时,先检查拼写、标签值与 namespace;不要把 Deployment 的 metadata.name 当成 Pod 标签。Service 选择的是同命名空间中符合条件的 Pod。
假设 Service 配置如下:
spec:
selector:
app: example-api
component: api
Pod 必须同时带有 app=example-api 和 component=api。只匹配一个键不会成为所需后端。应该修改 Service 的选择范围,还是修改 Deployment 的 Pod 模板标签,取决于应用原设计;不能删掉所有限定条件,让流量意外送到其他版本或其他应用。
保存原清单后再调整。模板标签变更可能触发 rollout,Service 选择器变更则会改变流量目标;先核对预期 Pod 与可用性,失败时恢复原配置与发布版本。
有匹配 Pod,还要查看端点的条件
现代 Kubernetes 可查看 EndpointSlice,不必依赖旧 Endpoints 对象:
kubectl get endpointslice -n team-app -l kubernetes.io/service-name=example-api -o yaml
核对地址、端口和 conditions。ready: false 表明该端点不能按普通就绪后端使用,继续查看对应 Pod 的 Ready 条件和事件:
kubectl describe pod example-api-abc123 -n team-app
容器处于 Running 不等于 Pod 已 Ready。就绪探针失败、初始化尚未完成、容器异常等情况,需要按实际事件处理。修正探针的路径、端口或前提,不能只为了出现地址而取消所有就绪检查。
EndpointSlice 有地址也不意味着每个地址都可正常接收新流量。还要结合 serving、terminating、Service 的 publishNotReadyAddresses 和具体代理实现判断;开启发布未就绪地址会改变语义,不是普通网站绕过故障的办法。
旧集群可使用对应版本支持的端点检查方式,但不要把早期日志或对象结构直接套进当前集群。
后端正确时,再沿端口和访问路径排查
若已经有预期的就绪后端,核对 Service 的 targetPort 是否指向应用实际监听端口。声明 containerPort 不会替应用启动监听,名称端口也必须能在目标 Pod 中正确解析。
然后区分 Service 内部访问、NodePort、Ingress 和外部负载均衡哪一层失败。端点正确仍连接拒绝时,应查看应用监听地址、网络策略与相应访问层,不要继续扩大标签选择范围。
修复的标准是:Service 选择的确为预期 Pod,EndpointSlice 中的地址和端口正确,就绪状态符合设计,应用原来的访问入口恢复。保留这几个检查结果,才能区分“后端已找到”与“流量真的已通”。


