摘要:结合 tcpdump 和 Wireshark 分析 TCP 握手、RST、重传与超时,按抓包位置、NAT 和请求返回路径定位 Kubernetes 网络故障。
这一节进入网络排障最实用的部分:通过抓包观察真实数据包,判断连接究竟在哪一步失败。
学习如何观察网络通信,而不是仅凭 curl 的报错猜测原因。
本节主要掌握:
- TCP 三次握手与四次挥手。
- 使用
tcpdump抓取和过滤数据包。 - 使用 Wireshark 分析 TCP 报文。
- 区分连接拒绝、超时、重传和应用层错误。
- 在 Kubernetes 中定位 Pod、Service 和跨节点网络故障。
一、先理解 TCP 连接建立过程
假设客户端访问一个 HTTP 服务:
客户端:10.244.1.10:40000服务端:10.244.2.20:8080TCP 连接通常通过三次握手建立。
sequenceDiagram
participant C as 客户端 10.244.1.10:40000
participant S as 服务端 10.244.2.20:8080
C->>S: SYN:请求建立连接
S->>C: SYN + ACK:服务端确认
C->>S: ACK:连接建立
三次握手完成后,客户端就可以发送 HTTP 请求数据。
如果握手过程中出现异常,抓包往往能够直接提供线索:
- 只有 SYN:连接请求发出,但尚未观察到响应。
- SYN 后收到 RST:连接被拒绝或主动重置,需要进一步定位发送 RST 的设备。
- SYN、SYN-ACK、ACK 全部出现:TCP 连接已建立,但应用仍可能返回错误或一直没有响应。
注意,单次抓包没有看到响应,不代表对端一定没有发送。抓包接口选择错误、数据包丢失或非对称路由也可能导致观察不完整。
二、tcpdump:Linux 命令行抓包工具
tcpdump 是 Linux 上常用的网络抓包工具,可以直接观察经过指定网络接口的数据包。
它在排查 Kubernetes 网络问题时特别有用,因为你可以分别在 Pod 网络命名空间、宿主机网卡和隧道接口上抓包,比较数据包在哪里消失或发生变化。
1. 安装与基础使用
Ubuntu / Debian:
sudo apt updatesudo apt install tcpdump查看网卡:
ip -br addr抓取某个接口的数据包:
sudo tcpdump -i eth0抓取全部接口:
sudo tcpdump -i any其中:
-i eth0:监听指定接口。-i any:监听 Linux 支持的所有接口。Ctrl+C:停止抓包并显示统计信息。
生产环境中不建议长时间无过滤抓包,因为流量可能很大,既影响分析效率,也可能记录敏感信息。
2. 过滤指定端口
假设要排查 TCP 8080 端口:
sudo tcpdump -i any 'tcp port 8080'只看某个目标 IP:
sudo tcpdump -i any 'host 10.244.2.20'只看某个源 IP:
sudo tcpdump -i any 'src host 10.244.1.10'只看两个 IP 之间的通信:
sudo tcpdump -i any \ 'host 10.244.1.10 and host 10.244.2.20'只抓 TCP SYN 报文:
sudo tcpdump -i any \ 'tcp[tcpflags] & tcp-syn != 0'如果想进一步排除握手成功时同时带有 ACK 标志的报文,可以使用:
sudo tcpdump -i any \ 'tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn'这类过滤条件有助于集中观察发起连接的 SYN 报文。
3. 常用参数
| 参数 | 作用 |
|---|---|
-n | 不解析 IP 地址对应的主机名 |
-nn | 不解析主机名和端口服务名 |
-i | 指定网络接口 |
-c 100 | 抓取 100 个数据包后停止 |
-s 0 | 尽可能抓取完整数据包 |
-w file.pcap | 将数据包保存到文件 |
-r file.pcap | 读取抓包文件 |
-tttt | 显示便于阅读的时间戳 |
-v | 显示更多协议细节 |
实际排障时,推荐先从下面这条命令开始:
sudo tcpdump -i any -nn -tttt \ 'host 10.244.2.20 and tcp port 8080'它可以减少名称解析干扰,并显示较容易比较的时间戳。
三、如何看懂 tcpdump 输出?
假设执行:
sudo tcpdump -i any -nn 'tcp port 8080'观察到:
10.244.1.10.40000 > 10.244.2.20.8080: Flags [S]10.244.2.20.8080 > 10.244.1.10.40000: Flags [S.]10.244.1.10.40000 > 10.244.2.20.8080: Flags [.]这代表:
[S]:SYN,客户端请求建立连接。[S.]:SYN + ACK,服务端确认请求。[.]:ACK,客户端确认服务端响应。
三次握手成功。
常见 TCP 标志:
| 标志 | 含义 |
|---|---|
[S] | SYN |
[S.] | SYN + ACK |
[.] | ACK |
[P.] | PSH + ACK,常见于携带应用数据的报文 |
[F.] | FIN + ACK,常见于有序关闭连接 |
[R.] | RST + ACK,连接重置 |
标志只是分析线索,不能单独代表某种故障。例如,RST 既可能来自目标应用所在主机,也可能由中间设备产生。
四、四种典型故障:通过抓包判断原因
场景一:持续发送 SYN,没有收到响应
抓包:
10.244.1.10.40000 > 10.244.2.20.8080: Flags [S]10.244.1.10.40000 > 10.244.2.20.8080: Flags [S]10.244.1.10.40000 > 10.244.2.20.8080: Flags [S]可能原因:
- 网络路径中存在丢包。
- NetworkPolicy 或防火墙阻断流量。
- 目标节点或目标 Pod 不可达。
- 服务端没有返回响应。
- 返回路径异常,导致响应无法到达客户端。
排查方法:在客户端和服务端两侧同时抓包。
客户端执行:
sudo tcpdump -i any -nn 'host 10.244.2.20 and tcp port 8080'服务端所在节点也执行相应抓包。
| 客户端观察 | 服务端观察 | 排查方向 |
|---|---|---|
| 发出 SYN | 没有收到 SYN | 检查中间网络、路由、策略和抓包接口 |
| 发出 SYN | 收到 SYN,但没有发出响应 | 检查服务监听、主机防火墙及内核处理 |
| 发出 SYN | 收到 SYN,也发出 SYN-ACK | 检查返回路径和客户端侧是否收到响应 |
| 完整握手 | TCP 已建立 | 继续检查应用层 |
场景二:收到 RST,连接被拒绝
抓包:
10.244.1.10.40000 > 10.244.2.20.8080: Flags [S]10.244.2.20.8080 > 10.244.1.10.40000: Flags [R.]这表示连接被重置,常见原因是目标端口没有进程监听,或者某个设备主动拒绝了连接。
在目标 Pod 内检查:
ss -lntp查看是否存在目标端口的监听进程。
注意,ss -lntp 是否能显示进程信息取决于权限和网络命名空间;如果容器内没有 ss,可以在宿主机上进入对应网络命名空间检查。
场景三:TCP 握手成功,但 HTTP 请求一直等待
抓包:
客户端 -> 服务端:SYN服务端 -> 客户端:SYN-ACK客户端 -> 服务端:ACK
客户端 -> 服务端:HTTP 请求数据但迟迟没有看到服务端返回应用数据。
这时,网络至少已经完成了 TCP 建连,应该进一步检查:
- 应用是否收到请求。
- 应用是否等待数据库或其他下游服务。
- 应用线程、协程或连接池是否耗尽。
- 服务端是否在处理请求时发生阻塞。
- 返回数据是否被发送,或者在返回路径上丢失。
不要把所有 HTTP 超时都归因于网络。TCP 建连成功不等于应用处理成功。
场景四:大量 TCP 重传
如果反复看到相同连接的数据包重传,通常说明发送方没有及时收到预期的确认或响应。
可能原因包括:
- 网络丢包。
- 链路拥塞。
- MTU 或路径 MTU 问题。
- 接收端处理能力不足。
- 返回路径丢包。
需要结合时间间隔、TCP 序列号、ACK 和两端抓包分析,不能仅凭重传就判断是某个节点故障。
五、Wireshark:图形化分析抓包文件
tcpdump 适合在服务器上快速抓包,Wireshark 则适合深入分析协议细节。
典型工作流程是:
flowchart TB
N0["服务器 tcpdump 抓包"]
N1["保存 .pcap 文件"]
N2["传输到分析电脑"]
N3["Wireshark 打开文件"]
N4["分析握手、重传、RST、HTTP/TLS 等"]
N0 --> N1
N1 --> N2
N2 --> N3
N3 --> N4
1. 保存抓包文件
sudo tcpdump -i any -nn -s 0 \ -c 1000 \ -w /tmp/network-debug.pcap \ 'host 10.244.2.20 and tcp port 8080'这里设置最多抓取 1000 个数据包,避免无边界地采集流量。
然后可以将文件复制到分析电脑:
scp user@node-ip:/tmp/network-debug.pcap .如果文件中可能包含敏感业务数据、Cookie 或认证信息,应严格限制文件访问权限,并在分析完成后按组织要求处理文件。
2. Wireshark 常用显示过滤器
Wireshark 的显示过滤器和 tcpdump 的抓包过滤器不是同一种语法。
| 目的 | Wireshark 显示过滤器 |
|---|---|
| 查看 TCP 流量 | tcp |
| 查看特定端口 | tcp.port == 8080 |
| 查看特定 IP | ip.addr == 10.244.2.20 |
| 查看 SYN | tcp.flags.syn == 1 |
| 查看 RST | tcp.flags.reset == 1 |
| 查看重传 | tcp.analysis.retransmission |
| 查看重复 ACK | tcp.analysis.duplicate_ack |
| 查看 DNS | dns |
Wireshark 还可以通过 Analyze → Follow → TCP Stream 将某条 TCP 连接中的双向应用数据串起来观察。
如果流量使用 HTTPS,抓包通常只能直接看到 TCP、TLS 等传输信息;要读取加密后的 HTTP 内容,需要合法且适当的 TLS 解密条件。
六、Kubernetes Pod 网络故障定位
现在把抓包方法应用到 Kubernetes。
假设:
客户端 Pod:10.244.1.10Node A:192.168.1.10
服务端 Pod:10.244.2.20Node B:192.168.1.20
服务端端口:8080客户端访问服务端:
curl -v --connect-timeout 3 http://10.244.2.20:8080第一步:确认 Pod 和节点
kubectl get pods -A -o widekubectl get nodes -o wide确认两个 Pod 的 IP 和所在节点。
第二步:在服务端抓包
登录 Node B:
sudo tcpdump -i any -nn \ 'host 10.244.1.10 and tcp port 8080'与此同时,从客户端 Pod 发起请求。
如果服务端侧抓不到客户端的 SYN,就应该继续检查从 Node A 到 Node B 的网络路径、CNI 数据面、路由及策略。
如果服务端能收到 SYN,但没有发出 SYN-ACK,则检查目标 Pod 的监听状态和主机网络处理规则。
如果服务端已经发出 SYN-ACK,就继续确认客户端侧是否收到它。
第三步:检查服务端监听
kubectl exec <server-pod> -- ss -lnt如果容器中没有 ss,可以使用临时调试容器,或者在节点上通过目标容器的网络命名空间执行相关命令。
第四步:检查 Service 与策略
如果直接访问 Pod IP 成功,但访问 ClusterIP 失败,再检查 Service 数据面:
kubectl get svckubectl get endpointslices -Akubectl get networkpolicy -A如果使用传统 kube-proxy 模式,再结合节点上的相关规则和 conntrack 信息分析。如果使用 eBPF 数据面,则需要使用相应 CNI 的诊断工具。
这里的关键是先通过对照测试缩小问题范围,而不是同时修改多个组件。
七、进阶:同一个请求在不同接口上为什么会显示不同的 IP?
假设客户端访问:
10.96.120.30:8080但后端 Pod 收到的目标地址是:
10.244.2.20:80这是 Service 转发过程中发生 DNAT 的典型结果。
如果你在不同位置抓包,可能看到:
| 抓包位置 | 可能观察到的目标地址 |
|---|---|
客户端 Pod 的 eth0 | ClusterIP 10.96.120.30:8080 |
| 节点上的某个网络处理点 | 取决于抓包接口及 NAT 处理阶段 |
后端 Pod 的 eth0 | 后端 Pod IP 10.244.2.20:80 |
如果还发生了 SNAT,后端看到的源 IP 也可能与客户端 Pod IP 不同。
因此,抓包分析必须同时记录:
- 抓包位置。
- 源 IP 与目标 IP。
- 源端口与目标端口。
- 抓包时间。
- 数据包是请求方向还是返回方向。
只有这样,才能把 NAT、路由和真实网络路径联系起来。
八、本节总结
今天最重要的能力不是记住抓包命令,而是建立一套分析顺序:
- SYN 无响应:检查请求路径、返回路径和过滤规则。
- 收到 RST:检查端口监听与重置来源。
- 握手成功但应用超时:继续检查应用和依赖服务。
- 大量重传:检查丢包、拥塞和 MTU 等问题。
- 不同接口看到不同地址:结合 NAT 与抓包位置解释。