注入自动检测

一种使用 OpenTelemetry Operator 进行自动检测的实现。

OpenTelemetry Operator 支持为 .NET、Java、Node.js、Python 和 Go 服务注入和配置自动检测库。

安装

首先,将 OpenTelemetry Operator 安装到您的集群中。

您可以使用 Operator 发布清单Operator Helm chartOperator Hub 来完成此操作。

在大多数情况下,您需要安装 cert-manager。如果您使用 Helm chart,则有一个选项可以生成自签名证书。

如果您想使用 Go 自动检测,则需要启用功能门。有关详细信息,请参阅 控制检测功能

创建 OpenTelemetry Collector (可选)

将容器中的遥测数据发送到 OpenTelemetry Collector 而不是直接发送到后端,这是一项最佳实践。Collector 有助于简化秘密管理,将数据导出问题(例如重试需求)与您的应用程序解耦,并允许您添加其他数据到您的遥测数据中,例如使用 k8sattributesprocessor 组件。如果您选择不使用 Collector,则可以跳到下一节。

Operator 提供了一个用于 OpenTelemetry Collector 的自定义资源定义 (CRD),该资源用于创建 Operator 管理的 Collector 实例。以下示例将 Collector 部署为部署(默认),但还有其他 部署模式 可用。

使用 Deployment 模式时,Operator 还会创建一个可用于与 Collector 交互的服务。服务名称是 OpenTelemetryCollector 资源名称加上 -collector 前缀。在我们的示例中,它将是 demo-collector

kubectl apply -f - <<EOF
apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
  name: demo
spec:
  config:
    receivers:
      otlp:
        protocols:
          grpc:
            endpoint: 0.0.0.0:4317
          http:
            endpoint: 0.0.0.0:4318
    processors:
      memory_limiter:
        check_interval: 1s
        limit_percentage: 75
        spike_limit_percentage: 15
    exporters:
      debug:
        verbosity: basic

    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [memory_limiter]
          exporters: [debug]
        metrics:
          receivers: [otlp]
          processors: [memory_limiter]
          exporters: [debug]
        logs:
          receivers: [otlp]
          processors: [memory_limiter]
          exporters: [debug]
EOF

上述命令将部署一个 Collector,您可以使用它作为 Pod 中自动检测的端点。

配置自动检测

为了管理自动检测,Operator 需要被配置为知道要检测哪些 Pod 以及为这些 Pod 使用哪种自动检测。这是通过 Instrumentation CRD 完成的。

正确创建 Instrumentation 资源对于实现自动检测至关重要。确保所有端点和环境变量都正确才能使自动检测正常工作。

.NET

以下命令将创建一个基本的 Instrumentation 资源,该资源专门配置用于检测 .NET 服务。

kubectl apply -f - <<EOF
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
spec:
  exporter:
    endpoint: http://demo-collector:4318
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: "1"
EOF

默认情况下,自动检测 .NET 服务的 Instrumentation 资源使用 otlphttp/protobuf 协议。这意味着配置的端点必须能够接收 OTLP over http/protobuf。因此,示例使用了 http://demo-collector:4318,它将连接到上一步创建的 Collector 的 otlpreceiverhttp 端口。

排除自动检测

默认情况下,.NET 自动检测附带 许多检测库。这使得检测变得容易,但也可能导致过多的或不需要的数据。如果您不想使用某些库,可以设置 OTEL_DOTNET_AUTO_[SIGNAL]_[NAME]_INSTRUMENTATION_ENABLED=false,其中 [SIGNAL] 是信号类型,[NAME] 是库的区分大小写的名称。

apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
spec:
  exporter:
    endpoint: http://demo-collector:4318
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: '1'
  dotnet:
    env:
      - name: OTEL_DOTNET_AUTO_TRACES_GRPCNETCLIENT_INSTRUMENTATION_ENABLED
        value: false
      - name: OTEL_DOTNET_AUTO_METRICS_PROCESS_INSTRUMENTATION_ENABLED
        value: false

了解更多

有关更多详细信息,请参阅 .NET 自动检测文档

Deno

