热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

基于eBPF的云原生可观测性开源项目Kindling之容器网络定界

背景随着kubernetes逐渐成为应用部署的事实标准,开发运维人员可以更便捷的部署、拓展应用程序,同时也带来了一系列的云上疑难杂症。其中最莫过于头疼

背景

随着kubernetes逐渐成为应用部署的事实标准,开发运维人员可以更便捷的部署、拓展应用程序,同时也带来了一系列的云上疑难杂症。其中最莫过于头疼的无非是网络问题。由于传统的虚拟机应用使用内核网络比较清晰,内核网络故障概率也比较少,问题往往出现在物理网络,即使问题出现在内核网络,也相对比较容易定界。而容器使用内核网络的方式出现了颠覆性的变化,比如使用了更多的二层、三层转发、不同namespace的通信、各种路由防火墙策略。在如此复杂的环境下,可能某一条网络规则的配置错误或者某个虚拟网络设备的状态不正常都会导致网络故障。

在如此复杂的网络场景下,我们的SRE或者研发工程师很难全局把控容器网络,可以说整个内核网络是一个黑盒。所以,面对这一系列的困境,kindling正在逐步尝试将内核网络白盒化以及帮助工程师确定是容器网络问题还是物理网络问题


Kindling的设想

基于以上问题,假如告诉用户数据包在哪个网络设备之后就“断链”是不是就能缩小问题的排查范围了呢?下图是flannel网络的vxlan模式通信图。

vxlan模式通信图

当podA发起一次调用podB的请求时,中间会经过veth设备、cni网桥、vxlan设备、物理网卡。


  • 对于该次请求而言,如果数据包已经从node1的ens192网卡上发送出去了,而node2并没有收到该次请求,则说明物理网络出现了问题。

  • 同理,对于该次请求而言,在cni0上和flannel.1之间出现了“断链”,则说明cni0和flannel.1之间的通信出现了问题。

接着,用户工程师可以在这个范围内去排查具体问题,比如:

物理网络问题,就看物理设备状态等。

cni0和flannel.1的通信问题则查看路由规则,防火墙策略等。

在这个基础上,用户工程师在排查类似网络问题时,不至于像无头苍蝇一样不知道如何下手,明确了在哪一阶段出现了问题


验证设想

为此,笔者动手使用eBPF去hook了一系列网络路径相关的函数,并且构造了一个cni0和flannel.1通信故障的场景。

使用以下命令开启阻断flannel.1设备接收数据包:

tc qdisc add dev flannel.1 root netem loss 100%

于是,笔者看到了大量网络数据包形成了“断链”,如图所示,该skb在经过cni0之后并没有如预想的那样到达flannel.1设备:



我们再来看看正常的网络数据包路径,使用以下命令关闭阻断:

tc qdisc del dev flannel.1 root netem loss 100%

很明显,如下图所示,数据包传输正常了:


如何实现


大致思路

由于数据包在内核中都会以sk_buff数据结构传递,所以我们只需要追踪容器网络中skb会触达的关键函数。由于不同的CNI会对容器发送的原始数据包进行不同的处理,比如flannel的vxlan模式会在容器以太网帧外增加vxlan头和一些主机的ip信息,所以skb的包头往往不能作为串联起这一串函数的key。我们选择skb的内存地址作为key,但是内存地址也会带来很多问题,比如skb的fclone机制和复用机制会影响key作为唯一值的判断。


追踪点位(函数)


  • 核心点位:net_dev_start_xmit(网卡发包)、netif_receive_skb(网卡收包)

  • 辅助判断点位:__kfree_skb、net_dev_alloc_skb

为什么选择这些点位,选择的标准是什么?


  1. 靠近网卡或者网络设备收发包,用于判断skb是否到达网络设备,net_dev_start_xmit和netif_receive_skb分别靠近网络设备收和发包,所以选择这两个点位作为主要数据来源

  2. 除了主要数据的来源,我们还需要一些点位来知道skb一次使命的完成(笼统点来说就是一个包处理完成)。而完成的标志往往是这个skb代表的内存地址被释放,重新申请或者复用,所以我们有了以下很多选择来组合使用:


  • 申请skb内存: alloc_skb、alloc_skb_fclone、dev_alloc_skb、netdev_alloc_skb
  • 释放skb内存: __kfree_skb

这些hook点被调用都非常频繁,为了尽量少的去hook,我们选择了kfree_skb+net_dev_alloc_skb,选择kfree_skb是因为释放的时候作为终点是最及时的,选择net_dev_alloc_skb是因为他不单单使用__alloc_skb来申请内存,而且有复用的逻辑,所以也必须解决这个场景,请看下列代码:

struct sk_buff *__netdev_alloc_skb(struct net_device *dev,unsigned int length, gfp_t gfp_mask)
{struct sk_buff *skb &#61; NULL;unsigned int fragsz &#61; SKB_DATA_ALIGN(length &#43; NET_SKB_PAD) &#43;SKB_DATA_ALIGN(sizeof(struct skb_shared_info));if (fragsz <&#61; PAGE_SIZE && !(gfp_mask & (__GFP_WAIT | GFP_DMA))) {void *data;if (sk_memalloc_socks())gfp_mask |&#61; __GFP_MEMALLOC;data &#61; __netdev_alloc_frag(fragsz, gfp_mask);if (likely(data)) {// 复用逻辑skb &#61; build_skb(data, fragsz);if (unlikely(!skb))put_page(virt_to_head_page(data));}} else {// else选择了 __alloc_skbskb &#61; __alloc_skb(length &#43; NET_SKB_PAD, gfp_mask,SKB_ALLOC_RX, NUMA_NO_NODE);}if (likely(skb)) {skb_reserve(skb, NET_SKB_PAD);skb->dev &#61; dev;}return skb;
}

