运维老鸟的排查笔记:当K8s服务访问不通时,我是如何顺着Service -> Endpoints -> Pod这条链‘抓虫’的 K8s服务访问故障排查实战从Service到Pod的逐层诊断手册当线上Kubernetes集群突然出现服务不可访问时那种头皮发麻的感觉每个运维都深有体会。上周三凌晨2点我正被手机警报惊醒——生产环境的核心支付服务突然返回502错误。本文将还原这次惊心动魄的排障过程展示如何像侦探破案一样沿着Service→Endpoints→Pod的链条揪出真凶。不同于教科书式的概念讲解这里只有血淋淋的实战经验和那些只有踩过坑才知道的细节。1. 第一现场Service层初步诊断接到报警后我第一时间检查了Service状态。很多人会直接kubectl get pods但这其实是错误的起点——在K8s架构中Service才是流量的第一入口。以下是关键诊断命令和对应分析# 查看问题Service的详细配置 kubectl describe svc payment-service -n finance输出中的几个致命字段需要特别关注Selector: apppayment,envprod Type: ClusterIP Port: 443/TCP TargetPort: 8443/TCP Endpoints: 10.244.1.23:8443,10.244.2.45:8443 Session Affinity: None发现疑点1Endpoints列表显示有两个Pod在服务但用户反馈完全无法连接。这提示我们需要深入检查Endpoints的真实状态。注意即使Endpoints显示有IP也不代表这些Pod真的健康。这是新手常犯的认知错误。此时应该立即核查Selector标签是否与Pod匹配常见拼写错误Service的targetPort是否与Pod监听端口一致是否存在NetworkPolicy阻断了流量2. 解剖Endpoints隐藏在表象下的真相Endpoints是Service和Pod之间的关键纽带也是排障中最容易被忽视的环节。执行以下命令查看详细端点信息kubectl get ep payment-service -n finance -o yaml健康状态下应该看到类似这样的输出subsets: - addresses: - ip: 10.244.1.23 nodeName: node-1 targetRef: kind: Pod name: payment-778b6c9465-2zx4z - ip: 10.244.2.45 nodeName: node-3 targetRef: kind: Pod name: payment-778b6c9465-v9lk9 ports: - port: 8443 protocol: TCP而我的实际输出却是subsets: - notReadyAddresses: - ip: 10.244.1.23 nodeName: node-1 targetRef: kind: Pod name: payment-778b6c9465-2zx4z - ip: 10.244.2.45 nodeName: node-3 targetRef: kind: Pod name: payment-778b6c9465-v9lk9 ports: - port: 8443 protocol: TCP致命发现所有Pod地址都被归类到notReadyAddresses下这意味着虽然Pod在运行但它们的就绪探针(Readiness Probe)检查失败K8s自动将其标记为不可用。这就是为什么Service看似正常但实际无法服务的原因。3. 深入Pod层揪出健康检查的元凶既然Endpoints显示Pod未就绪接下来需要检查Pod的具体状态kubectl get pods -n finance -l apppayment,envprod输出显示所有Pod都处于Running状态NAME READY STATUS RESTARTS AGE payment-778b6c9465-2zx4z 1/1 Running 0 3d payment-778b6c9465-v9lk9 1/1 Running 0 3d这看似矛盾的现象其实很常见——Pod进程在运行但应用内部可能已经死锁或无法响应健康检查。进一步查看Pod详情kubectl describe pod payment-778b6c9465-2zx4z -n finance在Events部分发现了关键线索Warning Unhealthy 3m (x12 over 8m) kubelet Readiness probe failed: HTTP probe failed with statuscode: 503根本原因应用的/healthz健康检查接口返回503错误。检查Pod日志后发现应用因数据库连接池耗尽而进入降级状态虽然主进程还在运行但已无法正常服务。4. 系统性修复与防御措施定位到根本原因后我们采取了以下紧急处理临时扩容Pod数量缓解压力kubectl scale deploy payment -n finance --replicas5调整就绪探针的失败阈值避免瞬时故障导致服务完全不可用readinessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 5 periodSeconds: 5 failureThreshold: 3 # 从默认1调整为3 successThreshold: 2增加HPA自动伸缩配置预防资源不足长期改进方案包括实现断路器模式避免级联故障优化数据库连接池管理配置更精细的PodDisruptionBudget5. 高级排障技巧与工具链在复杂场景下这些进阶方法能显著提升排障效率诊断工具组合# 检查Service的iptables规则适用于IPVS模式 iptables -t nat -L KUBE-SERVICES | grep payment # 使用临时Pod进行网络连通性测试 kubectl run -it --rm testpod --imagenicolaka/netshoot --restartNever -- curl http://payment-service:443常见陷阱对照表现象可能原因验证方法Endpoints为空Selector标签不匹配kubectl get pods --show-labelsPod在Endpoints但无法访问NetworkPolicy限制kubectl describe networkpolicy间歇性连接失败就绪探针配置过于敏感检查describe pod中的Events跨Namespace访问失败未使用完整域名(FQDN)尝试service.namespace.svc.cluster.local6. 构建预防性监控体系事后我们在监控系统中添加了这些关键指标告警Endpoints异常检测使用Prometheussum(kube_endpoint_address_not_ready{endpointpayment-service}) by (namespace, endpoint) 0就绪探针失败率告警rate(kubelet_probe_total{probe_typereadiness,resultfailed}[5m]) 0.1Service可用性黑盒监控- job_name: blackbox-http metrics_path: /probe params: module: [http_2xx] static_configs: - targets: - http://payment-service.finance.svc.cluster.local/healthz那次深夜故障让我深刻体会到K8s的抽象层在简化部署的同时也带来了新的复杂性。真正理解Service→Endpoints→Pod这条数据路径才能在危机来临时快速定位问题。现在我的团队已经养成了一个习惯——任何服务上线前必须用kubectl describe ep验证Endpoints状态这简单的一步就能避免50%的部署问题。