ZooKeeper 与 Kafka 三节点部署
本章部署 3 个 ZooKeeper 节点和 3 个 Kafka Broker,分别以 zk-1 至 zk-3、kafka-1 至 kafka-3 表示。所有名称都是示例,部署前要替换为受控内网 DNS;不能向公网暴露 ZooKeeper 端口或明文 Kafka 监听器。

1. 准备运行目录
Kafka 3.x ZooKeeper 模式需要与该发行版兼容的 JDK。程序、配置、日志与数据目录必须分离,Broker 数据目录应挂载独立持久化磁盘。
# 创建不可登录的系统账号,避免 Kafka 与 ZooKeeper 以 root 权限运行。
sudo useradd --system --home /nonexistent --shell /usr/sbin/nologin kafka
# 创建程序、配置、日志和持久化数据目录。
sudo install -d -o kafka -g kafka /opt/kafka /etc/kafka \
/var/lib/kafka/logs /var/lib/zookeeper /var/log/kafka
# 下载已完成兼容性测试的 Kafka 3.x 包;Kafka 4.x 不含 ZooKeeper 模式。
export KAFKA_VERSION=3.9.0
curl -fLO "https://archive.apache.org/dist/kafka/${KAFKA_VERSION}/kafka_2.13-${KAFKA_VERSION}.tgz"
sudo tar -xzf "kafka_2.13-${KAFKA_VERSION}.tgz" -C /opt/kafka --strip-components=1
sudo chown -R kafka:kafka /opt/kafka /etc/kafka /var/lib/kafka /var/lib/zookeeper /var/log/kafka
2. 配置 ZooKeeper Ensemble
在三个 ZooKeeper 节点上使用相同的配置文件。2181 是客户端端口,2888 用于节点同步,3888 用于 Leader 选举;防火墙只允许 ZooKeeper 节点相互访问 2888、3888,并仅允许 Broker 访问 2181。
# /etc/kafka/zookeeper.properties
# 数据目录必须在持久化磁盘,不能使用 /tmp。
dataDir=/var/lib/zookeeper
# 仅向 Broker 与受控运维网络开放客户端端口。
clientPort=2181
tickTime=2000
initLimit=10
syncLimit=5
# 最后的数字与各节点 myid 一一对应。
server.1=zk-1.example.internal:2888:3888
server.2=zk-2.example.internal:2888:3888
server.3=zk-3.example.internal:2888:3888
# 仅在 zk-1 执行;myid 必须与 server.1 的编号一致。
echo 1 | sudo tee /var/lib/zookeeper/myid
# 仅在 zk-2 执行;不要让多个节点使用同一 myid。
echo 2 | sudo tee /var/lib/zookeeper/myid
# 仅在 zk-3 执行;随后确保数据目录仍由 kafka 用户拥有。
echo 3 | sudo tee /var/lib/zookeeper/myid
sudo chown -R kafka:kafka /var/lib/zookeeper
# /etc/systemd/system/zookeeper.service
[Unit]
# 等待 DNS 与网络可用,避免 Ensemble 初始化时无法连接其他节点。
After=network-online.target
Wants=network-online.target
[Service]
# 以专用用户启动,并显式指定配置文件。
User=kafka
Group=kafka
ExecStart=/opt/kafka/bin/zookeeper-server-start.sh /etc/kafka/zookeeper.properties
Restart=on-failure
RestartSec=10
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target
3. 配置 Kafka Broker
以下为 kafka-1 的配置。kafka-2、kafka-3 必须分别使用不同的 broker.id、advertised.listeners 与数据卷,不能共享 log.dirs。
# /etc/kafka/server.properties on kafka-1
# Broker ID 在集群内唯一。
broker.id=1
# 实验可使用 PLAINTEXT;生产改用 SSL 或 SASL_SSL 并分离客户端监听器。
listeners=PLAINTEXT://0.0.0.0:9092
# 必须为客户端与其他 Broker 可解析的稳定 DNS,不能填 localhost。
advertised.listeners=PLAINTEXT://kafka-1.example.internal:9092
listener.security.protocol.map=PLAINTEXT:PLAINTEXT
inter.broker.listener.name=PLAINTEXT
# 每台 Broker 独享持久化日志目录。
log.dirs=/var/lib/kafka/logs
# ZooKeeper 模式的协调后端;/kafka 是隔离的 ZooKeeper 路径。
zookeeper.connect=zk-1.example.internal:2181,zk-2.example.internal:2181,zk-3.example.internal:2181/kafka
zookeeper.connection.timeout.ms=18000
# 新 Topic 的可靠性默认值;核心 Topic 仍须显式指定。
num.partitions=3
default.replication.factor=3
min.insync.replicas=2
unclean.leader.election.enable=false
auto.create.topics.enable=false
log.retention.hours=168
# /etc/systemd/system/kafka.service
[Unit]
# Broker 在 ZooKeeper Ensemble 可用后启动;远端 Ensemble 不可达时会自动重试。
After=network-online.target zookeeper.service
Wants=network-online.target
[Service]
# 使用专用账号与受控堆内存;堆大小须基于实际负载和主机内存调优。
User=kafka
Group=kafka
Environment="KAFKA_HEAP_OPTS=-Xms2g -Xmx2g"
ExecStart=/opt/kafka/bin/kafka-server-start.sh /etc/kafka/server.properties
Restart=on-failure
RestartSec=15
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target