根据你给出的三份真实配置,升级路径是:
```text
kafka_2.12-2.2.1
ZooKeeper模式
↓
kafka_2.12-3.9.1
KRaft静态Controller仲裁
↓
kafka_2.13-4.3.1
先保持静态仲裁启动
↓
升级metadata.version和kraft.version
↓
改成动态Controller仲裁配置
```
你当前已经到达:
```text
Kafka程序版本:4.3.1
metadata.version:4.0-IV3
kraft.version:1
```
但当前4.3.1配置仍然是:
```properties
controller.quorum.voters=1@private001v.tq.cztt.qianxin-inc.cn:29093
```
由于`kraft.version=1`已经生效,下一次重启前应改成:
```properties
controller.quorum.bootstrap.servers=private001v.tq.cztt.qianxin-inc.cn:29093
```
下面是完整升级过程。
# 一、升级前必须明确数据处理方式
从2.2.1 ZooKeeper直接执行KRaft `format`,属于停机转换或重建,不是官方在线元数据迁移。
如果旧集群中的以下信息必须完整保留:
* Topic元数据
* Topic配置
* ACL
* Consumer Group Offset
* 分区Leader和副本信息
* Producer ID及事务状态
应先用Kafka 3.9执行ZooKeeper→KRaft正式迁移。
如果旧实例本身没有重要数据,或者已经通过其他方式迁移数据,则可以使用你当前采用的停机格式化方式。
以下过程按照你当前的“单节点停机转换”整理。
# 二、2.2.1升级前检查
## 1. 确认旧Kafka进程
```bash
cd /qaxdata/s/services/kafka/kafka_29092/kafka_2.12-2.2.1
bin/kafka-topics.sh --version
ps -ef | grep '[k]afka.Kafka'
```
## 2. 记录旧Cluster ID
```bash
bin/zookeeper-shell.sh \
private001v.tq.cztt.qianxin-inc.cn:22181/kafka29092 \
get /cluster/id
```
保存返回的Cluster ID。
如果返回的是:
```text
SV6NxEtETaO5x7G0wzq3NQ
```
那么KRaft格式化时继续使用这个ID。
## 3. 导出Topic和消费组信息
```bash
bin/kafka-topics.sh \
--bootstrap-server private001v.tq.cztt.qianxin-inc.cn:29092 \
--list
```
```bash
bin/kafka-topics.sh \
--bootstrap-server private001v.tq.cztt.qianxin-inc.cn:29092 \
--describe
```
```bash
bin/kafka-consumer-groups.sh \
--bootstrap-server private001v.tq.cztt.qianxin-inc.cn:29092 \
--all-groups \
--describe
```
SASL环境需要传入已经配置认证信息的客户端文件。
## 4. 停止后备份
先正常停止Kafka:
```bash
bin/kafka-server-stop.sh
```
确认退出:
```bash
pgrep -af 'kafka.Kafka'
```
备份配置:
```bash
cd /qaxdata/s/services/kafka/kafka_29092
cp -a kafka_2.12-2.2.1/config \
config-2.2.1-backup
```
对下面目录做完整备份或磁盘快照:
```text
/qaxdata/s/services/kafka/kafka_29092/data
```
同时备份ZooKeeper数据。
# 三、2.2.1配置转换为3.9.1 KRaft配置
旧版ZooKeeper配置核心内容:
```properties
broker.id=1
zookeeper.connect=private001v.tq.cztt.qianxin-inc.cn:22181/kafka29092
authorizer.class.name=kafka.security.auth.SimpleAclAuthorizer
```
转换为3.9.1 KRaft后:
```properties
node.id=1
process.roles=broker,controller
controller.quorum.voters=1@private001v.tq.cztt.qianxin-inc.cn:29093
authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer
```
## Kafka 3.9.1完整配置
文件:
```text
/qaxdata/s/services/kafka/kafka_29092/kafka_2.12-3.9.1/config/server.properties
```
内容:
```properties
# Node and roles
node.id=1
process.roles=broker,controller
# Static KRaft controller quorum
controller.quorum.voters=1@private001v.tq.cztt.qianxin-inc.cn:29093
controller.listener.names=CONTROLLER
# Listeners
listener.security.protocol.map=CONTROLLER:PLAINTEXT,SASL_PLAINTEXT:SASL_PLAINTEXT
listeners=SASL_PLAINTEXT://0.0.0.0:29092,CONTROLLER://0.0.0.0:29093
advertised.listeners=SASL_PLAINTEXT://private001v.tq.cztt.qianxin-inc.cn:29092
inter.broker.listener.name=SASL_PLAINTEXT
# SASL
sasl.enabled.mechanisms=PLAIN
sasl.mechanism.inter.broker.protocol=PLAIN
# Authorization
authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer
allow.everyone.if.no.acl.found=true
# Threads
num.network.threads=3
num.io.threads=8
num.replica.fetchers=3
num.recovery.threads.per.data.dir=1
# Socket
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
# Message
message.max.bytes=10485760
# Storage
log.dirs=/qaxdata/s/services/kafka/kafka_29092/data
# Topic defaults
num.partitions=32
default.replication.factor=1
offsets.topic.replication.factor=1
# Retention
offsets.retention.minutes=315360000
log.retention.hours=72
log.segment.bytes=1073741824
log.retention.check.interval.ms=300000
# Cleaner and deletion
log.cleaner.enable=true
delete.topic.enable=true
```
不再保留以下2.2.1参数:
```properties
broker.id
port
advertised.host.name
zookeeper.connect
zookeeper.connection.timeout.ms
controlled.shutdown.enable
security.inter.broker.protocol
authorizer.class.name=kafka.security.auth.SimpleAclAuthorizer
```
# 四、首次建立3.9.1 KRaft存储
仅首次从ZooKeeper配置转换为KRaft时执行。
## 1. 检查数据目录
```bash
ls -la /qaxdata/s/services/kafka/kafka_29092/data
```
检查是否已有:
```bash
cat /qaxdata/s/services/kafka/kafka_29092/data/meta.properties
```
如果这里包含旧集群数据,不能随意删除或覆盖`meta.properties`。
## 2. 格式化KRaft存储
你已经使用的Cluster ID:
```text
SV6NxEtETaO5x7G0wzq3NQ
```
执行:
```bash
cd /qaxdata/s/services/kafka/kafka_29092/kafka_2.12-3.9.1
bin/kafka-storage.sh format \
-t SV6NxEtETaO5x7G0wzq3NQ \
-c config/server.properties
```
这条命令整个集群生命周期只执行一次。
检查:
```bash
cat /qaxdata/s/services/kafka/kafka_29092/data/meta.properties
```
应包含:
```properties
cluster.id=SV6NxEtETaO5x7G0wzq3NQ
node.id=1
```
# 五、启动Kafka 3.9.1
设置JAAS:
```bash
cd /qaxdata/s/services/kafka/kafka_29092/kafka_2.12-3.9.1
export KAFKA_OPTS="-Djava.security.auth.login.config=$PWD/config/kafka_server_jaas.conf"
```
启动:
```bash
bin/kafka-server-start.sh \
-daemon config/server.properties
```
检查日志:
```bash
tail -n 200 logs/server.log
```
检查监听端口:
```bash
ss -lntp | grep -E ':29092|:29093'
```
检查KRaft状态:
```bash
bin/kafka-metadata-quorum.sh \
--bootstrap-controller private001v.tq.cztt.qianxin-inc.cn:29093 \
describe --status
```
检查Feature:
```bash
bin/kafka-features.sh \
--bootstrap-controller private001v.tq.cztt.qianxin-inc.cn:29093 \
describe
```
3.9.1阶段预期:
```text
kraft.version FinalizedVersionLevel: 0
metadata.version FinalizedVersionLevel: 3.9-IV0
```
# 六、准备Kafka 4.3.1
Kafka 4.x已经删除Scala 2.12发行包,因此使用:
```text
kafka_2.13-4.3.1
```
Kafka 4.3.1服务端使用Java 17或更高版本:
```bash
java -version
```
建议明确设置:
```bash
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
export PATH=$JAVA_HOME/bin:$PATH
```
## 1. 复制业务配置
```bash
cd /qaxdata/s/services/kafka/kafka_29092
cp kafka_2.12-3.9.1/config/server.properties \
kafka_2.13-4.3.1/config/server.properties
cp kafka_2.12-3.9.1/config/kafka_server_jaas.conf \
kafka_2.13-4.3.1/config/kafka_server_jaas.conf
```
不要复制整个3.9的`config`目录。
Kafka 4.3使用Log4j 2,必须保留4.3.1原始文件:
```text
config/log4j2.yaml
config/tools-log4j2.yaml
```
检查:
```bash
ls -l kafka_2.13-4.3.1/config/*log4j*
```
你之前出现的:
```text
Reconfiguration failed: No configuration found
```
就是命令行工具没有找到有效Log4j2配置,但不代表KRaft命令执行失败。
# 七、第一次使用4.3.1启动时保持静态仲裁
第一次从3.9.1启动4.3.1时,集群还是:
```text
kraft.version=0
```
因此先保留:
```properties
controller.quorum.voters=1@private001v.tq.cztt.qianxin-inc.cn:29093
```
这时4.3.1配置可以与你现在展示的配置一致。
## 1. 停止3.9.1
```bash
cd /qaxdata/s/services/kafka/kafka_29092/kafka_2.12-3.9.1
bin/kafka-server-stop.sh
```
确认退出:
```bash
pgrep -af 'kafka.Kafka'
```
## 2. 启动4.3.1
```bash
cd /qaxdata/s/services/kafka/kafka_29092/kafka_2.13-4.3.1
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
export KAFKA_OPTS="-Djava.security.auth.login.config=$PWD/config/kafka_server_jaas.conf"
bin/kafka-server-start.sh \
-daemon config/server.properties
```
从3.9升级到4.3时绝对不要执行:
```bash
bin/kafka-storage.sh format
```
4.3.1直接读取3.9.1已经格式化的原数据目录:
```properties
log.dirs=/qaxdata/s/services/kafka/kafka_29092/data
```
# 八、验证4.3.1程序升级
确认程序版本:
```bash
bin/kafka-topics.sh --version
```
检查日志:
```bash
tail -n 200 logs/server.log
```
检查KRaft:
```bash
bin/kafka-metadata-quorum.sh \
--bootstrap-controller private001v.tq.cztt.qianxin-inc.cn:29093 \
describe --status
```
检查Feature:
```bash
bin/kafka-features.sh \
--bootstrap-controller private001v.tq.cztt.qianxin-inc.cn:29093 \
describe
```
刚启动4.3.1但尚未提升Feature时,应类似:
```text
metadata.version:
SupportedMaxVersion: 4.3-IV0
FinalizedVersionLevel: 3.9-IV0
kraft.version:
FinalizedVersionLevel: 0
```
这时完成的是“程序升级”,尚未最终升级集群元数据。
# 九、升级metadata.version
建议逐级确认,而不是启动4.3后立即全部提升。
## 1. 先最终升级到4.0
```bash
bin/kafka-features.sh \
--bootstrap-controller private001v.tq.cztt.qianxin-inc.cn:29093 \
upgrade \
--release-version 4.0
```
检查:
```bash
bin/kafka-features.sh \
--bootstrap-controller private001v.tq.cztt.qianxin-inc.cn:29093 \
describe
```
你现在已经达到:
```text
metadata.version FinalizedVersionLevel: 4.0-IV3
```
## 2. 升级KRaft动态仲裁功能
如果尚未升级:
```bash
bin/kafka-features.sh \
--bootstrap-controller private001v.tq.cztt.qianxin-inc.cn:29093 \
upgrade \
--feature kraft.version=1
```
你当前已经是:
```text
kraft.version FinalizedVersionLevel: 1
```
因此这一步不用重复执行。
# 十、当前必须修改4.3.1配置
由于你的集群已经是:
```text
kraft.version=1
```
按照Kafka 4.3规则,应从静态仲裁配置:
```properties
controller.quorum.voters=1@private001v.tq.cztt.qianxin-inc.cn:29093
```
改成动态仲裁引导地址:
```properties
controller.quorum.bootstrap.servers=private001v.tq.cztt.qianxin-inc.cn:29093
```
修改:
```bash
vi /qaxdata/s/services/kafka/kafka_29092/kafka_2.13-4.3.1/config/server.properties
```
删除:
```properties
controller.quorum.voters=1@private001v.tq.cztt.qianxin-inc.cn:29093
```
增加:
```properties
controller.quorum.bootstrap.servers=private001v.tq.cztt.qianxin-inc.cn:29093
```
检查:
```bash
grep -E \
'^(controller.quorum.voters|controller.quorum.bootstrap.servers)=' \
/qaxdata/s/services/kafka/kafka_29092/kafka_2.13-4.3.1/config/server.properties
```
只能输出:
```text
controller.quorum.bootstrap.servers=private001v.tq.cztt.qianxin-inc.cn:29093
```
Kafka官方明确要求:`kraft.version=1`生效后,删除`controller.quorum.voters`并配置`controller.quorum.bootstrap.servers`。[Kafka 4.3 KRaft升级说明](https://kafka.apache.org/43/operations/kraft/)
# 十一、Kafka 4.3.1最终配置
```properties
node.id=1
process.roles=broker,controller
controller.quorum.bootstrap.servers=private001v.tq.cztt.qianxin-inc.cn:29093
controller.listener.names=CONTROLLER
listener.security.protocol.map=CONTROLLER:PLAINTEXT,SASL_PLAINTEXT:SASL_PLAINTEXT
listeners=SASL_PLAINTEXT://0.0.0.0:29092,CONTROLLER://0.0.0.0:29093
advertised.listeners=SASL_PLAINTEXT://private001v.tq.cztt.qianxin-inc.cn:29092
inter.broker.listener.name=SASL_PLAINTEXT
sasl.enabled.mechanisms=PLAIN
sasl.mechanism.inter.broker.protocol=PLAIN
authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer
allow.everyone.if.no.acl.found=true
num.network.threads=3
num.io.threads=8
num.replica.fetchers=3
num.recovery.threads.per.data.dir=1
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
message.max.bytes=10485760
log.dirs=/qaxdata/s/services/kafka/kafka_29092/data
num.partitions=32
default.replication.factor=1
offsets.topic.replication.factor=1
offsets.retention.minutes=315360000
log.retention.hours=72
log.segment.bytes=1073741824
log.retention.check.interval.ms=300000
log.cleaner.enable=true
delete.topic.enable=true
```
修改完成后正常重启4.3.1并验证:
```bash
bin/kafka-server-stop.sh
```
```bash
bin/kafka-server-start.sh \
-daemon config/server.properties
```
```bash
bin/kafka-metadata-quorum.sh \
--bootstrap-controller private001v.tq.cztt.qianxin-inc.cn:29093 \
describe --status
```
# 十二、是否继续升级到metadata.version 4.3
你现在是:
```text
Kafka程序:4.3.1
metadata.version:4.0-IV3
kraft.version:1
```
这个状态可以正常运行。
生产、消费、事务、ACL及消费组都验证正常后,如需正式启用4.3元数据能力,再执行:
```bash
bin/kafka-features.sh \
--bootstrap-controller private001v.tq.cztt.qianxin-inc.cn:29093 \
upgrade \
--release-version 4.3
```
检查:
```bash
bin/kafka-features.sh \
--bootstrap-controller private001v.tq.cztt.qianxin-inc.cn:29093 \
describe
```
预期:
```text
metadata.version FinalizedVersionLevel: 4.3-IV0
```
这一步不可依赖降级恢复,执行前必须完成备份和业务验证。[Kafka 4.3.1升级指南](https://kafka.apache.org/43/getting-started/upgrade/)
最终过程可以压缩为:
```text
停止2.2.1
→ 备份Kafka数据和ZooKeeper
→ 转换3.9.1 KRaft配置
→ 仅首次执行storage format
→ 启动并验证3.9.1
→ 停止3.9.1
→ 使用同一数据目录启动4.3.1
→ 不再format
→ 验证业务
→ 提升metadata.version
→ 提升kraft.version=1
→ voters改为bootstrap.servers
→ 重启验证
→ 最后按需提升metadata.version到4.3
```
[root@private001v kafka_29092]# cat kafka_2.12-2.2.1/config/server.properties |grep -Ev '^$|^#'
broker.id=1
port=29092
advertised.host.name=private001v.tq.cztt.qianxin-inc.cn
num.network.threads=3
num.io.threads=8
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
message.max.bytes=10485760
log.dirs=/qaxdata/s/services/kafka/kafka_29092/data
num.partitions=32
default.replication.factor=1
offsets.topic.replication.factor=1
num.replica.fetchers=3
num.recovery.threads.per.data.dir=1
offsets.retention.minutes=315360000
log.retention.hours=72
log.segment.bytes=1073741824
log.retention.check.interval.ms=300000
log.cleaner.enable=true
zookeeper.connect=private001v.tq.cztt.qianxin-inc.cn:22181/kafka29092
zookeeper.connection.timeout.ms=6000
delete.topic.enable=true
controlled.shutdown.enable=true
listeners=SASL_PLAINTEXT://0.0.0.0:29092
advertised.listeners=SASL_PLAINTEXT://private001v.tq.cztt.qianxin-inc.cn:29092
security.inter.broker.protocol=SASL_PLAINTEXT
sasl.enabled.mechanisms=PLAIN
sasl.mechanism.inter.broker.protocol=PLAIN
authorizer.class.name=kafka.security.auth.SimpleAclAuthorizer
allow.everyone.if.no.acl.found=true
[root@private001v kafka_29092]# cat kafka_2.12-3.9.1/config/server.properties |grep -Ev '^$|^#'
node.id=1
num.network.threads=3
num.io.threads=8
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
message.max.bytes=10485760
log.dirs=/qaxdata/s/services/kafka/kafka_29092/data
num.partitions=32
default.replication.factor=1
offsets.topic.replication.factor=1
num.replica.fetchers=3
num.recovery.threads.per.data.dir=1
offsets.retention.minutes=315360000
log.retention.hours=72
log.segment.bytes=1073741824
log.retention.check.interval.ms=300000
log.cleaner.enable=true
delete.topic.enable=true
process.roles=broker,controller
controller.quorum.voters=1@private001v.tq.cztt.qianxin-inc.cn:29093
controller.listener.names=CONTROLLER
listener.security.protocol.map=CONTROLLER:PLAINTEXT,SASL_PLAINTEXT:SASL_PLAINTEXT
listeners=SASL_PLAINTEXT://0.0.0.0:29092,CONTROLLER://0.0.0.0:29093
advertised.listeners=SASL_PLAINTEXT://private001v.tq.cztt.qianxin-inc.cn:29092
inter.broker.listener.name=SASL_PLAINTEXT
sasl.enabled.mechanisms=PLAIN
sasl.mechanism.inter.broker.protocol=PLAIN
authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer
allow.everyone.if.no.acl.found=true
[root@private001v kafka_29092]# cat kafka_2.13-4.3.1/config/server.properties |grep -Ev '^$|^#'
node.id=1
num.network.threads=3
num.io.threads=8
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
message.max.bytes=10485760
log.dirs=/qaxdata/s/services/kafka/kafka_29092/data
num.partitions=32
default.replication.factor=1
offsets.topic.replication.factor=1
num.replica.fetchers=3
num.recovery.threads.per.data.dir=1
offsets.retention.minutes=315360000
log.retention.hours=72
log.segment.bytes=1073741824
log.retention.check.interval.ms=300000
log.cleaner.enable=true
delete.topic.enable=true
process.roles=broker,controller
controller.quorum.voters=1@private001v.tq.cztt.qianxin-inc.cn:29093
controller.listener.names=CONTROLLER
listener.security.protocol.map=CONTROLLER:PLAINTEXT,SASL_PLAINTEXT:SASL_PLAINTEXT
listeners=SASL_PLAINTEXT://0.0.0.0:29092,CONTROLLER://0.0.0.0:29093
advertised.listeners=SASL_PLAINTEXT://private001v.tq.cztt.qianxin-inc.cn:29092
inter.broker.listener.name=SASL_PLAINTEXT
sasl.enabled.mechanisms=PLAIN
sasl.mechanism.inter.broker.protocol=PLAIN
authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer
allow.everyone.if.no.acl.found=true
[root@private001v kafka_29092]#