容器间互通异常如何排查

wen IT资讯 32

本文目录导读:

容器间互通异常如何排查

  1. 第一阶段:确认基础网络连通性
  2. 第二阶段:检查 DNS 解析(Service 通信)
  3. 第三阶段:检查网络策略(NetworkPolicy)
  4. 第四阶段:检查防火墙与安全组(云环境/物理机)
  5. 第五阶段:检查 CNI 插件(Kubernetes 网络插件)
  6. 第六阶段:应用层与服务监听
  7. 第七阶段:特殊场景排查
  8. 总结快速排查流程图

容器间互通异常是 Kubernetes 及 Docker 环境中非常常见的问题,排查思路通常遵循 “从外到内,逐层剥离” 的原则:先看网络层,再看策略层,最后看应用层。

以下是一套系统化的排查步骤和常用命令:

第一阶段:确认基础网络连通性

确认容器是否在同一个网络栈

  • 场景: 两个容器在同一个 Pod 中(共享网络命名空间)。

    • 排查: 直接使用 localhost 通信,如果不行,检查容器内服务是否监听在 0.0.1 而非 0.0.0
    • 命令:
      # 进入 Pod 中的一个容器
      kubectl exec -it <pod-name> -c <container-1> -- sh
      # 尝试访问另一个容器的端口(使用 localhost)
      curl localhost:<port>
  • 场景: 两个容器在不同 Pod 中(通过 Service 或 Pod IP 通信)。

    • 排查: 确认 Pod IP 是否可达。
    • 命令:
      # 获取目标 Pod IP
      kubectl get pod <target-pod> -o wide
      # 从源 Pod 尝试 ping 目标 Pod IP(很多镜像默认无 ping 命令,可用 telnet 或 curl)
      kubectl exec -it <source-pod> -- ping <target-pod-ip>
      kubectl exec -it <source-pod> -- curl -v <target-pod-ip>:<port>

使用 kubectl run 创建一个临时调试 Pod

如果你的业务容器里没有 pingcurltelnetnc 等工具(比如基于 scratchdistroless 镜像),这是最有效的方法。

# 创建一个网络调试工具 Pod(如 nicolaka/netshoot)
kubectl run tmp-shell --rm -it --image nicolaka/netshoot -- /bin/bash
# 在调试 Pod 中测试与目标 Pod 的连通性
curl http://<service-name>.<namespace>.svc.cluster.local:<port>
ping <target-pod-ip>
nslookup <service-name>

第二阶段:检查 DNS 解析(Service 通信)

如果使用 Service 名称(而非 Pod IP)通信,DNS 问题是常见原因。

  • 排查点: 域名能否解析?解析出的 Cluster IP 是否正确?

  • 命令:

    # 在任意 Pod 内
    nslookup <service-name>.<namespace>.svc.cluster.local
    # nslookup 不可用,尝试
    host <service-name>
    cat /etc/resolv.conf  # 确认 nameserver 指向正确的 DNS Pod(通常是 kube-dns 的 Cluster IP)
  • 可能原因:

    • DNS Pod 宕机(kubectl get pods -n kube-system | grep dns)。
    • Pod 的 dnsPolicy 设置错误(如 DefaultNone)。
    • CoreDNS 配置问题。

第三阶段:检查网络策略(NetworkPolicy)

这是 Kubernetes 中最容易忽略的“隐形防火墙”。

  • 排查点: 是否有 NetworkPolicy 限制了源 Pod 或命名空间访问目标 Pod 的端口。

  • 命令:

    # 查看目标 Pod 所在命名空间的 NetworkPolicy
    kubectl get networkpolicy -n <namespace>
    kubectl describe networkpolicy <policy-name> -n <namespace>
  • 快速验证: 如果权限允许,可以尝试临时关闭 NetworkPolicy(创建一个允许所有流量的策略)或在没有 NetworkPolicy 的命名空间中测试。

第四阶段:检查防火墙与安全组(云环境/物理机)

