土法炼钢 · 系统与基础设施

【可观测性工程】日志管道:Fluent Bit、Vector、Logstash、Cribl 的取舍

文章导航

分类入口
architectureobservability
标签入口
#fluentbit#vector#logstash#cribl#log-pipeline#kubernetes#daemonset#backpressure#vrl#loki

目录

日志管道:Fluent Bit、Vector、Logstash、Cribl 的取舍

如果你问十个 SRE「可观测性栈中最容易出问题但最不受重视的组件是什么」,至少七个会回答「日志管道」。Metrics 有 Prometheus,Traces 有 OpenTelemetry——唯独日志管道二十年来从未统一。

一个 300 节点 Kubernetes 集群:DaemonSet 采集 + metadata 注入 + fan-out 到 Loki、ClickHouse、Kafka——看似 tail 文件然后 POST,却是故障率最高、监控覆盖最低的一层。本文从 Collect → Parse → Enrich → Filter → Route 五阶段拆解 Fluent Bit、Vector、Logstash、Cribl,覆盖 K8s DaemonSet 模式、背压(Backpressure)与 Fluent Bit vs Vector 假设模型对比(非自测 benchmark)。

前置:Logs 技术栈数据模型

日志管道五阶段架构

一、管道五阶段与失效模式

每一阶段独立失效;错误向下游放大为存储成本与排障盲区。

| 阶段 | 典型故障 | 检测信号 |
|------|----------|----------|
| Collect | tail 路径错、权限不足 | 吞吐归零 |
| Parse | multiline 截断 | ES/Loki 中残缺 stacktrace |
| Enrich | metadata 错绑 | 按 pod 过滤查不到 |
| Filter | 规则过宽丢 ERROR | 事故无日志 |
| Route | 下游单点挂 | output retry 飙升 |

1.1 Collect

