Contents

Kafka内外网访问

最近在研究 kafka 的 MirrorMaker, 内网需要复制外网 Kafka 的数据,但是实际配置中发现 外网 kafka 返回给 MirrorMaker的是内网IP,经过查询文档,需要修改 advertised.listeners listeners 相关的配置,经过在网上查询,找到了下面这篇优质的教程,收藏到博客


本文介绍了Kafka内外网访问的设置。

kafka的两个配置listeners和advertised.listeners

listeners

kafka监听的网卡的ip,假设你机器上有两张网卡,内网192.168.0.213和外网101.89.163.1 如下配置

1
listeners=PLAINTEXT://192.168.0.213:9092

那么kafka只监听内网网卡,即只接收内网网卡的数据,如果你不能把外网网卡流量转发到内网网卡(为什么要强调这一点,下面说),那么kafka就接收不到外网网卡数据。如果配置成外网ip同理。当然你可以配置成0.0.0.0,监听所有网卡。

advertised.listeners

我们观察kafka的配置文件server.properties,会发现里面记录了zookeeper集群的各个节点的访问地址,但是并没有记录kafka兄弟节点的地址。kafka节点启动后,会向zookeeper注册自己,同时从zookeeper中获取兄弟节点的地址,以便与兄弟节点通信。 同样,我们使用客户端连接kafka后,kafka返回给客户端的是集群各节点的访问地址,这个地址也是上面说的从zookeeper中获得的地址。 这个地址哪里来,就是kafka节点向zookeeper注册时提供的advertised.listeners。如果没有,就会使用listeners

三种情景,搭配使用这两个配置

只需要内网访问kafka

1
listeners=PLAINTEXT://192.168.0.213:9092

只需要内网访问kafka

你肯定想到了最简单的一个方法,listeners使用外网ip

1
listeners=PLAINTEXT://101.89.163.1:9092

需要外网访问

如果宿主机有外网网卡,这么配当然没问题。如果没有(ifconfig看不到外网ip的网卡,基本上就不存在这个外网网卡),很可能和我使用的的宿主机一样是通过NAT映射或者啥办法搞出来的外网ip,此时kafka无法监听这个外网ip(因为不存在,启动就会报错)。 这时候就是advertised.listeners真正发挥作用的时候了。使用如下配置:

1
2
listeners=PLAINTEXT://192.168.0.213:9092
advertised.listeners=PLAINTEXT://101.89.163.1:9092

此时一个完整的kafka客户端访问服务端的流程:

  • 客户端访问101.89.163.1:9092,被kafka宿主机所在环境映射到内网192.168.0.213:9092,访问到了kafka节点,请求获得kafka服务端的访问地址
  • kafka从zookeeper拿到自己和其他兄弟节点通过advertised.listeners注册到zookeeper的101.89.163.1:9092等外网地址,作为kafka的服务端访问地址返回给客户端
  • 客户端拿这些地址访问kafka集群,被kafka宿主机所在环境映射到各kafka节点的内网ip,访问到了kafka服务端……完美循环

你可能会问已经配置了访问地址,为什么还要在第一次访问的时候请求获得kafka的访问地址。因为如果是kafka集群,你可以选择只给客户端配置一个kafka节点的地址(这样是不推荐的),但是客户端必须要访问集群中的每一个节点,所以必须通过这个节点获得集群中每一个节点的访问地址。 如果不配置advertised.listeners=PLAINTEXT://101.89.163.1:9092,你会发现虽然你给kafka客户端配置的访问地址是101.89.163.1:9092,但是kafka客户端访问时报错,报错原因是Connection to node -1[192.168.0.213:9092] could not be established. Broker may not be available.。这就是因为不配置advertised.listenersadvertised.listeners默认使用listeners配置的地址,客户端拿到的就是listeners配置的内网地址

内外网分流

上面说的有外网ip的情况,直接配置外网ip有没有问题呢? 如果既要内网访问,又要外网访问,本来可以走内网的流量都走外网网卡,显然不合适;而且有的环境可能被配置成这些kafka宿主机是没有外网访问权限的,即虽然他可以访问自己的外网ip,但是访问不了兄弟节点的外网ip。这时候就要配置内外网。

仅内网网卡

1
2
3
4
5
listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
# EXTERNAL 配置为内网IP
listeners=INTERNAL://192.168.0.213:9092,EXTERNAL://192.168.0.213:19092
advertised.listeners=INTERNAL://192.168.0.213:9092,EXTERNAL://101.89.163.9:19092
inter.broker.listener.name=INTERNAL

有公网网卡

1
2
3
4
5
listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
# EXTERNAL 配置为公网IP
listeners=INTERNAL://192.168.0.213:9092,EXTERNAL://101.89.163.9:19092
advertised.listeners=INTERNAL://192.168.0.213:9092,EXTERNAL://101.89.163.9:19092
inter.broker.listener.name=INTERNAL

注意这两的区别是listenersEXTERNAL使用的ip不一样,一个使用内网ip,一个使用外网ip。

  • 如果你的kafka宿主机有外网网卡,只能用外网ip,若使用配置1,kafka通过listeners监听的两个端口都是内网网卡的数据,无法接收到外网网卡数据;
  • 如果你的kafka宿主机外网ip是映射来的,只能使用内网ip,原因也是上面说过的,不存在外网网卡,kafka启动监听就会报错,而使用内网ip有环境配置好的转发,可以接收到外网ip的数据。

阅读原文:CNSRE