尾部采样的策略与路由层
目标
设计五项尾部采样策略,在其前方放置 trace ID 路由层,亲自计算缓冲区内存,并将该值应用到 Operator CR。
为什么重要
尾部采样并不是“启用后就能降低成本”的功能。由于必须等所有 span 到达后才能作出决定,从 Agent 到 Collector 的网络流量完全不会减少,减少的只有后端存储和索引。作为代价,会新增三项开销:在 decision_wait 期间保留所有 span 的内存、将同一 trace 汇集到一个实例的路由层,以及运行该层的复杂度。因此,是否采用不能凭感觉,而要通过乘法决定。将每秒 trace 数乘以等待时间得到 num_traces,再乘以 span 数和大小得到内存。如果跳过这项计算,就可能在上限不足的状态下运行;旧 trace 被强制决策后,数据会消失,而指标却不会报告任何异常。
步骤
- 创建
/root/otca-sampling/tailsampling.yaml,在processors.tail_sampling中写入decision_wait: 30s、num_traces: 300000、expected_new_traces_per_sec: 10000。 - 在
policies中加入两项策略:name: keep-errors(type: status_code,status_code.status_codes中加入ERROR)和name: keep-slow(type: latency,latency.threshold_ms: 800)。 - 添加
name: drop-healthchecks策略。type: string_attribute,string_attribute.key: http.route,values为/healthz和/readyz,并设置invert_match: true。 - 添加
name: vip-slow策略。其type: and,并在and.and_sub_policy中放置两个子策略——一个type: string_attribute,要求tenant.tier为enterprise;另一个type: latency,设置threshold_ms: 300。最后添加name: baseline(type: probabilistic,probabilistic.sampling_percentage: 2),使策略总数达到 5 项。 - 在
/root/otca-sampling/loadbalancing.yaml中编写前置路由层。在exporters.loadbalancing中设置routing_key: traceID;resolver.dns.hostname使用包含otel-tailsampler的服务地址;设置resolver.dns.port: 4317。service.pipelines.traces的 Exporter 只能是[loadbalancing],Processor 中不能加入tail_sampling。 - 在
/root/otca-sampling/buffer-memory.txt中用三行写入计算结果:num_traces_required=(10,000 trace/s × 30s)、buffer_mb=(将 10,000 × 30 × 12 span × 1.2KB 换算为 MB 后四舍五入)、buffer_mb_with_headroom=(前者的 2 倍)。每行采用无空格的키=값格式。 - 创建命名空间
otca-sampling,并在/root/otca-sampling/collector-cr.yaml中编写 CR。apiVersion: opentelemetry.io/v1beta1、kind: OpenTelemetryCollector、metadata.name: otel-tailsampler、metadata.namespace: otca-sampling、spec.mode: deployment、spec.replicas: 3。在spec.config中包含第 1~4 步的tail_sampling(原样保留五项策略),并将spec.config.service.pipelines.traces.processors配置为tail_sampling位于batch之前,且batch位于最后。
参考
- 第 6 步计算:10000 × 30 × 12 × 1.2 = 4,320,000 KB。除以 1024 后四舍五入。
- 第 7 步的
spec.config结构与普通 Collector 配置文件相同。直接在其中放入receivers、processors、exporters、service。 - 常见错误 1:遗漏
invert_match。这样会只保留健康检查。 - 常见错误 2:在前置路由层中同时加入
tail_sampling。这样会在 span 汇集之前作出决策。 - 常见错误 3:将 CR 的
spec.mode设为daemonset。span 会分散到各节点,无法作出决策。
tail_sampling 基本值
创建 /root/otca-sampling/tailsampling.yaml,在 processors.tail_sampling 中写入 decision_wait: 30s、num_traces: 300000、expected_new_traces_per_sec: 10000。
decision_wait 是等待一个 trace 的所有 span 到达所留出的时间。太短会根据不完整的 trace 作出决策,太长则会导致内存激增。num_traces 来自每秒 trace 数与等待时间的乘积。
两项基于结果的策略
在 policies 中加入两项策略:name: keep-errors(type: status_code,status_code.status_codes 中加入 ERROR)和 name: keep-slow(type: latency,latency.threshold_ms: 800)。
这两项策略正是尾部采样存在的理由。头部采样只能按概率获得这些 trace,而这些规则可以 100% 保留它们。每项策略都包含 name、type,以及与 type 同名的配置块。
排除健康检查
添加 name: drop-healthchecks 策略。type: string_attribute,string_attribute.key: http.route,values 为 /healthz 和 /readyz,并设置 invert_match: true。
所有策略都表示“保留条件”。因此,要排除特定路由,需要一个反转匹配的选项。请使用按属性值列表匹配的策略类型。
and 组合策略与基础概率
添加 name: vip-slow 策略。其 type: and,并在 and.and_sub_policy 中放置两个子策略——一个 type: string_attribute,要求 tenant.tier 为 enterprise;另一个 type: latency,设置 threshold_ms: 300。最后添加 name: baseline(type: probabilistic,probabilistic.sampling_percentage: 2),使策略总数达到 5 项。
只有同时满足两个条件时才保留,需要使用组合策略。各子策略也是包含 name 和 type 的完整策略。最后,为其余 trace 添加概率策略。
前置路由层
在 /root/otca-sampling/loadbalancing.yaml 中编写前置路由层。在 exporters.loadbalancing 中设置 routing_key: traceID;resolver.dns.hostname 使用包含 otel-tailsampler 的服务地址;设置 resolver.dns.port: 4317。service.pipelines.traces 的 Exporter 只能是 [loadbalancing],Processor 中不能加入 tail_sampling。
决策层前方需要一层将同一 trace 的 span 汇集到一个实例。普通负载均衡器无法做到,必须使用以 trace ID 为键的 Exporter。此前置层不作采样决策。
计算缓冲区内存
在 /root/otca-sampling/buffer-memory.txt 中用三行写入计算结果:num_traces_required=(10,000 trace/s × 30s)、buffer_mb=(将 10,000 × 30 × 12 span × 1.2KB 换算为 MB 后四舍五入)、buffer_mb_with_headroom=(前者的 2 倍)。每行采用无空格的 키=값 格式。
计算方式为:每秒 trace 数 × 等待时间 × 每个 trace 的 span 数 × span 大小。将 KB 转换为 MB 时除以 1024,并对小数四舍五入。num_traces 的所需值只需相乘前两项。
OpenTelemetryCollector CR
创建命名空间 otca-sampling,并在 /root/otca-sampling/collector-cr.yaml 中编写 CR。apiVersion: opentelemetry.io/v1beta1、kind: OpenTelemetryCollector、metadata.name: otel-tailsampler、metadata.namespace: otca-sampling、spec.mode: deployment、spec.replicas: 3。在 spec.config 中包含第 1~4 步的 tail_sampling(原样保留五项策略),并将 spec.config.service.pipelines.traces.processors 配置为 tail_sampling 位于 batch 之前,且 batch 位于最后。
如果采用每个节点都启动实例的部署模式,同一 trace 的 span 会分散到多个节点,无法作出决策。CR 内的配置与 Collector 配置文件结构相同,Processor 顺序规则也完全适用。此环境没有 CRD,因此只需编写文件,并实际创建命名空间。