工程要点:CRI 路径 /var/log/containers/*.log;DaemonSet 挂则整节点停采。

    **Fluent Bit**:tail + kubernetes filter。  
    **Vector**:kubernetes_logs source。

    **验证**:`kubectl logs -n logging daemonset/fluent-bit --tail=20` 无 error;Loki 查询 job=fluentbit 的 ERROR 流持续。

1.2 Parse

工程要点:JSON 优先;GroK CPU 随 capture group 线性恶化。

    **Fluent Bit**:tail + kubernetes filter。  
    **Vector**:remap/filter/route transform。

    **验证**:`kubectl logs -n logging daemonset/fluent-bit --tail=20` 无 error;Loki 查询 job=fluentbit 的 ERROR 流持续。

1.3 Enrich

工程要点:K8s watch RBAC;cache TTL 与 Pod churn Trade-off。

    **Fluent Bit**:grep/modify/loki output。  
    **Vector**:remap/filter/route transform。

    **验证**:`kubectl logs -n logging daemonset/fluent-bit --tail=20` 无 error;Loki 查询 job=fluentbit 的 ERROR 流持续。

1.4 Filter

工程要点:PII 在 Agent 脱敏;DEBUG 可 drop-on-pressure。

    **Fluent Bit**:grep/modify/loki output。  
    **Vector**:remap/filter/route transform。

    **验证**:`kubectl logs -n logging daemonset/fluent-bit --tail=20` 无 error;Loki 查询 job=fluentbit 的 ERROR 流持续。

1.5 Route

工程要点:单 Agent fan-out;禁止双 DaemonSet tail 同文件。

    **Fluent Bit**:grep/modify/loki output。  
    **Vector**:remap/filter/route transform。

    **验证**:`kubectl logs -n logging daemonset/fluent-bit --tail=20` 无 error;Loki 查询 job=fluentbit 的 ERROR 流持续。

二、Fluent Bit 架构与配置

CNCF Graduated;C 单进程 event loop;常驻内存通常 < 50MB(idle),高吞吐仍低于 Vector 峰值。

```yaml
[SERVICE]
    Flush         1
    storage.path  /var/log/flb-storage/
    storage.sync  normal
    storage.backlog.mem_limit 50M

[INPUT]
    Name              tail
    Path              /var/log/containers/*.log
    Parser            cri
    Tag               kube.*
    Refresh_Interval  5
    Mem_Buf_Limit     50MB
    storage.type      filesystem

[FILTER]
    Name         kubernetes
    Match        kube.*
    Merge_Log    On
    Keep_Log     Off

[OUTPUT]
    Name     loki
    Match    kube.*
    Host     loki-gateway
    Port     80
    Labels   job=fluentbit
```

三、Vector 架构与 VRL

Rust DAG:source → transform* → sink;disk buffer 带 checkpoint。

```yaml
sources:
  k8s_logs:
    type: kubernetes_logs
    auto_partial_merge: true

transforms:
  parse_json:
    type: remap
    inputs: [k8s_logs]
    source: |
      . = parse_json!(string!(.message)) ?? .
      .cluster = "prod"

sinks:
  loki:
    type: loki
    inputs: [parse_json]
    endpoint: http://loki:3100
    encoding:
      codec: json
    labels:
      job: vector
      namespace: "{{ kubernetes.pod_namespace }}"
```

四、Fluent Bit vs Vector:假设模型对比

声明:以下为假设模型推导,非本文作者在本机复现的 benchmark。用于数量级选型,不可当作厂商 SLA。

![Fluent Bit vs Vector 资源对比(假设模型)](./fluentbit-vs-vector-benchmark.svg)

**统一假设**:
- 输入:nginx access log JSON,平均 450 bytes/行
- 负载:5000 行/s  sustained(单节点)
- 变换:JSON parse + 添加 5 个 metadata 字段
- 输出:HTTP 批量 POST(模拟 Loki push)
- 硬件:4 vCPU,8GB RAM,NVMe

| 指标 | Fluent Bit(假设) | Vector(假设) | 口径 |
|------|-------------------|----------------|------|
| CPU 占用 | 0.8–1.2 core | 0.4–0.7 core | 含 parse+output |
| RSS 内存 | 80–150 MB | 120–200 MB | 稳态 |
| 端到端 p99 延迟 | 2–5 s | 1–3 s | 含 batch 窗口 1s |
| 下游故障 10min | disk buffer 占 2GB 后 throttle | checkpoint 恢复无重复* | *at-least-once |

**解读**:
- Vector CPU 优势来自 Rust + 编译 VRL;Fluent Bit 胜在内存 footprint 与 K8s 成熟度。
- 若变换链 >10 个 regex,Vector 优势扩大;若仅 tail→Loki,Fluent Bit 足够。
- 应在你环境用 **相同 log 样本** 跑 24h 验证——替换上表假设值。

五、Logstash 与 Cribl

Logstash:JRuby + JVM,heap 1GB+;适合遗留 GroK 库。Elastic 推荐 Elastic Agent 做 edge 采集。

**Cribl Stream**:商业路由器;Splunk/ES 前过滤瘦身;Replay 调试。非采集器——常与 Fluent Bit/Beats 组合。

六、可靠性:Backpressure 与 Delivery 语义

策略 | 语义 | 风险 | |——|——|——| | drop | 可能丢 | ERROR 不可接受 | | memory buffer | at-most-once | OOM | | disk buffer | at-least-once | 写满磁盘 | | block input | 反压到应用 | 拖慢业务 |
**推荐**:ERROR/WARN disk buffer + 上限 + 告警;INFO 可 drop;DEBUG 默认不采。

```mermaid
flowchart LR
  IN[Input tail] --> BUF[Disk buffer capped]
  BUF --> OUT[Output Loki]
  OUT -->|fail| BUF
  BUF -->|full| DROP[Drop INFO / throttle]
```

七、Kubernetes DaemonSet 模式

yaml apiVersion: apps/v1 kind: DaemonSet metadata: name: fluent-bit namespace: logging spec: selector: matchLabels: app: fluent-bit template: spec: serviceAccountName: fluent-bit tolerations: - operator: Exists containers: - name: fluent-bit image: cr.fluentbit.io/fluent/fluent-bit:2.2 resources: limits: memory: 512Mi cpu: "1" requests: memory: 128Mi cpu: 100m volumeMounts: - name: varlog mountPath: /var/log - name: flb-storage mountPath: /var/log/flb-storage volumes: - name: varlog hostPath: path: /var/log - name: flb-storage emptyDir: sizeLimit: 10Gi

**注意**:`sizeLimit` 与 Fluent Bit `storage.total_limit_size` 对齐;`priorityClassName` 防 eviction。

八、四种方案选型矩阵

场景 | 推荐 | 理由 | |——|——|——| | K8s DaemonSet 默认 | Fluent Bit | 生态、Chart、内存 | | 复杂 VRL 变换 | Vector | 可维护性 | | 遗留 GroK | Logstash | 迁移成本 | | Splunk License 优化 | Cribl | 商业 ROI |

九、工程坑点

  1. Refresh_Interval 默认过大 → tail CPU 尖刺
    1. disk buffer 无 cap → 节点磁盘满
    2. 双 DaemonSet tail → 重复 + inode 竞争
    3. multiline 顺序错 → 先 merge 再 json parse
    4. Loki label 高基数$kubernetes['pod_name'] 作 label 慎用
    5. OTel + FB 双 buffer → 只一层硬上限
    6. charset 未声明 → 乱码
    7. RBAC 不足 → metadata 空
    8. log rotation 丢行 → 配置 Rotate_Wait
    9. Kafka output 无 acks=all → 静默丢

十、落地清单

十一、关键概念回顾

十二、下一步

下一篇 Traces 栈与采样

参考资料

  1. Fluent Bit Documentation, https://docs.fluentbit.io/
  2. Vector Documentation, https://vector.dev/docs/
  3. Logstash Reference, https://www.elastic.co/guide/en/logstash/current/
  4. Cribl Stream Docs, https://docs.cribl.io/stream/
  5. Grafana Loki Log Collection, https://grafana.com/docs/loki/latest/send-data/
  6. Kubernetes Logging Architecture, https://kubernetes.io/docs/concepts/cluster-administration/logging/
  7. CNCF Fluent Bit Graduation, https://www.cncf.io/projects/fluent-bit/

上一篇数据模型:五大支柱的内部表达

下一篇Traces 栈与采样:Jaeger、Tempo、Zipkin、SkyWalking

读完这篇,下一步读什么

优先读同系列或同问题的下一篇,把单篇消费变成主题集群。


By .