Kafka 去 ZooKeeper 化实战:KRaft 架构高可用部署实践与运维提升之道

Kafka 去 ZooKeeper 化实战:KRaft 架构高可用部署实践与运维提升之道

一、为什么选择 Kafka-Kraft 架构?

Kafka 作为分布式消息系统的标杆,长期依赖 ZooKeeper 进行元数据管理。但 Kafka-Kraft 模式通过引入自管理的元数据仲裁机制,彻底摆脱了 ZooKeeper 依赖,带来三大核心优势:

  1. 部署简化:减少运维组件,降低系统复杂度
  2. 性能提升:元数据操作延迟降低 40%
  3. 稳定性增强:消除脑裂风险,故障恢复更快

本文将手把手教你完成 Kafka-Kraft 集群的高可用部署,borker 之间连接和客户端连接 borker 使用简单密码验证。

注:Kafka 的 KRaft(Kafka Raft)功能最初在 Kafka 2.8.0 版本开始作为实验性功能引入,后续在 3.x 版本逐步稳定,并在 Kafka 4.0 版本成为默认模式,彻底替代 ZooKeeper。

系统要求:

  • 操作系统:CentOS 7+, Ubuntu 20.04+

  • Java 环境:JDK 17 或 Java 21(长期支持 LTS 版本)(推荐 OpenJDK)

    • CentOS 7.9 的默认 JDK​:CentOS 7.9 官方仓库默认提供 OpenJDK 8,直接运行 Kafka 4.0 会因 Java 版本不兼容导致启动失败
    • in Kafka 4.0, Kafka Clients and Kafka Streams require Java 11, while Kafka Brokers, Connect, and Tools, now require Java 17. 详见官方说明:Apache Kafka
  • 硬件配置

    • 内存:8GB+(生产环境建议 16GB+)
    • 磁盘:SSD/NVMe,预留 2 倍消息存储空间
    • CPU:4 核 +
  • 附加说明:
    在这里插入图片描述


二、系统架构图

在这里插入图片描述

三、部署架构

3.1 集群规划(3 节点示例)

  • 所有节点都既是 Broker 又是 Controller,但进程分离部署。
  • 使用 Kafka 4.0 内置的 KRaft 模式,不需要 ZooKeeper。
  • 所有 Controller 运行 Controller-only 模式。
  • 所有 Broker 运行 Broker-only 模式。
  • 所有节点必须能互相访问。
  • Kafka 从 2.8 引入 KRaft 模式开始,就支持将 ControllerBroker 合并部署(同一进程)或分离部署(不同进程),到了 Kafka 4.0,这两种模式都被支持和使用。

3.2 两种部署方式对比

Kafka 4.0 官方推荐:生产环境建议使用“Controller 与 Broker 分离部署”架构。

这是因为:

  • Controller 是 Kafka 中的重要“控制面组件”(如 topic metadata、集群管理、leader election)。
  • 独立 Controller 节点可以带来更高的可用性和更快的 failover。
  • 和 Kubernetes 的控制面/数据面分离理念一致。

本文以分离部署架构阐述安装过程。

四、安装与验证

4.1 安装 OpenJDK 17(需配置第三方仓库,每台机器都执行)

sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
sudo yum install -y java-17-openjdk-devel

4.2 验证版本

java -version  # 应输出"17.x.x"

4.3 下载并解压(每台机器都执行)

1、下载最新版 Kafka (Kraft 模式)
wget https://downloads.apache.org/kafka/4.0.0/kafka_2.13-4.0.0.tgz
2、解压至安装目录/opt
tar -xzf kafka_2.13-4.0.0.tgz
mv kafka_2.13-4.0.0 /opt/kafka

4.4 创建 kafka 数据目录及日志目录

mkdir -p /opt/kafka/data
mkdir -p /opt/kafka/logs

4.5 配置 Controller 节点