以下命令创建一个基本的 Instrumentation 资源,该资源配置用于检测 Deno 服务。

kubectl apply -f - <<EOF
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
spec:
  env:
    - name: OTEL_DENO
      value: 'true'
  exporter:
    endpoint: http://demo-collector:4318
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: '1'
EOF

当 Deno 进程以 OTEL_DENO=true 环境变量启动时,它们会自动将遥测数据导出到配置的端点。因此,示例在 Instrumentation 资源的 env 字段中指定了此环境变量,以便为使用此 Instrumentation 资源注入环境变量的所有服务设置此变量。

默认情况下,自动检测 Deno 服务的 Instrumentation 资源使用 otlphttp/proto 协议。这意味着配置的端点必须能够接收 OTLP over http/proto。因此,示例使用了 http://demo-collector:4318,它连接到上一步创建的 Collector 的 otlpreceiverhttp/proto 端口。

配置选项

默认情况下,Deno OpenTelemetry 集成将 console.log() 输出导出为
日志,同时仍然将日志打印到 stdout/stderr。您可以配置以下备用行为:

  • OTEL_DENO_CONSOLE=replace:仅将 console.log() 输出导出为日志;不打印到 stdout/stderr。
  • OTEL_DENO_CONSOLE=ignore:不将 console.log() 输出导出为日志;但会打印到 stdout/stderr。

了解更多

有关更多详细信息,请参阅 Deno 的 OpenTelemetry 集成 文档。

Go

以下命令将创建一个基本的 Instrumentation 资源,该资源专门配置用于检测 Go 服务。

kubectl apply -f - <<EOF
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
spec:
  exporter:
    endpoint: http://demo-collector:4318
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: "1"
EOF

默认情况下,自动检测 Go 服务的 Instrumentation 资源使用 otlphttp/protobuf 协议。这意味着配置的端点必须能够接收 OTLP over http/protobuf。因此,示例使用了 http://demo-collector:4318,它连接到上一步创建的 Collector 的 otlpreceiverhttp/protobuf 端口。

Go 自动检测不支持禁用任何检测。 有关更多详细信息,请参阅 Go 自动检测存储库。

Java

以下命令将创建一个基本的 Instrumentation 资源,该资源配置用于检测 Java 服务。

kubectl apply -f - <<EOF
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
spec:
  exporter:
    endpoint: http://demo-collector:4318
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: "1"
EOF

默认情况下,自动检测 Java 服务的 Instrumentation 资源使用 otlphttp/protobuf 协议。这意味着配置的端点必须能够通过 protobuf 有效负载接收 OTLP over http。因此,示例使用了 http://demo-collector:4318,它连接到上一步创建的 Collector 的 otlpreceiver 的 http 端口。

排除自动检测

默认情况下,Java 自动检测附带 许多检测库。这使得检测变得容易,但也可能导致过多的或不需要的数据。如果您不想使用某些库,可以设置 OTEL_INSTRUMENTATION_[NAME]_ENABLED=false,其中 [NAME] 是库的名称。如果您确切知道要使用的库,可以通过设置 OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED=false 来禁用默认库,然后使用 OTEL_INSTRUMENTATION_[NAME]_ENABLED=true,其中 [NAME] 是库的名称。有关更多详细信息,请参阅 抑制特定检测

apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
spec:
  exporter:
    endpoint: http://demo-collector:4318
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: '1'
  java:
    env:
      - name: OTEL_INSTRUMENTATION_KAFKA_ENABLED
        value: false
      - name: OTEL_INSTRUMENTATION_REDISCALA_ENABLED
        value: false

了解更多

有关更多详细信息,请参阅 Java 代理配置

Node.js

以下命令将创建一个基本的 Instrumentation 资源,该资源配置用于检测 Node.js 服务。

kubectl apply -f - <<EOF
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
spec:
  exporter:
    endpoint: http://demo-collector:4317
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: "1"
EOF

默认情况下,自动检测 Node.js 服务的 Instrumentation 资源使用 otlpgrpc 协议。这意味着配置的端点必须能够接收 OTLP over grpc。因此,示例使用了 http://demo-collector:4317,它连接到上一步创建的 Collector 的 otlpreceivergrpc 端口。

