使用 k8s 元数据改进故障排除

博客文章在发布后不会更新。这篇文章已经发布一年多了,其内容可能已过时,部分链接可能无效。在依赖任何信息之前,请务必核实。

将 Kubernetes 资源元数据附加到 OpenTelemetry Traces 非常有用,可以识别哪个资源(例如 pod)出现故障或存在性能问题。它对于跨其他信号进行关联也很有用,例如:您可以关联由同一个 pod 生成的日志和 Span。

在本文中,您将学习如何在不同场景下配置 OpenTelemetry Collector 以使用 k8sattributesprocessor

本文将不涵盖 OpenTelemetry Collector pipeline 的详细信息。有关这些详细信息,请参阅 Collector 文档

K8s 属性如何附加

总体而言,K8s 属性作为 资源 附加到 Traces。这有两个原因:

  1. K8s 属性符合资源定义:即记录遥测数据的实体。
  2. 它集中了这些元数据,这些元数据对于任何生成的 Span 都很重要。

让我们深入了解如何实现它!

使用 k8sattributes 处理器

这是一个 OpenTelemetry 处理器,它可以自动发现 pod 元数据并将其附加到与该 pod 生成的 Span 关联的资源上。如果 pod 属于 DeploymentReplicaSet,它还会发现其属性。

我们可以附加到资源的某些属性包括:

  • 节点名称 k8s.node.name
  • Pod 名称 k8s.pod.name
  • Pod UID k8s.pod.uid
  • 命名空间 k8s.namespace.name
  • Deployment 名称,如果 pod 是由 deployment 创建的,则为 k8s.deployment.name

这些属性符合 OpenTelemetry 语义约定。有关详细信息,请参阅 Kubernetes 资源语义约定

该处理器在内部维护一个 pod 列表及其关联属性,通常是 pod 的 IP 地址,并使用此属性来知道哪个 pod 生成了某个 Span。

k8sattributes processor data flow

在上图中,您可以看到数据流:Pod 表使用 Kubernetes API 获取,而 Pod IP 则从 Pod 与 Collector 之间的连接上下文中提取。

k8sattributesprocessor 可以根据 Collector 的配置方式在不同模式下工作。让我们探讨一种常见场景:当 Collector 作为 daemonset 部署时。

Daemonset 模式

让我们看看如何在 daemonset 模式下配置 Collector,在 k8sattributes 文档中也称为 agent 模式。

当我们以 daemonset 模式部署 Collector 时,每个节点都有一个 Collector pod。我们需要配置 Collector 服务帐户以拥有获取所有 Pod 信息的权限。为此,我们将创建一个具有必要权限的 ClusterRole

以下是使 k8sattributesprocessor 工作所需的最低权限:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: otel-collector
rules:
  - apiGroups: ['']
    resources: ['pods', 'namespaces']
    verbs: ['get', 'watch', 'list']

接下来,以 daemonset 模式部署 Collector。我们建议您设置一个过滤器,仅获取属于 Collector 所部署节点上的 Pod。这是因为如果您有一个大型集群,您不希望维护一个巨大的 Pod 列表。

这是本博客中用于演示处理器工作方式的清单:

apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
  name: otel-collector-daemonset
spec:
  mode: daemonset
  image: ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib:0.47.0
  serviceAccount: attributes-account
  env:
    - name: KUBE_NODE_NAME
      valueFrom:
        fieldRef:
          apiVersion: v1
          fieldPath: spec.nodeName
  config: |
    receivers:
      jaeger:
          protocols:
              grpc:
              thrift_binary:
              thrift_compact:
              thrift_http:
      otlp:
          protocols:
              grpc:
              http:

    processors:
         k8sattributes:
             filter:
                 node_from_env_var: KUBE_NODE_NAME
    exporters:
      jaeger:
        endpoint: jaeger-all-in-one-collector:14250
        tls:
          insecure: true

    service:
      pipelines:
        traces:
          receivers: [otlp, jaeger]
          processors: [k8sattributes]
          exporters: [jaeger]

需要注意的主要部分是它使用了 contrib Collector 镜像。k8sattributesprocessor 不是 OpenTelemetry Collector 核心的一部分,但 contrib 发行版中包含了它。其他需要注意的点是前面提到的过滤器,以及使用预先创建的特定服务帐户,该帐户具有获取 Pod 列表的权限。

接下来,部署清单和 vert.x 示例应用程序 来生成一些 Traces。

Jaeger UI showing the span attributes

正如您所见,Trace 的每个 Span 现在都已附加了相应的 Pod 属性。

如果您将上面的配置限制到特定命名空间,可以通过将命名空间添加到 k8sattributesprocessor 过滤器来实现,如下所示:

processors:
  k8sattributes:
    filter:
      namespace: my_namespace

这样,您可以创建一个 Role 而无需创建 ClusterRole,从而将 Collector 服务帐户的范围缩小到单个命名空间。

使用 Resource detector processor

最近,OpenTelemetry operator 在 Collector 容器上设置了 OTEL_RESOURCE_ATTRIBUTES 环境变量,其中包含 K8s pod 属性。这允许您使用 resource detector processor,该处理器将环境变量值附加到 Spans。这仅在 Collector 以 sidecar 模式部署时有效。

例如,如果您部署以下清单:

apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
  name: sidecar-for-my-app
spec:
  mode: sidecar
  image: ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib:0.47.0
  config: |
    receivers:
      jaeger:
        protocols:
          grpc:
          thrift_binary:
          thrift_compact:
          thrift_http:
      otlp:
        protocols:
          grpc:
          http:

    processors:
      resourcedetection:
        detectors: [env]
        timeout: 2s
        override: false

    exporters:
      jaeger:
        endpoint: jaeger-all-in-one-collector:14250
        tls:
          insecure: true

    service:
      pipelines:
        traces:
          receivers: [otlp, jaeger]
          processors: [resourcedetection]
          exporters: [jaeger]

然后部署 vert.x 示例应用程序,您可以看到 OTEL_RESOURCE_ATTRIBUTES 环境变量被注入了一些值到 sidecar 容器中。其中一些使用了 Kubernetes downward API 来获取属性值。

以下是环境变量值的示例:

- name: OTEL_RESOURCE_ATTRIBUTES
  value: k8s.deployment.name=dep-vert-x,k8s.deployment.uid=ef3fe26b-a690-4746-9119-d2dbd94b469f,k8s.namespace.name=default,k8s.node.name=$(OTEL_RESOURCE_ATTRIBUTES_NODE_NAME),k8s.pod.name=(OTEL_RESOURCE_ATTRIBUTES_POD_NAME),k8s.pod.uid=$(OTEL_RESOURCE_ATTRIBUTES_POD_UID),k8s.replicasetname=dep-vert-x-59b6f76585,k8s.replicaset.uid=5127bc38-e298-40e1-95df-f4a777e3176c

了解更多

本文介绍了如何配置 OpenTelemetry Collector 以将 Kubernetes 资源元数据作为资源属性附加到 OpenTelemetry Traces。所涵盖的场景虽然基础,但说明了如何向 Traces 添加此类元数据,以便您可以将该技术应用于其他更复杂的场景。如果您想了解有关不同场景或配置处理器的选项的更多信息,可以查看 K8sattributes processor 文档,其中可以找到更多场景,例如 sidecar,或者一个 Collector 作为 agent 向另一个 Collector 报告。

参考

最后修改于 2025 年 6 月 11 日: 警报清理 (#7090) (c392c714)