在 fluentd 驱动中如何对日志进行多租户隔离
解读
Docker 默认的 json-file 日志驱动在多租户场景下会把所有容器日志混写在一起,难以按租户拆分、检索与审计。
国内金融、政务云等合规场景要求日志数据物理或逻辑隔离,并满足等保 2.0“安全审计”条款。
因此面试官想确认你是否能把 Fluentd 驱动当成可插拔的日志总线,在 Docker 侧、Fluentd 侧、后端存储侧三层都做隔离,而不是简单地把日志“打出去”就完事。
知识点
- Docker Fluentd 驱动原理:dockerd 通过 fluentd-address=unix:///var/run/fluent.sock 或 TCP 端口,把容器 stdout/stderr 以 MessagePack 格式发给 Fluentd。
- 日志事件自带字段:container_id、container_name、source、log、partial_message、labels、env。
- Fluentd 路由核心:tag 是路由唯一依据,支持通配符与占位符,如 docker.{label:tenant_id}。
- 国内常用后端:阿里云 SLS、腾讯云 CLS、Kafka(金融区专用集群)、Elasticsearch(物理分片按租户隔离)。
- 合规要点:标签不可伪造、传输加密、落盘加密、查询 RBAC、生命周期≥180 天。
答案
我采用“Docker 侧打标签 + Fluentd 侧按 tag 路由 + 后端存储物理分池”的三级隔离方案,步骤如下:
-
启动容器时显式注入租户标签
docker run ‑-log-driver=fluentd ‑-log-opt fluentd-address=unix:///var/run/fluentd.sock
‑-label tenant_id=tenantA
‑-label project_id=projX
通过公司 CMDB 流水线强制校验,禁止用户自行篡改。 -
Fluentd 侧解析标签并构造租户级 tag
使用 record_transformer 插件把 label 注入到顶层字段:
<filter docker.**>
@type record_transformer
<record>
tenant {record.dig("docker", "labels", "project_id")}
</record>
</filter>
然后利用 rewrite_tag_filter 把原始 tag docker.{container_id} 重写成 tenant.{tenant}.{project}.{container_name},实现逻辑隔离。 -
按租户路由到不同输出池
使用 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 的索引,满足等保“数据分离”要求。 -
安全加固
- 传输层: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,降低合规成本。
-
灰度与回滚
在 Swarm Config 或 K8s ConfigMap 中管理 fluentd.conf,使用 fluentd-ctl configCheck 做热加载;若路由规则写错,5 秒内回滚到旧配置,避免日志断流。
拓展思考
- 如果租户数量动态增长(>1k),rewrite_tag_filter 会造成 Fluentd 内存暴涨,可改用 external plugin 把路由逻辑下沉到 Go micro-service,通过 gRPC 返回目标 topic,实现无状态水平扩展。
- 在边缘机房带宽受限时,可让 Fluentd 先按租户落地到 本地 NVMe(buffer_path /ssd/tenantA),再启用 chunk 级压缩+断点续传,节省 60% 专线费用。
- 国内部分银行要求日志不出域,可把 Fluentd 直接部署在物理裸金属宿主机的 systemd 里,利用 fluent-plugin-label-router 把敏感租户日志落盘到 国密加密盘,非敏感租户日志走公网 Kafka,实现同一套 Docker 平台、两种合规等级的混合隔离。