排除检测库

默认情况下,Node.js 的零代码检测启用了所有检测库。

要仅启用特定的检测库,您可以使用 OTEL_NODE_ENABLED_INSTRUMENTATIONS 环境变量,如 Node.js 零代码检测文档 中所述。

apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
# ... other fields skipped from this example
spec:
  # ... other fields skipped from this example
  nodejs:
    env:
      - name: OTEL_NODE_ENABLED_INSTRUMENTATIONS
        value: http,nestjs-core # comma-separated list of the instrumentation package names without the `@opentelemetry/instrumentation-` prefix.

要保留所有默认库并仅禁用特定的检测库,您可以使用 OTEL_NODE_DISABLED_INSTRUMENTATIONS 环境变量。有关详细信息,请参阅 排除检测库

apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
# ... other fields skipped from this example
spec:
  # ... other fields skipped from this example
  nodejs:
    env:
      - name: OTEL_NODE_DISABLED_INSTRUMENTATIONS
        value: fs,grpc # comma-separated list of the instrumentation package names without the `@opentelemetry/instrumentation-` prefix.

了解更多

有关更多详细信息,请参阅 Node.js 自动检测

Python

以下命令将创建一个基本的 Instrumentation 资源,该资源专门配置用于检测 Python 服务。

kubectl apply -f - <<EOF
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
spec:
  exporter:
    endpoint: http://demo-collector:4318
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: "1"
EOF

默认情况下,自动检测 Python 服务的 Instrumentation 资源使用 otlphttp/protobuf 协议(目前不支持 gRPC)。这意味着配置的端点必须能够接收 OTLP over http/protobuf。因此,示例使用了 http://demo-collector:4318,它将连接到上一步创建的 Collector 的 otlpreceiverhttp 端口。

从 operator v0.108.0 开始,Instrumentation 资源会自动为 Python 服务设置 OTEL_EXPORTER_OTLP_PROTOCOLhttp/protobuf。如果您使用的是旧版本的 Operator,则 **必须** 将此环境变量设置为 http/protobuf,否则 Python 自动检测将不起作用。

自动检测 Python 日志

默认情况下,Python 日志自动检测是禁用的。如果您想启用此功能,则必须按如下方式设置 OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED 环境变量:

apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: python-instrumentation
  namespace: application
spec:
  exporter:
    endpoint: http://demo-collector:4318
  env:
  propagators:
    - tracecontext
    - baggage
  python:
    env:
      - name: OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED
        value: 'true'

从 operator v0.111.0 开始,设置 OTEL_LOGS_EXPORTERotlp 不再是必需的。

排除自动检测

默认情况下,Python 自动检测附带 许多检测库。这使得检测变得容易,但也可能导致过多的或不需要的数据。如果您不想检测某些软件包,可以设置 OTEL_PYTHON_DISABLED_INSTRUMENTATIONS 环境变量。

apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
spec:
  exporter:
    endpoint: http://demo-collector:4318
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: '1'
  python:
    env:
      - name: OTEL_PYTHON_DISABLED_INSTRUMENTATIONS
        value:
          <comma-separated list of package names to exclude from
          instrumentation>

有关更多详细信息,请参阅 Python 代理配置文档

了解更多

对于 Python 特有的注意事项,请参阅 Python OpenTelemetry Operator 文档Python 代理配置文档


现在您的 Instrumentation 对象已创建,您的集群就具备了自动检测服务并向端点发送数据的能力。然而,OpenTelemetry Operator 的自动检测遵循选择加入模型。要激活自动检测,您需要向您的部署添加一个注解。

向现有部署添加注解

最后一步是选择加入您的服务以进行自动检测。这是通过更新您服务的 spec.template.metadata.annotations 来实现的,其中包含一个特定于语言的注解:

  • .NET: instrumentation.opentelemetry.io/inject-dotnet: "true"
  • Deno: instrumentation.opentelemetry.io/inject-sdk: "true"
  • Go: instrumentation.opentelemetry.io/inject-go: "true"
  • Java: instrumentation.opentelemetry.io/inject-java: "true"
  • Node.js: instrumentation.opentelemetry.io/inject-nodejs: "true"
  • Python: instrumentation.opentelemetry.io/inject-python: "true"

