关于云计算:如何在-Kubernetes-Pod-内进行网络抓包

8次阅读

共计 2838 个字符,预计需要花费 8 分钟才能阅读完成。

应用 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 运行的一个 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 -

kubectl plugin ksniff

ksniff 是一个 kubectl 插件,利用 tcpdumpWireshark 对 Pod 中的网络包实现近程抓取。应用这种办法既能够借助 Wireshark 的弱小性能,又能升高对 Pod 的影响。

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

外围能够了解成 tcpdump -w - | wireshark -k -i -,与后面应用 debug 容器的计划相似。

装置

通过 krew 装置:

$ kubectl krew install sniff

或者下载公布包,手动装置:

$ unzip ksniff.zip
$ make install

特权模式容器

应用阐明参考 ksniff 官网阐明,这里咱们只须要执行如下命令,默认就会重定向到 Wireshark,不须要显示地指定:

$ kubectl sniff echo -n default -f "port 8080"

除了应用 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 -

kubectl debug 长期容器

接下来也是之前介绍过的 kubectl debug,也就是为 Pod 增加长期容器。

同样咱们能够通过这种办法对 Pod 的网络进行抓包,长期容器咱们应用 addozhang/static-dump 镜像。

$ kubectl debug -i echo --image addozhang/static-dump --target echo -- /static-tcpdump -i eth0 

大家能发现这里将捕捉的内容间接输入在规范输入中了,而不是重定向到本地的 Wireshark。

本来长期容器应该是其中最靠近完满的计划:不需上传任何文件指标容器、无需批改 Pod、无需重启、无需特权、反对 distroless 容器。然而,当尝试重定向到 Wireshark 或者 tshark 的时候,会遇到 Data written to the pipe is neither in a supported pcap format nor in pcapng format. 问题。

最初通过一番折腾,也未能解决该问题。有解决了问题的敌人,也麻烦评论告知一下。感激!

文章对立公布在公众号 云原生指北

正文完
 0