1、修改配置 /opt/kafka/config/kraft/controller.properties(示例 controller-1)
# 标识该进程的角色为 controller(非 broker)
process.roles=controller
# 当前 controller 节点的唯一标识(需与 voters 中一致)
node.id=1
# Controller 集群成员列表,controller 之间进行选举和同步元数据
controller.quorum.voters=1@192.168.1.1:9093,2@192.168.1.2:9093,3@192.168.1.3:9093
# Controller 的监听地址及端口,供 broker 主动连接
listeners=CONTROLLER://192.168.1.1:9093
# controller.listener.names 必须定义为 CONTROLLER,用于与 broker 建立连接
controller.listener.names=CONTROLLER
# 定义 listener 名与实际协议的映射(此处 controller 使用 PLAINTEXT)
listener.security.protocol.map=CONTROLLER:PLAINTEXT
# Kafka 元数据及日志文件存储目录(controller 日志,如元数据变更等)
log.dirs=/opt/kafka/data/kraft-controller-logs
# 网络线程数(处理 broker 上报等)
num.network.threads=3
# IO 线程数
num.io.threads=8
# socket 发送缓冲区大小
socket.send.buffer.bytes=102400
# socket 接收缓冲区大小
socket.receive.buffer.bytes=102400
# 请求最大数据大小限制
socket.request.max.bytes=104857600
# 每个数据目录的恢复线程数(用于日志恢复)
num.recovery.threads.per.data.dir=1
# 日志保留时间(小时)
log.retention.hours=48
#日志滚动时间,强制 48 小时切分一次 segment 文件
log.roll.hours=48
# 日志段大小(1GB)
log.segment.bytes=1073741824
# 检查日志是否超期的周期(毫秒)
log.retention.check.interval.ms=300000

controller-2、controller-3 修改 node.id 和 IP 即可。

2、创建数据目录并初始化日志
# 第一步:只在一台机器上生成 UUID
CLUSTER_ID=$(bin/kafka-storage.sh random-uuid)
echo $CLUSTER_ID

然后复制 $CLUSTER_ID 的值,比如是 Z4EHo3vTQ7ijVn2E9cK9qw

mkdir -p /opt/kafka/data/kafka-controller-logs
cd /opt/kafka
# 第二步:在每个节点上执行相同的格式化命令
bin/kafka-storage.sh format -t Z4EHo3vTQ7ijVn2E9cK9qw -c config/kraft/controller.properties

注:初始化后,会生成/opt/kafka/data/kraft-controller-logs/meta.properties 文件,包含 cluster.id,version,node.id 三条信息,cluster.id 是集群唯一的,三个节点的 controller、broker 都一样。

4.6 配置 Broker 节点

1、修改配置 /opt/kafka/config/kraft/broker.properties(示例 broker-1)

使用了 SASL 简单密码验证,客户端使用密码连接。

# 标识该进程的角色为 broker(非 controller)
process.roles=broker
# 当前 broker 节点的唯一标识(需与 voters 中一致)
node.id=21
# Controller 选举相关配置(node.id@host:port),供 broker 连接
controller.quorum.voters=1@192.168.1.1:9093,2@192.168.1.2:9093,3@192.168.1.3:9093
# 对外(客户端)提供服务监听地址及端口,使用 SASL_PLAINTEXT 协议
listeners=SASL_PLAINTEXT://192.168.1.1:9092
# 指定 broker 间通信所使用的协议(这里为启用 SASL_PLAINTEXT)
security.inter.broker.protocol=SASL_PLAINTEXT
# 指定 broker 间通信使用哪个 listener 名(与上面 listeners 中配置一致)
inter.broker.listener.name=SASL_PLAINTEXT
# Broker 间通信使用的 SASL 机制为 PLAIN
sasl.mechanism.inter.broker.protocol=PLAIN
# 启用的 SASL 机制列表,这里仅启用 PLAIN
sasl.enabled.mechanisms=PLAIN
# 配置该 listener(SASL_PLAINTEXT)的认证信息(用户名密码、用户列表)
listener.name.sasl_plaintext.sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
  username="admin" \
  password="669H*e4U" \
  user_admin="669H*e4U" \
  user_user1="669H*e4U";
