AI Infra 训练营
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
HiHuo 主站
GitHub
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
HiHuo 主站
GitHub

tcpdump —— 命令行抓包

一句话定义

tcpdump 直接从内核网卡 / 接口抓原始网络包,按过滤条件显示或写文件。它是网络问题最终诊断工具——iptables / curl / ping 都看着没问题但还是不通时,tcpdump 给你"流量到底有没有到这里"的权威答案。

典型场景

  • pod 连不上 service:在 service 的 pod 抓 → 看包到没到
  • pod 间 ping 不通:在两端抓、对比
  • iptables 规则是否生效:抓抓那条规则前后接口
  • 应用 timeout:抓看 TCP 握手 / 重传
  • 看 K8s overlay 的真实包(外层 IP / 内层 IP)

装

apt install -y tcpdump            # Debian/Ubuntu
yum install -y tcpdump            # CentOS/RHEL

需要 root 跑(要 raw socket 权限)。


五个核心 flag

tcpdump -i eth0                            # 抓 eth0
tcpdump -i any                              # 抓所有接口
tcpdump -nn                                 # 不解析 IP / 端口名
tcpdump -w out.pcap                         # 写到 pcap 文件
tcpdump -r out.pcap                         # 读 pcap 文件回放

记住套路:tcpdump -i <iface> -nn -vv 'filter' -c 100

flag含义
-i <iface>指定接口(必加);any = 所有
-nn不解析 IP 和端口(必加,否则慢)
-v / -vv / -vvv详细程度
-c N抓 N 个包就退出
-s 0不截断(抓完整包)
-w file.pcap写文件(长期抓 / 复杂分析必用)
-r file.pcap读文件
-A打印 ASCII(HTTP 等明文协议好用)
-X同时打印 hex + ASCII
-e显示链路层(MAC 地址)
-Q in/out/inout只看入向 / 出向 / 都看

过滤表达式

tcpdump 用 BPF 过滤语法。可以按 host / port / protocol / 网段过滤。

按主机 / 端口

tcpdump -i any -nn 'host 10.0.24.28'                       # 跟某主机相关
tcpdump -i any -nn 'src host 10.0.24.28'                   # 源是这个
tcpdump -i any -nn 'dst host 10.0.24.28'                   # 目的是这个

tcpdump -i any -nn 'port 80'                                # 80 端口
tcpdump -i any -nn 'src port 22'                            # 源端口 22
tcpdump -i any -nn 'dst port 6443'                          # apiserver 端口

tcpdump -i any -nn 'host 10.0.24.28 and port 6443'         # AND
tcpdump -i any -nn 'host 10.0.24.28 or host 10.0.24.29'    # OR
tcpdump -i any -nn 'not port 22'                            # 反向

按协议

tcpdump -i any -nn 'icmp'                                   # 只看 ping
tcpdump -i any -nn 'tcp'
tcpdump -i any -nn 'udp port 53'                            # DNS 流量
tcpdump -i any -nn 'tcp port 80 and host www.example.com'

按 TCP flags(高级)

tcpdump -i any -nn 'tcp[tcpflags] & tcp-syn != 0'           # 只看 SYN(建连尝试)
tcpdump -i any -nn 'tcp[tcpflags] & (tcp-syn|tcp-ack) != 0' # SYN 或 ACK
tcpdump -i any -nn 'tcp[tcpflags] & tcp-rst != 0'           # 看 RST(被拒)

按网段

tcpdump -i any -nn 'net 10.0.24.0/24'                       # 集群内网
tcpdump -i any -nn 'src net 10.244.0.0/16'                  # pod CIDR 源

输出怎么读

14:23:45.123456 IP 10.0.24.28.43210 > 10.0.24.29.6443: Flags [S], seq 1, win 64240, length 0
14:23:45.124000 IP 10.0.24.29.6443 > 10.0.24.28.43210: Flags [S.], seq 1, ack 2, win 65535, length 0
14:23:45.124500 IP 10.0.24.28.43210 > 10.0.24.29.6443: Flags [.], ack 2, win 64240, length 0
14:23:45.125000 IP 10.0.24.28.43210 > 10.0.24.29.6443: Flags [P.], seq 1:100, ack 2, length 99: ...

读法:

  • 时间戳 IP 源.端口 > 目的.端口 : Flags [...] ...
  • Flags:
    • S = SYN(建连)
    • . = ACK
    • P = PSH(有数据要立即上送)
    • F = FIN(正常关闭)
    • R = RST(异常关闭/拒连)
  • seq / ack —— TCP 序号
  • length —— 载荷字节数

