如何使用 advancedSink 和 rawTransforms 转发日志
类型化的 LogForward 输出(kafka、elasticsearch、opensearch、syslog、http、console、blackhole、clickhouse)涵盖了大多数转发场景。advancedSink 输出则是处理其他所有情况的备用方案——它允许你按名称选择任意 Vector sink,并在 sink 写入之前,使用一组经过允许列表限制的少量 Vector transforms重新组织事件。
在以下情况下使用 advancedSink:
- 目标端是平台未作为类型化输出公开的供应商 sink(
datadog_logs、humio_logs、aws_s3、nats、gcp_cloud_storage等); - 目标端需要类型化输出不会生成的特定线路格式封装(OTLP
resourceLogs/scopeLogs/logRecords、Splunk HEC 批次等); - 转发路径需要比平台过滤器(
parse、filter、redact、prune、remapFields)更丰富的事件级重组能力——例如,将多条记录批量聚合到一个请求正文中,或编写组合多个条件的 VRL 谓词。
如果以上情况均不适用,请优先使用类型化输出和如何使用 LogForward 转发日志中介绍的标准过滤器——它们的验证更严格,也更易于审查。
目录
前提条件Spec 结构advancedSink.componentTypeadvancedSink.parametersadvancedSink.rawTransforms[]在平台 filters[] 条目和 rawTransforms[] 条目之间进行选择食谱食谱 A — 将审计记录转发到 Datadog,同时进行裁剪和丰富食谱 B — 将平台日志转发到通用 HTTP 接收端,同时使用 VRL 过滤器和采样食谱 C — 将平台日志作为 OTLP 信封转发到 OpenTelemetry Collector验证限制和注意事项相关主题前提条件
- 已安装 Alauda Container Platform Log Storage Management,并且
PlatformLogForward/platform-default为Ready。请参阅安装。 - v4.4 版本中提供的存储 operator 包含
advancedSink.rawTransforms字段,并且不会阻止在参数中使用batch/request。本文档中的模式假定你使用的是该版本。 spec.output.authSecretRef和spec.output.tls.caSecretRef引用的 Secret 位于cpaas-system中。
LogForward 仅位于 cpaas-system
与其他所有 LogForward 一样存在相同限制:admission webhook validate-lf.log.alauda.io 会拒绝 LogForward 位于 cpaas-system 之外的任何情况。每个 CR 都由平台管理员而非租户编写。
Spec 结构
advancedSink.componentType
按名称选择恰好一个 Vector sink 类型。名称与 Vector 自身文档中的名称一致,例如 http、datadog_logs、humio_logs、aws_s3、nats、elasticsearch(如果你希望使用其完整的配置项,而不是平台的类型化封装)。存储 operator 不维护按 sink 划分的允许列表,因为新版本的 Vector 添加 sink 的速度快于任何 Curated 列表的更新速度。Vector 会在启动时验证类型;如果名称错误,或 sink 依赖的 Vector feature flag 已关闭,Vector pod 将无法启动,并且 LogForward 会报告 Ready=False,其中包含针对 status.conditions 的解析器错误。
advancedSink.parameters
一个自由格式的对象,其键与所选 sink 的 Vector 配置相对应。嵌套对象会转换为嵌套 TOML 表({"encoding": {"codec": "json"}} 会变为 [sinks.output.encoding] codec = "json")。
保留键(admission webhook 会拒绝参数顶层的以下键):
名称相同的嵌套键(例如 {"resource": {"type": "gce_instance"}})不会被拒绝——webhook 只检查参数顶层。
之前保留、现在允许:batch 和 request。两者都是按 sink 设置的配置项;下面的 OTLP 封装方案需要使用 batch.max_events: 1 才能正常工作。
advancedSink.rawTransforms[]
一个可选的、有序的 Vector transforms 链,在平台过滤器之后、sink 写入之前运行。每个条目包含:
为什么是这六种类型?它们是本地、无副作用的 transforms——不会更改拓扑,不会创建子输出,也不会调用外部服务。route(多输出)会破坏 operator 的输入连接。lua(任意代码)存在安全风险。log_to_metric 应用于 metrics pipeline。
生成的 Vector pipeline 中的执行顺序:
operator 会在每个阶段连接 inputs;你无需自行编写 inputs(如果编写,webhook 也会拒绝)。
在平台 filters[] 条目和 rawTransforms[] 条目之间进行选择
两者存在重叠。经验法则如下:
可以自由组合使用:平台过滤器先运行,完成简单的字段级处理;然后由 rawTransforms 对已清理的事件执行更复杂的结构处理。
食谱
三个完整示例,从简单到复杂。
食谱 A — 将审计记录转发到 Datadog,同时进行裁剪和丰富
场景:将平台审计记录发送到 Datadog Logs。使用平台的 prune 过滤器删除噪声字段,然后使用 rawTransforms.remap 添加 Datadog 可用于路由的租户标签。
需要注意的事项:
authSecretRef.password→ Vector pod 上的OUTPUT_PASSWORD环境变量 →parameters中的${OUTPUT_PASSWORD}字面量会在 Vector 启动时展开。username键是 Secret 结构所必需的,但 Datadog 不会读取它。- 平台的
prune过滤器在remap之前运行,因此丰富处理 VRL 处理的是已经缩减的事件。 - VRL 中可能失败的操作(
to_string(x))必须包含回退值(?? "unknown"),否则整个 transform 会中止该事件。完整的 VRL 食谱集请参阅 operator 侧指南:log-storage-operator/docs/HOWTO_LF_ADVANCED_SINK_RAW_TRANSFORMS.md。
食谱 B — 将平台日志转发到通用 HTTP 接收端,同时使用 VRL 过滤器和采样
场景:将应用日志发送到通用 HTTP 接收端,但使用平台 filter 无法表示为单个谓词的复合条件来删除健康检查噪声,并以每个 pod 10% 的比例对保留的流进行采样,以控制数据量。
需要注意的事项:
- 平台的
redact过滤器与rawTransformsfilter/sample组合使用:先进行脱敏,然后删除,最后采样。 sample上的exclude字段可确保所有错误都得以保留,这是常见需求,但无法通过平台的filter过滤器表达。- 如果同时设置了
authSecretRef和parameters.request.headers.Authorization,Vector 的httpsink 将拒绝启动。请选择其中一种路径(与如何使用 LogForward 转发日志中的类型化 HTTP 输出规则相同)。
食谱 C — 将平台日志作为 OTLP 信封转发到 OpenTelemetry Collector
场景:将平台日志发送到 OTel Collector 的 otlphttp receiver。OTLP/HTTP 需要单个顶层 JSON 对象({resourceLogs: [...]}),而不是数组——因此该食谱使用 remap + reduce + remap 构建信封,并在 sink 上设置 batch.max_events: 1,使 Vector 不会将生成的单个信封重新批处理为数组。
需要注意的事项:
- 对于 OTLP/HTTP,
batch.max_events: 1是必需的。如果没有它,Vector 的httpsink 会将 reducer 的单个信封包装为单元素数组[{...}],而 OTel Collector 会以 400 错误拒绝该请求。 expire_after_ms用延迟换取批次大小。1 秒(如示例所示)是合理的默认值;在数据量非常大时将其降低到 500 ms,在数据量非常小时将其提高到 5 000 ms。关注 Collector 的max_request_body_size——如果信封超过该限制,请缩短expire_after_ms。- 时间戳(
timeUnixNano: "0")是占位符:Collector 将使用接收时间。若要保留真实事件时间,请将其替换为to_string(to_unix_timestamp(parse_timestamp!(.timestamp, "%+")) * 1000000000)。 - 如果 Collector 需要身份验证,请将其添加到
parameters.request.headers.Authorization(Bearer ${OUTPUT_PASSWORD}),并使用 Secret 的password中的密钥设置authSecretRef。
验证
与任何 LogForward 相同:
如果未进入 Ready 状态,请读取条件:
特定于 advancedSink 的常见 Ready=False 原因:
AdvancedSinkParametersRejected— 参数顶层设置了保留键(type、inputs、sources、transforms、route、buffer、acknowledgements、healthcheck)。RawTransformsRejected— 某个rawTransforms[*]条目包含不在允许列表中的type、重复的name,或者在其spec中写入了inputs/type。VectorValidateFailed— operator 会渲染 Vector 配置,将vector validate作为预检调用,并且仅在验证通过后才滚动更新 Deployment。条件消息会逐字包含 Vector 解析器错误;这几乎总是 Vector sink 字段名称拼写错误或 VRL 语法错误(fallible without ??)。
要调试 sink 实际发出的线上负载,请将 sink 的 uri 指向一个短期运行的 echo pod,然后读取接收到的内容——operator 端指南 log-storage-operator/docs/HOWTO_LF_ADVANCED_SINK_RAW_TRANSFORMS.md 提供了可直接复制的 echo pod 配方。
限制和注意事项
rawTransforms[*].type仅限于remap、filter、reduce、throttle、sample、dedupe。其他 Vector transform 类型(尤其是route和lua)会被拒绝。rawTransforms[*].spec不能携带inputs或type——这些由 operator 连接。- 一个
LogForward只有一个输出和一个 Vector Deployment。要扇出到多个目标,请创建多个LogForwardCR;它们只能通过复制粘贴共享平台过滤器(不存在跨 CR 的过滤器复用)。 - 平台过滤器(
filters[])和rawTransforms[]都会运行;先运行过滤器,再运行 rawTransforms。字段级操作使用前者,事件形状操作使用后者。 - 平台的
KafkaUser必须包含logforward-consumer-group 前缀 ACL 规则。没有该规则,Vector pod 会静默读取零条记录,而LogForward仍会报告Ready=True。有关 ACL 配置方法,请参阅安装。 advancedSink是一个逃生阀。Vector sink schema 可能会在 Vector 次要版本之间发生变化;operator 会在每次 reconcile 时将vector validate作为预检运行,并拒绝滚动更新损坏的配置,因此升级仍然安全,但存储 operator 进行 major 升级后,仍建议重新阅读 Vector sink 参考文档。
相关主题
- 使用 LogForward 转发日志 — 类型化输出(
kafka、elasticsearch、opensearch、syslog、http、console、blackhole、clickhouse)和平台过滤器目录。 - 将日志归档到第三方存储 —
razor consumer --database-type=file归档路径,用于 NFS / S3 冷存储,而非实时转发。 - 安装 — 存储 operator 的安装,以及
logforward-KafkaUser 前缀 ACL 规则。