基于本文回答
0
评论

如何排查一个 Service 无法访问的问题?(请描述排查思路)

知识点图片

排查 Kubernetes 中 Service 无法访问的问题,通常遵循 “从配置到后端,从内网到外网,从应用层到网络层” 的逻辑。

我们可以将排查思路想象成数据包的流向,一步步验证断点在哪里。以下是详细的排查步骤和思路:


核心排查路径图

Client -> DNS (CoreDNS) -> Service IP (ClusterIP) -> Kube-proxy (iptables/ipvs) -> Pod IP -> Container App


第一步:检查 Service 和 Endpoints(最常见问题)

思路: 首先确认 Service 是否正确关联到了后端的 Pod。如果 Service 找不到目标 Pod,流量自然无法转发。

  1. 查看 Service 状态:

    bash
    kubectl get svc <service-name> -n <namespace>
    • 确认 Service 是否存在。
    • 确认 CLUSTER-IP 是否已分配。
    • 确认 PORT(Service 暴露端口)和 TARGET-PORT(容器端口)定义是否符合预期。
  2. 检查 Endpoints(关键步骤):

    bash
    kubectl get endpoints <service-name> -n <namespace>
    • 正常情况: ENDPOINTS 列应该显示一个或多个 <PodIP>:<Port>
    • 异常情况: 如果显示 <none>,说明 Service 没有匹配到任何 Pod。
    • 原因排查:
      • 检查 Service 的 Selector(标签选择器)是否与 Pod 的 Labels 完全匹配。
      • 检查 Pod 是否处于 Running 状态(未就绪的 Pod 不会被加入 Endpoints)。
      • 检查 Pod 的 readinessProbe(就绪探针)是否失败。

第二步:检查后端 Pod 的健康状况

思路: 如果 Endpoints 正常,说明 K8s 认为后端有 Pod,但 Pod 本身可能无法处理请求。

  1. 直接访问 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 本身有问题,或者容器网络有问题。
  2. 检查 Pod 内部:

    • 应用监听端口: 确认容器内的应用是否真的监听在 targetPort 上(例如配置成了 8080,但应用监听 80)。
    • 应用日志: kubectl logs <pod-name> 查看是否有报错或崩溃。
    • 本地回环: kubectl exec 进入容器,尝试 curl localhost:<port>

第三步:检查 DNS 解析(如果是通过域名访问)

思路: 很多时候 IP 能通,但域名不通,这是 CoreDNS 的问题。

  1. 测试 DNS 解析:
    进入一个测试 Pod:
    bash
    nslookup <service-name>.<namespace>.svc.cluster.local
    • 如果无法解析: 检查 CoreDNS Pod 是否正常运行 (kubectl get pods -n kube-system -l k8s-app=kube-dns),或者检查 /etc/resolv.conf 配置。
    • 如果解析出的 IP 错误: 可能是 DNS 缓存或记录更新延迟。

第四步:检查 Service 网络层 (Kube-proxy/CNI)

思路: 如果 Pod 正常,DNS 正常,但访问 ClusterIP 不通,通常是节点上的流量转发规则(iptables/ipvs)或 CNI 插件的问题。

  1. 测试 ClusterIP 连通性:

    bash
    curl <Cluster-IP>:<Service-Port>

    如果超时或拒绝连接:

    • 检查 Kube-proxy: 确保每个节点上的 kube-proxy 正在运行且无报错。
    • 检查协议: 确认 Service 定义的协议(TCP/UDP)与应用一致。
  2. 检查网络策略 (NetworkPolicy):

    • 集群中是否配置了 NetworkPolicy?默认情况下 K8s 允许所有通信,但如果定义了策略,可能会拒绝特定 Namespace 或 Pod 的入站/出站流量。
  3. 节点级排查 (进阶):

    • 登录到节点,查看 iptables-save | grep <service-name>ipvsadm -ln,确认是否有对应的转发规则生成。

第五步:如果是从集群外部无法访问 (NodePort/LoadBalancer/Ingress)

思路: 内部正常,外部不通,问题在边缘入口。

  1. NodePort 模式:

    • 检查节点防火墙(Firewalld/UFW/Security Group)是否放行了该 NodePort 端口(默认 30000-32767)。
    • 检查是否监听:netstat -tpln | grep <node-port>
  2. LoadBalancer 模式:

    • 检查云厂商的负载均衡器状态(AWS/GCP/Aliyun 控制台)。
    • 检查 kubectl describe svc 中的 Events,看是否有分配 LB IP 失败的报错。
  3. Ingress 模式:

    • 检查 Ingress Controller 的 Pod 日志。
    • 检查 Ingress 规则(Host/Path)是否配置正确。
    • 检查 Ingress 后端 Service 端口是否匹配。

总结排查清单 (Checklist)

  1. Service 有 IP 吗? (kubectl get svc)
  2. Service 有 Endpoints 吗? (kubectl get ep) -> 最常见 (标签不匹配/Pod未就绪)。
  3. Pod 本身能通吗? (直接 curl Pod IP)。
  4. 容器端口监听对了吗? (targetPort vs 实际监听端口)。
  5. DNS 解析对吗? (nslookup)。
  6. 防火墙/NetworkPolicy 拦了吗?

通过以上步骤,通常能定位 99% 的 Service 访问问题。

右滑查看面试常问