《架构师》2023年3月
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

eBay为何以及如何转向OpenTelemetry

作者 Vijay Samuel 译者 平川 策划 Tina

本文最初发布于eBay官方博客。

为了更好地与行业可观测性标准保持一致,eBay做了一项关键调整,转向了OpenTelemetry。

引言

可观测性为组织提供了眼睛和耳朵。可观测性的一个主要好处是,通过有效揭示关键工作流中持续存在的、可能影响客户体验的问题来预防收入损失。可观测性生态圈在不断发展,OpenTelemetry世界的最新进展使我们不得不重新思考我们的策略,并转而使用它。eBay的观测平台Sherlock.io为开发人员和站点可靠性工程师(SRE)提供了一套强大的云原生服务,可用于观测支撑eBay生态系统的各种应用程序。Sherlock.io支持可观测性的三大支柱:指标、日志和跟踪。平台的指标存储是Prometheus存储引擎的一个集群和分片实现。我们使用Metricbeat代理每分钟抓取大约150万个Prometheus端点,采集到的数据存入指标存储中。这些端点每秒可以产生大约4000万条符合记录规则的样本数据。那些采集到的样本形成了存储在Prometheus上的30亿个活跃的样本序列。因此,eBay的可观测性平台规模非常大,这带来了新的挑战。

作为一个可观测平台提供商,eBay是最早使用代理抓取指标端点和跟踪日志文件的公司之一。正如我们在之前的博文中所讨论的那样,我们大量依赖Elastic Beats把信号接收到平台。Beats是一个轻量级的运维数据(例如指标和日志)传输工具。从2016年到2020年的五年时间里,我们在所有Kubernetes集群上将Filebeat和Metricbeat作为守护进程集(DaemonSets)来运行。守护进程集允许用户在Kubernetes集群的每个节点上部署给定的工作负载。然而,我们在一次内部黑客周期间进行了一项实验,得出了一些令人惊讶的结论,并促使我们重新考虑守护进程集的使用。在这篇博文中,我们讨论了我们遇到的一些问题,特别是指标抓取方面的问题,以及我们如何改进自己的解决方案。我们还将详细讨论我们如何在许可方面驾驭不断变化的开源生态,以及我们打算如何就使用OpenTelemetry这一方案达成一致。

指标检测

eBay的指标检测已经或多或少地在Prometheus端点上标准化了。各种应用程序的端点已通过各种检测实践暴露出来,例如(但不限于):

• Prometheus官方客户端(包括Java、Go、Python等)

• Micrometer

• OTEL SDK with Prometheus Exporter

• 当请求时放出一个Prometheus端点的自定义代码

eBay平台工程小组提供的框架内置了一个检测客户端,还暴露了各种指标端点,分别代表服务器端、客户端和数据库客户端指标。哪些Prometheus端点需要暴露出来以供抓取取决于应用程序的性质。应用程序所有者还可以暴露自己的端点来测量业务KPI。

Autodiscover

支持eBay生态系统的大多数应用程序都运行在eBay的内部Kubernetes提供程序Tess上。eBay运行着数百个基于Tess的Kubernetes集群,应用程序可以在任意数量的集群及集群的任意组合上运行。应用程序所有者可以选择将他们的应用程序指标与框架级工具中提供的指标放在一起。我们的代理需要确切地知道当前运行的Kubernetes Pod暴露了哪些端点。为了给代理提供这些信息,我们帮助丰富了Beats平台的功能,为的是可以执行一个叫做“基于线索的autodiscover”的任务。Autodiscover是一种Beats结构,它允许像Kubernetes API服务器这样的动态源向代理传递如下信息:

• 需要抓取的端点是什么?

• 端点是什么类型的——Dropwizard、Prometheus、Foobar,还是别的什么?

• 多久抓取一次?

• 代理还需要额外知道其他的信息吗,比如SSL证书?

随着所需的发现模式越来越复杂,我们与Beats开源社区建立了合作关系,以增强自动发现能力,满足我们的特有需求。以下是我们贡献的一些功能:

• 发现多组配置:传统的基于注解的抓取功能非常有限,因为用户只能为抓取管理器提供简单的配置。考虑到每个端点都可能有动态需求,如不同的处理方式和抓取间隔,我们增强了autodiscover,让它可以接受多组配置。

• 从命名空间注解中发现目标:声明抓取目标的指定方法要求在Pod规范中添加注解。然而,在那里添加注解意味着要重启Pod。如果更改的目的是针对框架上正在测量的指标,并且在每个已部署的应用程序上都可用,那么这是不可取的。为了避免重启所有的Pod,我们添加了autodiscover支持,以便可以额外查看命名空间级的注解。

在识别部署在Kubernetes集群上的目标方面,这些特性使Beats Autodiscover成为一种更通用、功能更丰富的发现机制之一。

