如何在 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

相关推荐

  • iStoreOS,新增备份系统教程

    一、写盘。 本文主要是x86物理机安装教程(因为物理机才能获取到温度等硬件信息),esxi下安装也很简单,跟安装任何openwrt一样,先转成vmdk文件,添加现有硬盘即可。 我们继续物理机安装教程,首先,用balenaEtcher工具将gz安装包写入U盘,必须要这么做。 所以,请务必写入普通的U盘。 二、接入主机。 将U盘插入小主机,同时将内置硬盘也接入小…

    2023年4月4日
    54900
  • K8S 中使用kubectl工具远程连接K8S集群

    一、概述 一般情况下,在k8smaster节点上集群管理工具kubectl是连接的本地http8080端口和apiserver进行通讯的, 当然也可以通过https端口进行通讯前提是要生成证书。所以说kubectl不一定部署在master上,只要能和apiserver进行通讯, 所以你可以将kubectl部署在任何一台你想连接到集群的主机上,以下将介绍基于证…

    2023年5月29日
    11600
  • 内网穿透—nps

    nps nps是一款轻量级、高性能、功能强大的内网穿透代理服务器。目前支持tcp、udp流量转发,可支持任何tcp、udp上层协议(访问内网网站、本地支付接口调试、ssh访问、远程桌面,内网dns解析等等……),此外还支持内网http代理、内网socks5代理、p2p等,并带有功能强大的web管理端 做微信公众号开发、小程序开发等—-> 域…

    2022年6月7日
    70000
  • 华为s5735交换机配置ssh远程登陆

    (1)进入aaa模式 (2)创建用户和账户:local-user 用户名 password cipher 密码 (3)开启用户登陆方式是ssh:local-user 用户名 service-type ssh telnet (4)赋予用户权限:local-user 用户名 privilege level 级别 (5)开启stelnet服务:stelnet se…

    2023年4月10日
    16900
  • 如何快速查看 Kubernetes Pod 崩溃前的日志

    当pod处于crash状态的时候,容器不断重启,此时用 kubelet logs 可能出现一直捕捉不到日志。解决方法: kubectl previous 参数作用:If true, print the logs for the previous instance of the container in a pod if it e…

    2023年7月13日
    11900

发表回复

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

在线咨询: QQ交谈

邮件:712342017@qq.com

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

关注微信