三次握手:SYN → SYN-ACK ([S.]) → ACK ([.])。 四次挥手:FIN → ACK → FIN → ACK。

信号速查

看到含义
只有 [S],无 [S.] 回应包没到对端 / 对端没监听 / 防火墙挡
[S.] 但客户端没 [.]客户端崩了 / 网络往返路径异常
[R] 频繁对端拒连(端口没监听 / 防火墙 REJECT)
大量重传(相同 seq)网络丢包
length 0 全是空 ACK正常 keep-alive

K8s 排错黄金套路

套路 1:节点之间 pod 网络通不通

# 在源节点 m1(pod IP 10.244.0.5)抓
ssh m1 'tcpdump -i any -nn host 10.244.1.5'

# 在目的节点 m2(pod IP 10.244.1.5)抓
ssh m2 'tcpdump -i any -nn host 10.244.0.5'

# 让两端同时抓
ssh m1 'tcpdump -i any -nn -c 20 host 10.244.1.5' &
ssh m2 'tcpdump -i any -nn -c 20 host 10.244.0.5' &

# 触发流量
kubectl exec pod-on-m1 -- curl http://10.244.1.5:8080

判断方向:

  • m1 抓到 SYN 出,m2 没抓到 → 包丢在路上(CNI / 路由问题)
  • m2 抓到 SYN 进、没 SYN-ACK 出 → 包到了但 pod 没监听 / 防火墙挡
  • m2 SYN-ACK 出、m1 没收到 → 回包丢

套路 2:HTTP 看明文(K8s service mesh 调试)

tcpdump -i any -nn -A 'tcp port 8080' -s 0
# -A 显示 ASCII,-s 0 不截断 → 看到完整 HTTP 请求 / 响应

但 HTTPS / TLS 看不了内容(加密)。要看 HTTPS 内容用别的方法(SSLKEYLOGFILE + Wireshark)。

套路 3:进入 pod 网络命名空间抓包

pod 里没装 tcpdump?在节点上抓那个 pod 的 netns:

# 找到 pod 容器 PID
PID=$(crictl inspect $(crictl ps -q --name my-pod) | jq '.info.pid')

# 进 netns 抓 pod 视角的包
nsenter -t $PID -n tcpdump -i any -nn -c 50

或者抓 host 侧的 veth(每个 pod 在节点上有一头 vethXXXX):

# 找 pod 的 veth
nsenter -t $PID -n ip link
# 3: eth0@if23                                    ← pod 内 eth0 指向 host ifindex 23

ip link | grep '@if'
# vethABCD@if3 ...
# 那个 host 侧 ifindex 23 的就是

tcpdump -i vethABCD -nn

套路 4:抓 DNS 看 CoreDNS 行为

tcpdump -i any -nn 'udp port 53' -A
# 看到 query name / response 内容

# 在某 pod 节点上抓
ssh m4 'tcpdump -i any -nn udp port 53 -c 20'
# 然后让 pod 解析
kubectl exec my-pod -- nslookup kubernetes.default

排查"pod 解析慢":能在节点上看到 query 发出但没回应?哪个 CoreDNS pod 收到?

套路 5:抓 K8s overlay 的内外层

CNI 用 VXLAN(flannel / weave)/ IPIP(calico)等 overlay:

tcpdump -i eth0 -nn 'udp port 4789'                # VXLAN
tcpdump -i eth0 -nn 'proto 4'                       # IPIP

# 看完整 payload
tcpdump -i eth0 -nn -e -s 0 'udp port 4789' -A

外层是节点 IP(10.0.24.x),解封装后内层是 pod IP(10.244.x.x)。tcpdump 能显示两层(要新版 tcpdump 才解析 VXLAN)。


写文件 + Wireshark 离线分析

复杂分析在本机用 Wireshark 看,不在 ssh 终端硬看:

# 在节点上抓 5 分钟(或 1000 个包)
tcpdump -i any -nn -w /tmp/trace.pcap -c 1000 'host 10.0.24.28 and port 6443'

# 或者:
timeout 300 tcpdump -i any -nn -w /tmp/trace.pcap 'host 10.0.24.28'

# 拷回本机
scp m1:/tmp/trace.pcap .

# 本机 Wireshark
open trace.pcap                                     # macOS
wireshark trace.pcap                                # Linux

Wireshark 比命令行强大百倍:协议解析、follow TCP stream、I/O 图表、专家提示等。


滚动 / 切片抓包

长时间抓避免单文件太大:

