白瑜庆:知乎基于Kubernetes的kafka平台的设计和实现

1,686 阅读14分钟

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~

  本文首发在云+社区,未经许可,不得转载。

自我介绍

我是知乎的技术中台工程师,现在是负责知乎的存储相关组件。我的分享主要基于三个,一个是简单介绍一下Kafka在知乎是的应用,另外一个是为什么做基于Kubernetes的Kafka平台,还有我们如何去实现了基于Kubernetes平台

Kafka在知乎的应用

Kafka一个是非常优秀的,消息或者是数据流的组件,在知乎承载了日志,数据收集,消息队列的服务日志,显而易见就包括业务,包括运行的DEBUG日志关键性日志。

数据传输,比如我们在浏览知乎的时候,有些用户行为或者内容特征,通过我们这个平台做数据的流失处理。

另外一个是Kafka实现对消息服务。简单地,就是我关注的A用户,我是不是应该基于关注用户行为上做很多事情,这是一个消息队列的服务。我们那个平台现在是部署超过有40个Kafka集群,这些集群都是独立的。另外上面有超过一千个topic,我们的Broker数有超过有两千个Kafka。平台从上线到现在已经运行有两年了,承载的数据量都是百TB级的,我们现在这个设计是Kafka集群,我们要实现多集群。因为是对于公司内部的平台,我们要保证高可用,平台架构底层其实是广大Broker管理员,上层是抽象出来的。Kafka的集群对业务其实也无感,。另外就是一个管理平台管理,我创建topic,去创建分区,或者做故障处理。第一,上层只可能有管理平台和客户端是对R业务有感,客户端我们要对客户端进行收敛,有一个客户端是原生支持的——Java。不同客端会有不同的表现,现在我们需要去收敛这个词,

为什么采用Kubernetes?

因为我们遇到的问题在早期的时候,知乎的Kafka是一个单集群,在大家使用率不高,或者在数据量增长不爆炸的时候,单集群大家用得还OK时有天发现有一个Broker挂了,等到大家都挂了,这时候才发现其实是一条路是不可以常走的。因此我们觉得我们认为集群和大型社科系统单点,大家会依赖集权,不管任何的业务,我写日志也好,发消息也好,或者我去做数据传输也好,这是不可以的。对于Kafka来,我们有一个开发,有各国的Top的概念,其实发生到业务来,每个topic都代表了不同的一个业务的场景,我们觉得对业务场景在内部要做分级,比如我重要的数据,我要做分析,我们的业务与Kafka的深耦合。当我先做了规划,去梳理一下发现为什么我会这么多,它topic为什么集中挂掉之后有人还没事,还非常的愤怒,觉得简单就是天灾。

那时候我们发现,其实我们的日志里面topic有很多类型,抽样出来,一种是日志,一种是数据和消息。数据,比如在做一个离线计算的时候,收集了用户数据或者我在APP里有埋点,这些数据可以通过开发管道或者spa或者我们的计算任务。另外一个是消息刚才也提到,比如我用户去做了一次关注或者点赞,触发后面一系列处理流程,很显然看出他们其实是有分级的。我们要把Kafka集群在内部要做成多集群的方式,然而根据我们套配合做出划分。

同类型的topic做不同集群的管理和配置。其实最简单的法是Kafka有分片,我们是做高可用,日志的分片可以少。消息容量是小的,对于数据大家都做,比如用Kafka做数据分析,肯定知道在离线技术,在数据分析时候看一下数据量是跟在线的时候应该是千倍万倍的这种关系,那就会出现一个问题——我们去规划一个设计就去实施的,最后结果我们的需求会变的非常多,比如一个A业务,我认为非常的重要,去做一个但是承载了一个,我每天有几百几十T的数据,那我是不是可以申请一个新的Broker。新的集群,别人不要跟我掺到一起,我提供的是基础数据,这样的话我们遇到问题是集群会越来越多,事实上现在很多已经是超过四十亿四十个了。服务器资源怎么去使用?因为早期部署的时候肯定单机部署,但又不是,比如我有一个普通的,比如我做了一个G,承载的数量有四个T,这样的话我部署一个消息任务是不是有点浪费?那不数数任务它是有点就太太小,其实我们提供一个提高资源利用率,希望从单机上部署更多的Broker,并且能够做到它们之间的相互的影响降到最低。实际上在我们实验实践中,磁盘其实是Kafka一个绕不开的问题

