K8s Service ClusterIP 不通但 Pod IP 直连正常:Readiness Probe 引发的诡异故障

1. 问题现象

  • 应用 A 通过 Service ClusterIP(10.96.x.x:8080)调用应用 B,持续报 connection refused 或超时
  • 直接 curl Pod IP(172.17.x.x:8080)却是通的
  • kubectl get svc 显示 Service 存在,CLUSTER-IP 正常分配
  • kubectl get endpoints 显示对应的 Endpoints 列表里有这个 Pod IP

2. 排查过程

Step 1 —— 确认 Pod 本身没问题

kubectl exec -it <pod-a> -- curl http://<pod-b-ip>:8080/health  # ✅ 200 OK

Pod 直接通信正常,排除应用层问题。

Step 2 —— 确认 Service 和 Endpoints

kubectl get svc app-b-svc -o yaml
kubectl get endpoints app-b-svc -o yaml

Endpoints 里 Pod IP 存在,说明 selector 匹配没问题。

Step 3 —— 检查 kube-proxy 规则

# iptables 模式
iptables-save | grep app-b-svc
# IPVS 模式
ipvsadm -Ln | grep <ClusterIP>

发现 iptables 规则存在,但 KUBE-SVC-xxx 链只配了 --probability 给旧 Pod IP,新 Pod 的 DNAT 规则缺失。

Step 4 —— 关键线索:kubectl describe ep

kubectl describe endpoints app-b-svc

输出:

Subsets:
  Addresses:          192.168.1.10
  NotReadyAddresses:  <empty>

但实际上 Pod B 有两个副本,新 Pod 的状态是 Running 但 Readiness gate 未就绪——这时候 Pod 不会出现在 Endpoints 的 Addresses 列表中,而旧 Pod 已经销毁了。

Step 5 —— 深挖 Readiness Probe

kubectl get pod app-b-xxx -o yaml | grep -A 10 readinessProbe

发现 readinessProbe 指向的 /actuator/health/readiness 返回 503——因为 Pod 启动后需要约 60s 加载配置,但探针 initialDelaySeconds 只设了 10s。

3. 根因

Readiness Probe 配置不当,导致 Pod 长时间处于 Running but NotReady 状态:

  1. 滚动更新时,新 Pod 启动慢,readiness 一直失败
  2. kube-proxy 不会将 NotReady 的 Pod 写入 iptables/IPVS 转发规则
  3. 旧 Pod 已被终止,但新 Pod 还没 Ready → Service 背后短时间内无可用 Endpoint
  4. 正好在这个窗口期,所有发往 Service ClusterIP 的请求全部失败

这解释了"诡异的矛盾"——Pod IP 直连通(Pod 在运行),但 ClusterIP 不通(kube-proxy 没有将流量转发到它)。

4. 解决方案

治本:调整探针参数

readinessProbe:
  httpGet:
    path: /actuator/health/readiness
    port: 8080
  initialDelaySeconds: 60   # 给足启动时间
  periodSeconds: 10
  failureThreshold: 5       # 容错 50s

治标:滚动更新加保护

strategy:
  type: RollingUpdate
  rollingUpdate:
    maxUnavailable: 0       # 确保至少有一个 Ready Pod
    maxSurge: 1             # 先启动新 Pod 再杀旧 Pod

监控补全

# PromQL 告警:Service Endpoint 数低于预期
count(kube_endpoint_address_available) by (endpoint) < 1

5. 复盘总结

  1. Pod Running ≠ 能接流量:Readiness Probe 是 Service 流量的唯一准入标准
  2. 启动慢的应用不能忽略 initialDelaySeconds:Java/Spring Boot 等重框架启动 30-60s 很常见
  3. 滚动更新 + 短探针 = 流量黑洞:新 Pod 被 kube-proxy 排除、旧 Pod 已销毁 → 无 Pod 可用
  4. 排查 ClusterIP 不通的优先步骤describe endpoints → 看 NotReadyAddresses → 查 Readiness Probe

应用场景:Kubernetes 1.26+、Java/Spring Boot 微服务

关键词:K8s Service、ClusterIP、Readiness Probe、kube-proxy、Endpoints、滚动更新

更多推荐