"登录服务器插网线抓包"的时代正在过去:应用藏在 Pod 里、网络跨着 Overlay、流量被 Sidecar 接管。本节解决两个新问题:容器环境里采集点怎么选(三种姿势与取舍)、以及把解剖能力从"事后开文件"延伸到"实时跟流水"(常驻采集、过滤器管线、告警输出)。2.3 节的远程采集与 7.1 节的管道功夫,在这里迎来它们的当代形态。
Pod 不是虚拟机:多数容器没有独立网卡,流量走宿主机上的虚拟以太网对(veth)。于是"在哪抓"变成三选一:
**姿势一:Pod 内采集。**最直接,代价是侵入镜像:
# 进 Pod 起一个临时 tcpdump(镜像里得有这把刀,或用调试容器挂靠) $ kubectl exec -it order-svc-7d9f8b6c5-xk2lm -- tcpdump -i any -s 256 -w - -U \ "tcp port 8080 and not port 22" | wireshark -k -i - # 临时容器方案(不污染业务镜像): $ kubectl debug -it order-svc-7d9f8b6c5-xk2lm --image=net-tools:latest -- tcpdump ...
-i any 在容器里格外重要——Pod 内不止一块逻辑接口(回环加 eth0)。姿势一的优势是视角就是应用视角,DNS 查询、本地回环全部可见;劣势是每查一个 Pod 要进一次,规模化困难。
**姿势二:伴生容器(Sidecar 式采集)。**在同一 Pod 加一个专职采集容器,共享网络命名空间:
# 采集容器的部署片段思路:与业务容器同 Pod,共享 net spec: containers: - name: app image: order-service:2.4 - name: sniffer image: net-tools:latest args: ["dumpcap","-i","any","-f","tcp port 8080","-w","/data/capture.pcapng"]
伴生容器看到的就是业务容器看到的(同一网络命名空间),且免侵入业务镜像、可整 Pod 级开关。代价是多一份资源开销、需要平台侧支持——这是"常态化采集"的候选姿势,临时排障不必动用。
**姿势三:宿主机采集。**看全局的最宽视野:
# 在 Pod 所在节点上,先找到容器的虚拟接口再抓 $ nsenter -t $(docker inspect -f '{{.State.Pid}}' $(docker ps -q -f name=order-svc)) \ -n tcpdump -i any -s 256 -w order.pcap "tcp port 8080" # 或直接抓宿主机物理口(Overlay 封装还在,需要解 VXLAN) $ sudo tcpdump -i eth0 -w node.pcap "udp port 4789"
宿主机视角能同时看到多个 Pod 的流量与封装层(VXLAN 的外层 UDP 头),代价是"跨节点流量带着封装,解析前要先剥"。Wireshark 能解 VXLAN 封装(解析器认得它),字段照常可筛——但多一层封装就多一份复杂度,定点排障优先前两种姿势。
Sidecar 代理(服务网格形态)接管了服务间流量后,有两件事值得勘验员知道。其一,本机回环上的明文:业务容器到 Sidecar 的那一段常是明文 HTTP/2 走回环——在 Pod 内抓回环,能看到加密前的应用语义(当然,这属于 6.2 节的授权范围问题)。其二,网格的遥测不替代解剖:网格控制面给出的是聚合拓扑与策略判定,字节层的"为什么"仍要回到解剖台——这与 7.1 节"值守给引擎、深挖回解剖"的分工一致。
传统工作流是"采集、传回、打开",实时解剖把三步并成一步——采集端常驻、过滤器即管线、输出接告警:
# 形态一:常驻探测器——每分钟汇报重传率 $ dumpcap -i eth0 -w - -f "tcp port 8443" \ | tshark -r - -Y "tcp.analysis.retransmission" -T fields -e frame.time_epoch \ | awk '{cnt[int($1/60)]++} END {for (m in cnt) printf "%d %d\n", m, cnt[m]}' \ | while read minute count; do [ "$count" -gt 50 ] && echo "分钟 $minute 重传 $count 次" | notify-ops done # 形态二:滚动窗口的实时指标(持续输出的活动版 8.1 统计) $ tshark -i eth0 -Y "tls.handshake.type == 1" -T fields -e frame.time_epoch \ | awk -v w=300 '{q[NR]=$1; if (q[NR]-q[NR-w+1]>0 && NR>w) shift} {print NR}'
形态一是 7.1 节流式统计的"值守化":同样的三级管道,尾巴上接了阈值判断与通知。形态二演示滚动窗口思路(取最近五分钟的握手速率)——实时分析的本质就是把第 8 章的统计仪器搬到流上,把"打开文件看区间"变成"水龙头上装仪表"。
工程上的三个提醒:常驻进程要用 dumpcap 或 tshark 而非 GUI(8.2 的边界);过滤器先在离线文件上调好再上线(现场改正则的代价很高);输出别直接进人工看的频道——聚合、阈值、降噪之后再给人(告警疲劳是值守系统的头号死因)。
⚠️ 容器环境里最容易翻车的是授权边界:Pod 内抓包看到的是业务容器的全部流量,包括其他租户经共享节点转发的部分(姿势三)。6.2 节的三问在云原生现场要加一问——"这个节点上还跑着谁"。
把三种姿势串成一次真实定位。案情:微服务 A 调用服务 B 偶发超时,两者分属同集群不同节点。
# 第 1 步:Pod 内确认应用视角(姿势一) $ kubectl exec -it svc-a-5d7f8b9c-x1y2 -- tcpdump -i any -c 200 -w /tmp/a.pcap "tcp port 8080" # 现象:超时发生时段,A 侧能看到请求发出、看不到 B 的响应到达 # 第 2 步:换 B 的 Pod 再看——对表定方向 $ kubectl exec -it svc-b-7c8d9e1f-z3w4 -- tcpdump -i any -c 200 -w /tmp/b.pcap "tcp port 8080" # 现象:B 侧同一时段"看到了请求、也回了响应"→ 响应消失在回程路上 # 第 3 步:宿主机视角看全局(姿势三),重点看封装层 $ ssh node-42 node$ sudo tcpdump -i eth0 -w /tmp/node.pcap "udp port 4789" -c 2000 # 解析 VXLAN 封装:外层 UDP 之内才是原始帧 $ tshark -r /tmp/node.pcap -Y "vxlan" -T fields -e ip.src -e ip.dst -c 5 10.244.1.17 10.244.2.34 10.244.2.34 10.244.1.17 <- 回程帧确实经过了节点:问题收窄到 CNI 转发
三步的推理链:A 看不到响应 → B 发了响应 → 回程帧到了节点但没进 Pod——病灶锁定在容器网络接口的转发路径,交给平台组处理。每一步都是"换一个采集点,二分一次故障域":应用视角、对端视角、节点视角,三个视角夹出位置。这个二分法在任何网络环境都成立,容器只是让"采集点"多了几个选项。
**问:生产集群能随便进 Pod 抓包吗?**不能——先把 6.2 的授权关过了再说。容器环境的特殊性在于:节点是共享的("这个节点上还跑着谁"),Pod 的生命周期是短的(证据会随 Pod 消失)。实操建议:需要留证的案子,抓完立刻把 pcap 拷出 Pod 再谈后续。
**问:滚动窗口的实时脚本会不会占用太多资源?**管道本身近乎零开销,开销大头是 dumpcap 的落盘(可以 -w - 不落盘纯流式)与 tshark 的解析(过滤器越简单越省)。给值守脚本设资源上限(容器的话设好 limit),并让它输出可观测的心跳——勘验工具自己也要被观测,这是值守系统的自我修养。
技术与环境都讲完了,终节收束——这张解剖台靠什么保持锋利,你在其中的长期位置。