在 fluentd 驱动中如何对日志进行多租户隔离

解读

Docker 默认的 json-file 日志驱动在多租户场景下会把所有容器日志混写在一起,难以按租户拆分、检索与审计。
国内金融、政务云等合规场景要求日志数据物理或逻辑隔离,并满足等保 2.0“安全审计”条款。
因此面试官想确认你是否能把 Fluentd 驱动当成可插拔的日志总线,在 Docker 侧、Fluentd 侧、后端存储侧三层都做隔离,而不是简单地把日志“打出去”就完事。

知识点

  1. Docker Fluentd 驱动原理:dockerd 通过 fluentd-address=unix:///var/run/fluent.sock 或 TCP 端口,把容器 stdout/stderr 以 MessagePack 格式发给 Fluentd。
  2. 日志事件自带字段:container_id、container_name、source、log、partial_messagelabelsenv
  3. Fluentd 路由核心:tag 是路由唯一依据,支持通配符与占位符,如 docker.containernamedocker.{container_name}**、**docker.{label:tenant_id}
  4. 国内常用后端:阿里云 SLS、腾讯云 CLS、Kafka(金融区专用集群)、Elasticsearch(物理分片按租户隔离)。
  5. 合规要点:标签不可伪造传输加密落盘加密查询 RBAC生命周期≥180 天

答案

我采用“Docker 侧打标签 + Fluentd 侧按 tag 路由 + 后端存储物理分池”的三级隔离方案,步骤如下:

  1. 启动容器时显式注入租户标签
    docker run ‑-log-driver=fluentd ‑-log-opt fluentd-address=unix:///var/run/fluentd.sock
    ‑-label tenant_id=tenantA
    ‑-label project_id=projX
    通过公司 CMDB 流水线强制校验,禁止用户自行篡改

  2. Fluentd 侧解析标签并构造租户级 tag
    使用 record_transformer 插件把 label 注入到顶层字段:
    <filter docker.**>
    @type record_transformer
    <record>
    tenant record.dig("docker","labels","tenantid")project{record.dig("docker", "labels", "tenant_id")} project {record.dig("docker", "labels", "project_id")}
    </record>
    </filter>
    然后利用 rewrite_tag_filter 把原始 tag docker.{container_id} 重写成 tenant.{tenant}.{project}.{container_name},实现逻辑隔离。

  3. 按租户路由到不同输出池
    使用 label 语法把不同租户流量分发到独立输出段:
    <match tenant.tenantA.>
    @type kafka2
    brokers 金融区专用 Kafka:9093
    ssl_ca_certs /certs/finance-ca.pem
    topic log-tenantA
    compression_codec gzip
    </match>
    <match tenant.tenantB.
    >
    @type elasticsearch
    hosts https://es-tenantB.corp:9200
    user fluentd
    password ${FLUENTD_ES_PW}
    index_name log-tenantB-%Y.%m.%d
    ssl_verify true
    </match>
    这样租户 A 的日志永远写不到租户 B 的索引,满足等保“数据分离”要求。

  4. 安全加固

    • 传输层:fluentd-address 使用 TLS over TCP,证书由公司 PKI 统一签发,双向 mTLS 防止伪造日志。
    • 存储层:Kafka topic 开启 ACL,Elasticsearch 按租户创建 role+index pattern,Kibana 空间隔离。
    • 审计层:fluentd 自带 metrics 插件,把每条日志的 tenant、project、byte 数打到 Prometheus,异常流量实时告警
    • 生命周期:通过 ILM 策略 30 天热温、90 天冷温、180 天后自动归档到 OSS,降低合规成本
  5. 灰度与回滚
    Swarm ConfigK8s ConfigMap 中管理 fluentd.conf,使用 fluentd-ctl configCheck 做热加载;若路由规则写错,5 秒内回滚到旧配置,避免日志断流。

拓展思考

  1. 如果租户数量动态增长(>1k),rewrite_tag_filter 会造成 Fluentd 内存暴涨,可改用 external plugin 把路由逻辑下沉到 Go micro-service,通过 gRPC 返回目标 topic,实现无状态水平扩展
  2. 在边缘机房带宽受限时,可让 Fluentd 先按租户落地到 本地 NVMe(buffer_path /ssd/tenantA),再启用 chunk 级压缩+断点续传节省 60% 专线费用
  3. 国内部分银行要求日志不出域,可把 Fluentd 直接部署在物理裸金属宿主机systemd 里,利用 fluent-plugin-label-router 把敏感租户日志落盘到 国密加密盘,非敏感租户日志走公网 Kafka,实现同一套 Docker 平台、两种合规等级的混合隔离。