介绍
k8s环境中遇到网络问题需要抓包排查怎么办?传统做法是登录pod所在节点,然后进入容器netns,最后使用节点上tcpdump工具进行抓包。
而ksniff使用kubectl将静态编译的tcpdump二进制文件上传到pod,并将其输出重定向到本地Wireshark,以获得流畅的网络调试体验。
安装
可以使用krew来安装也可以手动安装。
kubectl krew install sniff
wget https://github.com/eldadru/ksniff/releases/download/v1.6.2/ksniff.zip
unzip ksniff.zip
make install
使用
kubectl sniff <POD_NAME> [-n <NAMESPACE_NAME>] [-c <CONTAINER_NAME>] [-i <INTERFACE_NAME>] [-f <CAPTURE_FILTER>] [-o OUTPUT_FILE] [-l LOCAL_TCPDUMP_FILE] [-r REMOTE_TCPDUMP_FILE]
有时在生产环境我们可能无法直接在本地执行kubectl,需要经过跳板机,这个时候我们可以将抓到的包保存成文件,然后再拷到本地使用wireshark分析。
kubectl sniff -n ns nginx-xxx -o test.pcap
特权模式
为了减少攻击面并精简容器,许多生产就绪容器以非特权用户甚至临时容器的身份运行。
为了支持这些容器,ksniff现在附带了-p
(特权)模式。当使用-p
标志执行时,ksniff将在远程k8s集群上创建一个新的pod,该pod将有权访问节点docker守护程序。
ksniff 将使用该pod执行附加到目标容器网络命名空间的容器,并执行实际的网络捕获。
kubectl sniff -n ns nginx-xxx -p
查看明文
如果数据包内容很多都是明文 (比如 HTTP),只希望大概看下明文内容,可以指定-o -
将抓包内容直接打印到标准输出 (stdout):
kubectl sniff -n ns nginx-xxx -o -
也可以与其他工具集成,将数据包通过管道传输到stdout。并使用-f
来指定过滤条件。
kubectl sniff -n ns nginx-xxx -f "port 80" -o - | tshark -r -
windows环境使用
我电脑是windows的,不是mac,github上的示例是mac电脑,通过终端执行命令,调用出wireshark。但是不适合windows环境。
首先kubectl必须在本地的cmd或者powershell中执行,不能通过mobaxterm或者xshell等客户端执行。否则会报错:Error: exec: "wireshark": executable file not found in $PATH
所以需要重新下载kubectl.exe,重新安装krew和ksniff。
kubectl
下载
我使用的是kubectl-1.24.16版本。下载地址如下:
https://cdn.dl.k8s.io/release/v1.24.16/bin/windows/amd64/kubectl.exe
下载好后放到C:\Users\你电脑主机名
位置。
环境变量
然后添加kubectl环境变量:我的电脑--属性--高级系统设置--环境变量,点击Path,编辑。
这样就可以执行kubectl命令了。
添加config
在kubectl目录创建.kube
目录,再创建config文件。复制k8s集群context。确认可以执行命令:
krew
需要先安装git。然后下载krew.exe,下载地址如下:
https://github.com/kubernetes-sigs/krew/releases/download/v0.4.4/krew.exe
放到和kubectl同一个目录,安装:
.\krew install krew
添加环境变量:%USERPROFILE%\.krew\bin
再开个窗口,确认可以执行命令:
ksniff
windows的ksniff我这里用的是下面的命令(需要开全局科技),如果有make环境也可以手动安装。
kubectl krew install sniff
安装好后,执行命令:
wireshark
本地安装好wireshark后,添加wireshark环境变量,
这样就可以直接输入wireshark命令唤起wireshark。
抓包
kubectl get po
kubectl sniff nginx-9bc794fd9-s5ntq