Kafka 诞生于本地磁盘和固定集群的时代——Broker 持久化靠 JBOD,扩容靠手动加机器,成本靠"多买几块盘"硬扛。当事件流平台被搬上云,这套模型开始崩塌:存储成本远高于计算、Consumer 滞后时集群被迫保留海量冷数据、多租户隔离只能靠物理集群切割。分层存储、弹性 Consumer、Share Group、虚拟集群、FinOps 遥测,以及正在酝酿的无盘存储方案,正在从根本上重写 Kafka 的运维经济学。
分层存储:把冷数据从 Broker 磁盘卸载出去
传统 Kafka 的 log.retention.hours 本质上是在说——"不管数据有没有人读,Broker 都要在本地盘上扛这么久"。云上 SSD 每 GB 成本是对象存储的 10 倍以上,冷数据占着本地盘就是烧钱。
分层存储的核心思路:
- 热层:最近写入的数据留在 Broker 本地 SSD,保证低延迟读写。
- 冷层:超过阈值(时间或大小)的日志段被上传到 S3/GCS/Azure Blob,Broker 只保留元数据索引。
- Consumer 读冷数据:Broker 从对象存储拉回所需段,缓存到本地后返回给客户端,客户端无感知。
这意味着 retention 可以从几天拉长到几个月甚至无限,而 Broker 本地盘只需要容纳热数据窗口。对 FinOps 来说,这是最直接的成本杠杆——把 80% 的存储支出从 SSD 转移到对象存储。
下面是一个 Kafka 分层存储的典型配置片段(基于 Confluent Platform 7.x+ 的 KIP-405 实现):
# tiered-storage.properties — Broker 端配置
# 开启分层存储
kafka.tier.feature=true
kafka.tier.enable=true
# 冷层后端:S3
kafka.tier.s3.bucket=my-kafka-tiered-bucket
kafka.tier.s3.region=us-east-1
kafka.tier.s3.aws.credentials.provider.class=software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider
# 热层保留策略:本地保留最近 4 小时或 1 GB
kafka.tier.segment.hotset.ms=14400000
kafka.tier.segment.hotset.bytes=1073741824
# 冷层归档后本地段删除
kafka.tier.archiver.max.tasks=4
# 长期 retention 放开(冷层在 S3 上保留)
log.retention.ms=2592000000 # 30 天
运行前需要确保 Broker 所在节点有 S3 访问权限(IAM Role 或 AK/SK),且
kafka.tier.feature=true在集群范围内启用。
FinOps 遥测:让每一 GB 的成本可见
分层存储解决了"存哪里便宜"的问题,但 FinOps 要回答的是"谁在烧钱、烧在哪里"。云原生 Kafka 需要把存储、网络、计算的成本归因到具体的 Topic、Consumer Group 甚至租户。
实践中,这要求 Broker 端暴露细粒度指标,再通过 Prometheus + Grafana 或云厂商的 Cost Explorer 做关联分析:
# prometheus-kafka-cost-rules.yaml
# 用 recording rule 把 Kafka 指标和成本维度关联
groups:
- name: kafka_finops
interval: 60s
rules:
# 每个 Topic 的冷层存储量(GB)
- record: kafka:tiered_storage_bytes:topic
expr: |
sum(kafka_tier_storage_bytes{topic=~".+"}) by (topic, cluster)
/ 1024 / 1024 / 1024
# 每个 Consumer Group 的滞后量折算为热层占用
- record: kafka:consumer_lag_cost:group
expr: |
sum(kafka_consumer_group_lag_records{group=~".+"}) by (group, cluster)
* avg(kafka_log_segment_avg_bytes) / 1024 / 1024 / 1024
# 标注成本标签(需要外部 label mapping)
- record: kafka:cost_label:topic
expr: |
kafka:tiered_storage_bytes:topic
* on(topic, cluster) group_left(cost_center, team)
kafka_topic_cost_labels
有了这些 recording rule,Grafana 面板可以直接按 Team / Cost Center 展示"这个 Topic 在 S3 上每月花多少"、"这个 Consumer Group 的滞后导致热层多占多少 GB"。这才是 FinOps 的闭环——不是事后看账单,而是实时看指标做决策。
弹性 Consumer 扩容与 Share Group
Kafka 传统的 Consumer Group 模型有一个硬约束:一个 Partition 只能被同一个 Group 内的一个 Consumer 消费。这意味着 Consumer 并行度上限 = Partition 数。当流量突发时,你无法通过临时加 Consumer 实例来加速消费——除非你预先创建了足够多的 Partition,但那又会增加 Broker 端开销和延迟。
Share Group(KIP-932) 打破了这个约束:
- 多个 Share Consumer 可以并发读取同一个 Partition 的不同消息批次。
- Broker 端用"状态机"管理每条消息的交付状态(Ack / Nack / Redelivery),类似 JMS 的共享订阅。
- Consumer 实例数不再受 Partition 数绑定,可以按流量弹性伸缩。
这对云原生场景至关重要——Consumer 可以用 Kubernetes HPA 按滞后量自动扩缩,而不是被 Partition 数卡住:
# kafka-share-consumer-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: order-processor
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: order-processor
minReplicas: 2
maxReplicas: 20
metrics:
- type: External
external:
metric:
name: kafka_consumer_group_lag_records
selector:
matchLabels:
group: order-processor-share
topic: orders
target:
type: AverageValue
averageValue: "5000" # 每个 Pod 目标滞后 ≤ 5000 条
behavior:
scaleUp:
stabilizationWindowSeconds: 30
policies:
- type: Percent
value: 100
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
注意:Share Group 目前是预览特性,生产使用前需确认你使用的 Kafka 版本和客户端 SDK 的支持状态。HPA 的 External metric 需要 Prometheus Adapter 把
kafka_consumer_group_lag_records注册到 Kubernetes API。
虚拟集群:多租户的逻辑隔离
物理集群切割多租户是老办法——每个团队一个 Kafka 集群,运维成本爆炸。虚拟集群(如 WarpStream 的架构,或 Kafka 原生的 KIP-850 方案)在同一个物理集群上用逻辑命名空间隔离:
- 每个虚拟集群有独立的 Topic 命名空间、ACL、配额。
- Broker 端路由层根据客户端请求中的虚拟集群标识做隔离映射。
- 底层存储和计算资源池共享,但配额和权限边界清晰。
这直接降低了控制平面成本——一个 9 Broker 集群可以服务 20 个虚拟租户,而不是 20 个 3 Broker 集群。
无盘存储:把 Broker 变成纯计算节点
分层存储已经把冷数据卸到了对象存储,但 Broker 本地仍然需要 SSD 做热层。无盘存储(Diskless Broker) 走得更远——Broker 完全不带本地盘,所有数据(包括刚写入的热数据)直接写入远程存储(S3 或分布式块存储),Broker 只做计算:协议解析、顺序保证、Consumer 协调。
架构上的变化和代价:
| 维度 | 传统 Broker | 分层存储 Broker | 无盘 Broker |
|---|---|---|---|
| 写入路径 | 本地盘 → 刷盘确认 | 本地盘 → 异步上传 S3 | 直接写 S3/远程块存储 |
| 写延迟 | ~1-5 ms(本地 SSD) | ~1-5 ms(热层本地) | ~10-50 ms(取决于远程存储) |
| Broker 有状态性 | 重,GB 级本地数据 | 中,热层 GB 级 | 轻,几乎无本地状态 |
| 扩缩速度 | 分钟级(数据迁移) | 分钟级(热层迁移) | 秒级(无数据迁移) |
| 存储成本 | 高(全 SSD) | 中(SSD + S3) | 低(纯 S3/块存储) |
无盘方案的核心吸引力是弹性——Broker 可以像无状态 Pod 一样秒级扩缩,因为不需要迁移本地数据。但代价是写入延迟的上升和架构复杂度(需要强一致远程存储或客户端确认机制的重新设计)。
目前 WarpStream、Confluent 的无盘预览方案都在探索这个方向,但生产级稳定性仍需验证。
落地路径与决策清单
从传统 Kafka 到云原生架构不是一步到位的,以下是分阶段建议:
阶段一:分层存储先行 - 优先开启分层存储,这是 ROI 最高的改动——存储成本通常立减 60-80%。 - 先在非核心 Topic 上验证 S3 后端的稳定性,再逐步扩大覆盖。 - 确保 FinOps 指标同步上线,否则你无法量化收益。
阶段二:弹性 Consumer - 在流量有明显波峰波谷的场景引入 Share Group + HPA。 - 评估客户端改造工作量——Share Group 需要新 SDK 或协议扩展。 - 先在可容忍少量重复消费的场景(如日志聚合)试运行。
阶段三:虚拟集群与多租户 - 当集群数量 > 5 时,认真评估虚拟集群方案。 - 配额和 ACL 必须先到位,否则一个租户的流量风暴会打穿共享资源池。
阶段四:无盘 Broker(观望+小规模验证) - 无盘方案目前适合对延迟不敏感、对弹性要求极高的场景(如日志管道、指标流)。 - 核心交易链路暂不建议,写入延迟和一致性的边界条件还需要更多实战验证。 - 可以先用分层存储 + 小热层窗口做"准无盘"——热层只保留 1-2 小时数据,Broker 重启后快速从 S3 恢复。
云原生 Kafka 的本质不是"把 Kafka 跑在 K8s 上",而是把存储和计算解耦、把成本归因到租户、把弹性从 Partition 数解放到 Pod 数。分层存储是第一步,无盘存储是终局方向——但中间每一步都有具体的工程取舍,值得按场景逐步推进。