本文分享了如何将 eBPF 作为一种新的云原生技术来改善可观察性和安全工作流。入门门槛可能会很高,使用 eBPF 工具来辅助调试生产环境问题的步骤可能会很多。本文将学习如何使用现有工具并解决可观察性存储、警报和仪表盘方面的挑战。最好的工具就像备份一样——如果没有经过验证,它们就毫无用处。你将了解到混沌工程如何为我们提供帮助,并了解基于 eBPF 的可观察性和安全用例。通过专业的方式解决这些问题也为混沌工程本身带来了新的想法。文中还讨论了我们需要做的工作和需要面临的风险,并提出了未来调试生产环境问题需要改进的愿望清单。
开始使用 eBPF
使用 eBPF 程序和工具有多种方式,已经有太多的文章和建议,可能会让人感到不知所措。首先,我们需要定义用例和要解决的问题。获取更多底层监控指标是否有助于更快地解决生产事故?也许 Kubernetes 集群的安全性存在不确定性,我们是否有方法观察和减少恶意行为?微服务容器环境是一个观察行为和数据的好地方——但与在运行单体应用程序的虚拟机上读取文件相比,访问微服务数据通常更加困难。
调试和诊断生产环境问题:eBPF 用例
我们来看看实际的用例和工具,从中获得调试灵感,并弄清楚如何验证它们是否运行正常。
通过将额外收集的数据转换为指标和跟踪信息,eBPF 为我们带来了可观察性方面的好处。例如,我们可以使用自定义 Prometheus Exporter 收集底层的内核指标。更多面向开发人员的获得可观察性的方法是自动检测源代码,以便更好地了解应用程序性能,Pixie 就为开发人员提供了可用于获取可观察性的脚本语言。Coroot 用 eBPF 实现了 Kubernetes 服务映射,跟踪容器之间的流量,并提供 Ops/SRE 生产环境健康状况信息。Parca 的连续分析通过函数符号展开技术来跟踪应用程序代码内部的调用和性能。
安全是另一个 eBPF 可以为我们提供帮助的关键领域:检测未经授权的系统调用、回调连接或由恶意行为者(如比特币矿工或 rootkit)植入的事件系统调用。例如,Cilium 就提供了安全可观察性,并通过 Tetragon 进行预防。Aqua Security 的 Tracee 可以在 CLI 和 CI/CD 中使用,用于检测恶意行为。Falco 是一种 Kubernetes 威胁检测引擎,可能是云原生生态系统中最成熟的解决方案。GitLab 安全团队提供了一个特殊的用例,他们通过扫描包依赖安装脚本(例如 NodeJS 中的 package.json)来防止供应链攻击。
SRE/DevOps 团队需要合适的工具来进行快速调试,并在更接近全局的视图上查找根本原因。一些工具套件,如 Inspektor Gadget,可用于在 Kubernetes 中跟踪传出连接、调试 DNS 请求,等等。Caretta 可用于可视化服务依赖关系图。安全分发 eBPF 程序也需要新的想法:Bumblebee 通过利用 OCI 容器格式来打包 eBPF 程序,使其变得更加容易分发。
可观察性挑战
我们有多种可观察性数据类型,它们用于调试生产事件、分析应用程序性能、了解已知问题并看到潜在的未知问题。它们需要不同的存储后端,导致了我们的 DIY 疲劳。随着 eBPF 探针数据引入了更多的类型和来源,而我们无法将其转换为现有数据,这可能会让情况变得更加复杂。我们可能需要统一的可观察性数据存储,它需要具备伸缩性,以便存储大量的数据。
要处理某个故障,我们需要哪些确切的数据?诊断软件回归问题呢?找到最佳的数据保留期限是很困难的。自托管的存储后端也不可行,而 SaaS 可能又太贵。此外,我们还需要考虑成本效益和容量规划,这些有助于估算未来可观察性数据存储的增长。GitLab 基础设施团队推出的开源项目 Tamland 可以帮助我们进行容量规划和预测。
要从 eBPF 数据中获得更多的好处和洞察力,需要我们将其与警报和仪表盘集成在一起。如何减少公开的故障数量,并利用更多可用的洞察力来检测和修复问题?要进行异常检测、预测和趋势计算,我们需要整体的健康状态数据、与故障管理数据的交叉引用和“所有生产数据”——因为在微服务世界中,我们不会再去回答诸如“我的服务是否正常”这样的问题。
一个满是绿色的仪表盘,所有阈值都显示“OK”,但这并不能证明警报机制在正常工作,或者可以根据仪表盘信息快速解决关键问题。数据收集本身也可能受影响或遭到破坏,例如 eBPF 程序未按预期运行或生产环境发生了奇怪的内核错误。这带来了一个与模拟生产环境相关的问题:混沌工程——以可控的方式来破坏事物,验证服务级目标(SLO)、警报和仪表盘。我们可以用自己的经验来扩展混沌框架,例如用于云原生混沌工程的 Chaos Mesh,或集成到 CI/CD 工作流中的 Chaos Toolkit。来自混沌工程的模式也可以用于注入意外行为和执行安全测试,因为一切都会在随机混沌中有不同的表现,即使是安全漏洞。
破坏 eBPF 的可观察性
基于 eBPF 的工具和平台提供了极好的洞察力,有助于调试生产环境问题。这些工具和平台需要证明它们的优势并揭示它们的弱点,例如我们可以尝试破坏或攻击基础设施环境并观察工具 / 平台行为。我们先来关注可观察性和混沌工程。“金色信号”(延迟、流量、错误、饱和度)可以使用现有的混沌实验来验证,这些实验会注入 CPU/ 内存压力测试、TCP 延迟、DNS 随机响应等。
另一个实际的例子是收集底层的系统指标,包括 CPU、IO、内存。这可以使用 eBPF 的事件到 Prometheus 导出器来实现。为了验证收到的指标,现有的每一种类型(CPU、IO、内存压力、延迟)的混沌实验都可以帮助我们了解系统如何运行以及收集的数据是否有效。
开发人员可以从 Pixie 中受益,它提供了应用程序代码的自动增强能力,并在 Kubernetes 集群内创建服务映射。为了验证映射显示的数据是否正确,以及跟踪信息显示的是否是性能瓶颈,我们需要添加混沌实验来进行压力测试和网络攻击。然后,我们就可以看到服务映射和跟踪信息随着时间发生变化,并在生产故障发生之前对发现的问题行为采取行动。
对于 SRE 来说,可以通过安装 Inspektor Gadget 工具集合来有效地解决 Kubernetes 故障排除问题,帮助打破容器运行时黑盒的局限性。Inspektor Gadget 使用 eBPF 从容器通信路径上收集事件和指标,并将底层的 Linux 资源与高级的 Kubernetes 概念映射起来。这个工具集合提供了许多可用的 DNS、网络访问和内存分析部件,网站上将它们分类为建议、审计、profile、快照、top 和跟踪。你甚至可以使用“top ebpf”部件来可视化其他正在运行的 eBPF 程序的使用情况和性能。要测试它们的功能,建议单独运行它们,并进行与之匹配的混沌实验,例如,对于 DNS 请求,我们就随机返回或无响应。
安装 Coroot 并使用它的服务映射自动发现功能,我们可以实现更直观的 Kubernetes 故障排除和可观察性。可视化服务映射使用 eBPF 来跟踪容器网络连接,并使用 kube-state-metrics Prometheus 导出器中的指标将单个容器聚合为应用程序。Coroot 中的服务映射是混沌实验的绝佳目标——我们可以模拟影响服务的 TCP 连接(断开的或延迟的)或导致带宽增加的网络攻击,并验证仪表盘在故障条件下的状态。Coroot 还可以通过底层的 Prometheus 监控指标来检测 OOM 问题——对于泄漏内存的应用程序来说,这是一个完美的工具。在“Confidence with Chaos for your Kubernetes Observability”演讲中,我提供了一个演示用的示例应用程序,它只有在 DNS 失败时才会发生泄漏内存,就是专门针对这种情况的。
Parca 的持续分析(Continuous Profiling)功能使用 eBPF 来自动增强代码,这样开发人员就不需要为了添加分析调用而去修改代码,为他们节省了精力。Parca 代理会生成关于调用栈、函数调用时间的分析数据见解,有助于识别应用程序中的性能瓶颈。CPU/ 内存压力测试会影响应用程序行为,可以揭示竞态条件和死锁问题,并帮助我们了解我们要优化什么。
除了跟踪信息和日志,OpenTelemetry 还支持指标数据格式。有一个项目提供了用于内核、Kubernetes 集群或超级云的 eBPF 收集器。不同的收集器将指标事件发送到 Reducer(数据摄取器),它既支持将指标作为抓取端点提供给 Prometheus,也支持使用 gRPC 将它们发送到 OpenTelemetry 收集器端点。我们可以用已知的方式添加混沌实验:对系统进行压力测试,了解指标随着时间会发生怎样的变化。
最后但并非最不重要——一些场景涉及在高性能网络中作为 eBPF 程序运行运行的自定义 DNS 服务器。通过破坏 DNS 请求也有助于揭示它们的行为。
换一个角度:破坏 eBPF 的安全性
我们换一个角度,尝试破坏 eBPF 的安全性工具。一种方法是注入模拟权限升级的行为数据,并观察工具的反应。另一种方法是利用有数据分离要求的多租户环境,并模拟非预期的访问请求。
模仿攻击者通常很难,但当有人提到“跟踪系统调用、捕捉 rootkit 事件”,立刻引起了我的注意。搜索 Linux rootkit,我们会得到一些结果,了解它们有助于构建潜在的攻击模仿场景。在互联网上搜索 syscall hooking,可以找到更多资源,包括 tracee 维护人员关于使用 tracee 捕捉 rootkit 的演讲,其中涉及如何使用 Diamorphine rootkit。
在继续阅读和尝试运行示例之前,请不要在生产环境中做这些事情。创建一个隔离的测试虚拟机,下载并构建 rootkit,然后加载内核模块。它会隐藏自己并尽一切努力破坏系统。测试后删除虚拟机。
我们可以通过调用 Tracee CLI 来检测系统调用钩子。我们可以用下面的命令在 Docker 中运行 tracee——一个特权容器,映射了几个变量并指定要跟踪的事件“hooked_syscalls”。
问题是如何基于 rootkit 创建混沌实验?它并不是可靠的生产环境混沌测试,不过我们可以在生产环境中模拟 Diamorphine rootkit 的 getdents 系统调用 hook 方法,以此来验证是否触发了警报。
Cilium Tetragon 也通过类似的方式使用 eBPF 来检测恶意行为,并揭示了有关 rootkit 行为的新见解。检测和规则引擎显示了 rootkit 的夜间活动扩展到在给定端口上生成具有随机名称的进程。
我们来想象一个更实际的场景:运行在云虚拟机上、Kubernetes 集群中以及 CI/CD 部署环境中的比特币挖矿恶意软件。检测这些模式是问题的一部分——预防入侵是另一个尚未被解决的问题。我们仍然不建议在生产环境中基于 rootkit 构建混沌实验——但可以在 eBPF 程序中模拟系统调用负载。
这让我想到了一个新提议:构建仅用于模拟的混沌测试 rootkit。例如,hook getdents 系统调用,获取目录文件列表,然后就可以验证安全工具是否能够检测到模拟的安全问题。如果可能,模拟更多之前了解到的攻击。训练 AI/ML 模型也是一种有趣的用例,可以提供额外的模拟攻击来验证 eBPF 的安全工具和平台。
如何让混沌工程从 eBPF 中受益
在准备 QCon 伦敦的演讲时,我想到将 eBPF 作为一种为混沌实验收集和注入数据的方法。如果 eBPF 允许我们访问内核底层的信息,我们就可以修改数据并模拟生产事故。有一篇关于“通过系统调用最大化混沌工程错误注入现实性”的研究论文,其中介绍了 Phoebe 项目,它利用 eBPF 来捕获和控制系统调用。
现有的混沌实验发生在用户级别。例如,Chaos Mesh 中的 DNS Chaos 被注入到负责处理 Kubernetes 集群中所有 DNS 请求的 CoreDNS 中。如果有一个运行在内核中的 eBPF 程序,在 DNS 请求到达用户空间对其进行 hook 会怎样?它可以分析 DNS 请求,并通过为解析器请求返回错误响应来注入混沌。Xpress DNS 项目已经做了一些这方面的工作。这是一个用 BPF 编写的实验性 DNS 服务器,用于生成高吞吐量和低延迟的 DNS 响应。运行在用户空间的应用程序可以向 BPF 映射中添加 / 更改 DNS 记录,内核 eBPF 程序会读取 BPF 映射。这可以成为使用 DNS 和 eBPF 进行新的混沌实验的入口点。
基于所有已知的与 eBPF 混沌注入相关的想法,我们可以创建新的混沌实验来模拟 rootkit 行为,并以此来验证安全可观察性。通过拦截流量来制造 TCP/UDP 和 DNS 的延迟、增加 CPU 压力,这些想法可以帮助我们验证可靠性和可观察性。
混沌 eBPF:我们还有工作要做
eBPF 的优点和好处看起来已经很清楚了,但问题是我们将来需要在哪些领域进行投入?我们应该注意哪些风险?
一个重点领域是 DevSecOps 和 SDLC,eBPF 程序代码需要进行编译、测试、验证、安全扫描和分析潜在的性能问题。我们还需要避免潜在的供应链攻击。鉴于 eBPF 的复杂性,用户需要遵循安装指南,还可能需要应用 curl | bash 命令模式。
在 CI/CD 管道中自动测试 eBPF 程序是一件很棘手的事情,因为内核会在加载时验证 eBPF 程序并拒绝执行潜在的不安全的程序。有人尝试将 eBPF 验证器移出内核,并允许在 CI/CD 中测试 eBPF 程序。
eBPF 存在风险,其中一个很明显的风险是对内核级别的所有内容都具有根访问权限。你可以在 TLS 库函数调用(包含原始字符串)后立即 hook TLS 加密流量。在一些真实世界的案例中,一些 rootkit 和漏洞利用 eBPF 来绕过 eBPF。有一些研究使用特殊编程技术进行漏洞利用和数据访问,这些技术不会被 eBPF 安全执行工具检测到。猫鼠游戏将继续……
针对 eBPF 的愿望清单:
内容可睡眠的 eBPF 程序,可以暂停上下文,并在稍后继续(在编程语言中叫作“Fiber”)。
观察其他 eBPF 程序是否存在恶意行为的 eBPF 程序,类似于 Ops 中的 monitor-the-monitor(监控监视器)问题。
更多的入门指南、学习资源和平台抽象,它们可以降低学习这项新技术的门槛,让每个人都可以参与贡献。
结论
eBPF 是一种新的可观测性数据采集方法,为我们带来了网络见解和安全可观察性。我们可以从生产故障的调试中受益。混沌工程有助于验证可观察性和 eBPF 程序,在混沌实验中使用 eBPF 探针的想法将使其进行更快的迭代。此外,我们能够从传统指标监控之外的更多数据源(关联、验证和观察生产环境)中受益。这有助于我们通向 DataOps、MLOps/AIOps——AllOps。
开发人员可以从可观察性驱动开发的自动增强中受益。DevOps/SRE 团队通过混沌工程验证可靠性,DevSecOps 将看到更多云原生安全默认设置。在 CI/CD 中对 eBPF 程序进行测试和验证是一项重要的工作,其次是将所有的想法带到上游,并降低使用和贡献 eBPF 开源项目的门槛。
原文链接:
https://www.infoq.com/articles/debugging-production-ebpf-chaos
相关阅读:
Kubernetes 混沌工程平台 Chaos Mesh 升级 CNCF 孵化项目
评论