kubectl插件:把静态编译的tcpdump注入Pod,抓包直接送进本地Wireshark
ksniff 是一个 kubectl 插件,用一条命令对集群里任意 Pod 抓包:它把一个静态编译的 tcpdump 二进制上传进目标容器,在容器的网络命名空间里执行抓包,再把 pcap 流回本地交给 Wireshark 打开。
kubectl sniff <pod> [-n 命名空间] [-c 容器] [-i 网卡] [-f 过滤表达式] [-o 输出文件]
维护状态(重要): 项目已基本停止维护。最后一个 release 是 v1.6.2(2022-02-14),最后一次提交停在 2022-08-05 —— 截至 2026-09 已有约四年没有代码更新。仓库并未归档、仍可安装使用,但官方 README 同时写明「ksniff 目前还不是生产就绪状态,不建议对生产负载使用」。它仍是一个称手的调试工具,只是要有心理准备:遇到新版本 Kubernetes 或新运行时的问题,大概率等不到修复。
作者自己给出的方向也值得注意:README 的 Future Work 第一条就是「不再上传静态 tcpdump,改用 kubectl debug 临时容器」—— 这正是今天推荐的替代路径。
理解执行流程,才能看懂它的权限要求与失败现象:
1. 读取目标 Pod 的 spec,拿到它所在节点与容器运行时(docker / containerd / CRI-O)
2. 在目标 Pod 所在节点上创建一个临时 Pod(特权,能访问节点的容器运行时 socket)
3. 该临时 Pod 把静态编译的 tcpdump 二进制拷进目标容器的文件系统
4. 在目标容器的网络命名空间里执行 tcpdump,输出 pcap 流
5. 本地的 ksniff 接收这个流,交给 Wireshark 或写入文件
6. 清理:结束抓包,并删掉临时 Pod 与上传的二进制
由此可以推出几个结论:
- 不需要节点上预装 tcpdump(第 3 步自带)
- 必须有权限在目标命名空间创建 Pod(第 2 步)
- 目标容器的文件系统必须可写(第 3 步要落文件)
- 用的是 Pod 的网络命名空间,不是容器(第 4 步)
# 推荐:通过 krew 安装
kubectl krew install sniff
# 手工安装
unzip ksniff.zip
make install
# 确认插件已就绪
kubectl krew list | grep sniff
kubectl sniff --help
-n <namespace> 目标 Pod 所在命名空间
-c <container> 只抓某个容器,缺省抓 Pod 里第一个容器
-i <interface> Pod 的网卡名,缺省抓全部网卡
-f "<filter>" tcpdump 抓包过滤表达式
-o <file> pcap 写到本地文件;用 -o - 表示写 stdout
-l <path> 本地 tcpdump 二进制路径
-r <path> 上传到容器里的远端路径
-p 特权模式,用于 scratch / 非特权容器
--image <image> air-gap 环境下替换默认容器镜像
--tcpdump-image <img> air-gap 环境下替换 tcpdump 镜像
# 抓某个 Pod 的全部流量,自动拉起本地 Wireshark
kubectl sniff nginx-6f8b9c-x7k2p
# 指定命名空间与容器
kubectl sniff backend-0 -n prod -c app
# 加过滤表达式(引号不能省)
kubectl sniff backend-0 -n prod -f "port 8080 and host 10.244.1.7"
# 只抓 eth0
kubectl sniff backend-0 -n prod -i eth0
# 写到文件而不是拉起 Wireshark
kubectl sniff backend-0 -n prod -o /tmp/backend.pcap
# 管道给 tshark(无图形界面服务器上的常用姿势)
kubectl sniff backend-0 -n prod -f "port 80" -o - | tshark -r -
很多生产容器以非 root 运行,甚至是 scratch(没有 shell、没有可写目录)。这时用 -p:
kubectl sniff backend-0 -n prod -p
-p 模式会额外创建一个特权 Pod,该 Pod 能访问节点上的容器运行时(docker / containerd),用它把 tcpdump 拷进目标容器的文件系统,再在目标容器的网络命名空间里执行抓包。
这解释了 ksniff 的一个关键设计:它自带 tcpdump,不依赖节点上有没有装 tcpdump。「在节点上装 tcpdump」不是 ksniff 的前置条件。
kubectl sniff backend-0 -n prod \
--image <私有仓库>/docker \
--tcpdump-image <私有仓库>/tcpdump
也可以用环境变量:KUBECTL_PLUGINS_LOCAL_FLAG_IMAGE、KUBECTL_PLUGINS_LOCAL_FLAG_TCPDUMP_IMAGE。
# 权限够不够(需要能 create pod / get pod / exec)
kubectl auth can-i create pods -n prod
kubectl auth can-i create pods --subresource=exec -n prod
# 看 ksniff 到底做了什么(它会在目标命名空间里创建临时 Pod)
kubectl get pods -n prod -w
# 目标容器的文件系统是不是可写(不可写就用 -p)
kubectl exec -it backend-0 -n prod -- touch /tmp/probe
# Wireshark 版本
wireshark --version
# 1. 临时容器(1.25+ 默认可用,推荐)
kubectl debug -it backend-0 --image=nicolaka/netshoot --target=app
# 进去之后自己在共享网络命名空间里抓
tcpdump -i eth0 -nn port 8080 -w /tmp/cap.pcap
# 2. 直接在节点上抓(能看到 veth 与宿主机侧)
nsenter -t <pid> -n tcpdump -i any -nn port 8080
# 3. 有 CNI 可观测性时用它,不抓包也能看丢包原因
kubectl -n kube-system exec ds/cilium -- cilium-dbg monitor --type drop
# 4. 只想看 L7 请求内容时,用服务网格或 Sidecar 的 access log
kubectl logs backend-0 -n prod --tail=100
-p),以及你有权限在目标命名空间里创建 Pod。-p 特权模式会创建一个能访问节点容器运行时的特权 Pod,它绕过了 Pod 的安全边界。在开启 Pod Security Admission 的命名空间里,这个 Pod 会被策略直接拒绝;在安全审计里也是高风险动作,生产环境使用前请确认授权。pcap: network type 276 unknown or unsupported,Protocol 列显示 UNKNOWN。Ubuntu LTS 自带版本常常偏低,需要换官方 PPA。-c 只影响在哪个容器里执行 tcpdump,不影响能看到哪些流量;要区分容器,只能靠端口与进程信息。-p 模式下创建的还是特权 Pod。很多团队的默认 edit 角色并不包含这些权限。kubectl debug 临时容器。它不往业务容器写文件、不需要额外镜像、由 kubelet 原生支持;配合 nicolaka/netshoot 这类自带 tcpdump 的镜像,能覆盖 ksniff 的绝大部分场景。这也是 ksniff 作者自己指的方向。-f 收窄过滤条件。kubectl — ksniff是它的插件kubectl-debug — 同类思路的调试工具ephemeral-containers — 推荐的现代替代方案network-troubleshooting — 抓包在排查流程中的位置mtu — 抓包判断大包是否被丢弃crictl — 定位容器与节点上的运行时hubble — 不抓包也能看流量的方案