Administrator
Administrator
发布于 2026-10-28 / 0 阅读
0
0

Kubernetes 故障排查(09):Service 访问失败:先查后端选择,再查端口和数据路径

面向初级运维,使用 Linux 节点和稳定 Kubernetes API。命令按 Bash 编写。本文为教学故障场景,日志及结果为示意,不冒充生产实测;执行前确认 context、命名空间和权限。

一、遭遇情况:Pod 明明正常,访问 Service 却失败

应用 Pod Ready,容器日志也正常,但同命名空间客户端请求 Service 超时或连接失败。有人准备重启 kube-proxy,实际可能只是 Service selector 写错。

本篇场景是 Pod 标签为 app: web,Service 却选择 app: web-typo。Service 对象创建成功,也分配到 ClusterIP,但没有匹配的业务后端。

二、原因分析:Service 对象存在,不代表流量有落点

带 selector 的 Service 根据命名空间内匹配的 Pod 形成后端,EndpointSlice 表达这些端点及条件。Pod 存在、标签匹配、端点就绪和目标端口正确,缺一项都可能影响访问。

Service 从请求到应用的排查链路

port 是访问 Service 使用的端口,targetPort 指向后端应用端口;containerPort 是声明信息,不会替应用自动启动监听。不要把这三个字段当作同一个“端口号”。

三、排查思路:先验证应用,再验证抽象层

kubectl get pods -n 目标命名空间 -o wide --show-labels
kubectl get service 目标服务 -n 目标命名空间 -o yaml
kubectl get endpointslice -n 目标命名空间 -l kubernetes.io/service-name=目标服务 -o yaml

把占位名称替换为实际值。核对 Service selector 与 Pod 标签是否一字不差;EndpointSlice 不只看 IP,还要看 ready 等条件、端口与目标对象。常规业务应优先检查 EndpointSlice,不把旧 Endpoints 输出当作唯一依据。

在同一类客户端环境中比较 Pod IP 与 Service 名/IP:直接 Pod 也失败,先看应用、CNI 或策略;Pod 成功而 Service 失败,再查选择、端口和数据路径。ClusterIP 通常从集群内部访问,不要用外部电脑直接访问失败作为唯一证据。

四、实践:一个 selector 拼错的最小服务

保存为 kt09-service.yaml:

apiVersion: v1
kind: Namespace
metadata:
  name: kt09
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: kt09
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:stable-alpine
          ports:
            - name: http
              containerPort: 80
          readinessProbe:
            httpGet:
              path: /
              port: http
---
apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: kt09
spec:
  selector:
    app: web-typo
  ports:
    - name: http
      port: 80
      targetPort: http
kubectl apply -f kt09-service.yaml
kubectl rollout status deployment/web -n kt09 --timeout=120s
kubectl run client -n kt09 --image=busybox:1.37 --restart=Never --command -- sleep 3600
kubectl wait --for=condition=Ready pod/client -n kt09 --timeout=120s
kubectl get endpointslice -n kt09 -l kubernetes.io/service-name=web -o yaml
kubectl exec client -n kt09 -- wget -T 3 -qO- http://web:80/

预期 Service 没有匹配的可用后端,请求失败,具体失败方式由集群网络实现决定。再直接请求实际 Web Pod:

pod_ip=$(kubectl get pod -n kt09 -l app=web -o jsonpath='{.items[0].status.podIP}')
kubectl exec client -n kt09 -- wget -T 3 -qO- "http://$pod_ip:80/"

若基础网络及策略允许,直接请求应返回 Nginx 页面,这将故障进一步限定在 Service 相关层。

五、修复实践:只修错误选择器

kubectl patch service web -n kt09 --type=merge -p '{"spec":{"selector":{"app":"web"}}}'
kubectl get endpointslice -n kt09 -l kubernetes.io/service-name=web -o yaml
kubectl exec client -n kt09 -- wget -T 3 -qO- http://web:80/

预期匹配到 Ready 的 Web 后端,并获得页面响应。控制器更新需要时间,刚打完补丁仍失败时应观察端点是否已经更新,不必立即重启整个网络组件。

如果后端存在而访问失败,再核对 targetPort、应用监听、NetworkPolicy,以及 kube-proxy 或集群采用的其他 Service 数据面。不是所有集群都用同一套 iptables 规则,不要直接套用清空规则的命令。

六、port-forward 为什么可能让人误判

kubectl port-forward service/web 本机端口:服务端口 会选择关联 Pod 建立诊断转发,不等于从客户端经过 ClusterIP 的完整路径。因此 port-forward 成功,能支持“某个后端应用可响应”,不能单独证明 Service VIP 转发正常。

七、验证与总结

在故障原来的客户端条件下,再验证 Service 名、ClusterIP 与业务响应。确认新 Pod 扩缩容后端仍正确,修复也已写回部署源文件。

这类故障应从应用、selector、端点条件和端口逐层走向数据面。先证明配置链路完整,再怀疑集群组件,往往能避免影响全局的误操作。

官方参考


上一篇 · 系列目录 · 下一篇


评论