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

相关推荐

  • 网站常见错误代码及解决方案

    有时候大家在打开网页时会遇到各种各样的错误报告,比如404,500之类的,这些错误是服务器接到浏览器的请求后访回的状态码,专业术语叫服务器信息头,不同的状态码有不同的含义,了解一些有利于搞清楚哪里出了问题。 注:本文仅供学习 一、HTTP4xx(请求错误) HTTP错误400 由于语法格式有误,服务器无法理解此请求。不作修改,客户程序就无法重复此请求。 HT…

    2022年6月13日
    82200
  • iStoreOS,新增备份系统教程

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

    2023年4月4日
    1.6K00
  • iptables与firewalld的区别

    iptables与firewalld的区别 firewalld可以动态修改单条规则,动态管理规则集,允许更新规则而不破坏现有会话和连接。而iptables,在修改了规则后必须得全部刷新才可以生效; firewalld使用区域和服务而不是链式规则; firewalld默认是拒绝的,需要设置以后才能放行。而iptables默认是允许的,需要拒绝的才去限制; fi…

    2022年8月9日
    49800
  • nexttrace(开源的全能可视化网络路由追踪工具)的安装

    nexttrace是一款开源可视化的路由追踪工具 nexttrace 是一个用 Go 语言编写的高性能、轻量化的分布式追踪系统。它是一个命令行工具,在命令行使用可以展示清晰的 TraceRoute 路由信息,同时支持根据地图进行可视化的展示,看完一目了然。 如何安装使用 使用如下方式即可安装 nexttrace 工具: 使用示例 DEMO nexttrace…

    2023年4月12日
    42400
  • 如何快速查看 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日
    34700

发表回复

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

在线咨询: QQ交谈

邮件:712342017@qq.com

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

关注微信