跳转至

如何通过宿主机nsenter和tcpdump抓包pod网络通信

要在 Kubernetes Pod 内部使用 nsenter + tcpdump 抓取 HTTP 请求的详细流量,需在 Pod 所在的宿主机(Node)上操作,因为 nsenter 是宿主机级别的工具,用于进入容器的网络命名空间(netns)。

前提条件

  • 你有 SSH 登录 Pod 所在 Node 的权限
  • 你有 root 或 sudo 权限(nsenter 和 tcpdump 需要)
  • 宿主机已安装 tcpdump(若无,用 apt install tcpdump 或 yum install tcpdump 安装)
  • 你知道目标 Pod 名称 和 所在 Namespace

确认 Pod 所在节点

kubectl get pod <pod-name> -n <namespace> -o wide

输出示例:

NAME        READY   STATUS    NODE       ...
my-app-7d5   1/1     Running   node-03    ...

SSH 登录到该节点

ssh user@node-03
sudo -i  # 切换到 root

获取容器的 PID

nerdctl inspect $CONTAINER_ID | grep -i pid
PID=$(crictl inspect $CONTAINER_ID -o go-template='{{.info.pid}}')
echo "PID: $PID"

使用 nsenter 进入容器网络命名空间并抓包

nsenter -t $PID -n tcpdump -i any -nn -s 0 -A 'tcp port 80 or tcp port 443'

参数说明:

  • -t $PID:目标进程 PID
  • -n:进入其 network namespace
  • -i any:监听所有接口(容器内通常只有 eth0,但 any 更保险)
  • -nn:不解析主机名和端口名(避免 DNS 查询干扰)
  • -s 0:捕获完整包(默认只抓 262144 字节,可能截断 HTTP body)
  • -A:以 ASCII 格式打印包内容(可读 HTTP 请求/响应)
  • 'tcp port 80 or tcp port 443':只抓 HTTP/HTTPS 流量

输出示例:

10:30:15.123456 IP 10.244.2.10.54321 > 93.184.216.34.80: Flags [P.], seq 1:200, ack 1, win 501, options [nop,nop,TS val 123456 ecr 789012], length 199: HTTP: GET /api/user HTTP/1.1
E..{..@.@...........P..P...!.............
GET /api/user HTTP/1.1
Host: api.example.com
User-Agent: curl/7.68.0
Accept: */*

写入文件

# 在宿主机上创建临时目录
mkdir -p /tmp/tcpdump
nsenter -t $PID -n tcpdump -i any -nn -s 0 -w /tmp/tcpdump/pod-http.pcap 'tcp port 80 or tcp port 443'

只抓特定域名或路径的流量(可选)

由于 tcpdump 无法直接过滤 HTTP 路径,但可以用关键字匹配:

# 抓包含 "GET /login" 的请求
nsenter -t $PID -n tcpdump -i any -nn -s 0 -A | grep -A5 -B5 "GET /login"

# 或保存后过滤
nsenter -t $PID -n tcpdump -i any -nn -s 0 -w /tmp/cap.pcap
tcpdump -A -r /tmp/cap.pcap | grep "Authorization"

参考

安装 crictl:

curl -L <https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.28.0/crictl-v1.28.0-linux-amd64.tar.gz> | tar zx -C /usr/local/bin