首先磁盘不可以做数据持久化,但是我们遇到了很多的问题,有量突增的或者流量大的时候,磁盘首先容量会有问题,比如我有申请了1T的磁盘,那可能我现在写一天给我写两天就已经写到了3T。

另外一个问题就是磁盘的LUTOC其实IOPS过高这种问题出现的话,开发的性能是有很大的下降的。既然Broker可以做到多部署,那我们就在磁盘层面上做隔离,先在保证这种不要互相影响,就是比如数据和消息,Broker在磁盘这个层面要做好,做到互相不影响,因此我们想到的方法就是磁盘是不是可以分开,在物理层面就分开,并且开它本身又有副本。

这种物理存在分开是可以接受的,而且如果出现故障,完全是在可控范围之内的,而是可期的。因此我觉得把分开,我们当时选服务器,正好黑石这边也提供了一种叫高性能的服务器,其实非常满足我们需求,它有12个高性能的磁盘,是单盘的,他不做瑞的,每个盘就是容量还不小。它的CPU和内存上面其实有优势的,因为Kafka是对内存是有要求的,比如走的文件缓存,内存是满足我需求的CPU,现在英特尔的CPU性能还蛮。我们就采用了黑色这款高性能服务器,现在我们的平台都主要部署在这种服务器。底层的服务器想好了,资源划分想好了,就是怎么去管理它?

我们先讲一个有意思的,我们平台之前有一个开发的管理平台是自写自演的,实现了部署Broker,包括渲染配置,去做迁移的,这个平台比较私有,而且在运维上面或者管理上面不是很方便,而且观众很高兴来同事都要从代码层面学习,从那一套我们的平台学习影响,或者是有一个更好的方案来去解决。如果激情数增加到了保证的不可数增加,并且是服务器如果坏掉了,你看我们如何感染管理他,调度的时候我们如何去考虑到按照磁盘这个维度做调度。因此我们想到QQ那铁丝,因为之前我们有很多的一个在容器化方面的实践,早期在开发上QQ来此之前其实知乎在ks上部署了很多计算任务,在这上面有很多积累,所以我们想利用它的管理功能和容器的技术进行资源管理。另外一个是应用程序管理。

Kafka on Kubernetes

首先解决问题设计Kafka容器,无非就是四个问题——内存,CPU,网络和存储。另外一个问题是我们怎么实现具体调度Kafka容器

首先是内存和CPU。其实CPU是比较难以预估的,因为根据咨询类型不同,对于内存和CPU消耗是不同的,Kafka本身是不强,依赖于CPU。但是在实际使用中还是有些问题的,比如咱们Kafka不是做批量,但很多时候有时候大家对它比较理解得透的时候,会把批量会得很小,比如我降低延迟,要保证每一条消息都确切的投放过去,把Brokers收得很小,这时候会造成一个什么问题?CPU会高,但是很这种问题我们可以通过调高CPU来解决。如果不出现这种大流量的话,一般内存是不会超过八个G的,而且一般使用会更低,所以我们的基准的容器会设置成8G根据实际使用时间长,经常会做调整,这个调整可以在IT市场很容易改。

另外网络方面就是我们对外服务,采用的是一种独立的内网ip方式,比如我每一个Broker都有一个独立的ip,实际上因为我们的单机上会部署很多容器,所以每个都有IP,并且将这个ip注册在内网DNS上面,这样照好处是对于使用者来说,不需要知道具体容器的ip。这个是网络又有一个很好的方式——可以做单机的多ip网络设计,至少可以满足我们的需求,这是容器方面的设计。默认支持的磁盘的挂载方式是HostParh Volume,这种方式是最优的,因为Kafka在本地磁盘性能最好的,而且能够充分利用到本地的这种高效的文件缓存,我们本身的磁盘性能也是非常棒的,至少我可以满足我的需求。

因此我们就应该是本地的目录一个cosplay,也就到K2起来之后是给他的,请求的配置挂载到服务器的磁盘,黑色框是我们的一个容器,开发目录指向的蓝色框是服务器上的一个磁盘或者服务器上的目录。虽然我们的集群看来就是这个样子的,每一个方块代表网上有很多的部署的Broker。业务上面可以反过来看,每个蓝色的地方代表Broker。