tcpdump -i any -w /tmp/cap-%Y%m%d-%H%M.pcap -G 60 -C 100 -W 5 'host 10.0.24.28'
flag含义
-G 60每 60 秒切一个文件
-C 100单个文件 100 MB 上限
-W 5滚动 5 个文件后覆盖(环形)

适合"问题不定时发生,长跑等它出现"。


性能 / 接口选择

-i any 的代价

-i any 比 -i <具体接口> 慢且会重复(同一个包可能在 eth0、cni0、vethXXXX 都被抓一次)。

排错明确接口时指定单一接口:

tcpdump -i eth0       # 比 -i any 快

-s 0 抓完整包

老版 tcpdump 默认 -s 96 只抓前 96 字节(snap length)。看 HTTP 内容时不够:

tcpdump -i eth0 -nn -A -s 0

新版默认 65535(够大),但养成 -s 0 习惯保险。

-Q 控制方向(节省噪音)

tcpdump -i eth0 -nn -Q in 'tcp port 80'        # 只看入向
tcpdump -i eth0 -nn -Q out 'tcp port 80'       # 只看出向

常见踩坑

坑 1:忘加 -nn,tcpdump 卡死

tcpdump -i eth0 host m1
# 卡在那里

-n 不解析 IP / 端口名(默认会反向 DNS);-nn 完全不解析。永远加 -nn。

坑 2:过滤表达式没引号、被 shell 吃了

tcpdump -i eth0 host 10.0.24.28 and port 6443
# 报错或意外行为,因为 shell 把 and 当独立命令

用单引号包:

tcpdump -i eth0 -nn 'host 10.0.24.28 and port 6443'

坑 3:在错的接口抓

tcpdump -i eth0 'host 10.244.1.5'                  # K8s pod IP
# 什么也抓不到

pod 流量可能走 cni0、flannel.1 或 vethXXXX,不一定经 eth0。不确定就用 -i any 然后再缩小范围。

坑 4:抓 K8s overlay 的内层 IP 抓不到

tcpdump -i eth0 -nn 'host 10.244.1.5'              # pod IP
# 抓不到 —— 因为节点间是 VXLAN 封装,外层是节点 IP

抓 overlay 内层要在解封装后的接口(cni0 / flannel.1)抓,或抓 VXLAN 端口 udp port 4789。

坑 5:抓完留下大文件不清

tcpdump -i eth0 -w /tmp/cap.pcap                   # 跑了一小时
ls -lh /tmp/cap.pcap
# 5.2 GB

抓包很容易撑爆节点磁盘。用 -C -W 切片 + 环形覆盖、或者 -c 限制包数。

坑 6:包数显示 0 packets captured

tcpdump -i any -nn 'host 10.0.24.28' -c 10
# 0 packets captured, 0 packets received by filter

可能:

  • 真的没有流量
  • 过滤表达式写错(语法对、但匹配不到)
  • 抓错接口

去掉过滤先看有没有流量:tcpdump -i any -nn -c 10。

坑 7:root 才能跑

$ tcpdump
tcpdump: ... permission denied

普通用户没 cap:sudo tcpdump ... 或 ssh root。

或者给 tcpdump 设 capability(不推荐生产):

setcap 'cap_net_raw,cap_net_admin=eip' /usr/sbin/tcpdump

坑 8:在 K8s pod 里抓没权限

kubectl exec my-pod -- tcpdump -i eth0
# permission denied

pod 通常不带 NET_ADMIN capability。两种做法:

  1. 用 kubectl debug 起带特权的 sidecar:
    kubectl debug my-pod -it --image=nicolaka/netshoot --target=app
    
  2. 在节点上抓 pod netns(见上面套路 3)

替代 / 关联工具

工具比 tcpdump
tsharkWireshark 命令行版,协议解析更强
ngrep像 grep 那样在流量里搜字符串
iftop实时看哪些连接占带宽
nethogs按进程看流量
bpftrace / bcceBPF 探针更细粒度
cilium monitorCilium 集群里看 eBPF datapath 包

但 tcpdump 是最通用、最可靠的——任何 Linux 系统装一下立刻能用。


关联命令

  • ip —— 看路由 / 接口、找到要抓的接口
  • iptables —— 抓包验证规则是否生效
  • ss —— 看监听端口,先确认对端在听
  • curl —— tcpdump 抓的同时 curl 产生流量
  • dig —— DNS 用 dig 直接看,比 tcpdump 抓 53 端口更直接
  • nsenter —— 进 pod netns 抓包
在 GitHub 上编辑此页