注解的可能值可以是:

  • "true" - 注入当前命名空间中默认名称的 Instrumentation 资源。
  • "my-instrumentation" - 注入当前命名空间中名称为 "my-instrumentation"Instrumentation CR 实例。
  • "my-other-namespace/my-instrumentation" - 从另一个命名空间 "my-other-namespace" 注入名称为 "my-instrumentation"Instrumentation CR 实例。
  • "false" - 不注入

或者,可以将注解添加到命名空间,这将导致该命名空间中的所有服务选择加入自动检测。有关更多详细信息,请参阅 Operator 的自动检测文档

选择加入 Go 服务

与其他语言的自动检测不同,Go 通过 sidecar 运行的 eBPF 代理进行工作。选择加入后,Operator 会将此 sidecar 注入到您的 Pod 中。除了上面提到的 instrumentation.opentelemetry.io/inject-go 注解外,您还必须为 OTEL_GO_AUTO_TARGET_EXE 环境变量 提供一个值。您可以通过 instrumentation.opentelemetry.io/otel-go-auto-target-exe 注解设置此环境变量。

instrumentation.opentelemetry.io/inject-go: 'true'
instrumentation.opentelemetry.io/otel-go-auto-target-exe: '/path/to/container/executable'

此环境变量也可以通过 Instrumentation 资源设置,其中注解具有更高的优先级。由于 Go 自动检测需要设置 OTEL_GO_AUTO_TARGET_EXE,因此您必须通过注解或 Instrumentation 资源提供一个有效的可执行文件路径。如果未设置此值,则会导致检测注入中止,从而保持原始 Pod 不变。

由于 Go 自动检测使用 eBPF,因此还需要提升的权限。当您选择加入时,Operator 注入的 sidecar 将需要以下权限:

securityContext:
  privileged: true
  runAsUser: 0

自动检测基于 musl 的 Python 容器

从 operator v0.113.0 开始,Python 自动检测还支持一个注解,该注解允许它在具有不同 C 库(而非 glibc)的镜像上运行。

# for Linux glibc based images, this is the default value and can be omitted
instrumentation.opentelemetry.io/otel-python-platform: "glibc"
# for Linux musl based images
instrumentation.opentelemetry.io/otel-python-platform: "musl"

故障排除

如果您在自动检测代码时遇到问题,可以尝试以下一些方法。

检测资源是否已安装?

安装 Instrumentation 资源后,通过运行此命令来验证它是否已正确安装,其中 <namespace> 是部署 Instrumentation 资源的命名空间:

kubectl describe otelinst -n <namespace>

示例输出

Name:         python-instrumentation
Namespace:    application
Labels:       app.kubernetes.io/managed-by=opentelemetry-operator
Annotations:  instrumentation.opentelemetry.io/default-auto-instrumentation-apache-httpd-image:
               ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-apache-httpd:1.0.3
             instrumentation.opentelemetry.io/default-auto-instrumentation-dotnet-image:
               ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-dotnet:0.7.0
             instrumentation.opentelemetry.io/default-auto-instrumentation-go-image:
               ghcr.io/open-telemetry/opentelemetry-go-instrumentation/autoinstrumentation-go:v0.2.1-alpha
             instrumentation.opentelemetry.io/default-auto-instrumentation-java-image:
               ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-java:1.26.0
             instrumentation.opentelemetry.io/default-auto-instrumentation-nodejs-image:
               ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-nodejs:0.40.0
             instrumentation.opentelemetry.io/default-auto-instrumentation-python-image:
               ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-python:0.39b0
API Version:  opentelemetry.io/v1alpha1
Kind:         Instrumentation
Metadata:
 Creation Timestamp:  2023-07-28T03:42:12Z
 Generation:          1
 Resource Version:    3385
 UID:                 646661d5-a8fc-4b64-80b7-8587c9865f53
Spec:
...
 Exporter:
   Endpoint:  http://demo-collector.opentelemetry.svc.cluster.local:4318
