核心方法:造新桥、引车流、拆老桥
面对这种“心脏不停跳”的升级手术,核心秘诀在于设计一个稳妥的“过渡期”。最忌讳的就是简单粗暴地一刀切。整个过程的精髓,是通过三次节奏清晰的滚动重启,让集群先进入一个新旧协议共存、再平稳切换的状态。
如果把整个过程想象成交通疏导,就非常直观了:
1. 造新桥:在旁边新开一个带安检(认证)的通道,原有的老桥(无认证端口)继续通行,保证交通不中断。
2. 引车流:引导车辆(业务流量)分批、有序地开到新桥上。关键是,这个过程对路面管理者(Kafka Broker)来说是热更新,不需要封路重启。
3. 内部换乘:等所有外部车辆都熟悉了新桥,再把内部工作车辆(Broker间通信)的路线也切换到新桥上。
4. 拆老桥:最后,确认老桥上已经没有任何车流了,再安全地拆除这个不设防的旧通道。
思路清晰了,下面就进入具体的实操环节,一步步拆解。
Step 0:准备工作 (配置 JAAS 与超级用户)
在动手修改Kafka配置之前,基础工作必须做扎实。首先需要在每个Broker节点上准备认证文件。这里以兼顾安全性与易用性的SASL/SCRAM机制为例(它比PLAIN方式更安全)。
创建JAAS配置文件(例如/opt/kafka/config/kafka_server_jaas.conf),配置好Broker自身的认证信息。随后,最关键的一步是在Kafka启动脚本(如kafka-server-start.sh)或系统的环境变量中将其注入:
export KAFKA_OPTS="-Djava.security.auth.login.config=/opt/kafka/config/kafka_server_jaas.conf"
Step 1:开启双端口与“兼容模式”
这一步的目标很明确:让Broker同时开放一个新端口(用于未来的认证访问)和一个旧端口(维持现有业务)。相当于建好了新桥,但老桥依然通车。
需要修改集群中所有Broker的server.properties配置文件:
# 1. 监听器同时开启老端口(9092)和新端口(9093)
listeners=PLAINTEXT://0.0.0.0:9092,SASL_PLAINTEXT://0.0.0.0:9093
advertised.listeners=PLAINTEXT://<贵司外网IP>:9092,SASL_PLAINTEXT://<贵司外网IP>:9093
# 2. 内部Broker间通信【暂时保持】无认证协议(这是平滑的关键!)
inter.broker.listener.name=PLAINTEXT
sasl.enabled.mechanisms=SCRAM-SHA-256
# 3. 启用ACL鉴权插件并配置超级用户(必须设置,否则后续无法管理)
authorizer.class.name=kafka.security.authorizer.AclAuthorizer
super.users=User:admin;User:kafka
# 4. 【高亮注意】允许未配置ACL的请求默认放行!
allow.everyone.if.no.acl.found=true
操作与结果:配置完成后,对集群进行第一次滚动重启。重启后,老业务在9092端口上一切如常,而新的9093 SASL端口已准备就绪。这里allow.everyone.if.no.acl.found=true这个参数至关重要,它确保了在开启ACL插件后,那些还没来得及配置权限的现有业务不会被突然阻断,给了我们充足的迁移缓冲期。
Step 2:客户端灰度迁移(⚠️ Kafka 无需重启!)
从这里开始,压力就从运维侧转移到了业务侧。好消息是,这个阶段完全是动态的,Kafka Broker本身不需要任何重启!
1. 按需分配账号与ACL:
管理员使用kafka-configs.sh工具动态创建业务所需的账号,并用kafka-acls.sh赋予其对特定Topic的精确读写权限。这些权限信息会实时写入Kafka的元数据,Broker热加载即可生效。
# 示例:授予 user_app1 对 topicA 的读写权限
bin/kafka-acls.sh --bootstrap-server localhost:9093 --command-config admin.properties \
--add --allow-principal User:user_app1 --operation Read --operation Write --topic topicA
2. 业务应用灰度更新:
业务方将其应用程序中的Kafka客户端连接地址,从原来的9092改为9093,同时在客户端配置中添加SASL认证信息(如用户名、密码)。
3. 实现平滑过渡:
业务方只需重启自己的客户端应用,流量就会无声无息地从9092端口切换到9093端口。运维人员可以悠然地盯着监控大盘,看着9092端口的流量曲线缓缓降为零,而9093端口的曲线逐渐攀升至满载。整个过程业务无感知。
Step 3:切换集群内部通信协议
当监控确认所有生产流量都已100%迁移到9093的SASL端口后,下一步就需要加固“后方”——将Kafka Broker之间的内部通信(例如副本同步、Leader选举、元数据传播)也升级为加密认证通道。
再次修改所有Broker的server.properties,只改动一个关键参数:
# 将内部通信协议从PLAINTEXT切换为SASL_PLAINTEXT
inter.broker.listener.name=SASL_PLAINTEXT
操作:进行第二次滚动重启。至此,集群内外所有通信均已走在安全的“新桥”之上。
Step 4:彻底封死“老桥”,收紧安全策略
很多追求效率的工程师会想:“第三步和第四步能不能合并?既然业务都切走了,我在改内部协议时,顺手把老端口关了不行吗?”
务必警惕,这是一个极其危险的想法,很可能导致集群瞬间瘫痪!
避坑原理解析:
滚动重启是一台台Broker依次进行的。假设你合并操作,重启了Broker A。此时,A只监听SASL端口,并且只用SASL协议与其他Broker通信。
然而,还没来得及重启的Broker B,其配置仍认为内部通信应该使用PLAINTEXT协议。它会尝试去连接Broker A的PLAINTEXT端口(9092)。但你已经在A上关闭了这个端口,结果就是B遭遇Connection Refused。
瞬间,副本同步链断裂,ISR列表剧烈抖动,Controller的元数据更新无法送达——精心规划的“零停机”升级计划将立刻破产。
所以,必须耐心等到第三步完成,所有Broker都重启完毕并已使用SASL内部通信后,才能执行这最后的收尾步骤。
最终修改所有Broker的server.properties:
# 1. 移除PLAINTEXT监听器,彻底关闭9092端口
listeners=SASL_PLAINTEXT://0.0.0.0:9093
advertised.listeners=SASL_PLAINTEXT://<贵司外网IP>:9093
# 2. 收紧ACL安全策略,关闭默认放行,实现严格的白名单控制
allow.everyone.if.no.acl.found=false
操作与结果:执行第三次(也是最后一次)滚动重启。重启完成后,9092端口正式下线。从此,任何没有合法凭证或试图越权访问的请求,都会被Kafka坚决拒之门外。
总结
给高速运行的核心数据总线“上锁”,确实是一项需要精细操作的任务。其平滑升级的精髓,概括起来就是那句老话:“先立后破”。
严格遵循“造新桥、引车流、内部换乘、再拆老桥”这四个阶段,耐心完成三次滚动重启。只要步骤清晰、执行稳妥,完全可以在业务方毫无感知的情况下,将一个“裸奔”的Kafka集群,升级为一座配置了完备认证与鉴权机制的安全堡垒。
