Kubernetes常见的网络抓包思路

1. 宿主机上捕获

我们知道应用其实是运行在 Pod 内的 Container 里的,所以只要定位到 Container 被调度到了哪个 Node 上,在相应的 Node 里,对容器进行抓包即可。

0) 先决条件

需要有宿主机的访问权限

1) 定位 Pod 的 containerID 以及它所运行的宿主机 IP

在 Kubernetes 集群内执行下面这个指令,并从返回的结果中拿到两个信息

  1. 宿主机 IP
  2. container ID

获取格式:

kubectl get pod \ -n ${NAMESPACE} ${POD_NAME} \ -o json|jq '.status|{hostIP: .hostIP, container: [.containerStatuses[]|{name: .name, containerID: .containerID}]}'
Kubernetes常见的网络抓包思路

2) 查找网络接口索引

通过 ssh 登陆到 Pod 所在的宿主机上,然后在容器内执行 cat /sys/class/net/eth0/iflink,查找容器中的网卡与宿主机的 veth 网卡之间的对应关系

格式:

docker exec -it ${CONTAINER_ID} /bin/bash -c 'cat /sys/class/net/eth0/iflink'
Kubernetes常见的网络抓包思路

3) 查找与 container 内部链接的宿主机网络接口

在宿主机上做 ip link | grep "刚才获取的数字:" 操作

Kubernetes常见的网络抓包思路

4) 在宿主机上指定网络接口抓包

格式:

tcpdump -i ${获取的外部网络接口} -w /root/tcpdump.pcap

最后,我们通过 tcpdump 指令,将报文保存到文件中

Kubernetes常见的网络抓包思路

我们 ping 一下 pod 所在的 IP,将 tcpdump 导出的文件使用 wireshark 进行分析

Kubernetes常见的网络抓包思路
Kubernetes常见的网络抓包思路

我们可以看一下来源IP 为 172.25.244.192 这个 IP 是发出 ping 命令的主机使用 tunl0 设备传输过去的,使用 tunl0 模式是因为跨节点了

Kubernetes常见的网络抓包思路

如果使用pod所在的宿主思考机192.168.1.12 ping pod 的 IP,则不会经过 tun0

Kubernetes常见的网络抓包思路

思考

通常情况下,并不是所有的开发者都能触碰到宿主机的权限的,所以这种方式只适合集群运维人员,而且这种操作确实也过于繁琐了。

对于开发者来说,离我们最近的还是 Pod,下面我们来看下直接通过 Pod 是如何进行抓包的。

2. 在 Pod 内抓包

0) 先决条件

  1. 目标 Pod 内的容器里必须要有 tcpdump 工具
  2. 本地安装 wireshark

1) 执行以下命令对目标 Pod 抓包

格式:

kubectl exec ${POD_NAME} -c ${CONTAINER_NAME} -- tcpdump -i eth0 -w - | wireshark -k -i -

思考

不难发现,这种方法比第一种在执行层面上少了很多步骤。

只要满足了 2 个前置条件,执行一条指令即可通过 wireshark 来解析报文,而且不需要宿主机的权限,但是它会存在一个问题:就是容器里必须要有 tcpdump 这个工具

一般来说你可能会想到两个解决办法:

  1. 将 tcpdump 打包到镜像里。但是这样做,它不仅会增加镜像包的大小,也会有一定的风险,另外你不可能要求三方的镜像也必须默认装上对吧?
  2. 有同学说,直接进入容器里做现场安装咯?但是,你有没有想过,很多客户部署的环境都是要求隔离外网的,甚至有些 base image 用的是 无发行版镜像

3. 通过 ephemeral containers 抓包

值得一提的是 Kubernetes 在 v1.16 [Alpha] 开始支持 Ephemeral Containers,它正好可以解决上面提的 2 个痛点,临时容器对于排除交互式故障非常有用,Kubernetes 在 v1.23 [beta] 已经默认开启该功能了。比如我使用 nicolaka/netshoot

netshoot介绍

netshoot是一款开源的容器网络诊断工具,本质上是一个容器,里面默认安装了一些常用网络诊断工具,如tcpdump、netstat等,被称为网络排障瑞士军刀容器。