...
 Propagators:
   tracecontext
   baggage
 Python:
   Image:  ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-python:0.39b0
   Resource Requirements:
     Limits:
       Cpu:     500m
       Memory:  32Mi
     Requests:
       Cpu:     50m
       Memory:  32Mi
 Resource:
 Sampler:
Events:  <none>

OTel Operator 日志是否显示任何自动检测错误?

通过运行此命令检查 OTel Operator 日志中是否有与自动检测相关的任何错误:

kubectl logs -l app.kubernetes.io/name=opentelemetry-operator --container manager -n opentelemetry-operator-system --follow

资源是否以正确的顺序部署?

顺序很重要!Instrumentation 资源需要在部署应用程序之前部署,否则自动检测将不起作用。

回忆自动检测注解

annotations:
  instrumentation.opentelemetry.io/inject-python: 'true'

当 Pod 启动时,上面的注解会告诉 OTel Operator 在 Pod 的命名空间中查找 Instrumentation 对象。它还会告诉 Operator 将 Python 自动检测注入到 Pod 中。

它会向应用程序的 Pod 添加一个名为 opentelemetry-auto-instrumentationinit-container,然后该 init-container 用于将自动检测注入到应用程序容器中。

然而,如果在应用程序部署时 Instrumentation 资源尚不存在,则无法创建 init-container。因此,如果应用程序在部署 Instrumentation 资源之前部署,则自动检测将失败。

要确保 opentelemetry-auto-instrumentation init-container 已成功启动(或根本未启动),请运行以下命令:

kubectl get events -n <your_app_namespace>

这应该会输出类似以下内容:

53s         Normal   Created             pod/py-otel-server-7f54bf4cbc-p8wmj    Created container opentelemetry-auto-instrumentation
53s         Normal   Started             pod/py-otel-server-7f54bf4cbc-p8wmj    Started container opentelemetry-auto-instrumentation

如果输出中缺少 opentelemetry-auto-instrumentationCreated 和/或 Started 条目,则表示您的自动检测存在问题。这可能是以下任何原因造成的:

  • Instrumentation 资源未安装(或未正确安装)。
  • Instrumentation 资源在应用程序部署之后安装。
  • 自动检测注解中存在错误,或注解位置错误 — 请参阅下面的 #4。

请务必检查 kubectl get events 的输出,其中可能包含错误信息,这些信息有助于指出问题所在。

自动检测注解是否正确?

有时自动检测会因自动检测注解中的错误而失败。

以下是一些需要检查的事项:

  • 自动检测是否适用于正确的语言?
    • 例如,在检测 Python 应用程序时,请确保注解没有错误地写成 instrumentation.opentelemetry.io/inject-java: "true"
    • 对于 **Deno**,请确保您使用的是 instrumentation.opentelemetry.io/inject-sdk: "true" 注解,而不是包含字符串 deno 的注解。
  • **自动检测注解是否在正确的位置?** 在定义 Deployment 时,注解可以添加到两个位置之一:spec.metadata.annotationsspec.template.metadata.annotations。自动检测注解需要添加到 spec.template.metadata.annotations,否则将不起作用。

自动检测端点是否配置正确?

Instrumentation 资源 的 spec.exporter.endpoint 属性定义了要发送数据的位置。这可以是 OTel Collector,也可以是任何 OTLP 端点。如果省略此属性,则默认为 https://:4317,这很可能不会将遥测数据发送到任何地方。

当将遥测数据发送到位于同一 Kubernetes 集群中的 OTel Collector 时,spec.exporter.endpoint 应引用 OTel Collector Service 的名称。

例如

spec:
  exporter:
    endpoint: http://demo-collector.opentelemetry.svc.cluster.local:4317

此处,Collector 端点设置为 http://demo-collector.opentelemetry.svc.cluster.local:4317,其中 demo-collector 是 OTel Collector Kubernetes Service 的名称。在上面的示例中,Collector 运行在与应用程序不同的命名空间中,这意味着 opentelemetry.svc.cluster.local 必须附加到 Collector 的服务名称之后,其中 opentelemetry 是 Collector 所在的命名空间。