Kafka 集群开启 SASL 认证实战(二):外置 ZooKeeper 之 kafka 与 zk 间认证
很多场景下 Kafka broker 对内网客户端可以不加认证,但 kafka 与 ZooKeeper 之间的通道必须锁 ------zk 里存着 broker 元数据和消费者位移,谁都能连上去
rmr /一键清空。本篇讲外置 ZooKeeper 场景下只做 kafka↔zk 间 SASL 认证的最小配置,不动 broker 对客户端的协议,业务应用零改造。配置在 ZooKeeper 3.6.3 + Kafka 2.5.1 生产集群验证通过。
系列导航
| 篇 | 场景 | 链接 |
|---|---|---|
| 一 | 内置 ZooKeeper 的 Kafka 集群加 SASL 全套配置 | 已发布,点击直达 |
| 二 | 外置 ZooKeeper,只做 kafka↔zk 之间认证(本篇) | 本篇 |
| 三 | 外置 ZooKeeper 完整版:quorum 认证 + zk ACL + 客户端认证 | 敬请期待 |
一、适用场景与版本要求
适用判断:客户端都在可信内网、等保只要求"关键链路认证"时,用本篇最小方案;如果 kafka 也要对客户端加密码,直接看第三篇。
硬性限制 :ZooKeeper 3.6.0 及以上 ------sessionRequireClientSASLAuth 等参数 3.6 才有。本文以 3.6.3 为例。
最终效果:zk 的 quorum(集群节点间)通信和 server-client 通信都要求 SASL,kafka 用账号连 zk,其他未认证客户端一律拒绝。
二、停服务
登录每台服务器,先杀 Kafka 再杀 ZooKeeper:
bash
[root@kafka01 ~]# jps
29552 Jps
11923 QuorumPeerMain
13053 Kafka
[root@kafka01 ~]# kill -9 11923 13053
三、ZooKeeper 侧配置
进入 zk 配置目录(本文密码用 Test@12345 演示,上线前替换):
bash
cd /opt/module/apache-zookeeper-3.6.3-bin/conf
3.1 zk_server.jaas(服务端身份 + 客户端账号库)
text
Server {
org.apache.zookeeper.server.auth.DigestLoginModule required
user_super="Test@12345"
user_zkclient="Test@12345";
};
QuorumServer {
org.apache.zookeeper.server.auth.DigestLoginModule required
user_quorum="Test@12345";
};
QuorumLearner {
org.apache.zookeeper.server.auth.DigestLoginModule required
username="quorum"
password="Test@12345";
};
三个段的分工:
| 段 | 用途 |
|---|---|
Server |
zk 对客户端提供服务时的认证,user_xxx 是账号库(kafka 用 zkclient 这个账号连入) |
QuorumServer |
zk 集群选举/复制通道的服务端身份 |
QuorumLearner |
follower/observer 节点作为 learner 连 leader 时的客户端身份 |
3.2 zk_client.jaas(zk 自带命令行工具用)
text
Client {
org.apache.zookeeper.server.auth.DigestLoginModule required
username="zkclient"
password="Test@12345";
};
3.3 java.env(挂载 JAAS 的 JVM 参数)
bash
vi java.env
bash
SERVER_JVMFLAGS="-Djava.security.auth.login.config=/opt/module/apache-zookeeper-3.6.3-bin/conf/zk_server.jaas"
CLIENT_JVMFLAGS="${CLIENT_JVMFLAGS} -Djava.security.auth.login.config=/opt/module/apache-zookeeper-3.6.3-bin/conf/zk_client.jaas"
3.4 zoo.cfg 追加认证参数
properties
# ===== Server-Server (quorum) 互相认证 =====
quorum.auth.enableSasl=true
quorum.auth.learnerRequireSasl=true
quorum.auth.serverRequireSasl=true
quorum.auth.learner.saslLoginContext=QuorumLearner
quorum.auth.server.saslLoginContext=QuorumServer
# 建议设为集群节点数 n*2
quorum.cnxn.threads.size=6
# ===== Server-Client 之间认证 =====
authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
# 强制客户端必须 SASL 认证(zk >= 3.6.0)
sessionRequireClientSASLAuth=true
sessionRequireClientSASLAuth=true是"锁死"的关键------不开的话,不带认证的客户端照样能连。zk 集群里 observer 节点没有投票权,但不影响本配置。
把 4 个文件拷贝到 zk 集群所有节点。
四、Kafka 侧配置
4.1 kafka.jaas(只需要 Client 段)
bash
cd /opt/module/kafka_2.12-2.5.1/config
vi kafka.jaas
text
Client {
org.apache.kafka.common.security.plain.PlainLoginModule required
username="zkclient"
password="Test@12345";
};
注意 LoginModule 用的是 kafka 包里的 PlainLoginModule (不是 zk 的 DigestLoginModule)------kafka 连 zk 走 PLAIN 机制即可,账号对应 zk_server.jaas 里的
user_zkclient。
4.2 server.properties
追加一行:
properties
zookeeper.client.sasl=true
同样检查并注释掉残留的旧配置:
properties
#advertised.host.name=192.168.10.31
#advertised.port=9092
4.3 启动脚本挂 JAAS
修改 kafka/bin/kafka-run-class.sh(一处生效,所有 kafka 命令行工具都会带上):
bash
vi /opt/module/kafka_2.12-2.5.1/bin/kafka-run-class.sh
在脚本靠前位置添加:
bash
export KAFKA_OPTS="-Djava.security.auth.login.config=/opt/module/kafka_2.12-2.5.1/config/kafka.jaas"
kafka.jaas 拷贝到所有 broker 节点,server.properties 按各节点 IP 调整后分发。
五、启动与验证
先 zk 后 kafka:
bash
cd /opt/module/apache-zookeeper-3.6.3-bin
./bin/zkServer.sh start
cd /opt/module/kafka_2.12-2.5.1
./bin/kafka-server-start.sh -daemon ./config/server.properties
验证三连:
bash
# 1. broker 正常注册(说明 kafka->zk 认证通了)
./bin/kafka-topics.sh --bootstrap-server 192.168.10.31:9092 --list
# 2. 裸连 zk 被拒(不带 JAAS 的 zkCli 直接连会被 sessionRequireClientSASLAuth 挡掉)
./bin/zkCli.sh -server 192.168.10.31:2181
# 3. 命令行生产消费不受影响(本方案不动客户端协议)
./bin/kafka-console-producer.sh --broker-list 192.168.10.31:9092 \
--producer.config ./config/producer.properties --topic test-topic
六、踩坑清单
| 坑 | 现象 | 解法 |
|---|---|---|
| zk 版本低于 3.6.0 | sessionRequireClientSASLAuth 不生效或不识别 |
先升级 zk |
忘注释 advertised.host.name |
broker 起来了客户端连不上 | 注释掉旧配置 |
| java.env 路径写错 | zk 起不来,日志报找不到 LoginModule | 核对绝对路径 |
| 只改了部分 zk 节点 | 集群选举分裂、脑裂 | 所有 zk 节点同步改 |
| kafka.jaas 用了 zk 的 DigestLoginModule | broker 连 zk 认证失败 | 用 kafka 的 PlainLoginModule |
总结
外置 zk 只锁 kafka↔zk 通道的方案,改动集中在 zk 侧 4 个文件(jaas×2 + java.env + zoo.cfg)+ kafka 侧 2 处(kafka.jaas + zookeeper.client.sasl),客户端协议完全不动,业务零感知。下一篇是本系列终章:在外置 zk 场景上叠加 kafka 客户端认证和 zk ACL 白名单,做到"内外都锁死",敬请期待。
你们 zk 集群现在有没有裸奔?有没有被误操作删过节点的经历?评论区聊聊。
系列文章配置在 ZooKeeper 3.6.3 + Kafka 2.5.1 生产集群验证;示例密码请替换后使用。