OBI 指标的基数

概述如何计算默认 OBI 安装产生的指标的基数,考虑到被监控环境的大小和复杂性。

OBI 指标的基数高度依赖被监控环境的大小和复杂性,因此无法提供一个简单且准确的公式。

本文档试图提供对默认 OBI 安装可能产生的指标基数的近似估计。它分为几个部分,分别对应 OBI 可以生成的每种指标类型,因为每种指标系列都可以被选择性地启用或禁用。

为了简化,以下公式假定为单个集群。您应该将每个集群的基数乘以相应的值。

术语

在继续之前,我们应该澄清一些可能含糊不清或有解释空间的概念。

  • 实例:每个被监控的目标。在应用级指标中,它将是服务或客户端实例。在 Kubernetes 中,它将是 Pod。一个应用实例可能运行在多个进程中。在网络级指标中,每个实例是 OBI 实例,它监控给定主机上的所有网络流量。
  • 实例所有者:在 Kubernetes 中,大多数实例(Pod)都有一个所有者资源。有时您可能希望报告有关所有者而不是实例的数据,以控制基数。实例所有者的示例包括 Deployment、DaemonSet、ReplicaSet 和 StatefulSet,但如果 Pod 没有所有者(独立 Pod),则 Pod 本身被报告为所有者。
  • URL 路径:是 URL 请求的原始路径,如客户端发送和服务器接收的,例如:/clients/348579843/command/833
  • URL 路由:是 URL 请求的聚合路径,语义上分组以控制基数。它通常模仿某些 Web 框架在代码中定义 HTTP 请求的方式,例如:/clients/{clientId}/command/{command_num}
  • 操作:描述请求的功能。
    • HTTP:所有 HTTP 动词,例如 GET,后跟 URL 路由。
    • gRPC:服务的路径。
    • SQL:SQL 命令,例如 SELECTUPDATE 或其他命令,后跟目标表。
    • Kafka:Produce/Fetch。
  • 服务器:是接收和处理 HTTP 或 gRPC 请求的任何实例。服务器也可以是客户端。
  • 客户端:是提交 HTTP、gRPC、数据库或 MQ 请求的任何实例。客户端也可以是服务器。
  • 服务:在 Kubernetes 上下文中,是由一组服务器提供的功能,这些服务器通过通用的主机名和端口访问。
  • 端点:是标识服务、服务器或客户端的 IP 地址或主机名和端口。
  • 返回码:由每个服务调用返回,描述执行结果的一些元信息。对于 HTTP,它们是 HTTP 状态码,对于其他协议,通常是 0(成功)或 1(错误)。

应用级指标

对于应用级指标,我们无法遵循简单的乘法公式,因为有多个因素影响基数,但它们之间并非线性相关。

例如,HTTP 路由的数量和服务器地址的数量都会增加基数,但我们不能简单地将它们相乘,因为并非所有服务器实例都接受相同的 HTTP 路由。

以下公式可以提供一个非常粗略的最大限制,但在我们的测量中,实际基数比计算结果低两个数量级。因此,我们建议采用基于测量的方法,而不是试图提前计算基数。

然而,以下是可能影响总体基数的因素列表:

  • 实例:被监控实体的数量。它们可以是服务和客户端。
  • MetricNames:应用级指标名称的数量。这取决于 OBI 监控的应用程序类型。为将要报告的每个指标计数。
  • 客户端指标,当 OBI 监控执行其他应用程序请求的应用程序时。
    • http.client.request.duration
    • http.client.request.body.size
    • rpc.client.duration
    • sql.client.duration
    • redis.client.duration
    • messaging.publish.duration
    • messaging.process.duration
  • 服务器端指标,当 OBI 监控接收其他应用程序请求的应用程序时。
    • http.server.request.duration
    • http.server.request.body.size
    • rpc.server.duration
  • HistogramBuckets 需要考虑并乘以每个指标,因为每个应用级指标都是一个直方图。桶在 OBI 中是可配置的,但对于持续时间指标,默认数量是 15,对于正文大小指标是 11,外加 2 个指标(直方图总数和计数)。
  • 操作等同于调用的功能。在 HTTP 服务中,它会组合 HTTP 方法和 HTTP 路由;在 RPC 中,它是 RPC 方法名。
  • 端点是服务器地址和端口的数量。
  • ReturnCodes 是操作可能结果的数量。通常在 gRPC 中是 Ok/Err,或 HTTP 状态码。

示例计算

所示的基数公式中的操作数可能会重叠。例如,一个被监控的客户端应用程序可能会发送 /foo/bar HTTP 请求,并连接到服务 A 和服务 B,所以

  • 操作:2
  • 端点:2

Operations * Endpoints 的商会将基数乘以 4。然而,如果 /foo 路由是服务 A 独有的,而 /bar 路由是服务 B 独有的,则实际基数乘数仅为 2。

