基于Kubernetes在AWS上部署Kafka时遇到的一些问题
作者:Jack47
转载请保留作者和原文出处
欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源。
交代一下背景:我们的后台系统是一套使用Kafka消息队列的数据处理管线:Kafka->Logstash->Elasticsearch。这些组件都跑在Docker的容器环境里,我们是基于Kubernetes来编排整个后端的数据处理管线上的容器。Kafka需要暴露在外网里,接收Kafka Producer(filebeat, collectd)发过来的消息。本文是记录基于Kubernetes在AWS上部署Kafka 0.9.x版本时遇到的问题和排查思路。
为了能够在外网也能访问Kafka,Kafka组件对应的Kubernetes ServiceType选用的是NodePort,Kafka集群有三个节点,即Kafka Server有三个Broker。对外暴露的端口是39092,三个Broker对应的外网IP分别是 59.64.11.21,59.64.11.22,59.64.11.23。Kafka组件部署完成后,使用Kafka producer连接Server,配置的kafka bootstrap_servers是 59.64.11.22:39092。这里之所以端口使用的是 39092,而非9092,是因为Kubernetes对外暴露的端口,分配的是39092。接着往下看,你会发现这样会有问题。
connection refused
Kafka client的日志里报错:
2016-11-22T07:23:33.312102145Z 2016-11-22T07:23:33Z WARN Failed to connect to broker 59.64.11.21:30791: dial tcp 52.198.148.31:30791: getsockopt: connection refused
2016-11-22T07:23:33.312102145Z
2016-11-22T07:23:33.312102145Z 2016-11-22T07:23:33Z WARN kafka message: client/metadata got error from broker while fetching metadata:%!(EXTRA *net.OpError=dial tcp 52.198.148.31:30791: getsockopt: connection refused)
第一反应是去看AWS实例的安全组(Security Group),发现忘了允许39092这个端口的接入。配置完成后,重启Kafka client。
No available broker
接下来遇到了这个错误:
2016-11-22T07:23:33.312102145Z 2016-11-22T07:23:33Z WARN kafka message: client/metadata no available broker to send metadata request to
2016-11-22T07:23:33.312102145Z 2016-11-22T07:23:33Z WARN client/brokers resurrecting 1 dead seed brokers
Google一番,然后通过阅读Kafka的文档(一定要注意查看对应版本的文档),发现原因了。
当Kafka broker启动时,它会在ZK上注册自己的IP和端口号,客户端就通过这个IP和端口号来连接。在AWS这种IaaS环境下,由于java.net.InetAddress.getCanonicalHostName调用拿到的HostName是类似ip-172-31-10-199这样的只有内网才能访问到的主机名,所以默认注册到ZK上的IP是内网才能访问的内网IP。此时就需要显示指定 advertised.host.name, advertised.listeners参数,让注册到ZK上的IP是外网IP。
例如对于 59.64.11.22 IP对应的broker,需要在 server.properties 配置文件里增加如下三个配置:
advertised.listeners=PLAINTEXT://59.64.11.22:9092
advertised.host.name=59.64.11.22
advertised.port=9092
估计读者们也会跟我一样犯迷糊,为什么需要三个参数来配置IP和端口号呢,用一个advertised.listeners不就搞定了吗?后来发现最新版本0.10.x broker配置弃用了advertised.host.name 和 advertised.port 这两个个配置项,就配置advertised.listeners就可以了。:joy
found some partitions to be leaderless
2016-11-22T02:58:36Z WARN kafka message: client/metadata found some partitions to be leaderless
又是 Read The Fucking Manual,发现Kafka生产者会先连接 bootstrap_servers列表里的某个节点,这台机器只是用来获取集群的元数据(meta data):拿到topics,partitions和 replicas的信息。查到写入的topic对应的leader节点(可能不是刚才的那个节点)后,与之建立连接,然后发送实际的数据给leader。有了这个背景知识,上面的这个错误信息就不难理解了,说明获取元数据没问题,但是连不到对应的leader节点。经过跟同事探讨,发现了问题所在:Kafka使用的Kubernetes ServiceType是NodePort,而NodePort这种服务类型是有负载均衡的,所以Kafka producer连接 leader节点时,由于有负载均衡,所以实际会连到其他节点上。把Kafka从Kubernetes的普通服务改为了无头服务(Headless),然后端口要从NodePort改为HostPort这种类型。这样就没有负载均衡,同时又能从外网访问Kafka节点。
还是不行
上述改动改完后,发现还是报 found some partitions to be leaderless 的错。实在不行,那就只能去zk上去看看到底broker是什么状态了。
root@kafka-0:/usr/share/easemon/kafka/bin# ./zookeeper-shell.sh 10.10.18.3
ls /brokers/ids
[1012, 1013, 1014]
可以看到 有三个broker,id分别是 1012,1013,1014。然后接着看看这些broker注册的IP地址(接着在 zookeeper-shell里执行命令):
get /brokers/ids/1012
{"jmx_port":-1,"timestamp":"1480404348685","endpoints":["PLAINTEXT://59.64.11.22:9092"],"host":"59.64.11.22","version":2,"port":9092}
看起来也符合预期,注册到 59.64.11.22的9092端口上了。
那就看看filebeat这个topic相关的信息吧:
/usr/share/easemon/kafka/bin/kafka-topics.sh --zookeeper localhost:2181 --describe --topic filebeat
Topic:filebeat PartitionCount:3 ReplicationFactor:1 Configs:
Topic: filebeat Partition: 0 Leader: 1005 Replicas: 1005 Isr: 1005
Topic: filebeat Partition: 1 Leader: 1006 Replicas: 1006 Isr: 1006
Topic: filebeat Partition: 2 Leader: 1007 Replicas: 1007 Isr: 1007
等等,这里三个分区的leader怎么是1005,1006,1007呢,应该是1012,1013,1014才对。然后想到应该是Kafka的数据(通过配置项log.dirs指定位置)没有放到持久存储上,而是放到了Docker容器内,导致每次重新部署后,原来的数据都丢了,节点都注册到新的brokerID上去了。修改完成后,重新部署,发现Kafka上终于有数据了。
关于 Broker id
多说两句,我们环境中Kafka的Broker id是使用默认自动生成的id,所以都是1000以上的。而如果你的环境中如果是手工指定的,必须在1000以下,否则根据这篇文章,Kafka不报错,会直接退出。
自动创建Topic
auto.create.topics.enable 参数可以用来配置Kafka Server是否自动创建topic,但这个是针对Producer而言的,如果Consumer消费某个不存在的topic时,是不会触发自动创建的逻辑的。所以当Consumer消费某个不存在的topic时,由于具体的实现不一样,可能会出现报错的情况。
参考资料:
如果您看了本篇博客,觉得对您有所收获,请点击右下角的“推荐”,让更多人看到!
基于Kubernetes在AWS上部署Kafka时遇到的一些问题的更多相关文章
- 解读与部署(三):基于 Kubernetes 的微服务部署即代码
在基于 Kubernetes 的基础设施即代码一文中,我概要地介绍了基于 Kubernetes 的 .NET Core 微服务和 CI/CD 动手实践工作坊使用的基础设施是如何使用代码描述的,以及它的 ...
- 在Kubernetes上部署应用时我们常忽略的几件事
根据我的经验,大多数人(使用Helm或手动yaml)将应用程序部署到Kubernetes上,然后认为他们就可以一直稳定运行. 然而并非如此,实际使用过程还是遇到了一些"陷阱",我希 ...
- 关于在eclipse上部署Tomcat时出现8080等端口被占用问题的解决方法
问题描述: 在eclipse中部署Tomcat时,出现如下错误. 解决方法如下: 方法一: 1.开始->cmd->输入命令netstat -ano出现下图所示(注意下边显示有些错位,最后一 ...
- 在ubuntu18.04上部署项目时遇到的问题总结
因为在实验室中,有几台空闲的机子,我便选了一台准备做一个本地的服务器,因为买的阿里云学生机和之前用于FQ的机子感觉都不太顺手,阿里的学生机配置稍低,FQ用的服务器延迟太高.开始在centos和ubun ...
- 在ubuntu上部署hadoop时出现的问题
1. 配置ssh登录 不须要改动/etc/ssh/sshd_config 2. 新建hadoop用户时,home以下没有hadoop文件夹 用以下命令创建 useradd -m hadoop 3. n ...
- aws上部署zabbix3.4
三台机器 10.0.0.149 AmazonLinux2.0 zabbix-server zabbix-agent 10.0.1.61 CentOS6.9 zabbix-agent 10.0.1.11 ...
- 在AWS中部署OpenShift平台
OpenShift是RedHat出品的PAAS平台.OpenShift做为PAAS平台最大的特点是它是完全容器化的PAAS平台,底层封装了Docker和Kubernetes,上层暴露了对开发者友好的接 ...
- Kafka实战(七) - 优雅地部署 Kafka 集群
既然是集群,必然有多个Kafka节点,只有单节点构成的Kafka伪集群只能用于日常测试,不可能满足线上生产需求. 真正的线上环境需要考量各种因素,结合自身的业务需求而制定.看一些考虑因素(以下顺序,可 ...
- Win10上部署Apollo配置中心
基于Docker在Win10上部署Apollo配置中心 https://www.jianshu.com/p/a1215056ce75 http://nobodyiam.com/2016/07/09/i ...
随机推荐
- OpenCASCADE Job - dimue
- 再谈C#采集,一个绕过高强度安全验证的采集方案?方案很Low,慎入
说起采集,其实我是个外行,以前拔过阿里巴巴的客户数据,在我博客的文章:C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子) 中,介绍过采集用的工具,其实很Low的,分析 ...
- 深入研究Visual studio 2017 RC新特性
在[Xamarin+Prism开发详解三:Visual studio 2017 RC初体验]中分享了Visual studio 2017RC的大致情况,同时也发现大家对新的Visual Studio很 ...
- SDWebImage源码解读 之 NSData+ImageContentType
第一篇 前言 从今天开始,我将开启一段源码解读的旅途了.在这里先暂时不透露具体解读的源码到底是哪些?因为也可能随着解读的进行会更改计划.但能够肯定的是,这一系列之中肯定会有Swift版本的代码. 说说 ...
- 深入node之Transform
Transform流特性 在开发中直接接触Transform流的情况不是很多,往往是使用相对成熟的模块或者封装的API来完成流的处理,最为特殊的莫过于through2模块和gulp流操作.那么,Tra ...
- 游戏AI系列内容 咋样才能做个有意思的AI呢
游戏AI系列内容 咋样才能做个有意思的AI呢 写在前面的话 怪物AI怎么才能做的比较有意思.其实这个命题有点大,我作为一个仅仅进入游戏行业两年接触怪物AI还不到一年的程序员来说,来谈这个话题,我想我是 ...
- 升级npm
查看npm的所有版本 运行命令: npm view npm versions 命令运行后,会输出到目前为止npm的所有版本. [ '1.1.25', '1.1.70', '1.1.71', '1.2. ...
- BPM配置故事之案例5-必填与水印文本
物资申请表改好了,但是没过两天老李又找来了. 老李:这个表格每次都是各个部门发给我们,再由我们采购部来填,太影响效率了,以后要让他们自己填. 小明:那就让他们填呗,他们有权限啊. 老李:可是他们说不会 ...
- Xcode 锁终端
锁终端 输入: <1>cd /Applications/Xcode.app 回车 结果显示: Xcode.app 输入: <2>sudo chown -hR root:whee ...
- transient关键字的用法
本篇博客转自 一直在路上 Java transient关键字使用小记 1. transient的作用及使用方法 我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,Java ...