1. 引言:为什么需要两套参考实现
OpenTelemetry(OTel)已经成为云原生可观测性的事实标准,但"标准"只解决了协议与 SDK 层面的问题,真正落地到生产环境时,最难的往往不是埋点,而是 Collector 怎么部署、怎么管理、怎么控制成本。
本文拆解两套公开的参考实现:
- Skyscanner:跨 24 个生产集群、数百个 Collector 实例的大规模统一管理方案;
- Mastodon:每个 Namespace 一个 Collector 的极简设计,由小团队维护。
两者没有优劣之分,只有规模与团队约束的匹配度差异。理解它们的取舍,比照搬任何一套配置都更有价值。
2. 两套参考实现的对比:大规模 vs 小团队的 OTel 策略
先给出一张整体对比表,后续章节再逐项展开。
| 维度 | Skyscanner | Mastodon |
|---|---|---|
| 集群规模 | 24 个生产集群 | 少量集群,单团队维护 |
| Collector 部署模式 | Gateway(集中式)+ 少量 DaemonSet | 每个 Namespace 一个 Deployment |
| 配置管理 | GitOps + 集中式配置分发 | 随应用清单一起版本化 |
| 多租户隔离 | 按集群/团队划分管道 | 按 Namespace 天然隔离 |
| 采样策略 | 分层采样 + 尾部采样 | 头部采样为主,低比例 |
| 团队投入 | 专职可观测性平台团队 | 兼职维护,追求"零运维" |
| 核心目标 | 统一治理、成本可控 | 简单、可预测、够用 |
一句话总结:Skyscanner 用架构复杂度换治理能力,Mastodon 用功能克制换维护成本。
从整体策略上看,两套方案的取舍可以抽象成一条对比路径:
3. Skyscanner 方案:跨 24 个生产集群的 Collector 管理架构
3.1 架构分层
Skyscanner 的可观测性平台团队面对的核心问题是:24 个集群、大量业务团队、多种信号(traces/metrics/logs),如何避免每个团队各自为政。
他们的做法是分层 Collector:
- 节点级 Agent:以 DaemonSet 形式运行,负责接收本节点上应用通过 OTLP 上报的数据,做最轻量的处理(如资源属性补全、批处理)。
- 集群级 Gateway:每个集群一组 Gateway,承担采样、过滤、路由、限流等重活。
- 区域聚合层:跨集群汇聚后再写入后端,减少后端连接数与写入压力。
3.2 配置管理:把 Collector 当代码管
24 个集群意味着 24 份(甚至更多)配置。Skyscanner 的关键经验是:
- 配置集中版本化:所有 Collector 配置存放在统一仓库,通过 GitOps 下发,禁止手工改线上配置;
- 配置分层复用:基础配置(batch、memory_limiter、health_check)作为公共片段,各集群只覆盖差异部分;
- 变更灰度:配置变更先在单个集群验证,再逐步推广,避免一次错误配置打穿全部集群。
配置从提交到全量生效的流程可以概括为:
3.3 大规模下的稳定性要点
- 每个 Collector 必须配置
memory_limiter,防止突发流量导致 OOM; - Gateway 前面加负载均衡,避免单实例热点;
- 对下游后端做背压保护,队列满时优先丢弃低优先级数据而不是阻塞应用。
4. Mastodon 方案:每个 Namespace 一个 Collector 的极简设计
4.1 设计思路
Mastodon 的规模远小于 Skyscanner,团队也没有专职可观测性工程师。他们的选择非常直接:每个 Namespace 部署一个 Collector Deployment。
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: otel-collector
namespace: mastodon
spec:
replicas: 1
selector:
matchLabels:
app: otel-collector
template:
metadata:
labels:
app: otel-collector
spec:
containers:
- name: otel-collector
image: otel/opentelemetry-collector-contrib:0.100.0
args: ["--config=/conf/config.yaml"]
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 256Mi
volumeMounts:
- name: config
mountPath: /conf
volumes:
- name: config
configMap:
name: otel-collector-config
4.2 为什么这样够用
- 隔离天然成立:Namespace 本身就是租户边界,一个 Collector 只处理本 Namespace 的数据,不需要复杂的路由规则;
- 配置随应用走:Collector 的 ConfigMap 和业务清单放在同一个仓库,改配置和改应用是同一个 PR;
- 故障域小:某个 Collector 挂了只影响一个 Namespace,不会引发全局雪崩;
- 心智负担低:没有 Gateway 层、没有跨集群聚合,新人半天就能看懂。
数据流向非常直观,每个 Namespace 自成一条独立链路:
4.3 代价与边界
这套方案的代价也很明确:
- 实例数量随 Namespace 线性增长,资源利用率不高;
- 无法做跨 Namespace 的全局采样与聚合;
- 每个 Collector 都要单独配置后端导出,重复度高。
适用边界:Namespace 数量在几十个以内、团队没有专职平台工程师、对成本不极度敏感。
5. Collector 部署模式选择:DaemonSet、Sidecar 还是 Gateway
三种模式各有适用场景,实际生产中往往是组合使用。
| 模式 | 优点 | 缺点 | 典型场景 |
|---|---|---|---|
| DaemonSet | 每节点一个,资源可控;就近采集主机指标 | 无法做跨节点聚合;升级影响整节点 | 主机指标、日志采集 |
| Sidecar | 与应用同生命周期,隔离性最好 | 实例数爆炸,资源开销大 | 多租户强隔离、特殊协议转换 |
| Gateway | 集中处理,便于采样/路由/限流 | 单点压力大,需要高可用设计 | 统一出口、尾部采样 |
5.1 选择建议
- 默认从 DaemonSet 起步:覆盖大部分节点级采集需求,运维成本最低;
- 需要集中治理时加 Gateway:采样、脱敏、路由这类"重活"放在 Gateway,Agent 保持轻量;
- Sidecar 谨慎使用:只在强隔离或协议转换场景下使用,否则实例数会失控。
Skyscanner 采用的是 DaemonSet + Gateway 的组合,Mastodon 则用 Namespace 级 Deployment 近似 Gateway 的角色,但范围缩小到单个租户。
三种部署模式在数据链路中的位置关系如下:
6. 采样策略与数据管道优化:控制成本的同时保持可观测性
6.1 分层采样
采样是控制成本最有效的手段,但粗暴地全局降采样会丢掉关键链路。推荐分层:
- 头部采样(Head Sampling):在 SDK 侧按比例采样,成本最低,但无法基于完整链路做决策;
- 尾部采样(Tail Sampling):在 Collector 侧基于完整 trace 决策,可保留所有错误链路和慢链路;
- 组合策略:SDK 侧先做 10%~20% 的头部采样,Gateway 侧再做尾部采样,保留 100% 错误与超阈值慢请求。
分层采样在链路中的决策位置如下:
6.2 尾部采样配置示例
yaml
processors:
tail_sampling:
decision_wait: 10s
num_traces: 100000
policies:
- name: errors-policy
type: status_code
status_code:
status_codes: [ERROR]
- name: slow-traces-policy
type: latency
latency:
threshold_ms: 500
- name: baseline-policy
type: probabilistic
probabilistic:
sampling_percentage: 5
6.3 数据管道优化要点
- 批处理 :
batchprocessor 放在管道末端,减少网络往返; - 内存保护 :
memory_limiter放在管道最前端,先于所有处理逻辑; - 属性裁剪 :用
attributes/transformprocessor 删除无用标签,降低存储成本; - 队列与重试 :导出端配置
sending_queue与retry_on_failure,避免后端抖动导致数据丢失; - 按信号分管道:traces、metrics、logs 使用独立 pipeline,避免互相拖累。
yaml
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [otlphttp]
metrics:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [prometheusremotewrite]
7. 总结:如何选择适合自己团队的方案
把两套方案抽象成决策路径:
核心结论:
- 先解决部署模式,再谈采样:部署架构决定了后续治理的上限;
- 配置必须版本化:无论规模大小,手工改线上 Collector 配置都是事故源头;
- 采样要分层:头部采样控基线成本,尾部采样保关键链路;
- 不要过早追求统一:小团队照搬大规模方案,往往先被运维复杂度拖垮。
OpenTelemetry 的价值在于它给了你统一的协议与组件,但架构决策仍然要回到自己的规模、团队与成本约束上。