必须通过官方滚动迁移:先升Kafka至3.4+(推荐3.7.2),再用kafka-metadata-quorum.sh导出ZooKeeper元数据并注入KRaft;跳过步骤将导致ClusterId不匹配、__cluster_metadata初始化失败、offset丢失等事故。

直接迁移不可行,必须走官方支持的“滚动迁移”路径:先升级 Kafka 到 3.4+(推荐 3.7.2),再用 kafka-metadata-quorum.sh 工具将 ZooKeeper 中的元数据导出、转换、注入 KRaft 集群。跳过中间步骤或强行替换配置,会导致 ClusterId 不匹配、__cluster_metadata topic 初始化失败、消费者 offset 丢失等生产级事故。
迁移前必须确认的 4 个硬性条件
缺一不可,否则 kafka-metadata-quorum.sh migrate 命令会直接报错退出:
-
bin/kafka-topics.sh --version输出必须 ≥3.4.0(3.7.2 是当前最稳的选择) - 旧集群必须处于稳定运行状态,所有分区
Leader在线,ISR集合完整(用bin/kafka-topics.sh --describe检查) - 旧
server.properties中的log.dirs目录下必须存在有效的meta.properties文件,且其中cluster.id可读 - 新 KRaft 集群的
controller.quorum.voters必须配置为奇数节点(如1@192.168.0.110:9093,2@192.168.0.111:9093,3@192.168.0.112:9093),且所有 controller 节点已启动但尚未初始化元数据
kafka-metadata-quorum.sh migrate 的实际执行要点
这个命令不是“一键迁移”,而是分阶段触发元数据同步和校验。它不会自动重启 broker 或 controller,所有操作需人工控制节奏:
- 必须在任意一台旧 ZooKeeper 集群的 broker 节点上执行,且该节点要能连通新 controller 集群的
9093端口(KRaft controller 默认监听端口) - 命令中
--source-zk-connect必须指定 ZooKeeper 连接串(如localhost:2181),不能写成127.0.0.1—— 否则因 hostname 解析失败导致get /cluster/id失败 - 首次运行时加
--dry-run参数,它会输出将要迁移的 topic 数量、分区总数、consumer group 数量,但不真正写入;确认无误后再去掉该参数 - 迁移过程中,旧集群照常提供服务,新 controller 日志里会出现大量
MigrationDriver和MetadataLoaderTRACE 级日志,这是正常现象;关键看最后是否打印Migration completed successfully
迁移后最容易被忽略的 3 个验证动作
很多团队卡在“看起来成功了,但消费端一直 rebalance”这一步,问题往往出在验证不全:
- 检查新集群的
__cluster_metadatatopic 是否已创建且有数据:bin/kafka-topics.sh --bootstrap-server localhost:9092 --topic __cluster_metadata --describe,Replicas字段必须非空,且LogEndOffset> 0 - 对比新旧集群的
cluster.id:旧集群从meta.properties读,新集群用bin/kafka-metadata-quorum.sh --bootstrap-server localhost:9092 describe --status | grep clusterId查,二者必须严格一致 - 验证 consumer group offset:用
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --group test-group --describe查新集群中的 offset,再与迁移前用--zookeeper参数查到的旧值比对;若不一致,说明__consumer_offsetstopic 没被正确重放,需回退并检查offsets.topic.replication.factor是否 ≥ controller 节点数
整个迁移过程最耗时的环节不是命令执行,而是 controller 节点间通过 Raft 日志同步元数据——尤其当旧集群有上千个 topic、数万个分区时,__cluster_metadata 的初始快照生成和广播可能持续数分钟。这段时间内不要重启任何 controller,也不要修改 controller.quorum.voters,否则 Raft log index 会断裂,只能清空 metadata.log 重来。


















