KAFKA跨主机部署网络不通解决思路
Kafka的部署不仅需要集群可用,同时需要对orderer节点可连,这就是为什么有的时候,kafka集群本身没问题,但是orderer却总是报错。
为了试验kafka剥离方案的可行性,跨阿里云网络和内网进行部署。
部署环境如下:
K8s部署在阿里云环境上,192.168.8.108可连外网,作为master;192.168.8.107不能连外网,作为slave;
Kafka集群部署在内网192.168.9.21等集群上,都可以连外网。

因为orderer节点会起在slave机器上,也就是107这台机器,它无法直连外网。因此,通过nginx转发来保证orderer可以连上kafka集群,如下图所示。
那么advertised listeners的配置就尤为重要,毕竟这是kafka节点保存在zookeeper集群中的brokers元信息,orderer最终是通过这些地址去访问kafka的。
如果将kafka0的KAFKA_ADVERTISED_LISTENERS地址设为192.168.9.21:9092,虽然集群创建正常,但是orderer无法连上云象的内网地址,也就是无法连上kafka。所以,选择将kafka0的KAFKA_ADVERTISED_LISTENERS地址设为192.168.8.108:9092,然后在108上设置nginx代理,连接到 公网IP:9092,这样就可以连上kafka节点了。
尝试Setupbaas 发现orderer仍然报错kafka集群异常,但是kafka的启动日志没有任何异常。
setup的流程很长,还要清理环境,用kafkaclient来调试会方便很多。 fabric用的go语言client是sarama,简单改一下里面的producer就可以起一个简单的client,来测试kafka集群是否可用了。
用producer向kafka写入数据,发现报错信息如下:

报错说明,现在这个partiton没有leader,我们知道kafka每个partiton都会有一个leader,负责client的读写。
为了确认测试用的partition到底有没有leader,通过kafka内部的kafka-topic.sh来查看详细信息。

结果发现,topic首先是创建成功了,partition leader也是存在的,那么为什么client没有获取到该partition的leader信息呢?
带着疑问,查看sarama的部分源码,发现传给kafkaclient(例如orderer里面的producer)的addrlist只是作为seedbrokers,从seedbrokers里面尝试去连接kafka server来获取metadata。
这个metadata里面包括了,注册在zk里面的所有brokers的信息, kafkaclient实际上是与这些brokers进行交互的,所以即使seedbroker填的不全,有时候也不影响kafka集群的使用。



根据报错信息,可以发现GetMetadata返回的信息里面有ErrLeaderNotAvailable报错。


由上图可知,GetMetadata向kafkabroker发送了获取metadata的请求,并且key是3。
查看kafka源码,可以找到kafkaAPI如何处理key为3的请求。




GetMetadata在zk里面创建了topic,并且标记为无leader状态,每个新建的topic都是处于LEADER_NOT_AVAILABLE的状态的,那问题应该出现在metadata的更新上面,负责管理各个partition状态的组件是controller,是不是controller哪里出了问题了?
难道kafka启动日志里有报错被忽略了吗?搜索Controller相关log,发现并没有报错。

ZookeeperLeaderElector: 主要用于KafkController Leader选举,选举出Controller是broker1,但是后续却没有给出controller报错信息。
实际上,controller作为kafka的组件,日志另有输出,报错如下,确实是访问不到broker的地址。

controller是随机选择一个kafka节点上启动的,为了同步副本状态,controller需要连接上每一个kafka节点,因为advertised listener地址在容器里访问不到,所以controller与各个broker的连接出现异常。
进入容器查看网络连接情况,通过netstat –ae发现其中一个kafka有不正常的连接。

通过zkCli.sh发现,这正是controller所在的kafka,可以坐实是controller的问题了。

问题的原因找到了,但是为什么用kafka自带的脚本查出来的topic状态确实正常的呢?
查看该脚本调用的函数,发现改脚本调用的函数查询的数据居然来自于zk,并不是从kafka中获得。因为所有kafka连接zk并不存在问题,所以可以得出一致的topic 描述,看来使用这个脚本去查看topic状态也得慎重。

所以表面上可以创建topic,partition也存在leader终于有了解释。
Client在GetMetadata的时候,第一次创建了无主topic,在retry的时候,kafkaclient获取的metadata信息是来自于kafka的MetadataCache,因为controller的原因partitionState没有更新,所以返回的topic信息仍然有LEADER_NOT_AVAILABLE报错。
但是为什么正常情况,却没有返回这个LEADER_NOT_AVIALABLE呢?
在每个Broker的KafkaServer对象中都会创建MetadataCache组件, 负责缓存所有的metadata信息。



可见查询partitionMetadata时,是通过partitionState来判断存活的brokers里面是否有leader。如果有partitionState未更新,就返回LEADER_NOT_AVIALABLE的metadata,否则就可以返回最新的metadata。
Controller是如何更新partitionState的呢?
集群所有partition状态是由PartitionStateMachine来管理的。




