如何排查一个 Service 无法访问的问题?(请描述排查思路)
排查 Kubernetes 中 Service 无法访问的问题,通常遵循 “从配置到后端,从内网到外网,从应用层到网络层” 的逻辑。
我们可以将排查思路想象成数据包的流向,一步步验证断点在哪里。以下是详细的排查步骤和思路:
核心排查路径图
Client -> DNS (CoreDNS) -> Service IP (ClusterIP) -> Kube-proxy (iptables/ipvs) -> Pod IP -> Container App
第一步:检查 Service 和 Endpoints(最常见问题)
思路: 首先确认 Service 是否正确关联到了后端的 Pod。如果 Service 找不到目标 Pod,流量自然无法转发。
查看 Service 状态:
bashkubectl get svc <service-name> -n <namespace>- 确认 Service 是否存在。
- 确认
CLUSTER-IP是否已分配。 - 确认
PORT(Service 暴露端口)和TARGET-PORT(容器端口)定义是否符合预期。
检查 Endpoints(关键步骤):
bashkubectl get endpoints <service-name> -n <namespace>- 正常情况:
ENDPOINTS列应该显示一个或多个<PodIP>:<Port>。 - 异常情况: 如果显示
<none>,说明 Service 没有匹配到任何 Pod。 - 原因排查:
- 检查 Service 的
Selector(标签选择器)是否与 Pod 的Labels完全匹配。 - 检查 Pod 是否处于
Running状态(未就绪的 Pod 不会被加入 Endpoints)。 - 检查 Pod 的
readinessProbe(就绪探针)是否失败。
- 检查 Service 的
- 正常情况:
第二步:检查后端 Pod 的健康状况
思路: 如果 Endpoints 正常,说明 K8s 认为后端有 Pod,但 Pod 本身可能无法处理请求。
直接访问 Pod IP:
绕过 Service,直接从集群内的另一个 Pod(如 debug pod)尝试访问目标 Pod 的 IP 和端口。bash# 在集群内找个临时容器测试 kubectl run -it --rm debug --image=curlimages/curl -- sh curl <Pod-IP>:<Container-Port>- 如果通: 说明 Pod 正常,问题出在 Service 层(Kube-proxy/IPVS/DNS)。
- 如果不通: 说明 Pod 本身有问题,或者容器网络有问题。
检查 Pod 内部:
- 应用监听端口: 确认容器内的应用是否真的监听在
targetPort上(例如配置成了 8080,但应用监听 80)。 - 应用日志:
kubectl logs <pod-name>查看是否有报错或崩溃。 - 本地回环:
kubectl exec进入容器,尝试curl localhost:<port>。
- 应用监听端口: 确认容器内的应用是否真的监听在
第三步:检查 DNS 解析(如果是通过域名访问)
思路: 很多时候 IP 能通,但域名不通,这是 CoreDNS 的问题。
- 测试 DNS 解析:
进入一个测试 Pod:bashnslookup <service-name>.<namespace>.svc.cluster.local- 如果无法解析: 检查 CoreDNS Pod 是否正常运行 (
kubectl get pods -n kube-system -l k8s-app=kube-dns),或者检查/etc/resolv.conf配置。 - 如果解析出的 IP 错误: 可能是 DNS 缓存或记录更新延迟。
- 如果无法解析: 检查 CoreDNS Pod 是否正常运行 (
第四步:检查 Service 网络层 (Kube-proxy/CNI)
思路: 如果 Pod 正常,DNS 正常,但访问 ClusterIP 不通,通常是节点上的流量转发规则(iptables/ipvs)或 CNI 插件的问题。
测试 ClusterIP 连通性:
bashcurl <Cluster-IP>:<Service-Port>如果超时或拒绝连接:
- 检查 Kube-proxy: 确保每个节点上的
kube-proxy正在运行且无报错。 - 检查协议: 确认 Service 定义的协议(TCP/UDP)与应用一致。
- 检查 Kube-proxy: 确保每个节点上的
检查网络策略 (NetworkPolicy):
- 集群中是否配置了
NetworkPolicy?默认情况下 K8s 允许所有通信,但如果定义了策略,可能会拒绝特定 Namespace 或 Pod 的入站/出站流量。
- 集群中是否配置了
节点级排查 (进阶):
- 登录到节点,查看
iptables-save | grep <service-name>或ipvsadm -ln,确认是否有对应的转发规则生成。
- 登录到节点,查看
第五步:如果是从集群外部无法访问 (NodePort/LoadBalancer/Ingress)
思路: 内部正常,外部不通,问题在边缘入口。
NodePort 模式:
- 检查节点防火墙(Firewalld/UFW/Security Group)是否放行了该 NodePort 端口(默认 30000-32767)。
- 检查是否监听:
netstat -tpln | grep <node-port>。
LoadBalancer 模式:
- 检查云厂商的负载均衡器状态(AWS/GCP/Aliyun 控制台)。
- 检查
kubectl describe svc中的 Events,看是否有分配 LB IP 失败的报错。
Ingress 模式:
- 检查 Ingress Controller 的 Pod 日志。
- 检查 Ingress 规则(Host/Path)是否配置正确。
- 检查 Ingress 后端 Service 端口是否匹配。
总结排查清单 (Checklist)
- Service 有 IP 吗? (
kubectl get svc) - Service 有 Endpoints 吗? (
kubectl get ep) -> 最常见 (标签不匹配/Pod未就绪)。 - Pod 本身能通吗? (直接 curl Pod IP)。
- 容器端口监听对了吗? (targetPort vs 实际监听端口)。
- DNS 解析对吗? (
nslookup)。 - 防火墙/NetworkPolicy 拦了吗?
通过以上步骤,通常能定位 99% 的 Service 访问问题。
右滑查看面试常问