如何在 Kubernetes Pod 内进行网络抓包

使用 Kubernetes 时,经常会遇到一些棘手的网络问题需要对 Pod 内的流量进行抓包分析。然而所使用的镜像一般不会带有 tcpdump 命令,过去常用的做法简单直接暴力:登录到节点所在节点,使用 root 账号进入容器,然后安装 tcpdump。抓到的包有时还需要拉回本地,使用 Wireshark 进行分析。而且整个过程非常繁琐,跨越几个环境。

正好前几天也做了一次抓包问题排查,这次就介绍一下快速进行网络抓包的几种方法。

TL;DR

几种方法各有优缺点,且都不建议在生产环境使用。假如必须使用,个人倾向于 kubectl debug 临时容器的方案,但这个方案也有不足。

  • 使用额外容器:这种方案为了 Pod 添加一个额外的容器,使用了静态编译的 tcpdump 进行抓取,借助了多容器共享网络空间的特性,适合 distroless 容器。缺点是需要修改原来的 Pod,调式容器重启会引起 Pod 重启。

  • kubectl plugin ksniff:一个 kubectl 插件。支持特权和非特权容器,可以将捕获内容重定向到 wireshark 或者 tshark。非特权容器的实现会稍微复杂。

  • kubectl debug 临时容器:该方案对于 distroless 容器有很好的支持,临时容器退出后也不会导致 Pod 重启。缺点是 1.23 的版本临时容器才进入 beta 阶段;而且笔者在将捕获的数据重定向到本地的 Wireshark 时会报数据格式不支持的错误。

环境

使用 k3d 创建 k3s 集群,这里版本选择 1.23:

$ k3d cluster create test --image rancher/k3s:v1.23.4-k3s1

抓包的对象使用 Pipy[1] 运行的一个 echo 服务(返回请求的 body 内容):

$ kubectl run echo --image addozhang/echo-server --image-pull-policy IfNotPresent

为了方便访问,创建一个 NodePort Service:

$ kubectl expose pod echo --name echo --port 8080 --type NodePort

挂载容器

在之前的文章我们介绍调试 distroless 容器的几种方法时曾用过修改 Pod 添加额外容器的方式,新的容器使用镜像 addozhang/static-dump 镜像。这个镜像中加入了静态编译tcpdump

修改后的 Pod:

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: echo
  name: echo
spec:
  containers:
  - image: addozhang/echo-server
    imagePullPolicy: IfNotPresent
    name: echo
    resources: {} 
  - image: addozhang/static-dump
    imagePullPolicy: IfNotPresent
    name: sniff
    command: ['sleep', '1d']
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

重新部署后,就可以使用下面命令将抓取网络包并重定向到本地的 Wireshark:

$ kubectl exec -i echo -c sniff -- /static-tcpdump -i eth0 -U -w - | wireshark -k -i -
daf3c5835486acd7659dcd6d96430149.gif
debug-container

kubectl plugin ksniff

ksniff[2] 是一个 kubectl 插件,利用 tcpdump  和 Wireshark 对 Pod 中的网络包实现远程抓取。使用这种方法既可以借助 Wireshark 的强大功能,又能降低对 Pod 的影响。

ksniff 的实现是上传一个静态编译的tcpdump 到 Pod 中,然后将 tcpdump 的输出重定向到本地的 Wireshark 进行调试。

核心可以理解成 tcpdump -w - | wireshark -k -i -,与前面使用 debug 容器的方案类似。

安装

通过 krew[3] 安装:

$ kubectl krew install sniff

或者下载发布包,手动安装:

$ unzip ksniff.zip
$ make install

特权模式容器

使用说明参考 ksniff 官方说明[4],这里我们只需要执行如下命令,默认就会重定向到 Wireshark,不需要显示地指定:

$ kubectl sniff echo -n default -f "port 8080"
a2d36978c4cfa077836809bbebc9fa7d.gif
ksniff

除了使用 Wireshark,可以使用其命令行模式的 tshark

$ kubectl sniff echo -n default -f "port 8080" -o - | tshark -r -

非特权模式容器

对于无特权的容器,就无法使用上面的方法了,会收到如下的错误提示:

INFO[0000] command: '[/tmp/static-tcpdump -i any -U -w - port 8080]' executing successfully exitCode: '1', stdErr :'static-tcpdump: any: You don't have permission to capture on that device
(socket: Operation not permitted)

不过,Ksniff 对此类容器也提供了支持。通过添加 -p 参数,ksniff 会创建一个新的可以访问节点上 Docker Daemon 的 pod,然后将容器附加到目标容器的网络命名空间,并执行报文捕获。

注意,笔者使用的是 k3s 的环境,执行命令时需要通过参数指定 Docker Daemon 的 socket 地址 --socket /run/k3s/containerd/containerd.sock

$ kubectl sniff echo -n default -f "port 8080" --socket /run/k3s/containerd/containerd.sock -p | wireshark -k -i -
8e76e98fd26621e476d880d9ec6b4305.gif
ksniff-priviledged

kubectl debug 临时容器

接下来也是之前介绍过的 kubectl debug ,也就是为 Pod 添加临时容器[5]

同样我们可以通过这种方法对 Pod 的网络进行抓包,临时容器我们使用 addozhang/static-dump 镜像。

$ kubectl debug -i echo --image addozhang/static-dump --target echo -- /static-tcpdump -i eth0
e2aa9e3adc12d320afdc8c6b32365035.gif
ephermeral-sniff-stdout

大家能发现这里将捕获的内容直接输出在标准输出中了,而不是重定向到本地的 Wireshark。