由以上代码可见,partitionState更新需要通过ControllerChannelManager。ControllerChannelManager负责维护Controller Leader与集群中其他broker之间连接,是管理这个集群的基础。
然而,ControllerChannelManager在启动时就出问题了,连不上其他的broker,所以无法所有的kafka metadata都没能更新。controller必须连上advertised listeners,包括其自身所在的broker。
问题解决方案:
如果将kafka0的KAFKA_ADVERTISED_LISTENERS地址设为public.ip.net:9092,阿里云192.168.8.107上倒是可以通过修改host文件,把public.ip.net解析成192.168.8.108。这样,107在访问public.ip.net时,会连到108并通过nginx转发到192.168.9.21:9092。orderer需要连kafka集群的话,需要在k8s容器里添加host才行。
问题总结:
1、advertised listeners不仅需要让orderer可连接,还需要让每个可能成为controller的kafkabroker容器可连才行。
2、这种表面可以创建topic,实际集群无法使用的情况,可以考虑查看controller的日志。
3、kafka自带的kafka-topic脚本,描述的是zk里面的信息,并不一定于kafka里面的数据一致,需要慎重使用。
转载请注明出处:https://www.cnblogs.com/zooqkl
KAFKA跨主机部署网络不通解决思路的更多相关文章
- kubernetes跨网段pod网络不通问题
kubernetes跨网段问题 k8s的master是10.10.10.0网段,新加了一些node,网段是172.16.100.0网段,造成容器直接网络不能相互访问. 部署k8s的时候也部署了flan ...
- Ubuntu网络不通解决办法
如下问题: 尝试和Host主机互ping也不通, Ubuntu: vmware 桥接模式 IP:192.168.1.202/24 gateway:192.168.1.1 Host主机:网络正常 IP: ...
- Exsi6.6主机网络不通解决办法
Exsi虚拟机网络偶尔不通,防火墙性能不足 解决办法,断开网络连接再重连
- (转) docker跨主机 macvlan 网络配置
原文链接 https://github.com/alfredhuang211/study-docker-doc/blob/master/docker%E8%B7%A8%E4%B8%BB%E6%9C%B ...
- u-boot-2014-04 网络不通解决一例
不久前我移植了u-boot-214-04到Tq2440的板子上,基本功能都有了,网卡也可以使用了.有一天打算把u-boot-2010-06也也一直到tq2440上,移植完后发现u-boot-214-0 ...
- Docker系列04—跨主机网络方案(overlay/weave)
在前面详细讲解了几种网络模式:none,host,bridge,container.他们解决了单个主机间的容器的通信问题,并不能实现多个主机容器之间的通信. 跨主机网络方案包括两大类: 1,docke ...
- centos7下安装docker(15.6docker跨主机网络---Weave)
Weave是weaveworks开发的容器网络解决方案.weave创建的虚拟网络可以将部署在多个主机上的容器连接起来.对于容器来说,weave就像一个巨大的网络交换机,容器可以直接通信,无需NAT和端 ...
- centos7下安装docker(15.1跨主机网络)
之前学习了单个host上的网络,我们知道单个host上的网络有:none,host,bridge和joined,他们解决了单个host上面的容器通信的问题:接下来我们讨论跨主机间容器通信的方案 跨主机 ...
- Docker跨主机网络——overlay
前言 在Docker网络--单host网络一文中,我为大家总结了Docker的单机网络相关知识和操作,单机网络比较容易.本文我为大家总结Docker跨主机通信相关知识.同样本文大部分内容以CloudM ...
随机推荐
- Asp.net Web Api开发(第四篇)Help Page配置和扩展
https://blog.csdn.net/sqqyq/article/details/52708613
- minikube windows hyperx填坑记
minikube windows hyperx填坑记 安装了一天半,还是没行,先放弃 开始 minikube start --vm-driver=hyperv --hyperv-virtual-swi ...
- python smtp 发邮件 添加附件
# -*- coding:utf-8 -*- # __author__ = 'justing' import os import smtplib from email.mime.multipart i ...
- UML作业第一次:UML用例图绘制
UML第一次作业 一. 用例图:用例图(usecase diagram)是UML用于描述软件功能的图形.用例图包括用例.参与者及其关系,用例图也可以包括注释和约束.程序员要画时序图啥的用其他的比较麻烦 ...
- linux----------yum一些安装命令汇总
1.yum install -y psmisc 安装killall命令 2.yum install -y lrzsz 安装sz(下载)和rz(上传)命令 3.yum ins ...
- 004-CSS怎样让背景充满整个屏幕
<!doctype html><html><body> ...Your content goes here...</body></html> ...
- 用mongols轻松打造websocket应用
用websocket做聊天系统是非常合适的. mongols是一个运行于linux系统之上的开源c++库,可轻松开启一个websocket服务器. 首先,build一个websocket服务器. #i ...
- Installing ROS Indigo on the Raspberry Pi
Installing ROS Indigo on the Raspberry Pi Description: This instruction covers the installation of R ...
- CentOS7编译安装SVN(subversion1.9.7)
参考连接0:http://www.programering.com/a/MDMzYDMwATg.html参考连接1:http://www.zsythink.net/archives/13180.系统信 ...
- python垃圾回收机制与小整数池
python垃圾回收机制 当引用计数为0时,python会删除这个值. 引用计数 x = 10 y = x del x print(y) 10 引用计数+1,引用计数+1,引用计数-1,此时引用计数为 ...