通过守护进程集抓取指标的局限性

我们第一次尝试大规模运行Metricbeat是在每个Kubernetes集群上将其作为守护进程集运行。每个Pod都有一个CPU和1GB的内存用于处理该节点上暴露的所有指标。当Metricbeat启动时,它向API服务器请求该集群上的所有命名空间以及运行它的节点上部署的Pod。有了这些信息,它就可以整理每个Pod及其命名空间上的注解并创建配置。下面是我们观察到的一些结果:

• 资源碎片:假设我们为N个节点集群运行N个Beat,如果单个Beat管道的自举成本(bootstrapping cost)为50MB,那么我们实际浪费了50*N MB的资源。在有3000个节点的Kubernetes集群上,这加起来是150GB!

• 轮询大型端点时的OOM问题:我们看到,在客户公开的端点中,有的端点有多达15万个条目。一些巨大的端点,如“kube-state-metrics”,可达300万个条目,每次轮询会生成600MB的数据。当一个节点上出现这样的用例时,抓取就变得不可靠了。

下图展示了当Beats实例(如Metricbeat、Filebeat和Auditbeat)部署为DaemonSet时,如何与Sherlock.io平台交互:

转向集群本地抓取

在处理一个不相关的项目时,我们使用了一种快捷方式,为集群中的所有目标运行单个Metricbeat实例。当我们观察运行Metricbeat所使用的CPU和内存时,看到的数值简直令人震惊。在部署过程中,我们看到了以下情况:

• Kubernetes节点数:2851

• CPU使用量:29核

• 内存使用量:57GB

• 摄入速度:每秒238K样本

• 每个节点监控的端点数:4

• 监控的每个节点的平均内存使用量:20MB

• 监控的每个节点的平均CPU使用量:0.01核

单个Metricbeat实例以DaemonSet模式监控一个节点上数量相近的端点,消耗大约200MB内存(10倍)和大约0.6核CPU(60倍)。整个集群累计消耗将达570GB内存和大约1700个CPU。迁移到集群本地实例总共可以节省大约90%的硬件资源。

这使我们不得不重新考虑处理抓取的方法。在整个集群中运行一个实例意味着当该实例升级或发生故障时,所有的抓取在那个时间点都将停止。为了减少故障,我们将Metricbeat部署为具有N个副本的StatefulSet。整个Pod列表根据Metricbeat实例的数量进行N路分片,每个实例监控其分配到的分片:

xxHash(pod uid) % statefulset_size == instance number

每个实例都会对API服务器做一次完整的扫描,但除了它应该监控的内容之外,其他内容会被忽略。这个模型很适合Metricbeat,因为它主要抓取Prometheus端点,并且这个活动可以发生在Tess节点之外。一个有3000个节点的大型Kubernetes集群有多达30个实例,CPU和内存的数量也更多,与作为节点上的守护进程相比,这让它能够抓取的端点多许多。如果一个Metricbeat实例重启,则只有该实例监控的端点的抓取工作会短暂停止,故障百分比将降到实例总数的1/N。

新的部署模式如下图所示:

解耦Autodiscover

虽然与使用守护进程集相比,采用集群局部抓取的可扩展性要好许多,但这个模式还有改进的空间。新的问题出现了,特别是在集群规模比较大、Pod密度比较高时。考虑到每个Metricbeat实例都必须扫描所有的Pod并选择它需要监控的Pod,初始扫描花费的时间可能会很长,这取决于给定集群中Pod的数量。在推广过程中,这非常成问题,因为Metricbeat Pod一旦重启,就需要长达10分钟的时间才能重启抓取。因为对各种资源Metricbeat请求设置了大量的WATCH,所以这种技术还会给API服务器带来沉重的负担,而这取决于实例的数量。

经过进一步的评估,我们决定将Autodiscover移出代理并实现它自己的控制循环。这个循环将完成以下工作:

• 实现一个逻辑和Beats Autodiscover类似的解析器;

• 发现所有可以进行抓取工作的代理;

• 选择其中一个代理;

• 并将配置传递给所选代理以监视目标。

这个控制循环会做出重要的决策,如在代理崩溃、代理过度分配和其他故障场景下调整工作负载。考虑到解析注解的逻辑已经从代理解耦,只要新代理一一实现了Beats提供的功能,为任何代理生成配置就都非常简单了。

OpenTelemetry出现

2019年,Open Tracing和Open Census社区同意联合实现OpenTelemetry。OpenTeleme try计划的目标是提供与供应商无关的API、SDK和工具,用于采集、转换数据并发送给任何可观测后端。考虑到我们选择了Kubernetes,它同样提供了与供应商无关的API来管理云上的容器,因此,投资这样一个项目似乎是很自然地选择,这非常适合我们在eBay使用开源软件的方式。2021年,我们开始试验分布式跟踪,看看它对我们的开发人员有什么用。