# 用于指定 broker 与 controller 通信使用的 listener 名,必须在 listener.security.protocol.map 中映射
controller.listener.names=CONTROLLER
# 定义 listener 名和实际使用的协议映射关系(SASL_PLAINTEXT 用于客户端和 broker,CONTROLLER 用于连接 controller)
listener.security.protocol.map=CONTROLLER:PLAINTEXT,SASL_PLAINTEXT:SASL_PLAINTEXT
# Kafka 数据存储目录(用于保存日志、分区数据等)
log.dirs=/opt/kafka/data/kraft-broker-logs
# 网络线程数(用于处理网络请求)
num.network.threads=3
# IO 线程数(用于处理磁盘等 I/O 操作)
num.io.threads=8
# socket 发送缓冲区大小
socket.send.buffer.bytes=102400
# socket 接收缓冲区大小
socket.receive.buffer.bytes=102400
# 请求最大数据大小限制(单位:字节)
socket.request.max.bytes=104857600
# 默认分区数量(创建 topic 时未指定分区数时使用)
num.partitions=24
# 每个数据目录的恢复线程数(用于日志恢复)
num.recovery.threads.per.data.dir=1
# consumer offset 主题副本数
offsets.topic.replication.factor=2
# 事务状态日志的副本数
transaction.state.log.replication.factor=2
# topic 默认副本数(除非另行指定)
default.replication.factor=2
# 事务日志的最小同步副本数(防止数据丢失)
transaction.state.log.min.isr=1
# Kafka 新功能:共享协调器状态主题副本数(例如 Group 共享)
share.coordinator.state.topic.replication.factor=1
# 同上,最小 ISR
share.coordinator.state.topic.min.isr=1
# 日志保留时间(小时)
log.retention.hours=48
#日志滚动时间,强制 48 小时切分一次 segment 文件
log.roll.hours=48
# 日志段大小(默认 1GB)
log.segment.bytes=1073741824
# 检查日志是否超期的周期(毫秒)
log.retention.check.interval.ms=300000
# 副本最大抓取大小(用于 replica 同步数据)
replica.fetch.max.bytes=5242880
# 是否允许自动创建 topic(生产环境建议禁用)
auto.create.topics.enable=false

broker-2、broker-3 修改 node.id 和 IP 即可。

密码配置说明:

注意: 3.6.2 需要使用外部 JAAS 文件,并删除内嵌的“listener.name.sasl_plaintext.sasl.jaas.config”的配置,否则无法启动。
以下是3.6.2版本的配置示例和启动方法,按需取用,4.0版本跳过下述内容直接跳转看:2、创建数据目录并初始化。
kafka_server_jaas.conf

KafkaSever {
    org.apache.kafka.common.security.plain.PlainLoginModule required
    username="admin"
    password="669H_e4U"_
    user_admin="669H*e4U";
};
# 启动方式一,执行bin/kafka-server-start.sh前,告诉jvm KAFKA_OPTS的参数配置
export KAFKA_OPTS="-Djava.security.auth.login.config=/opt/kafka/config/kafka_server_jaas.conf"
bin/kafka-server-start.sh config/kraft/broker.properties
#  启动方式二
KAFKA_OPTS="-Djava.security.auth.login.config=/opt/kafka/config/kafka_server_jaas.conf" bin/kafka-server-start.sh config/kraft/broker.properties
2、创建数据目录并初始化日志(每台 Broker)
mkdir -p /data/kafka-broker-logs
cd /opt/kafka
bin/kafka-storage.sh format -t Z4EHo3vTQ7ijVn2E9cK9qw -c config/kraft/broker.properties

