4. Pipeline隔离基础:为每个租户创建独立Pipeline

在多租户可观测性架构中,Pipeline隔离是最基础也是最重要的安全边界。每个租户拥有独立的OpenTelemetry Collector Pipeline,意味着数据从接收、处理到导出的全链路都不会与其他租户的数据发生交叉。本章将深入讲解如何为每个租户创建独立的Pipeline,并通过配置示例展示Receiver与Exporter的绑定关系。

4.1 为什么需要Pipeline隔离

在单Pipeline架构中,所有租户的数据流经同一个处理链路,存在以下风险:

  • 数据泄露:租户A的敏感指标可能被错误路由到租户B的导出目标
  • 资源抢占:一个租户的突发流量可能阻塞其他租户的数据处理
  • 配置冲突:不同租户的采样率、过滤规则、批处理参数无法独立调整
  • 故障扩散:某个租户的Exporter故障可能导致整个Collector Pipeline阻塞

通过为每个租户创建独立的Pipeline,可以实现:

  • 数据强隔离:每个Pipeline拥有独立的Receiver、Processor、Exporter实例
  • 资源独立控制:可为每个Pipeline分配独立的CPU、内存配额
  • 配置独立管理:每个Pipeline的采样、过滤、批处理策略完全独立
  • 故障域隔离:单个Pipeline的故障不会影响其他租户的数据流

4.2 多Pipeline架构设计

OpenTelemetry Collector支持在同一个配置文件中定义多个Pipeline,每个Pipeline由receivers、processors、exporters三个核心组件构成。多租户场景下,每个租户对应一个独立的Pipeline,如下图所示:

多租户Pipeline隔离架构 租户A Pipeline Receiver A OTLP/gRPC :4317 Processor A 采样+过滤+批处理 Exporter A OTLP :4318 租户B Pipeline Receiver B OTLP/gRPC :4319 Processor B 采样+过滤+批处理 Exporter B OTLP :4320 租户C Pipeline Receiver C OTLP/gRPC :4321 Processor C 采样+过滤+批处理 Exporter C OTLP :4322 隔离要点 独立端口 独立处理链路 隔离要点 独立配置 独立资源配额 隔离要点 故障隔离 独立监控

4.3 Pipeline配置示例

以下是一个为三个租户(tenant-a、tenant-b、tenant-c)配置独立Pipeline的完整示例。每个租户使用不同的接收端口和导出目标。

receivers:
  otlp/tenant-a:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

  otlp/tenant-b:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4319
      http:
        endpoint: 0.0.0.0:4320

  otlp/tenant-c:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4321
      http:
        endpoint: 0.0.0.0:4322

processors:
  batch/tenant-a:
    timeout: 5s
    send_batch_size: 1000

  batch/tenant-b:
    timeout: 10s
    send_batch_size: 500

  batch/tenant-c:
    timeout: 3s
    send_batch_size: 2000

  memory_limiter/tenant-a:
    check_interval: 1s
    limit_mib: 512

  memory_limiter/tenant-b:
    check_interval: 1s
    limit_mib: 256

  memory_limiter/tenant-c:
    check_interval: 1s
    limit_mib: 1024

exporters:
  otlp/tenant-a:
    endpoint: backend-a.example.com:4317
    tls:
      insecure: false
    headers:
      "x-tenant-id": "tenant-a"

  otlp/tenant-b:
    endpoint: backend-b.example.com:4317
    tls:
      insecure: false
    headers:
      "x-tenant-id": "tenant-b"

  otlp/tenant-c:
    endpoint: backend-c.example.com:4317
    tls:
      insecure: false
    headers:
      "x-tenant-id": "tenant-c"

service:
  pipelines:
    traces/tenant-a:
      receivers: [otlp/tenant-a]
      processors: [memory_limiter/tenant-a, batch/tenant-a]
      exporters: [otlp/tenant-a]

    traces/tenant-b:
      receivers: [otlp/tenant-b]
      processors: [memory_limiter/tenant-b, batch/tenant-b]
      exporters: [otlp/tenant-b]

    traces/tenant-c:
      receivers: [otlp/tenant-c]
      processors: [memory_limiter/tenant-c, batch/tenant-c]
      exporters: [otlp/tenant-c]

4.4 Receiver与Exporter的绑定关系

在OpenTelemetry Collector中,Pipeline的绑定关系通过service.pipelines节定义。每个Pipeline名称由信号类型和租户标识组成,例如traces/tenant-a。绑定规则如下:

