Hello folks,我是 Luga,今天我们来聊一下“监控”话题,主要是云原生生态下针对 Container 的监控,这里,主要探讨的是“技术”层面。
自从近十年前 Docker 和 Kubernetes 等容器相关技术发展以来,容器改变了大家对资源管控的认知,容器基于共享底层 OS 内核,将应用程序的执行环境彼此隔离。同时,通常以兆字节为单位,使用的资源比虚拟机少很多,而且启动速度较高。除此之外,基于容器可以做到在相同的硬件上更密集地打包,而不需要花费太多的精力和开销,从而达到“降本增效”之效。
的确,容器技术的天生优势很多,然而,其最大缺点之一便是难以对其整个体系进行有效性“监控”,尤其是容器的“短暂性”,再加上它们从托管它们的服务器中抽象出来,使得很难以高效、有效的方式从容器中收集监控数据。
幸运的是,随着技术的革新,新技术的不断涌现,有一种很有前途的新技术可以为容器监控难题提供解决方案。它称为 eBPF,基于此技术,使得我们对传统的监控 Docker 和 Kubernetes 工作负载的思想及方法进行颠覆性创新。
基于传统模型
在传统理念中,想要能够“全方位”对容器进行有效监控,开发人员、运维人员或 DevOps 工程师面临着如下共同的挑战:
1、基于不同的业务场景,针对某一个应用程序,其可能包含数十个甚至数百个单独的容器部署。同时,每个容器都必须进行单独监控,从而增加了部署监控代理以及从每个容器中收集必要数据所需的工作成本。
2、基于容器生命周期状态而言,当某一容器因各种不同的原因导致关闭时,存储在容器内的数据就会消失,而且通常无法准确预测容器何时可能关闭。因此,我们便不能定期拉取监控数据。这与我们所设想的初衷不匹配,期望能够实时收集从每个容器中进行数据获取。
3、除此之外,由于容器是从托管它们的服务器的操作系统中抽象出来,并且,基于不同的环境,它们可能需要在不同的 Node 周围进行飘移,所以,基于主机的监控方法效果往往达不到预期的需求。使得无法能够轻松地在每台服务器上运行代理并使用其来监视所有容器。
其实,从本质上而言,目前市场上有多种方案可供选择以解决上述各种挑战,但最流行、通用的策略便是使用所谓的 Sidecar 模式来部署容器监控代理。在 Sidecar 模式下,监控代理能够在特殊容器内运行,这些容器与它们监控的容器一起运行。这种方法比尝试在主机上部署监控代理更有效。它还消除了直接从应用程序逻辑中公开监控数据的需要,这需要对源代码进行复杂的更改。
在 Sidecar 模型中,可观察性或安全工具作为 Sidecar 容器注入到每个 Pod 中。需要注意的是,Sidecar 也是一个容器,Pod 中的所有容器都可以共享网络命名空间和卷信息等内容,所以 Sidecar 可以看到 Pod 中其他容器中发生的事情。为了在 Pod 里部署 Sidecar,需要在 YAML 中进行配置。这项操作可以是手动进行,也可能是自动进行。当然,可以将 Sidecar 定义注入应用程序 YAML,从而实现自动化部署。
然而,基于 Sidecar 模式有一个天生的缺点:资源的敏感性,即它不能充分有效地使用资源。必须在承载实际工作负载的每个容器旁边部署一个边车容器,这意味着在实际的生产环境中我们最终会运行更多的容器。由于所有这些额外的容器都需要 CPU 和内存资源,因此它们会为我们所构建的容器集群预留更少的资源。
除此之外,Sidecar 模式另一个缺陷便是“配置的合规性”,如果 Sidecar 没有得到正确的配置,便无法在 Pod 中正常运行。这是 Sidecar 另一个脆弱点,如果恶意用户设法运行了一个 Pod,并避免了 Sidecar 的注入,那就无法看到该 Pod 中发生了什么。
基于 eBPF 模型
eBPF 提供了一种方法来解决这个问题,即在不消耗大量资源的情况下监控每个容器。eBPF 给 Linux内核带来了可编程性,由于其安全、灵活、对应用无侵入的特点,在云原生网络、安全、可观测性方面带来了很多创造性的应用。
eBPF 于 2015 年推出,是 Linux 的一项功能,可以直接在 Linux 内核中运行程序,而不是在无法直接访问内核资源的“用户空间”中运行程序。
eBPF 源于 BPF,本质上是处于内核中的一个高效与灵活的虚类虚拟机组件,以一种安全的方式在许多内核 Hook 点执行字节码。BPF 最初的目的是用于高效网络报文过滤,经过重新设计,eBPF 不再局限于网络协议栈,已经成为内核顶级的子系统,演进为一个通用执行引擎。开发者可基于 eBPF 开发性能分析工具、软件定义网络、安全等诸多场景。
eBPF 架构原理
总体而言,eBPF 分为 User Space(用户空间)程序和 Kernel Space(内核)程序两部分:
1、User Space 程序负责加载 BPF 字节码至内核,如需要,也会负责读取 Kernel Space 回传的统计信息或者事件详情;
2、Kernel Space 中的 BPF 字节码负责在 Kernel Space 中执行特定事件,如需要,也会将执行的结果通过 maps 或者 perf-event 事件发送至 User Space。
其中 User Space 程序与 Kernel Space BPF 字节码程序可以使用 map 结构实现双向通信,这为 Kernel Space 中运行的 BPF 字节码程序提供了更加灵活的控制。
关于 eBPF 的架构参考,如下图所示:
基于上述的架构图,我们可以看到整个工作原理涉及如下:
1、eBPF 程序基于事件驱动,并附加到代码路径上。代码路径包含特定的触发器(称为钩子),这些触发器在传递时执行任何附加的 eBPF 程序。钩子的一些示例包括Network Events(网络事件)、System Calls(系统调用)、Functions Entries(函数入口)和Kernel Tracepoints(内核跟踪点)等。
2、触发时,代码首先编译为 BPF 字节码。反过来,字节码在运行前会经过验证,以确保它不会创建循环。此步骤可防止程序意外或故意损害 Linux 内核。
3、在 Hook 触发程序后,它会进行由内核预先定义好的 Helper 调用。通常,这些调用主要为 eBPF 配备多种访问内核功能的函数。
eBPF 最初被用作在过滤网络数据包时提高可观察性和安全性的一种方式。然而,随着时间的推移,它成为使用户提供的代码实现更安全、更方便、性能更好的一种方式。由于在内核中运行,eBPF 程序消耗的资源往往较少,不仅如此,其还可以访问在他们运行的服务器上运行的任何进程所产生的数据。
eBPF 核心优势
从本质上来讲,eBPF 的闪亮点主意体现在“观测”和“安全” 2 个层面,其主要应用于 “追踪” User Space 进程。基于如上,其优势主要涉及如下:
1、高性能
eBPF 可以将数据包处理从 Kernel Space 移动到 User Space。同样,eBPF 是一个准时(JIT)编译器。编译字节码后,将调用 eBPF,而不是对每种方法的字节码进行新的解释,基于此种机制,极大地提高了效率。
2、可编程性
使用 eBPF 有助于在不添加额外层的情况下提高环境的功能丰富度。同样,由于代码直接在内核中运行,因此可以在 eBPF 事件之间存储数据,而不是像其他跟踪器那样转储数据。
3、安全性
程序被有效地沙箱化了,这意味着内核源代码仍然受到保护并保持不变。eBPF 程序的验证步骤确保资源不会被运行无限循环的程序阻塞。
4、侵入性低
与构建和维护内核模块相比,创建 Hook 内核函数的代码的工作更少。当用作调试器时,eBPF 不需要停止程序来观察其状态。
以上为最为核心的优势,当然,除了上述之外,也有其他的优势:例如,单一、强大且可访问的跟踪流程框架;强劲的表现力等等。
eBPF 应用场景
eBPF 的真正强大之一是低侵入性,也意味着无需改动就可以让程序在内核中运行,使得其能够观测到所有的容器和 Pod 中发生的事情,不需要在任何地方修改任何YAML,也不需要在应用程序中添加脚本。这就是为什么有许多新项目基于 eBPF 以及这种技术令人兴奋的原因之一。
eBPF 正在或已经在云原生生态体系中获得较为广泛的关注及青睐。基于此,若使用 eBPF 技术,其应用场景主要涉及如下:
1、基于内核层面的观测性
在此种场景下,eBPF 能够更快、更准确地进行切入,也不涉及上下文切换带来的性能影响;除此之外,eBPF 程序是基于事件型的,因此,没有特定的触发器,任何额外的事件都不会运行。
2、传统监控力不从心
在分布式和基于容器的环境中,eBPF 能够将“监控”之力发挥的淋漓尽致,尤其是在一些进程可视化场景中。eBPF 可以访问有关进程和在这些进程中运行的程序的信息,也有关于网络流量的信息。如果我们将这些信息结合在一起,进行整合,那么就会得到这样的信息:可以确切的看到哪个进程、在哪个 Node 上、在哪个 Pod 中、在哪个命名空间、正在运行什么可执行文件、在处理哪个特定的网络连接等。毕竟,在这些环境中,eBPF 可以缩小可见性差距,提供 HTTP 流量的可见性。
因此,基于上述所述,如果你想监控容器,那么,则可以编写一个 eBPF 程序,拦截与每个容器相关的进程,并进行监控数据收集。最终会得到一个比传统的 Sidecar 容器占用更少资源的监控解决方案。
同时,不必在为监控目的收集的数据量上做出妥协。实际上,大家所想要的关于每个容器的状态和性能的每条信息都可以通过内核获得。
使用基于 eBPF 的监控方法,甚至部署和管理也变得更简单。我们不必部署和编排一堆 Sidecar 容器,只需在 K8s Cluster 中的每个 Node 上运行一个 eBPF 程序即可。可能大家会问,如果 eBPF 是容器监控的绝佳解决方案,为什么不是每个人都在使用它?
“你怎么知道别人没有在用?” 这里面涉及的因素较多,可能因为技术的成熟度、也许因为人的懒惰性,但这也不能阻止新技术的革新、新技术的侵入。可能大多数现有的容器监控工具都被设计为基于 Sidecar 模式,而不是利用 eBPF。但这种现象已经在逐渐改变。Cilium 等工具已经在使用 eBPF 来提高效率和可见性。许多可观察性供应商——例如 VMware、Splunk 和 New Relic 等等——也在探讨 eBPF 的潜力,将其进行封装集成。
因此,如果你觉得传统的容器监控方法不如法眼、太他妈的 Low,尤其是在降本增效方面,此种策略耗尽我们的应用程序或资源并且难以管理,那么不妨考虑尝试一下 eBPF,或许,它会给你带来不一样的惊喜~
Adiós !