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

相关推荐

  • 七层网络协议详细解释

    1、七层、五层、四层模型划分 互联网的本质就是一系列的网络协议,这个协议就叫OSI协议(一系列协议),按照功能不同,分工不同,人为的分层七层。实际上这个七层是不存在的。没有这七层的概念,只是人为的划分而已。区分出来的目的只是让你明白哪一层是干什么用的。 每一层都运行不同的协议。协议是干什么的,协议就是标准。 实际上还有人把它划成五层、四层。 七层划分为:应用…

    2022年8月21日
    1.3K00
  • 使用 netstat 命令来管理各个端口的网络连接

    了解 netstat NETSTAT命令有什么作用?NETSTAT一般用于显示与IP 、TCP 、UDP 和ICMP 协议相关的统计数据,一般用于检测本机各端口的网络连接情况。netstat 是一个快速收集你的服务器网络连接信息的有用工具。定期网络监测是了解你的系统的重要组成部分,对帮助你保持你的系统安全有着重要意义。将这一步纳入你的日常…

    2022年6月10日
    1.3K00
  • Traceroute(路由追踪)的原理及实现

    现实世界中的网络是由无数的计算机和路由器组成的一张的大网,应用的数据包在发送到服务器之前都要经过层层的路由转发。而Traceroute是一种常规的网络分析工具,用来定位到目标主机之间的所有路由器 原理 在介绍Traceroute的原理之前,需要了解几个技术名词: 具体到traceroute的实现细节上,有两种不同的方案: 基于UDP实现 在基于UDP的实现中…

    2023年4月12日
    89900
  • 一款好用的网络检测工具——mtr

    当客户端访问目标服务器或负载均衡,使用 ping 命令测试出现丢包或不通时,可以通过 MTR 等工具进行链路测试来判断问题来源。 mtr (My traceroute)是结合了 traceroute 命令和 ping 命令功能网络诊断工具。 mtr基本原理 网络诊断工具,例如 ping、traceroute、mtr 都使用的 “ICMP” 包来测试…

    2023年6月27日
    1.1K00
  • Stream流式编程

    如何创建 Stream 对象 从集合创建:我们可以通过调用集合的 stream() 方法来创建一个 Stream 对象。例如: 从数组创建:Java 8 引入了 Arrays 类的 stream() 方法,我们可以使用它来创建一个 Stream 对象。例如: 通过 Stream.of() 创建:我们可以使用 Stream.of() 方法直接将一组元素转换为 …

    2023年9月4日
    79900

发表回复

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

在线咨询: QQ交谈

邮件:712342017@qq.com

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

关注微信