原本临时容器应该是其中最接近完美的方案:不需上传任何文件目标容器、无需修改 Pod、无需重启、无需特权、支持 distroless 容器。然而,当尝试重定向到 Wireshark 或者 tshark 的时候,会遇到 Data written to the pipe is neither in a supported pcap format nor in pcapng format. 问题。

最后经过一番折腾,也未能解决该问题。有解决了问题的朋友,也麻烦评论告知一下。感谢!

参考资料

[1]

Pipy: https://github.com/flomesh-io/pipy

[2]

ksniff: https://github.com/eldadru/ksniff

[3]

krew: https://github.com/GoogleContainerTools/krew

[4]

ksniff 官方说明: https://github.com/eldadru/ksniff#usage

[5]

临时容器: https://kubernetes.io/zh/docs/concepts/workloads/pods/ephemeral-containers/

<think>好的,我需要解决用户关于在Xshell中对Kubernetes进行抓包的命令或工具的问题。首先,用户提到了Xshell,这是一个常用的SSH客户端,主要用于远程连接服务器。而Kubernetes环境中的抓包通常涉及容器网络,所以需要明确抓包的目标是哪个Pod或节点。 接下来,我需要回忆常见的抓包工具。用户之前提到的Wireshark和Fiddler都是抓包工具,但它们在图形界面下使用较多。而Xshell是命令行环境,可能需要使用命令行工具如tcpdump或tshark。Kubernetes中的Pod可能分布在多个节点上,因此可能需要先确定目标Pod所在的节点,然后进入该节点或Pod内部进行抓包。 然后,考虑Kubernetes特有的方法,比如kubectl的命令。例如,使用kubectl exec进入Pod内部运行tcpdump,或者使用kubectl port-forward将端口转发到本地,再配合本地工具抓包。此外,是否有其他工具如kubectl-debug这样的插件可以辅助诊断。 还要注意权限问题,在Pod中执行tcpdump可能需要特权模式,或者Pod的镜像中是否预装了tcpdump。如果没有,可能需要临时安装,或者使用ephemeral container(临时容器)来进行调试,这需要Kubernetes版本支持。 用户可能遇到的问题包括如何定位Pod、如何获取必要的权限、如何在命令行环境下进行抓包并保存结果。因此,步骤可能包括: 1. 使用kubectl get pods找到目标Pod。 2. 使用kubectl exec进入Pod执行tcpdump命令。 3. 如果没有tcpdump,可能需要安装或使用其他方法。 4. 或者使用节点级别的抓包,通过SSH到节点再运行tcpdump。 5. 使用kubectl port-forward结合本地抓包工具。 还需要提醒用户注意安全性和权限,以及抓包文件的分析方法。可能还需要提到如何过滤特定的流量,例如针对某个端口或服务名。 另外,参考之前用户提供的引用,虽然直接关于抓包的是Fiddler和Wireshark,但Xshell环境下可能需要命令行工具。不过引用[3]提到的MobaXterm可能也支持一些终端操作,但用户明确问的是Xshell,所以主要关注命令行解决方案。 总结回答结构:先介绍常用工具如tcpdump,然后分步骤说明如何在Kubernetes环境中使用,包括进入Pod、节点抓包、端口转发等方法,并提到注意事项如权限和文件分析。最后生成相关问题。</think>在Xshell中对Kubernetes集群进行抓包时,主要依赖命令行工具和Kubernetes原生调试命令。以下是具体方法和步骤: --- ### 一、使用`tcpdump`进行容器内抓包 1. **定位目标Pod** 通过`kubectl get pods -n <命名空间>`找到需要抓包Pod名称和所在节点。 2. **进入Pod执行抓包** ```bash kubectl exec -it <pod名称> -n <命名空间> -- tcpdump -i eth0 -w /tmp/capture.pcap ``` - `-i eth0`:指定网卡(容器默认网卡一般为eth0) - `-w`:将抓包结果保存为pcap文件 *注意:若Pod内无tcpdump,需在容器镜像中预先安装或使用临时容器[^1]。* 3. **从Pod导出抓包文件** ```bash kubectl cp <pod名称>:/tmp/capture.pcap ./capture.pcap -n <命名空间> ``` --- ### 二、节点级抓包(通过SSH连接节点) 1. **通过Xshell登录Kubernetes节点** 使用SSH连接Pod所在节点。 2. **在节点上抓取容器流量** ```bash tcpdump -i any port <目标端口> -w node_capture.pcap ``` - `-i any`:监听所有网卡 - `port`:过滤特定端口(如HTTP服务的80端口) --- ### 三、使用`kubectl port-forward`配合本地抓包 1. **将Pod端口转发到本地** ```bash kubectl port-forward <pod名称> 8080:80 -n <命名空间> ``` 2. **在本地使用Wireshark或tcpdump** ```bash tcpdump -i lo port 8080 -w local_capture.pcap ``` - 通过转发端口`8080`捕获流量[^2] --- ### 四、高阶工具推荐 1. **kubectl-debug插件** 通过临时容器注入调试工具(如tcpdump): ```bash kubectl debug <pod名称> -it --image=nicolaka/netshoot ``` 2. **Ksniff工具** 专为Kubernetes设计的抓包工具,自动生成pcap文件: ```bash kubectl sniff <pod名称> -n <命名空间> -o capture.pcap ``` --- ### 注意事项 - **权限问题**:抓包可能需要`CAP_NET_ADMIN`权限,可通过Pod的`securityContext`配置。 - **流量过滤**:使用`tcpdump`表达式过滤无关流量(如`host 10.1.1.1 and tcp port 443`)。 - **资源占用**:长时间抓包可能影响容器性能,建议限制抓包时长(如`-G 60 -W 5`)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值