OpenTelemetry OpenTelemetry

将遥测数据发送到后端并保护管线安全

为 Tempo、Loki 和 Prometheus 配置 OTLP exporter,外加 TLS、认证和 secret。

14 min 中级

收集遥测数据只是工作的一半;另一半是把它安全地交付到正确的地方。本指南展示如何为常见的开源后端配置 exporter(示例使用 Grafana 栈),以及如何用 TLS、认证和不进入配置文件的 secret 来保护进出 Collector 的流量。

OTLP exporter:gRPC 与 HTTP

有两个 exporter 使用 OTLP:

  • otlp 使用 gRPC。端点是 host:port,没有 scheme,通常是 4317 端口。
  • otlphttp 使用 HTTP。端点是一个 URL,通常是 4318 端口,exporter 会在其后追加信号路径(/v1/traces、/v1/metrics、/v1/logs)。

使用名称后缀来定义多个同类型的 exporter:

exporters:
  otlp/tempo:
    endpoint: tempo.observability.svc.cluster.local:4317
    tls:
      insecure: true
  otlphttp/loki:
    endpoint: http://loki.observability.svc.cluster.local:3100/otlp
  otlphttp/prometheus:
    endpoint: http://prometheus.observability.svc.cluster.local:9090/api/v1/otlp

值得了解的后端细节:

  • 当在其配置中启用了 OTLP receiver 时,Tempo 直接在它的 receiver 端口(4317 gRPC、4318 HTTP)上接受 OTLP。
  • Loki 在其 HTTP 端口的 /otlp 上接受 OTLP 日志,所以使用 otlphttp 时最终 URL 变成 /otlp/v1/logs。
  • Prometheus 在 /api/v1/otlp/v1/metrics 接受 OTLP 指标,但只有在启动时启用了 OTLP receiver 时才行(--web.enable-otlp-receiver 标志)。

请在你所运行版本的每个产品文档中确认这些路径。然后把每种信号路由到它的后端:

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlp/tempo]
    logs:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlphttp/loki]
    metrics:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlphttp/prometheus]

一条管线可以有多个 exporter,把相同的数据发送到多个地方,例如一个主后端和一个归档。

Exporter 上的 TLS

对于任何穿越不可信网络的内容,请使用 TLS:

exporters:
  otlp/backend:
    endpoint: otlp.example.com:4317
    tls:
      ca_file: /etc/otel/certs/ca.crt        # to trust a private CA
      cert_file: /etc/otel/certs/client.crt  # for mutual TLS
      key_file: /etc/otel/certs/client.key

对于公共 CA,你可以省略整个 tls 块,因为会使用系统根证书。insecure: true 会禁用 TLS,仅用于集群内的开发。在生产环境中避免使用 insecure_skip_verify: true,因为它移除了 TLS 提供的保护。

Receiver 上的 TLS 与认证

在网络端口上监听的 Collector 应当要求 TLS,并且如果有任何你无法控制的东西可以访问到它,还应当要求认证。

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
        tls:
          cert_file: /etc/otel/certs/server.crt
          key_file: /etc/otel/certs/server.key
          client_ca_file: /etc/otel/certs/ca.crt   # require client certificates (mTLS)

对于基于令牌的认证,使用认证扩展。bearertokenauth 扩展既可以发送也可以检查令牌:

extensions:
  bearertokenauth/client:
    scheme: Bearer
    token: ${env:BACKEND_TOKEN}

exporters:
  otlphttp/backend:
    endpoint: https://otlp.example.com
    auth:
      authenticator: bearertokenauth/client

service:
  extensions: [bearertokenauth/client]

要验证传入的请求,存在其他扩展,比如 basicauth 和 oidc,通过 auth: { authenticator: <name> } 从 receiver 中引用。可用的选项因发行版和版本而异,所以请查看扩展的 README。

对于简单的基于头部的凭据,你也可以在 exporter 上设置头部:

exporters:
  otlphttp/saas:
    endpoint: https://otlp.vendor.example.com
    headers:
      api-key: ${env:VENDOR_API_KEY}

让 secret 远离配置

永远不要把令牌或密码字面地写进存放在 Git 中的配置文件。改为引用环境变量,并从 secret 存储提供该变量:

exporters:
  otlphttp/backend:
    headers:
      authorization: Bearer ${env:BACKEND_TOKEN}

在 Kubernetes 上,从 Secret 注入该变量:

env:
  - name: BACKEND_TOKEN
    valueFrom:
      secretKeyRef:
        name: otel-backend
        key: token

Secret 本身应当在 Git 中加密(例如用 SOPS,如 Flux 指南所示),或从 secret 管理器同步。Collector 还支持 file: provider(${file:/path/to/secret}),它读取挂载的文件,适合作为卷挂载并由平台轮换的 secret。无论你使用哪种来源,请确认该 provider 在你的发行版中可用;contrib 构建包含其中几个。

网络暴露

由于 Collector 通常运行在集群内部,它的默认姿态很重要:

  • 有意识地绑定。 较新的版本默认将 receiver 绑定到 localhost,这很安全但其他容器无法访问。只对应当可访问的端口使用 0.0.0.0,并用 NetworkPolicy、TLS 或认证来保护它们。
  • 禁用你不使用的东西。 移除未使用的 receiver 和 Service 端口,保持攻击面小。
  • 调试端点是给运维人员用的。 让 zpages 和 pprof 保持在 localhost,永远不要公开暴露它们。
  • 在导出之前脱敏。 在凭据、令牌和个人数据离开你的网络之前,用 attributes 或 transform processor 删除它们(参见生产就绪指南)。

一个只允许应用命名空间访问 Collector 的 NetworkPolicy:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-otlp-from-apps
  namespace: observability
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: opentelemetry-collector
  policyTypes: [Ingress]
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              telemetry: "enabled"
      ports:
        - protocol: TCP
          port: 4317
        - protocol: TCP
          port: 4318

验证

  1. 运行 otelcol validate --config=config.yaml 以捕获 YAML 和 schema 错误。
  2. 启动 Collector,并在日志中检查 exporter 的连接或 TLS 错误。
  3. 发送一个测试 span,然后在后端中查找它。如果它没有到达,请将 exporter 的协议和端口与后端实际监听的进行比较。
  4. 检查 Collector 自己的指标中的 otelcol_exporter_send_failed_* 计数器,当后端拒绝数据时它们会上升。

热门指南