在计算基数时,为您的计算设置乐观和悲观的界限。

以下示例说明了如何计算示例系统的基数。客户端和后端都由 OBI 监控。其他组件是外部的。

Example architecture

悲观计算将是

#Instances * #MetricNames * #HistoBuckets * #Operations * #Endpoints * #ReturnCodes =
= 2 * 5 * 177/3 * 37/3 =2771

引用的数字

  • 2 个实例,客户端和后端。
  • 5 种指标类型,取决于它们的作用和协议。
    • Client
      • rpc.client.duration
    • 后端作为 RPC 服务器。
      • rpc.server.duration
    • 后端作为 SQL 和 HTTP 客户端。
      • http.client.request.duration
      • http.client.request.body.size
      • sql.client.duration
  • 17 个直方图指标,因为大多数指标都是基于持续时间的。
  • 7 个操作:RPC Add/List/Delete,HTTP PUT,SQL Insert/Select/Delete。
  • 3 个端点:后端、身份提供商和数据库。
  • 7 个返回码:RPC OK/Err,HTTP 200/401/500,SQL OK/Err。

看起来基数不应超过 163。然而,这个数字既不现实也不准确,因为一些乘数可能不适用于整个系统。例如,SQL 方法不应与 RPC 和 HTTP 指标相乘。

在这个简单的场景中,我们可以手动计算出最大基数增加到 396,这远低于初始计算的 2771。

#实例指标端点操作Code
1Clientrpc.client.duration后端AddOK
2Clientrpc.client.duration后端AddErr
3Clientrpc.client.duration后端ListOK
4Clientrpc.client.duration后端ListErr
5Clientrpc.client.duration后端DeleteOK
6Clientrpc.client.duration后端DeleteErr
7后端rpc.server.durationAddOK
8后端rpc.server.durationAddErr
9后端rpc.server.durationListOK
10后端rpc.server.durationListErr
11后端rpc.server.durationDeleteOK
12后端rpc.server.durationDeleteErr
13后端http.client.request.duration身份提供商PUT /login200
14后端http.client.request.duration身份提供商PUT /login401
15后端http.client.request.duration身份提供商PUT /login500
16后端http.client.request.body.size身份提供商PUT /login200
17后端http.client.request.body.size身份提供商PUT /login401
18后端http.client.request.body.size身份提供商PUT /login500
19后端sql.client.durationDBInsertOK
20后端sql.client.durationDBInsertErr
21后端sql.client.durationDBSelectOK
22后端sql.client.durationDBSelectErr
23后端sql.client.durationDBDeleteOK
24后端sql.client.durationDBDeleteErr

为简洁起见,我们没有计算直方图桶。接下来我们将指标实例乘以直方图桶,再加上直方图 _count_sum

  • 3 个正文大小指标实例 x 13 = 39
  • 21 个持续时间指标实例 x 17 = 357

总计计入的基数:396

以上示例说明了提供一个公式来计算基数影响是困难的。我们能够计算出一个非常简单的示例的确切基数,其中所有信息都已知。在大型 Kubernetes 集群中,由于我们对应用程序及其互连方式知之甚少,这项工作将是不可能的。

网络级指标

计算网络级指标比计算应用级指标更简单,因为 OBI 只提供一个计数器:obi.network.flow.bytes。然而,基数也取决于您的应用程序的互连程度。

obi.network.flow.bytes 的默认属性是:

  • 方向(请求/响应)
  • Kubernetes 中的源和目标端点所有者:k8s_src_owner_namek8s_dst_owner_namek8s_src_owner_typek8s_dst_owner_typek8s_src_namespacek8s_dst_namespace
  • k8s_cluster_name:每个集群唯一。我们假定单个集群,如同其他指标一样。

简化的、悲观的公式将是:

#Directions * #SourceOwners * #DestinationOwners

我们假设所有源所有者都连接到所有目标所有者。应用连接因子更现实,例如一个拥有 100 个 Deployment/DaemonSet/StatefulSet 的集群,其中每个所有者平均连接到其他 2 个所有者,其基数将是:

2 个方向 x 100 个源所有者 x 2 个目标所有者 = 400

服务图指标

服务图指标针对可以被应用程序指标监控的实例生成,例如 HTTP、RPC、SQL、Redis 和 Kafka。网络指标则为任何具有网络流量的实例生成,无论其使用何种协议。

服务图指标生成以下指标:

  • traces_service_graph_request_client:直方图,15 个桶。
  • traces_service_graph_request_server:直方图,15 个桶。
  • traces_service_graph_request_failed_total:计数器。
  • traces_service_graph_request_total:计数器。

每个指标还有以下属性:

  • source:obi。
  • clientclient_namespace
  • serverserver_namespace