众所周知,容器下网络空间是相互隔离的,与宿主机的网络空间也是隔离的,往往需要通过工具进入容器空间排查问题,但是业务容器不一定安装了常见的调试工具,netshoot在这样的场景提供了很大的便利。

  • 提供了“瑞士军刀”式的开箱即用的工具箱,包括各类网络诊断工具。
  • 通过与业务容器共享网络命名空间,可以不重启、“不侵入”业务容器,对容器网络进行调试排错。
  • K8s环境下pod中的容器共享网络命名空间,netshoot可以以sidecard对业务容器进行排错。

netshoot镜像构成

Kubernetes常见的网络抓包思路

netshoot代码比较少,核心代码就是这样一个dockerfile,可以看到里面安装了很多的工具,与另一款Linux系统瑞士军刀busybox不同,netshoot主要关注在网络工具。

Kubernetes使用过程

用法格式:

kubectl debug -i ${POD_NAME}  --image=nicolaka/netshoot  --target=${CONTAINER_NAME} -- tcpdump -i eth0 -w - | wireshark -k -i -
# 或者进入容器进行网络检测
kubectl debug -ti ${POD_NAME} --image=nicolaka/netshoot

但是,如果你的集群版本比较低,在 v1.23 版本以下,且集群管理员并没有开启 Ephemeral Containers 这个特性,咋办咧?
如果是在生产环境,你不可能让管理员升级集群版本,或者开启某一个特性来做 Debug 吧?

那么问题来了,有没有一种工具,它既可以做到不用触碰宿主机,又可以不必在目标 Pod 内的容器里提前安装 tcpdump 呢?

4. 通过 Ksniff 抓包

ksniff 是一个 kubectl 的插件,它利用 tcpdump 和 Wireshark 对 Kubernetes 集群中的任何 Pod 启动远程抓包。

0) 先决条件

安装 Krew

krew 是一个用来管理 kubectl 插件的工具,类似于 apt 或 yum,支持搜索、安装和管理 kubectl 插件

安装:

(
  set -x; cd "$(mktemp -d)" &&
  curl -fsSLO "https://storage.googleapis.com/krew/v0.2.1/krew.{tar.gz,yaml}" &&
  tar zxvf krew.tar.gz &&
  ./krew-"$(uname | tr '[:upper:]' '[:lower:]')_amd64" install \
    --manifest=krew.yaml --archive=krew.tar.gz
)

安装完成后,把 krew 的二进制文件加入环境变量 PATH 中:

export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"

最后,再执行 kubectl 命令确认安装成功:

$ kubectl plugin list
The following kubectl-compatible plugins are available:
/home/<user>/.krew/bin/kubectl-krew

首次使用前,请执行下面的命令更新插件索引:

kubectl krew update

一旦安装完 Krew 后,就可以通过以下指令完成 sniff 的安装

kubectl krew install sniff

1) 执行 kubectl sniff 命令抓包

格式:

kubectl sniff ${POD_NAME} -n ${NAMESPACE}

执行 sniff 命令后,本地会自动启动 Wireshark 进行抓包,如下图

kubectl sniff nginx-6799fc88d8-l5tv5 -n default

sniff日志

Kubernetes常见的网络抓包思路

从运行的日志来看,sniff 是将本地的 static-tcpdump 文件上传到 Pod 的指定容器的 /tmp 目录下,然后在容器内,通过运行以下命令来达到抓包的目的

/tmp/static-tcpdump -i any -U -w -

另外需要说明的是,如果你是在服务器上执行,且服务器并没有安装 wireshark,你可以将报文输出到文件中,然后用本地的 wireshark 来解析报文。

kubectl sniff httpbin -n default -o httpbin.pcap

Kubernetes常见的网络抓包思路
Kubernetes常见的网络抓包思路

这里可以看出,网络是从k8s-master01通过tunl0访问过去的,因为网址我们输入的是master01的IP地址

发布者:LJH,转发请注明出处:https://www.ljh.cool/39722.html

(0)
上一篇 2024年1月10日 下午4:05
下一篇 2024年1月11日 下午3:43

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注