背景
事情是这样的,我们在外地有一套资源池,我们需要通过kafka把数据拿到本地资源池来进行计算。资源池之间通过承载网传输,我们所谓的承载网是一种可以跨资源池的内网,这里为和资源池内部的网络作区分,我把承载网称为外网,资源池内部的网络称为内网。资源池的网络比较复杂,首先,为了安全,不是所有服务器都能访问外网,需要有外网机器进行nat映射,将请求转发到内网机器的HA上,通过HA转发到不同机器,比如我们要用到的Kafka。
Kafka监听地址
Kafka的配置中有两处监听配置,分别是:
listeners
advertised.listeners
listeners
是kafka监听网卡的ip,绑定哪块网卡的ip,kafka就可以监听来自哪块网卡的请求。假设机器上一块内网网卡一块外网网卡,listeners
绑定外网网卡时就只能接收来自外网的请求,绑定内网网卡同理。这里要特别明确一下几种特殊情况,监听localhost
时,不监听网卡,只能通过localhost:xxxx访问;监听0.0.0.0
时,会接收所有网卡的请求。
advertised.listeners
是kafka向zookeeper注册的地址,kafka某个节点启动时,会向zookeeper注册自己,这时就会将advertised.listeners
的地址注册到zookeeper,同时获取集群内其他节点的通信地址,即其他节点的advertised.listeners
。advertised.listeners
如果不配置,会默认使用listeners
绑定的ip。
监听两个ip实现内外网分流
我们的需求是通过外网能够访问Kafka集群,那么将kafka监听的ip都设置为外网网卡的ip即可,但这样kafka节点间的通讯也通过外网,会有很多安全隐患。所以理想的情况是,集群间通讯使用内网,外部对集群的访问通过外网。
如果想实现上述的内外网分流,需要将两个ip都进行绑定(监听),然后通过inter.broker.listener.name
指定内网broker直接通讯使用内网ip。
具体实施方法这里要分两种情况讨论:
- 机器有外网网卡;
- 机器没有外网网卡,需要其他机器映射网络或转发。
机器有外网网卡
对于机器本身有外网网卡的情况,只需要将内网网卡与外网网卡都进行监听。
listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
listeners=INTERNAL://内网ip:9093,EXTERNAL://外网ip:9092
advertised.listeners=INTERNAL://内网ip:9093,EXTERNAL://外网ip:9092
inter.broker.listener.name=INTERNAL
需要注意的是,绑定两个ip的端口不可以相同。如果对外使用9092,那内网调用就不能再使用9092了,反之同理。
这里listeners
和advertised.listeners
的EXTERNAL
都监听外网网卡的ip,客户端拿的集群信息也是外网ip,可以实现外网访问。
机器没有外网网卡
如果机器本身没有外网网卡,需要由其他机器转发请求过来实现外网访问,这个时候要注意了,listeners
的EXTERNAL
需要使用内网ip。
listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
listeners=INTERNAL://内网ip:9093,EXTERNAL://内网ip:9092
advertised.listeners=INTERNAL://内网ip:9093,EXTERNAL://外网ip:9092
inter.broker.listener.name=INTERNAL
当我们通过kafka客户端链接kafka时,kafka会从zookeeper获取kafka集群的信息,这时候客户端得到的就是advertised.listeners
的信息。因此我们将advertised.listeners
中的EXTERNAL
配置为外网ip,客户端通过该外网ip访问kafka集群,因为网络层面配置了转发,请求会被转发到内网ip,从而完成对kafka集群的访问。
这里对于kafka请求的原理可以参考我的另一篇文章Kafka概述与原理初探,对kafka的原理与生产、消费方式进行了一定的解释。
参考资料
特别感谢猫仙草大佬的文章kafka的listeners和advertised.listeners,配置内外网分流
读过之后真的是醍醐灌顶,解决了我大大的疑惑。