如何在 Kubernetes 下轻松抓取应用网络包

#1. 宿主机上捕获

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

0) 先决条件

需要有宿主机的访问权限

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

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

  1. 宿主机 IP = 172.18.0.xxx
  2. container ID = 78e91175699f.....
# 注: 需要替换 namespace 和 pod name
➜ kubectl get pod \
-n ${NAMESPACE}${POD_NAME} \
-o json|jq '.status|{hostIP: .hostIP, container: [.containerStatuses[]|{name: .name, containerID: .containerID}]}'
{
"hostIP": "172.18.0.xxx",
"container": [
{
"name": "linkerd-proxy",
"containerID": "docker://78e91175699f8cc0a3b0ff87da97407c19c7a86706a5b74e2d86f4428a4de75a"
},
{
"name": "nginx",
"containerID": "docker://7a6f7eabc2d5112437d30ee8ec1aa7ef963e97c3d09c3bc63613a70d106d7d01"
}
]
}

2) 查找网络接口索引

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

# 注: 需要替换 container id
docker exec -it ${CONTAINER_ID} /bin/bash -c 'cat /sys/class/net/eth0/iflink'
10227

3) 查找网络接口信息

在宿主机上做 ip link 操作

ip link |grep 10227
10227: calicf227ed888a@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP mode DEFAULT group default

4) 在宿主机上抓包

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

tcpdump -i calicf227ed888a@if4 -w /root/tcpdump.pcap 

#2. 在 Pod 内抓包

0) 先决条件

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

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

# 注: -c ${CONTAINER_NAME} 是可选择的。如果 Pod 中仅包含一个容器,就可以忽略它
kubectl exec${POD_NAME} -c ${CONTAINER_NAME} -- tcpdump -i eth0 -w - | wireshark -k -i -

#3. 通过 ephemeral containers 抓包

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

比如我使用 nicolaka/netshoot[3] 镜像用来调试,用法如下

# 注: 需要替换 pod name 和 container name
kubectl debug -i ${POD_NAME} \
--image=nicolaka/netshoot \
--target=${CONTAINER_NAME} -- tcpdump -i eth0 -w - | wireshark -k -i -

#4. 通过 Ksniff 抓包

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

0) 先决条件

安装 Krew
(
set -x; cd"$(mktemp -d)" &&
curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/krew.tar.gz" &&
tar zxvf krew.tar.gz &&
KREW=./krew-"$(uname | tr '[:upper:]' '[:lower:]')_$(uname -m | sed -e 's/x86_64/amd64/' -e 's/arm.*$/arm/')" &&
"$KREW" install krew
)
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"
安装 sniff 插件

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

kubectl krew install sniff

1) 执行 kubectl sniff 命令抓包

# 注:需要替换 pod name 和 namespace
kubectl sniff ${POD_NAME} -n ${NAMESPACE}

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

如何在 Kubernetes 下轻松抓取应用网络包

以下是 sniff 运行的日志,我只提取了日志的关键部分

➜ kubectl sniff httpbin -n default

time="2022-02-20T19:56:13+08:00" level=info msg="using tcpdump path at: '/Users/linqiong/.krew/store/sniff/v1.6.1/static-tcpdump'"
time="2022-02-20T19:56:13+08:00" level=info msg="selected container: 'httpbin'"
time="2022-02-20T19:56:13+08:00" level=info msg="uploading file: '/Users/linqiong/.krew/store/sniff/v1.6.1/static-tcpdump' to '/tmp/static-tcpdump' on container: 'httpbin'"
....
time="2022-02-20T19:56:14+08:00" level=info msg="tcpdump uploaded successfully"
time="2022-02-20T19:56:14+08:00" level=info msg="spawning wireshark!"
time="2022-02-20T19:56:14+08:00" level=info msg="start sniffing on remote container"
time="2022-02-20T19:56:14+08:00" level=info msg="executing command: '[/tmp/static-tcpdump -i any -U -w - ]' on container: 'httpbin', pod: 'httpbin', namespace: 'default'"

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

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

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

kubectl sniff httpbin -n default -o httpbin.pcap

文章来源:https://www.cnaaa.net,转载请注明出处:https://www.cnaaa.net/archives/9551

(0)
杰斯的头像杰斯
上一篇 2023年8月16日 下午6:10
下一篇 2023年8月17日 下午4:33

相关推荐

  • 端口隔离和VLAN的区别

    对于大型网络,我们常常对于ip的规划比较烦恼,也有很多朋友问到,对于1000个以上的终端设备如何去设置它的ip地址呢? 对于大型网络,它的ip规划我们常常的做法是划分vlan,因为划分vlan有诸多好处,方便管理以及提升了整个网络的安全性。当然除了划分vlan有其它的方法吗?答案是肯定,那就是端口隔离。这两种方法在ip规划中使用的最多,我们本期来详细了解vl…

    2023年12月14日
    8100
  • 华为交换机恢复出厂设置的方法

    常用的三种恢复出厂配置的方法:长按PNP键恢复出厂配置、一键式恢复出厂配置,以及通过清空配置文件来恢复出厂配置。 1、长按PNP键恢复出厂配置 对于支持PNP键的设备,用户可通过长按(6秒以上)PNP键,使设备恢复出厂配置并自动重新启动。PNP键如下图所示。 2、一键式恢复出厂配置 在用户视图下,执行命令reset factory-configuration…

    2023年5月8日
    46900
  • Linux系统VPS云服务器网络速度性能测试一键脚本分享

    收集的一些常用的测试脚本部分经过实际测试,基本可以正常使用,关于脚本测试出来数据的准确性,需要自行甄别,仅供参考。 本站所收集的一键脚本均来自网络,不对其收集的脚本负责,请注意保管并备份资料,建议多尝试几个脚本进行测试。 附件下载测试 秋水逸冰硬件信息/带宽测试 测试VPS基础信息,以及下载速度,来自秋水逸冰:https://bench.sh/ 老鬼硬件信息…

    2022年6月8日
    1.5K00
  • Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化…

    引言 早期的业务都是基于单体节点部署,由于前期访问流量不大,因此单体结构也可满足需求,但随着业务增长,流量也越来越大,那么最终单台服务器受到的访问压力也会逐步增高。时间一长,单台服务器性能无法跟上业务增长,就会造成线上频繁宕机的现象发生,最终导致系统瘫痪无法继续处理用户的请求。 ❝ 从上面的描述中,主要存在两个问题:①单体结构的部署方式无法承载日益增长的业务…

    2023年3月16日
    23000
  • 宝塔面板下,打开phpmyadmin显示空白页的解决方法

    在宝塔面板里装完phpmyadmin但是进不去数据库的这种情况太常见了 1. 没开放888端口 当我们进phpmyadmin的时候,端口默认为888,这时,我们就要检查宝塔面板和阿里云或腾讯云等控制器里的安全组的888端口是否开放。 2. 环境不兼容 如果是纯静态,选择php版本即可。 如果PHP版本较高,则可以切换到低版本的PHP。

    2022年6月11日
    1.2K00

发表回复

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

在线咨询: QQ交谈

邮件:712342017@qq.com

工作时间:周一至周五,8:30-17:30,节假日休息

关注微信