首页 > 其他分享 >如何在 Kubernetes 下轻松抓取应用网络包

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

时间:2023-05-24 13:44:05浏览次数:35  
标签:sniff Kubernetes 宿主机 抓取 轻松 Pod tcpdump 抓包

在 Kubernetes 的实际使用过程中,我们经常会碰到一些业务上的异常问题,一般情况下通过日志监控和链路追踪足以能够对问题做出排查与诊断了。但是,在某些场景下,只靠这些手段往往是不够的,一些和网络相关的问题有时候非常棘手。

奇妙的Linux世界 Linux 爱好者聚集地,各种硬核干货文章和新奇内容推荐,定期发放福利红包。快加入我们,一起愉快玩耍! 223篇原创内容 公众号


我通过身边的案例观察到,服务上线出现问题时,通常具备网络排查能力的工程师,不论是在定位问题,还是在解决问题上,都会比不具备该能力的工程师快上很多。

所以。。。对开发工程师来说,学会在 Kubernetes 里抓包 是一项非常重要的技能,下面我来和大家分享一下,在 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 

思考

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

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

#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 -

思考

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

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

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

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

所以...上面两个方法不是说不能用,只能说不是最好的解决方案罢了。

#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 -

思考

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

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

非常好的一个问题,社区正好提供了 ksniff[4] 这个插件替我们解决了这个难题,下面我们一起来看一下吧。

#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 进行抓包,如下图

图片wireshark

以下是 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


其余参数大家可以自行摸索做一下尝试。

推荐阅读

  • Ksniff: packet capture at pod level for k8s[5]

总结

文章主要分享了在 Kubernetes 下是如何进行网络抓包的,并不涉及抓包分析技术。说到底,抓包技术主要还是要学会 tcpdump 和 Wireshark 这两个工具的用法,抓包分析技术其实是一门实践课,理论看得再多,用处也不大。

它需要的是实践...再实践...

参考资料

[1]

无发行版镜像: https://github.com/GoogleContainerTools/distroless

[2]

Ephemeral Containers: https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers/

[3]

nicolaka/netshoot: https://github.com/nicolaka/netshoot

[4]

ksniff: https://github.com/eldadru/ksniff

[5]

Ksniff: packet capture at pod level for k8s: https://kubesandclouds.com/index.php/2021/01/20/ksniff/

 

本文转载自:「Cloud Native 101」,原文:https://url.hi-linux.com/fqjqt,版权归原作者所有。欢迎投稿,投稿邮箱: [email protected]

标签:sniff,Kubernetes,宿主机,抓取,轻松,Pod,tcpdump,抓包
From: https://www.cnblogs.com/cheyunhua/p/17428067.html

相关文章

  • Kubernetes(k8s)最大启动时长研究
    一、前言应用部署在Kubernetes(k8s)上,有些应用启动慢一些,没启动好就又被k8s重启了二、处理过程1.看日志[2023-05-2314:38:52.249]|-INFO|-[background-preinit]|-o.h.v.i.u.Version[0]|-[TID:N/A]|-HV000001:HibernateValidator6.1.7.Final[2023-05-2314:40:11.817]|-......
  • 2步轻松实现ASP.NET Core托管服务执行定时任务
    最近接到一个新项目,需要在项目里添加一个后台任务,定时去发邮件通知客户;由于是一个比较小型的项目,不希望引入Quartz.Net、Hangfire等太重的框架,同时也没持久化要;寻觅了一下发现ASP.NETCore本身带有托管服务,可以执行定时任务。ASP.NETCore提供了IHostedService接口,它使我们能够创......
  • 【CentOS 7系统管理员必看】如何轻松检测软中断,优化系统性能?
    在CentOS7中,软中断是一种中断类型,它由内核发起并在内核空间中执行,用于处理网络、存储和其他异步事件。软中断的主要工作是将网络数据包、磁盘IO等异步事件传递给应用程序的工作队列中,以便应用程序可以及时处理这些事件。然而,如果软中断的数量过多,就会对系统的性能产生负面影响,......
  • kubernetes部署Open-LDAP、Go-admin-ldap
    1.搭建openLDAP1.1.创建命名空间kubectlcreatenamespacekube-ops1.2.创建pvc存储使用的是nfs方式挂载,storageClassName为默认,所以可写可不写。mkdir-p~/ldap;cd~/ldapcat>pvc.yaml<<EOFapiVersion:v1kind:PersistentVolumeClaimmetadata:name:ldap-dat......
  • Kubernetes 控制平面组件:etcd
    Kubernetes控制平面组件:etcd¶etcd¶Etcd是CoreOS基于Raft开发的分布式key-value存储,可用于服务发现、共享配置以及一致性保障(如数据库选主、分布式锁等)。在分布式系统中,如何管理节点间的状态一直是一个难题,etcd像是专门为集群环境的服务发现和注册而设计,它提供了数据TTL失......
  • Kubernetes 初始化容器及静态Pod和Pod调度策略
    初始化容器kubernetes1.3版本引入了initcontainer初始化容器特性。主要用于在启动应用容器(appcontainer)前来启动一个或多个初始化容器,作为应用容器的一个基础。#查看要修改的内核参数[root@kmaster~]#sysctl-a|grepvm.overcommit_ratiovm.overcommit_ratio=50#输......
  • 数据抓取使用HTTP隧道代码示例
    以下是使用Python的requests库实现HTTP隧道的代码示例:```pythonimportrequests#设置代理服务器地址和端口号proxy_host='127.0.0.1'proxy_port='8888'#设置目标网站URLurl='ExampleDomain'#创建Session对象session=requests.Session()#设置代理服务器session.proxies......
  • Kubernetes编程——什么是 Kubernetes 编程?
    什么是Kubernetes编程?  这里的Kubernetes编程指开发原生Kubernetes应用,这类应用通过与API服务器进行开发,直接查询、更新资源的状态。 这里不会在`Controller`和`Operator`中,这里也不会过多关注操作层面的东西,而是会关注开发和测试的阶段。 因此,我们会聊下......
  • 解决Anroid7.0以上版本无法抓取微信浏览器中Https请求
    为什么安卓7.0以上的系统,微信7.0版本以上无法抓取https包?原因:1.安卓7.0之后,提高了系统安全性。APP默认不信任用户域的证书2.微信7.0以后更新了安全机制,加入了防止中间人attack的机制详情可搜索sslpinning了解防止中间人attackSSLPinninghttps的网站使用使用伪证书可以抓到,但app......
  • Java开发 Shiro框架详解(轻松入门)
    ShiroShiro简介什么是Shiro?ApacheShiro是一个Java的安全(权限)框架。Shiro可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE环境,也可以用在JavaEE环境。Shiro可以完成,认证,授权,加密,会话管理,Web集成,缓存等.官网:shiro.apache.org/官方文档十分钟快速入门:shiro.a......