另外&#xff0c;fclone是较新版 kernel 中添加的一个特性&#xff0c;以前版本的 kernel 中 skb 在分配的时候都是 从后备高速缓存(lookaside cache)skbuff_head_cache 中获取 sk_buff 的结构&#xff1b;而现在可以 在调用 alloc_skb()&#xff0c;通过 fclone 参数选择从 skbuff_head_cache 或者 skbuff_fclone_cache 中分配。两者的区别在于 skbuff_head_cache 在创建时指定的单位内 存区域的大小是 sizeof(structsk_buff)而 skbuff_fclone_cache 在创建时指定的单位内存区域大小是 2*sizeof(struct sk_buff)。所以&#xff0c;一个内存地址可能完成两次使命&#xff0c;如果单单为了解决这个问题而去hook __alloc_skb 那无疑是不值得的&#xff0c;所以我们选择从skb的数据结构中或者fclone的值&#xff0c;来判断是否进入了该逻辑。

于是&#xff0c;我们针对这些hook点做了如下的数据分析&#xff1a;


​额外的问题


  • 为了判断skb最终有没有从物理网卡出去&#xff0c;我们需要智能或者手动配置物理网卡的名称或者mac地址&#xff0c;这里智能识别选择了收发包最多的网卡作为物理网卡&#xff0c;这个逻辑在大部分场景下是没有问题的。为了防止意外情况&#xff0c;也提供了手动配置的方式

  • 对于同主机pod的调用&#xff0c;用路由来识别&#xff0c;发现路由指向本机&#xff0c;则过滤掉这些数据&#xff0c;因为这些数据会影响“断链”的判断

  • 为了性能考虑&#xff0c;只传递出起始点到终点时间比较长的数据&&最终目的地不是容器网卡或者物理网卡的数据


最终事件


字段

描述

类型

tuple

eth0网卡抓到的四元组

tuple

devs[]

网络设备序列

char[]

duration

起始点到终点的时间段&#xff0c;比如容器网卡到物理网卡的时间

u32


性能损耗

​可以看出&#xff0c;由于网络函数被触发频率比较高&#xff0c;所以在5000左右的tps下还是给用户程序的cpu造成了13%的额外损耗。

Kindling是一款基于eBPF的云原生可观测性开源工具&#xff0c;旨在帮助用户更好更快的定界云原生系统问题&#xff0c;并致力于打造云原生全故障域的定界能力。

Kindling项目地址&#xff1a;Kindling

在云可观测性方面有任何疑问欢迎与我们联系&#xff1a;Kindling官网


推荐阅读
  • 单片微机原理P3:80C51外部拓展系统
      外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
  • 三角测量计算三维坐标的代码_双目三维重建——层次化重建思考
    双目三维重建——层次化重建思考FesianXu2020.7.22atANTFINANCIALintern前言本文是笔者阅读[1]第10章内容的笔记,本文从宏观的角度阐 ... [详细]
  • 如果应用程序经常播放密集、急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了。因为MediaPlayer存在如下缺点:1)延时时间较长,且资源占用率高 ... [详细]
  • 解决Only fullscreen opaque activities can request orientation错误的方法
    本文介绍了在使用PictureSelectorLight第三方框架时遇到的Only fullscreen opaque activities can request orientation错误,并提供了一种有效的解决方案。 ... [详细]
  • 本文回顾了作者初次接触Unicode编码时的经历,并详细探讨了ASCII、ANSI、GB2312、UNICODE以及UTF-8和UTF-16编码的区别和应用场景。通过实例分析,帮助读者更好地理解和使用这些编码。 ... [详细]
  • 网站访问全流程解析
    本文详细介绍了从用户在浏览器中输入一个域名(如www.yy.com)到页面完全展示的整个过程,包括DNS解析、TCP连接、请求响应等多个步骤。 ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • 本文介绍如何使用 Python 的 DOM 和 SAX 方法解析 XML 文件,并通过示例展示了如何动态创建数据库表和处理大量数据的实时插入。 ... [详细]
  • com.hazelcast.config.MapConfig.isStatisticsEnabled()方法的使用及代码示例 ... [详细]
  • 如何在Java中使用DButils类
    这期内容当中小编将会给大家带来有关如何在Java中使用DButils类,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。D ... [详细]
  • php更新数据库字段的函数是,php更新数据库字段的函数是 ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • Docker 中创建 CentOS 容器并安装 MySQL 进行本地连接
    本文详细介绍了如何在 Docker 中创建 CentOS 容器,并在容器中安装 MySQL 以实现本地连接。文章内容包括镜像拉取、容器创建、MySQL 安装与配置等步骤。 ... [详细]
  • 本文详细介绍了MySQL数据库的基础语法与核心操作,涵盖从基础概念到具体应用的多个方面。首先,文章从基础知识入手,逐步深入到创建和修改数据表的操作。接着,详细讲解了如何进行数据的插入、更新与删除。在查询部分,不仅介绍了DISTINCT和LIMIT的使用方法,还探讨了排序、过滤和通配符的应用。此外,文章还涵盖了计算字段以及多种函数的使用,包括文本处理、日期和时间处理及数值处理等。通过这些内容,读者可以全面掌握MySQL数据库的核心操作技巧。 ... [详细]
  • 本文详细解析了使用C++实现的键盘输入记录程序的源代码,该程序在Windows应用程序开发中具有很高的实用价值。键盘记录功能不仅在远程控制软件中广泛应用,还为开发者提供了强大的调试和监控工具。通过具体实例,本文深入探讨了C++键盘记录程序的设计与实现,适合需要相关技术的开发者参考。 ... [详细]
author-avatar
大约在冬季1122_867
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有