注:这里的“Z4EHo3vTQ7ijVn2E9cK9qw”一定要使用初始化 controller 时生成的 cluster.id,不然无法组成同一集群。

4.7 启动服务(按顺序)

1、创建 kafka 用户(如无)
sudo useradd -r -m -s /sbin/nologin kafka
sudo chown -R kafka:kafka /opt/kafka
2、手工启动方式
  • 启动 3 个 Controller 节点(顺序尽量一起)
cd /opt/kafka
nohup bin/kafka-server-start.sh config/kraft/controller.properties > controller.log 2>&1 &
或
bin/kafka-server-start.sh --daemon config/kraft/controller.properties
  • 等 Controller 组成 quorum 后,启动 3 个 Broker 节点
cd /opt/kafka
nohup bin/kafka-server-start.sh config/kraft/broker.properties > broker.log 2>&1 &
或
bin/kafka-server-start.sh --daemon config/kraft/broker.properties
3、使用 systemd 管理应用启动
  • Controller 节点 systemd 服务文件

路径:/etc/systemd/system/kafka-controller.service

[Unit]
Description=Apache Kafka Controller Node
After=network.target
[Service]
Type=simple
User=kafka
Group=kafka
# JVM 内存参数
Environment="KAFKA_HEAP_OPTS=-Xms2G -Xmx2G"
# 日志输出位置,Kafka 日志配置文件中引用 ${kafka.logs.dir}
Environment="KAFKA_OPTS=-Dkafka.logs.dir=/opt/kafka/logs"
# 3.6.2版本:Environment="KAFKA_OPTS=-Djava.security.auth.login.config=/opt/kafka/config/kafka_server_jaas.conf -Dkafka.logs.dir=/opt/kafka/logs"
ExecStart=/opt/kafka/bin/kafka-server-start.sh /opt/kafka/config/kraft/controller.properties
Restart=on-failure
RestartSec=10
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target
4、Broker 节点 systemd 服务文件

路径:/etc/systemd/system/kafka-broker.service

[Unit]
Description=Apache Kafka Broker Node
Requires=kafka-controller.service
After=kafka-controller.service
[Service]
Type=simple
User=kafka
Group=kafka
# JVM 内存参数
Environment="KAFKA_HEAP_OPTS=-Xms4G -Xmx4G"
# 日志输出位置,Kafka 日志配置文件中引用 ${kafka.logs.dir}
Environment="KAFKA_OPTS=-Dkafka.logs.dir=/opt/kafka/logs"
ExecStart=/opt/kafka/bin/kafka-server-start.sh /opt/kafka/config/kraft/broker.properties
Restart=on-failure
RestartSec=10
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target
5、启用并启动服务

Controller 节点

bash复制编辑sudo systemctl daemon-reexec
sudo systemctl daemon-reload
sudo systemctl enable kafka-controller
sudo systemctl start kafka-controller
sudo systemctl status kafka-controller

Broker 节点

bash复制编辑sudo systemctl daemon-reexec
sudo systemctl daemon-reload
sudo systemctl enable kafka-broker
sudo systemctl start kafka-broker
sudo systemctl status kafka-broker
6、查看日志(以 systemd 方式启动)

Controller 节点日志

journalctl -u kafka-controller -f

Broker 节点日志

journalctl -u kafka-broker -f

4.8 功能验证(任意 Broker 节点上)

1、客户端连接配置(client.properties)
security.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
  username="admin" \
  password="669H*e4U";
2、创建测试 Topic
bin/kafka-topics.sh --create \
  --topic test-topic \
  --bootstrap-server 192.168.1.1:9092 \
  --command-config client.properties \
  --partitions 3 \
  --replication-factor 2