计算方式类似于网络指标,但基数更高。

  • 我们报告了一系列指标/直方图,而不是单个计数器指标,总基数为 36,两个 15+2 直方图 + 2 个计数器。
  • 而不是按实例的所有者(例如 Deployment)进行聚合,客户端是提交请求的实例,而服务器可能是所有者,因为它通常通过单个服务实例访问。

Span 指标

  • traces_spanmetrics_latency:直方图,15 + 2 个桶。
  • traces_spanmetrics_calls_total:计数器。
  • traces_spanmetrics_size_total:计数器。
  • traces_spanmetrics_response_size_total:计数器。

可能为每个指标增加基数的属性是:

  • 服务/服务命名空间/实例 ID。
  • Span 类型:Client/Server/Internal。
  • Span 名称:通常是操作的名称,可能具有高基数。
  • 返回码。

最大基数可粗略计算为:

19 metric buckets * 3 span kinds * #Instances * #Operations * #ReturnCodes

正如在前面的应用指标计算示例中所述,我们假设大量的 HTTP 返回码只会乘以 HTTP 服务,或者某些实例组只会有部分路由。

案例研究:OpenTelemetry Demo 的基数

在本节中,我们计算部署在 3 节点本地集群中的 OpenTelemetry Demo 的基数。我们禁用了示例应用程序中的所有内置 OpenTelemetry 监控,并部署了 OBI 来执行监控。

测量应用级指标

由于大多数监控实例既是客户端又是服务,为了更准确,我们忽略了公式中的 #instances 参数。

#MetricNames * (#HistoBuckets+2) * #Operations * #Endpoints * #ReturnCodes

为了最小化影响最终基数的属性的非线性效应,我们分别计算所有指标类型(HTTP、gRPC 和 Kafka)的基数。

HTTP 指标

  • 4 个指标:客户端、服务器、请求大小和时间。
  • 平均 15 个直方图桶。
  • 已知操作:75 个,从运行中的 OTel Demo 中测量,使用 PromQL 查询:group by (http_request_method, http_route)({__name__=~"http_.*"})
  • 26 个端点,从运行中的 OTel Demo 中测量,使用 PromQL 查询:group by (server_address, server_port)({__name__=~"http_.*"})
  • 6 个响应状态码:200、301、308、403、408 和 504,从运行中的 OTel Demo 中提取。

HTTP 指标的总计、最大计算限制是:

4 x 15 x 75 x 26 x 6 =~ 702,000

这表明该公式对于应用级指标的无效性,因为测量到的数字要低得多,即使是对于所有已知的应用指标类型。

count({__name__=~"http_.*|rpc_.*|sql_.*|redis_.*|messaging_.*"}) → 9,600

测量网络级指标

对于网络级指标,如果我们假设 2 个方向(请求/响应)以及 21 个部署请求所有 21 个部署的信息,我们得到以下基数数字:

2×21×21 = 882

了解架构后,如果我们只计算架构图中的箭头并假设它们是双向的,我们可以得到一个较低的估计。

2x29 = 58

网络指标衡量 OpenTelemetry Demo 的连接、其他内部集群连接以及监控流量,因此实际基数更高。

count(obi_network_flow_bytes_total) → 330

我们可以按命名空间对流量进行分组,以更好地了解哪些部分属于 OpenTelemetry Demo,使用以下查询:

count(obi_network_flow_bytes_total) by (k8s_src_namespace, k8s_dst_namespace)

返回以下信息:

k8s_src_namespacek8s_dst_namespacecount
defaultdefault156
kube-systemdefault47
defaultkube-system47
default14
default14
kube-system13
kube-system13
gmp-system3
gmp-system3
defaultgmp-system1
gmp-systemdefault1

OpenTelemetry Demo 在 Demo 组件之间生成的网络指标数量为 156。default 命名空间既是源也是目标。还有到 kube-systemgmp-system 或根本没有命名空间的流量,这属于外部连接、遥测或 Kubernetes 管理。

测量服务图指标

网络指标常用于构建服务图,但实际的服务图指标将具有不同的形状。

  • 我们有 2 个计数器指标和 2 个带有 16+2 个桶的直方图指标,而不是单个计数器指标。
  • 服务图指标通常忽略内部 Kubernetes 流量或来自未进行应用程序级别监控的实例的任何流量。

测量到的数字是:

count({__name__=~".*service_graph.*"}) → 2300

测量 Span 指标

在应用级指标计算中,我们证明了由于参数众多,很难获得分析数字。我们可以通过 PromQL 测量来获得 Span 指标基数的正确测量值。

count({__name__=~".*spanmetrics.*"}) → 3900


最后修改于 2025 年 8 月 11 日:迁移 beyla 文档以支持 OBI (#7399) (c6df1ca9)