Pipeline名称 Receiver绑定 Processor绑定 Exporter绑定 隔离级别
traces/tenant-a otlp/tenant-a memory_limiter/tenant-a, batch/tenant-a otlp/tenant-a 完全隔离
traces/tenant-b otlp/tenant-b memory_limiter/tenant-b, batch/tenant-b otlp/tenant-b 完全隔离
traces/tenant-c otlp/tenant-c memory_limiter/tenant-c, batch/tenant-c otlp/tenant-c 完全隔离
关键原则:每个Pipeline中的Receiver、Processor、Exporter实例必须使用唯一的命名空间(通过/后缀区分)。即使多个租户使用相同类型的组件(如otlp),也必须通过不同的命名后缀来创建独立的组件实例。

4.5 绑定关系的数据流验证

为了验证Receiver与Exporter的绑定关系是否正确,可以通过以下步骤进行数据流追踪:

  1. 确认Receiver端口唯一性:每个租户的Receiver监听不同的端口,确保数据不会错发
  2. 检查Processor链:每个Pipeline的Processor链独立配置,租户A的采样率不会影响租户B
  3. 验证Exporter目标:每个Exporter指向不同的后端地址或使用不同的认证头
  4. 测试故障隔离:停止租户A的Exporter,验证租户B和C的数据流不受影响

以下是一个验证绑定关系的测试命令示例:

# 向租户A的Receiver发送测试数据
curl -X POST http://localhost:4318/v1/traces \
  -H "Content-Type: application/json" \
  -d '{"resourceSpans": [{"resource": {"attributes": [{"key": "tenant", "value": {"stringValue": "tenant-a"}}]}}]}'

# 检查租户A的Exporter是否收到数据(假设后端有健康检查端点)
curl http://backend-a.example.com:4318/health

4.6 常见配置错误与避坑

常见错误1:Receiver端口冲突
如果两个租户的Receiver配置了相同的端口,Collector启动时会报端口冲突错误。务必为每个租户分配独立的端口号。
常见错误2:Processor实例共享
不要在不同Pipeline中引用同一个Processor实例(如batch),否则会导致数据交叉。始终使用命名后缀创建独立实例。
常见错误3:Exporter目标混淆
确保每个租户的Exporter指向正确的后端地址。建议在Exporter的请求头中添加租户标识,便于后端进行二次验证。

4.7 隔离效果验证矩阵

完成Pipeline配置后,建议使用以下验证矩阵确认隔离效果:

验证场景 操作 预期结果 验证方法
数据隔离 向租户A的Receiver发送数据 数据仅出现在租户A的Exporter 检查后端A的日志,确认无数据到达后端B
资源隔离 对租户A施加高负载 租户B和C的延迟不受影响 监控各Pipeline的处理延迟指标
配置隔离 修改租户A的采样率为10% 租户B和C的采样率保持不变 对比各Pipeline的输出数据量
故障隔离 停止租户A的Exporter后端 租户B和C的数据流正常 检查Collector日志,确认只有租户A的Pipeline报错

4.8 多信号类型的Pipeline隔离

除了traces信号,metrics和logs信号也需要同样的隔离策略。以下是一个包含三种信号类型的完整隔离配置片段:

service:
  pipelines:
    traces/tenant-a:
      receivers: [otlp/tenant-a]
      processors: [memory_limiter/tenant-a, batch/tenant-a]
      exporters: [otlp/tenant-a]

    metrics/tenant-a:
      receivers: [otlp/tenant-a]
      processors: [memory_limiter/tenant-a, batch/tenant-a]
      exporters: [otlp/tenant-a]

    logs/tenant-a:
      receivers: [otlp/tenant-a]
      processors: [memory_limiter/tenant-a, batch/tenant-a]
      exporters: [otlp/tenant-a]

    traces/tenant-b:
      receivers: [otlp/tenant-b]
      processors: [memory_limiter/tenant-b, batch/tenant-b]
      exporters: [otlp/tenant-b]

    metrics/tenant-b:
      receivers: [otlp/tenant-b]
      processors: [memory_limiter/tenant-b, batch/tenant-b]
      exporters: [otlp/tenant-b]

    logs/tenant-b:
      receivers: [otlp/tenant-b]
      processors: [memory_limiter/tenant-b, batch/tenant-b]
      exporters: [otlp/tenant-b]
最佳实践:对于同一个租户的多种信号类型,可以共享同一个Receiver端口(OTLP协议支持多信号复用),但Processor和Exporter建议保持独立,以便针对不同信号类型设置不同的处理策略。