如果是在云平台(AWS、阿里云、GCP)或物理机上部署,外部网络限制可能会影响容器。

  • 排查点:
    • 节点安全组: 节点之间的安全组规则是否允许节点上的 Pod CIDR 流量互通?某些云平台默认禁止非 VPC 内部流量。
    • iptables/ebtables: 节点上的 iptables 规则是否被其他工具(如 Docker、Calico、Flannel)错误修改。
    • 命令(在 K8s 节点上):
      # 查看 iptables 过滤表
      iptables -L -n -v
      # 查看 NAT 表(K8s 通过 iptables 实现 Service 负载均衡)
      iptables -t nat -L -n -v | grep <service-name>
      # 如果是 Calico,检查 Felix 规则
      calicoctl get policy

第五阶段:检查 CNI 插件(Kubernetes 网络插件)

CNI 负责分配 IP 和设置网络。

  • 常见问题:

    • IP 冲突: 两个 Pod 被分配了相同的 IP。
    • 路由缺失: 节点上的路由表未正确配置。
    • Overlay 隧道故障: 如 VXLAN、Geneve 隧道断开。
  • 命令(在节点上):

    # 检查路由表,确认目标 Pod CIDR 指向正确的网关(通常是 Cilium/Calico 的接口)
    route -n
    ip route
    # 检查 CNI 插件日志(Calico)
    journalctl -u kubelet -f | grep -i cni
    # 查看 Calico 的 felix 日志
    journalctl -u calico-node

第六阶段:应用层与服务监听

如果网络层面完全通,但业务返回错误(如 502、Connection Refused、超时),问题在应用本身。

  • 排查点:

    1. 服务监听地址: 容器内进程是否监听了 0.0.0 或 ?如果只监听 0.0.1,外部(包括其他 Pod)无法访问。
    2. 端口映射: Service 定义的 targetPort 是否与容器内进程监听的端口一致?
    3. 健康检查: Pod 是否处于 Running 状态且 Ready 条件为 True
    4. 容器内进程启动时间: 进程启动慢导致端口尚未开放。
  • 命令:

    # 确认 Pod 就绪
    kubectl get pod <target-pod> -w
    # 查看容器日志
    kubectl logs <target-pod> <container-name>
    # 进入容器,检查端口监听状态(需要进程权限)
    kubectl exec -it <target-pod> -- netstat -tunlp
    # 或
    kubectl exec -it <target-pod> -- ss -tunlp

第七阶段:特殊场景排查

场景 A:Pod 启动后短暂可通,随后异常

  • 原因: 通常是 网络策略istio(服务网格)在 Pod Ready 后动态注入了 Sidecar(如 Envoy),并锁定了网络规则。
  • 查看: kubectl get pod <pod-name> -o yaml,观察是否有 istio-proxy 等 sidecar 容器以及 initContainers 的网络设置。

场景 B:跨节点通信不通,同节点通信正常

  • 原因: 节点间网络(Node Network)不通,或 CNI 的路由未在所有节点上同步。
  • 排查: 在节点上用 pingtraceroute 测试另一个节点的 Pod CIDR 网段。

场景 C:不同命名空间通信异常

  • 原因: 最可能的是 NetworkPolicy(默认隔离)或 全局策略
  • 验证: 使用 curl 时带上完整的 FQDN:<service>.<namespace>.svc.cluster.local

总结快速排查流程图

[问题:A 无法访问 B]
        |
        v
1.  A 能 ping 通 B 的 Pod IP 吗?
        |
   (是) <---> (否) --> 检查节点路由表、CNI 插件、安全组、节点间网络
        |
        v
2.  DNS 解析 Service 名正确吗?
        |
   (是) <---> (否) --> 检查 CoreDNS、resolv.conf、FQDN 拼写
        |
        v
3.  A 尝试 curl B 的端口,连接错误?
        |
    (Connection Refused) --> B 的服务是否监听在 0.0.0.0?  targetPort 是否正确?
        |
    (Connection Timeout) --> 检查 NetworkPolicy、云安全组、iptables 规则
        |
    (HTTP 4xx/5xx) --> 业务应用层问题,检查日志和配置

最后建议: 当排查陷入僵局时,最有效的方法是 构造一个最小可复现环境(一个测试命名空间,一个测试 Pod,一个简单的 nginx 镜像),然后逐步还原生产环境的配置(如添加 NetworkPolicy、Istio 注入),看哪一步导致异常。

抱歉,评论功能暂时关闭!