1. Kafka 单节点 KRaft 模式部署与基础验证
KRaft 单节点部署的核心对象与数据流
KRaft 模式把原本由 ZooKeeper 承担的元数据管理职责内化到 Kafka 自身:每个 broker 同时充当 Controller 角色,元数据以日志形式写入 __cluster_metadata 这个内部 topic。单节点部署时,一个进程既负责元数据仲裁,也负责数据读写,因此配置的关键在于让 process.roles、node.id、controller.quorum.voters 三者自洽。
部署前的关键配置项
KRaft 模式不需要 ZooKeeper,但必须显式声明节点角色和仲裁者列表。以下是最小可用的 server.properties 核心片段,假设主机 IP 为 192.168.1.10,Kafka 版本为 3.7.x:
process.roles=broker,controller
node.id=1
controller.quorum.voters=1@192.168.1.10:9093
listeners=PLAINTEXT://192.168.1.10:9092,CONTROLLER://192.168.1.10:9093
advertised.listeners=PLAINTEXT://192.168.1.10:9092
controller.listener.names=CONTROLLER
listener.security.protocol.map=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
log.dirs=/var/kafka-logs
num.partitions=1
offsets.topic.replication.factor=1
transaction.state.log.replication.factor=1
transaction.state.log.min.isr=1
注意:单节点部署时,
offsets.topic.replication.factor 和 transaction.state.log.replication.factor 必须设为 1,否则内部 topic 创建会因副本数不足而失败。这是单节点 KRaft 最常见的启动阻塞点。
格式化存储目录并启动
首次启动前必须用 kafka-storage.sh 生成集群 UUID 并格式化日志目录。这个 UUID 会写入 meta.properties,后续所有节点必须一致。
# 生成集群 UUID
CLUSTER_ID=$(bin/kafka-storage.sh random-uuid)
echo "Cluster ID: $CLUSTER_ID"
# 格式化存储目录
bin/kafka-storage.sh format -t $CLUSTER_ID -c config/kraft/server.properties
# 启动 broker(前台运行,便于观察日志)
bin/kafka-server-start.sh config/kraft/server.properties
启动日志中应出现以下关键行,用于确认 KRaft 仲裁已就绪:
[RaftManager nodeId=1] Completed transition to Leader—— 本节点成为 Controller Leader[KafkaServer id=1] started—— Broker 服务启动完成[SocketServer listenerName=PLAINTEXT] Awaiting socket connections on 192.168.1.10:9092—— 客户端监听就绪
创建测试主题并完成生产消费闭环
验证分三步:创建主题、生产消息、消费消息。每一步都对应一个可观察的结果。
# 1. 创建测试主题
bin/kafka-topics.sh --create \
--topic quickstart-events \
--bootstrap-server 192.168.1.10:9092 \
--partitions 1 \
--replication-factor 1
# 2. 查看主题详情,确认分区与副本分配
bin/kafka-topics.sh --describe \
--topic quickstart-events \
--bootstrap-server 192.168.1.10:9092
# 3. 生产消息(输入后按 Ctrl+D 结束)
bin/kafka-console-producer.sh \
--topic quickstart-events \
--bootstrap-server 192.168.1.10:9092
> hello-kraft
> second-message
# 4. 消费消息(从头读取)
bin/kafka-console-consumer.sh \
--topic quickstart-events \
--bootstrap-server 192.168.1.10:9092 \
--from-beginning
结果判读:消费者应输出
hello-kraft 和 second-message。如果只看到主题创建成功但消费无输出,优先检查 --from-beginning 是否遗漏,以及生产者是否真正发送了消息(控制台生产者需要回车换行后才发送)。
元数据存储验证
KRaft 模式下,主题元数据不再存于 ZooKeeper,而是写入 __cluster_metadata 内部 topic。可以通过以下命令确认元数据日志已生成:
# 查看日志目录结构
ls -la /var/kafka-logs/__cluster_metadata-0/
# 应看到 00000000000000000000.log 等分段文件
# 以及 meta.properties 中的 cluster.id 与 node.id
同时可用 kafka-metadata-quorum.sh 查看仲裁状态:
bin/kafka-metadata-quorum.sh \
--bootstrap-server 192.168.1.10:9092 \
describe --status
输出中 CurrentVoters 应包含 1@192.168.1.10:9093,LeaderId 为 1,CurrentObservers 为空。这表示单节点仲裁正常运行。
常见启动失败与排查
| 现象 | 可能原因 | 排查动作 |
|---|---|---|
启动报 InconsistentClusterIdException | 格式化时使用的 UUID 与 meta.properties 中不一致 | 检查 log.dirs 下 meta.properties 的 cluster.id,重新格式化或清理目录 |
启动报 No readable meta.properties files | 未执行 kafka-storage.sh format | 先格式化再启动 |
| 客户端连接被拒绝 | advertised.listeners 配置为 localhost 或错误 IP | 改为客户端可访问的主机 IP,重启 broker |
| 内部 topic 创建失败 | 副本因子大于可用 broker 数 | 将 offsets.topic.replication.factor 等设为 1 |
可复用的验证清单
- 进程角色:
process.roles=broker,controller已设置 - 节点 ID:
node.id=1与controller.quorum.voters中的 ID 一致 - 仲裁者:
controller.quorum.voters=1@主机IP:9093可被本机解析 - 监听器:
listeners同时包含 PLAINTEXT 和 CONTROLLER,且advertised.listeners使用客户端可达 IP - 存储:已执行
kafka-storage.sh format,meta.properties存在 - 启动日志:出现
Completed transition to Leader与KafkaServer id=1 started - 主题:
kafka-topics.sh --describe显示分区 1、副本 1、Leader 为 1 - 闭环:生产者发送的消息能被消费者从 beginning 读出
- 元数据:
kafka-metadata-quorum.sh describe --status显示 LeaderId=1、CurrentVoters 含本节点