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

将Kubernetes资源元数据附加到OpenTelemetry跟踪中有助于确定哪个资源(例如Pod)发生故障或存在性能问题。这对于跨其他信号进行关联也非常有用,例如:您可以关联由同一Pod生成的日志和跨度。

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

本文不涵盖OpenTelemetry Collector管道的详细信息。有关此详细信息,请参阅收集器文档

如何添加K8s属性

在高层次上,K8s属性作为资源附加到跟踪中。这有两个原因:

  1. K8s属性符合资源的定义:记录遥测的实体
  2. 它集中了该元数据,对于任何生成的跨度都是相关的。

让我们深入了解如何做到这一点!

使用k8sattributes处理器

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

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

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

此类属性符合OpenTelemetry语义约定。详细信息请参阅[Kubernetes资源语义约定][]。

处理器内部维护着一个Pod列表以及相关的属性,通常是Pod的IP地址,并使用此属性来了解哪个Pod生成了某个跨度。

k8sattributes处理器数据流

在上图中,您可以看到数据的流动方式:使用Kubernetes API获取Pod列表,同时从Pod和收集器之间的连接上提取Pod IP。

k8sattributesprocessor可以在不同模式下工作,具体取决于如何配置收集器。让我们探索一个常见的场景,即以守护程序集方式部署收集器。

守护程序集模式

我们来看看如何以守护程序集模式(也称为k8sattributes文档中的代理模式)配置收集器。

在守护程序集模式下部署收集器时,每个节点有一个收集器Pod。我们需要配置收集器服务帐户以具有获取所有Pod信息的权限。为此,我们将创建一个具有必要权限的ClusterRole

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

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

接下来,部署守护程序集模式的收集器。我们建议您设置一个过滤器,只获取属于部署收集器所在节点的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收集器镜像。k8sattributesprocessor不是OpenTelemetry Collector核心的一部分,而是contrib发行版中的一部分。还有其他值得注意的事项,如上面提到的过滤器以及使用先前创建的特定服务帐户,该服务帐户包含获取Pod列表的权限。

接下来,部署清单和[vert.x示例应用程序][]以生成一些跟踪。

Jaeger UI显示具有属性的跨度

正如您所看到的,每个跟踪的跨度现在都附带了相应的Pod属性。

如果要将上述配置限制为特定命名空间,可以在k8sattributesprocessor过滤器中添加命名空间,如以下示例所示:

processors:
  k8sattributes:
    filter:
      namespace: my_namespace

这样,您可以创建一个Role而不需要创建一个ClusterRole,将收集器服务帐户的范围限制为单个命名空间。

使用资源检测器处理器

根据最近的更改OpenTelemetry operator将K8s Pod属性的值设置为收集器容器上的OTEL_RESOURCE_ATTRIBUTES环境变量。这使您可以使用资源检测器处理器,它将环境变量的值附加到跨度中。这仅在将收集器部署为旁车模式时才起作用。

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

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环境变量在旁车容器中的值被注入了一些值。其中一些使用Kubernetes下行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跟踪中。虽然所涵盖的场景很基本,但说明了如何向跟踪添加此类元数据,以便您可以将该技术融入到更复杂的场景中。如果您想了解更多不同场景或配置处理器的选项,可以参考K8s属性处理器文档,其中提供了更多的场景,例如旁车模式或一个收集器作为代理向另一个收集器报告。

参考资料