作者: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.2159.64.11.2259.64.11.23。Kafka组件部署完成后,使用Kafka producer连接Server,配置的kafka bootstrap_servers59.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.nameadvertised.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时,由于具体的实现不一样,可能会出现报错的情况。

参考资料:

Kafka in a nutshell


如果您看了本篇博客,觉得对您有所收获,请点击右下角的“推荐”,让更多人看到!

资助Jack47写作,打赏一个鸡蛋灌饼吧
微信打赏
支付宝打赏

基于Kubernetes在AWS上部署Kafka时遇到的一些问题的更多相关文章

  1. 解读与部署(三):基于 Kubernetes 的微服务部署即代码

    在基于 Kubernetes 的基础设施即代码一文中,我概要地介绍了基于 Kubernetes 的 .NET Core 微服务和 CI/CD 动手实践工作坊使用的基础设施是如何使用代码描述的,以及它的 ...

  2. 在Kubernetes上部署应用时我们常忽略的几件事

    根据我的经验,大多数人(使用Helm或手动yaml)将应用程序部署到Kubernetes上,然后认为他们就可以一直稳定运行. 然而并非如此,实际使用过程还是遇到了一些"陷阱",我希 ...

  3. 关于在eclipse上部署Tomcat时出现8080等端口被占用问题的解决方法

    问题描述: 在eclipse中部署Tomcat时,出现如下错误. 解决方法如下: 方法一: 1.开始->cmd->输入命令netstat -ano出现下图所示(注意下边显示有些错位,最后一 ...

  4. 在ubuntu18.04上部署项目时遇到的问题总结

    因为在实验室中,有几台空闲的机子,我便选了一台准备做一个本地的服务器,因为买的阿里云学生机和之前用于FQ的机子感觉都不太顺手,阿里的学生机配置稍低,FQ用的服务器延迟太高.开始在centos和ubun ...

  5. 在ubuntu上部署hadoop时出现的问题

    1. 配置ssh登录 不须要改动/etc/ssh/sshd_config 2. 新建hadoop用户时,home以下没有hadoop文件夹 用以下命令创建 useradd -m hadoop 3. n ...

  6. 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 ...

  7. 在AWS中部署OpenShift平台

    OpenShift是RedHat出品的PAAS平台.OpenShift做为PAAS平台最大的特点是它是完全容器化的PAAS平台,底层封装了Docker和Kubernetes,上层暴露了对开发者友好的接 ...

  8. Kafka实战(七) - 优雅地部署 Kafka 集群

    既然是集群,必然有多个Kafka节点,只有单节点构成的Kafka伪集群只能用于日常测试,不可能满足线上生产需求. 真正的线上环境需要考量各种因素,结合自身的业务需求而制定.看一些考虑因素(以下顺序,可 ...

  9. Win10上部署Apollo配置中心

    基于Docker在Win10上部署Apollo配置中心 https://www.jianshu.com/p/a1215056ce75 http://nobodyiam.com/2016/07/09/i ...

随机推荐

  1. jQuery学习之路(8)- 表单验证插件-Validation

    ▓▓▓▓▓▓ 大致介绍 jQuery Validate 插件为表单提供了强大的验证功能,让客户端表单验证变得更简单,同时提供了大量的定制选项,满足应用程序各种需求.该插件捆绑了一套有用的验证方法,包括 ...

  2. 从零开始编写自己的C#框架(27)——什么是开发框架

    前言 做为一个程序员,在开发的过程中会发现,有框架同无框架,做起事来是完全不同的概念,关系到开发的效率.程序的健壮.性能.团队协作.后续功能维护.扩展......等方方面面的事情.很多朋友在学习搭建自 ...

  3. 流程开发Activiti 与SpringMVC整合实例

    流程(Activiti) 流程是完成一系列有序动作的概述.每一个节点动作的结果将对后面的具体操作步骤产生影响.信息化系统中流程的功能完全等同于纸上办公的层级审批,尤其在oa系统中各类电子流提现较为明显 ...

  4. C++随笔:.NET CoreCLR之GC探索(4)

    今天继续来 带大家讲解CoreCLR之GC,首先我们继续看这个GCSample,这篇文章是上一篇文章的继续,如果有不清楚的,还请翻到我写的上一篇随笔.下面我们继续: // Initialize fre ...

  5. 修改session垃圾回收几率

    <?php //修改session垃圾回收几率 ini_set('session.gc_probability','1'); ini_set('session.gc_divisor','2'); ...

  6. interpreter(解释器模式)

    一.引子 其实没有什么好的例子引入解释器模式,因为它描述了如何构成一个简单的语言解释器,主要应用在使用面向对象语言开发编译器中:在实际应用中,我们可能很少碰到去构造一个语言的文法的情况. 虽然你几乎用 ...

  7. Dropzone.js实现文件拖拽上传

    dropzone.js是一个开源的JavaScript库,提供 AJAX 异步文件上传功能,支持拖拽文件.支持最大文件大小.支持设置文件类型.支持预览上传结果,不依赖jQuery库. 使用Dropzo ...

  8. BPM配置故事之案例3-参与者与数据自动加载

    这才过了两天,阿海又来了. 阿海:公司决定改进管理方式,以后物资申请的申请人和申请部门要写具体使用人的名字和部门了. 小明:不是要让我改回去吧? 阿海:那太麻烦了,你能不能把申请人改成选择,选好人自动 ...

  9. Apache Cordova开发Android应用程序——番外篇

    很多天之前就安装了visual studio community 2015,今天闲着么事想试一下Apache Cordova,用它来开发跨平台App.在这之前需要配置N多东西,这里找到了一篇MS官方文 ...

  10. Linux监控工具介绍系列——vmstat

      说来惭愧,玩Linux这么久了,居然没有玩转vmstat这个命令,对很多指标的具体意义都有点模糊不清,花了点时间好好学习.整理一下这个命令的相关资料.因为这个命令确实比较重要,而且频繁用到. 命令 ...