3、查看已创建的 Topic
bin/kafka-topics.sh --list --bootstrap-server 192.168.1.1:9092 --command-config ./client.properties
bin/kafka-topics.sh --describe --topic test-topic --bootstrap-server 192.168.1.1:9092 --command-config ./client.properties
4、生产测试消息
bin/kafka-console-producer.sh \
  --topic test-topic \
  --bootstrap-server 192.168.1.1:9092 \
  --producer.config client.properties
5、消费测试消息
bin/kafka-console-consumer.sh \
  --topic test-topic \
  --from-beginning \
  --bootstrap-server 192.168.1.1:9092 \
  --consumer.config client.properties
6、集群健康检查
  • 查看 Broker 状态
bin/kafka-broker-api-versions.sh --bootstrap-server 192.168.1.1:9092 --command-config ./client.properties
#以下检查Controller选举,注意此命令不支持SASL,只能用于没有认证的broker。
bin/kafka-metadata-quorum.sh --bootstrap-server 192.168.1.1:9092 describe --status

五、性能调优指南

5.1 关键性能参数

在这里插入图片描述

5.2 压力测试脚本

1、生产者性能测试
bin/kafka-producer-perf-test.sh \
  --topic perf-test \
  --num-records 1000000 \
  --record-size 1024 \
  --throughput -1 \
  --producer.config client.properties \
  --bootstrap-server 192.168.1.1:9092
2、消费者性能测试
bin/kafka-consumer-perf-test.sh \
  --topic perf-test \
  --messages 1000000 \
  --bootstrap-server 192.168.1.1:9092 \
  --group abcd-group \
  --consumer.config client.properties

5.3 监控指标解读

  • 生产吞吐:> 100 MB/s(单节点)
  • 消费吞吐:> 150 MB/s(单节点)
  • P99 延迟:< 50ms(SSD 环境)
  • Controller 切换:< 2000ms

六、常见故障处理

6.1 Controller 选举失败

现象:NotEnoughReplicasException

解决

  1. 检查 controller.quorum.voters 配置一致性
  2. 验证网络连通性(9093 端口)
  3. 检查防火墙规则

6.2 副本不同步

现象:UnderReplicatedPartitions 持续增长

解决

检查副本状态

# **列出 Kafka 中所有**「副本未同步」(under-replicated partitions)**的分区详情**。
bin/kafka-topics.sh --describe \
  --under-replicated-partitions \
  --bootstrap-server 192.168.1.1:9092 \
  --command-config ./client.properties

当某个 follower 副本滞后太多或宕机时,就会出现 under-replicated 状态。

优先解决方案

bin/kafka-leader-election.sh \
  --election-type PREFERRED \
  --bootstrap-server 192.168.1.1:9092 \
  --command-config ./client.properties

Kafka 为每个分区设定了一个“首选 leader”(即 replicas 列表中的第一个 broker)。

在正常运行中,如果 leader 发生故障,Kafka 会临时选举其他副本为 leader。

这个命令的作用就是:
尝试把每个分区的 leader 切换回“首选副本”,以优化集群分布和性能。

6.3 磁盘空间不足

自动清理策略

# 按时间保留(默认7天)
log.retention.hours=168
# 按大小保留(100GB)
log.retention.bytes=107374182400
# 紧凑删除策略(保留每个Key最新值)
cleanup.policy=compact

6.4 kafka3.6.2 与 kafka4.0.0 启动区别

启动 Kafka 3.6.2 时的注意

nohup bin/kafka-server-start.sh config/server.properties > kafka.log 2>&1 &

启动 Kafka 4.0.0 时的注意

bin/kafka-server-start.sh --daemon config/kraft/broker.properties
bin/kafka-server-start.sh --daemon config/kraft/broker.properties

• 支持内嵌 JAAS 配置,也可以外部指定 JAAS 文件

• 支持 Controller 和 Broker 分离,适合 KRaft 模式集群


🔔 想了解更多云原生、自动化、运维管理方面的内容?请关注我,干货持续更新!咱们“ 键上江湖 ”见!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值