当时,在OpenTelemetry Collector的代码库中,我们看到了它的一些功能的巨大潜力,包括预定义的指标类型、日志和跟踪文件,以及使用Prometheus抓取管理器从OpenMetrics端点收集指标。为了实现分布式跟踪,我们选择了OpenTelemetry Collector以及OpenTelemetry SDK。接下来,我们应该弄清楚如何将指标和日志收集移到Open Telemetry Collector中。这项工作可不简单,因为我们需要在不停机的情况下补全所有欠缺的功能,与新的开源社区建立关系,并替换一个大规模的指标收集基础设施。2022年初,我们开始了将指标抓取向OpenTelemetry Collector迁移的艰巨任务。

迁移

因为我们将发现逻辑从代理中解耦了,所以实际的迁移工作就只是生成OpenTelemetry Collector可以理解的配置。每次有新的Pod启动时,都必须把这些配置推送给它,并在Pod死亡时进行清理。然而,OpenTelemetry Collector有一个严重的缺陷:不能动态地重新加载配置。OpenTelemetry收集器有一个“管道”的概念,它定义了如何接收、处理和导出指标。为了方便动态地重新加载管道,我们提出了一个“filereloadreceiver”,它可以查看一个包含“局部管道”描述文件的目录,这些局部管道可以插入到收集器的整个管道中。每个需要抓取指标的Pod都有一个局部管道,由Autodiscover控制器生成并推送到收集器。在这个过程中,另一项比较复杂的工作是,将我们依赖的每个功能在Beats平台和OpenTelemetry Collector之间创建一个映射表。例如,Beats中的字段会被转换为OpenTelemetry上的属性处理器。有了这样的映射和filereloadreceiver,我们就能够为OpenTelemetry Collector生成新的配置,如下所示:

如上所示,我们能够保持Pod/Namespace注解的终端用户契约相同,并在底层简单地替换代理。这大大简化了推出新代理的实际工作。最后一个障碍是Elastic Beats、OpenTelemetry,有时甚至是Prometheus抓取管理器之间的语义不匹配。我们花了几个月的时间,才最终替换掉了生产环境中的所有Metricbeat。我们在OpenTelemetry Collector项目中发现并帮助修复的一些差异包括:

• 将以“_”开头的消毒标签和指标名称与Prometheus对齐;

• 能够禁用标签消毒( label sanitization);

• 正确处理以“:”开头的指标名称;

• 能够使用正则表达式提取Pod标签。

事实证明,这些问题很难发现,有时只有当我们为了使用OpenTelemetry Collector而设法升级Kubernetes集群时才会发现这些问题。一旦遇到这样的问题,回滚就成了唯一的选项,我们不得不回到绘图板旁。一个权宜之计是编写一个比较脚本,可以使用Metricbeat和OpenTelemetry Collector抓取端点,将它们采集到指标存储中,并比较指标名称和标签,以确保抓取的内容彼此相同。这大大增强了我们继续前进的信心。

有时,向前推进仅仅意味着放弃对某些功能的支持。对于Dropwizard Metrics支持,我们就是这样做的,并让用户做了迁移。除了语义差异之外,我们还在积极地为项目添加我们认为至关重要的功能,如支持Exemplar。

经过几个月的努力工作,再加上社区的支持,我们很高兴地宣布,Metricbeat已经完全停用,并为OpenTelemetry Collector所取代。我们现在正忙着对Filebeat做同样的事,早期的性能基准测试看上去非常有希望。到目前为止,我们已经为这个项目做出了10多项贡献,但这只是一个非常富有成果的合作的开始。

小结

过去5年,eBay遇到了几次需求激增,迫使我们对一些传统观念进行重新思考。我们从守护进程集入手,发现在规模比较大时,它的成本过高,而且也不可靠。我们迁移到了集群本地模型,将代理的成本降低了约90%,但在API服务器和代理上,我们还是做了一些多余的工作。我们将发现逻辑解耦,迁移到执行调度的控制循环中,并将代理变为可以接受抓取目标的无状态进程。鉴于OpenTelemetry日益成熟,我们转而使用OpenTelemetry Collector来收集指标,并积极努力地在日志上做同样的事。我们将继续积累大规模运行代理的经验,并根据需要进行调整。我们将继续与OpenTelemetry社区合作,因为它将继续为可观测生态系统的标准化铺平道路。现在我们使用了OpenTelemetry为开发人员提供一个行业认可的开放性标准,并向Sherlock.io发送遥测数据。随着社区的发展,我们将支持性能分析等新特性,并把它们引入平台,让整个开发社区受益。

原文链接

https://tech.ebayinc.com/engineering/why-and-how-ebay-pivoted-to-opentelemetry