第一,CPU和内存并不是问题,网络其实已过测试过的,服务器网络是二世纪的20G带宽,每个盘我们经过测试,是有一点几个G性能,即便把每个盘所有人都跑满,其实这是灾难情况,他只有不会超过20个G,因此我们不在考虑范围之内,我们考虑的是磁盘的高可用目标,让单个集群的Broker在节点要尽量做到分散

第二是节点上的存储使用尽量均匀

算法是根据服务器磁盘状态计算分数,分数高者被调度。另外就是磁盘的使用情况,如果有更多的可用盘,我们倾向于把Broker挂在了上面。其实它用了一个简单的方式,假设创建一个红色集群,实际上A和C都可以,但C是最优的,因为C上面的Broker数比较少。如果要创建一个蓝色集群,那显然是A是最优的。另外,在实际使用情况下要更复杂,因为得考虑到分片的高可用。按照算法去实现会遇到了一个实际性的问题——用HostPat是有很大局限性,一致性不好,比如需要去管理要调度的节点,因为如果用class的话需要去注册一个本身选择的word,或者其实我是不知道被调到哪个节点上。另外主机上要去挂载的目录其实是没有人管理的。这是我们遇到的问题,当时我们希望是既要利用到HostPath,只有挂在本地的磁盘这种特性来提高我们的性能管理。

而且我要能够选出合理节点,并且能够管理到这个存储。因此我们在当时对Kubernetes做改造,实现磁盘和调度器的算法,可以实现实时更新磁盘信息。但是实现方式是通过假设创建实例.

本地磁盘管理

如果Broker已经在设备上建立起来,磁盘也被用了,那如何去管理它?事实上磁盘管理只能进入第三方的Agent。

故障处理和提升资源利用时会预留空间,比如为了快速处理故障不做签署,首先就是成本太高,现在做的是快速恢复,因此我们会预留1到2个盘,即快速处理盘,因此只要把软件指向这个容器,就可以马上启用,并且不会有太大的网络开销。另外就是在主机层面,即把分片在主机层面是做分开,做到高可用。

但我们遇到一个问题——需要把客户端统一,因为技术平台化。那如何把客户端做到统一?我们的看这里,客户端可以去读Consul信息,检查topic是不是有用。还有个好处是,如果做迁移的时候,因为事情使了很多方,生产和消费方式是很多的,而且一般流程是先于生产方,消费方就过来,大家可能有业务,可能大家如果按照这种注册方式的话,其实迁移过程是可以同步的。在这个地方更改信息,整个这个生产所生产的消费,都可以感受到,就是另外就是易用性会提高。且用这种方式有好处是有一个集群比如我整个集群全部断掉了,虽然事没发生过,但是作为一个备用的方式的话,我们会有一个灾备集群把所有的客户端都可以直接迁移过去。

Q/A

Q: 你好,麻烦问一下,一个集群里面可能有很多topic,不同的用户消费topic的时候,用户之间是怎么隔离的?会不会消费到其他的topic数据?想问一下有没有什么隔离的好的办法?你一个集群里有多少套?集群里有多个topic,数据我就不想让别人看到吗?当然我如果提供一个客户端给他,他就能把所有的数据看得到,有没有什么好的办法?

A:其实是这样的,就是在我们的一个情况称,如果这个进群它有多少Broker,假如在这个会相互影响,我们还是建议把它不是相互影响,因为集群面不可能只给一个用户只提供一个集群,就是我们一个大的集群,会有很多用户在使用他的数据,都是不同的topic进来的吗?他消费的时候如果我没有隔离的话,我只要给他客户端,它所有的数据都看得到吗?只能通过我在前面去做提供什么API服务来这种方式,有没有?Kafka本身有没有什么好的办法去本身应该是有认证。 

了解更多详情,请戳下面的链接:

知乎基于Kubernetes的Kafka平台的设计和实现.pdf


问答
apache kafka vs apache storm如何使用?
相关阅读
陈新宇:CKafka在人脸识别PASS中的应用
杨原:腾讯云Kafka自动化运营实践
饶军:Apache Kafka的过去,现在,和未来


此文已由作者授权腾讯云+社区发布,原文链接:https://cloud.tencent.com/developer/article/1114620?fromSource=waitui