亚马逊AWS官方博客

关于在 AWS 上运行 Apache Kafka 的最佳实践

Original URL:https://amazonaws-china.com/cn/blogs/big-data/best-practices-for-running-apache-kafka-on-aws/

 

注意: 本文的撰写时间早于Amazon MSK的上线日期。Amazon MSK是一项面向Apache Kafka的全托管、高可用性、高安全性服务。我们建议您直接使用Amazon MSK,而非在EC2实例中运行您自主管理的Apache Kafka集群。当然,如果您需要在EC2上运行Apache Kafka,那么本文提供的最佳实践与指导方针仍然适用。

——————————————-

本文是与Intuit公司合作撰写的特约文章,旨在分享在AWS上运行Apache Kafka集群的经验、最佳实践与建议。感谢Vaishak Suresh以及Intuit公司各位同事们的贡献与支持。

援引Intuit公司的自我评价:Intuit是一家领先的AWS企业客户,为市场提供各类业务与财务管理解决方案。关于Intuit公司与AWS合作的更多详细信息,请参阅我们之前发布的《在AWS上使用Apache Spark Streaming与Apache Kafka实现实时流处理》博文。Apache Kafka是一套开源分布式流平台,可帮助用户构建各类实时流式应用程序。

本文中提到的各项最佳实践,基于我们两年多以来在AWS上运行及操作大规模Kafka集群所积累到的经验心得。本文的目标在于帮助各位正在AWS上运行Kafka集群、以及正在考虑将本地Kafka部署迁移至AWS的客户找到更理想的实现途径。

AWS也提供Amazon Kinesis Data Streams,一项Kafka替代性全托管服务。

在Amazon EC2上运行Kafka部署能够带来一种高性能且可扩展性强的解决方案,高效实现流数据提取。AWS为Kafka部署提供多种不同的实例类型与存储选项组合,因此带来的部署拓扑也会非常的复杂与丰富,用户要找到最符合自身需求的配置也非常困难。

在本文中,我们将从以下几个方面探索在AWS上搭建与维护Kafka集群的诀窍:

  • 部署注意事项与模式选择
  • 存储选项
  • 实例类型
  • 网络
  • 升级
  • 性能调优
  • 监控
  • 安全性
  • 备份与恢复

注意:在生产环境中部署Kafka集群时,大家还需要考虑一系列重要因素,例如消息数量、消息大小、监控、故障处理以及其他运维问题。

部署注意事项与模式选择

在本节中,我们将探讨适用于AWS平台的各种Kafka部署选项,以及各个选项的优缺点。一套成功的部署方案必须考虑到这些具体选项,并在实际选择时充分考虑到可用性、一致性以及运维成本等因素。

单AWS区域、三可用区、全主动模式

一种典型的部署模式(全主动模式)是在单一AWS区域之内使用三个可用区。每个可用区内部署一套Kafka集群,同时附带Apache ZooKeeper与Kafka生产/消费实例,具体如下图所示。

在这种模式下,Kafka集群部署具有以下特征:

  • Kafka生产实例与Kafka集群部署在同一可用区内。
  • 使用Elastic Load Balancer将数据均匀分发至三个Kafka集群当中。
  • Kafka消费实例将来自三个Kafka集群的数据聚合起来。

Kafka集群的故障转移则通过以下方式实现:

  • 标记所有Kafka生产实例。
  • 停止消费实例。
  • 调度并重新堆叠Kafka。
  • 重启消费实例。
  • 重启Kafka生产实例。

下面来看这种模式的优势与缺点。

优势 缺点
  • 高可用性
  • 可承受两个可用区发生故障。
  • 故障转移期间不存在消息丢失。
  • 部署难度低。
  • 运维较高:
    • 所有变更都需要部署三次,每个Kafka集群部署一次。
    • 需要对三个Kafka集群进行维护与监控。
    • 需要对三个消费集群进行维护与监控。

必须重新启动才能修复并升级Kafka集群中的代理。在这种模式下,我们需要对各个集群分别进行滚动升级。

单一区域、三个可用区、主-备模式

另一种典型的部署模式(主-备)是在单一AWS区域内部署单一Kafka集群,而各Kafka broker及ZooKeeper则分布在三个可用区之间。另外建立一个类似的Kafka集群充当备用集群,详见下图。我们可以通过MirrorMaker使用Kafka镜像功能,借此在任意两个集群之间复制消息内容。

在这种模式下,Kafka集群部署将具有以下特征:

  • Kafka生产实例将被部署在全部三个可用区内。
  • 只有一个Kafka集群跨三个可用区进行部署(主动)。
  • ZooKeeper实例将被部署在所有可用区内。
  • 代理均匀分布在全部三个可用区内。
  • Kafka消费实例可跨全部三个可用区进行部署。
  • 部署体系内还包含备用Kafka生产实例以及一个多可用区Kafka集群。

Kafka集群的故障转移通过以下方式实现:

  • 将流量切换至备用Kafka生产集群与Kafka集群。
  • 重新启动消费实例以对接备用Kafka集群。
  • 下面来看这种模式的优势与缺点。对于0.10或更低的Kafka版本,我们需要额外分配主题副本,以便将各副本分配给不同可用区上的代理(机架感知)。
优势 缺点
  • 与第一种模式相比,运维成本更低。
  • 只需要一套Kafka集群即可实现数据的管理与消费。
  • 可以在不激活备用Kafka集群的前提下处理单可用区故障。
  • 由于需要在各Kafka broker之间进行跨可用区数据传输,因此延迟将相应增加。
  • 对于0.10或更低的Kafka版本,我们需要额外分配主题副本,以便将各副本分配给不同可用区上的broker(机架感知)。
  • 一旦出现网络故障(ZooKeeper无法识别Kafka代理),则集群可用性可能受到影响。
  • 故障转移期间,传输中的消息可能丢失。

Intuit公司建议在单一AWS区域内使用单一Kafka集群,并将broker分布在三个可用区(即单区域、三可用区模式)当中。这种模式拥有远超其他模式的容错能力,可用区故障亦不会导致Kafka停机。

存储选项

我们可以通过以下两种存储选项,在Amazon EC2中实现文件存储:

临时存储位于Amazon EC2实例之内。这种方式可以根据实例类型提供较高的IOPS。另一方面,Amazon EBS存储卷则拥有更高的弹性水平,用户可以根据存储需求对IOPS进行单独配置。EBS存储卷在恢复时间方面也拥有明显的优势。大家选择的存储方案在很大程度上由Kafka集群所支持的工作负载类型决定。

Kafka提供内置容错机制,可跨越多个实例(可配置具体数量)复制数据分区。一旦某个代理发生故障,用户可以从集群当中托管有其他副本的各代理处提取数据并实现恢复。取决于数据传输的实际大小,恢复过程与相关网络流量也有可能存在很大差别。这些反过来,又会最终影响到集群的整体性能。

下表对比了使用实例存储与使用EBS存储的具体优势。

实例存储 EBS
  • 对于中大型Kafka集群,建议大家使用实例存储。这是因为在规模较大的集群当中,读取/写入流量将分布在大量代理当中,因此单一代理丢失所产生的影响较小。但对于规模较小的集群,故障节点的快速恢复则变得非常重要。因此如果使用实例存储,则小型Kafka集群中恢复故障代理的时间周期将更长,且会造成更多的网络传输流量。
  • 对于h1、i3以及d2这样的存储优化型实例,特别适合充当Kafka这类分布式应用程序的存储方案。
  • 在Kafka部署中使用EBS的主要优势在于,一旦代理发生故障或者因其他原因而需要更换,EBS能够显著减少数据传输流量。替换用代理可以更快加入集群。
  • 当实例发生故障或终止时,存储在EBS上的数据将得到保留。存储在EBS存储卷上的代理数据将保持不变,用户能够将该EBS存储卷挂载至新的EC2实例之上。被替代的代理中的大部分复制数据已经被保存在EBS存储卷内,无需通过网络从其他代理处复制。只有初始代理发生故障时,后续变更才需要在网络上传输。这将显著加快代理的恢复速度。

Intuit公司之所以选择EBS,是因为其业务经常需要对实例进行重新调整部署,而且EBS还能够提供其他一些额外助益。

Kafka部署中通常使用的复制因子为3。考虑到EBS在其自身存储层也有多副本机制,因此Intuit选择的Kafka的复制因子为2(而非3)。

实例类型

实例类型的选择,通常由Kafka集群上流式应用程序所需要的存储类型决定。如果您的应用程序需要临时存储,那么h1、i3以及d2实例往往是大家的最佳选项。

Intuit公司使用r3.xlarge实例对应代理,r3.large对应ZooKeeper,并使用ST1(吞吐量优化型磁盘驱动器)EBS匹配Kafka集群。

下面来看Intuit测试中的基准示例配置:

配置 代理字节 (MB/s)
  • r3.xlarge
  • ST1 EBS
  • 12 brokers
  • 12分区
总计346.9

如果需要使用EBS存储,不妨考虑AWS提供的新型r4实例。相较于原有R3实例,此r4实例在以下方面有所提升:

  • 处理器速度更快(Boradwell架构)。
  • 默认对EBS进行优化。
  • 具有基于弹性网络适配器(ENA)的网络功能,能够在较低配置条件下实现10 Gbps传输速率。
  • 使用成本比R3实例低20%。

注意:最佳实践建议大家始终检查实例类型的最新变更

网络

对于Kafka这类分布式系统,网络无疑扮演着非常重要的角色。快速可靠的网络将保证各节点之间能够轻松通信,而可用的网络吞吐量上限则控制着Kafka能够处理的最大流量。网络吞吐量与磁盘存储通常是决定集群大小的主要因素。

如果大家希望集群能够接收高读取/写入流量,请选择提供10 Gb/s传输性能的实例类型。

此外,请通过选项保证代理间的网络流量保持在专用子网之内,这意味着客户端将能够接入各代理。代理与客户端之间的通信将使用相同的网络接口与端口。关于更多详细信息,请参阅EC2实例IP寻址说明文档

如果大家需要在一个以上的AWS区域内部署集群,则可使用跨区域VPC对等网络连接位于两个AWS区域内的两个VPC。但请注意,跨可用区部署场景会带来网络传输成本。

升级

Kafka在发展早期对向下兼容不够重视,但随着项目发展,其向下兼容性也做得越来越好。在Kafka升级期间,大家应该确保生产者与消费者客户端的版本等于或低于当前待升级版本。升级完成之后,大家即可开始使用新的协议版本及其支持的一切新功能。目前我们可以通过三种方式进行升级,下面具体展开讨论。

滚动升级或就地升级

在滚动或就地升级场景下,我们每次只对一个Kafka broker进行升级。这里推荐大家选择滚动重启方案以避免给最终用户带来停机影响。

停机升级

如果您可以接受停机,则可暂时关闭整个集群,升级各个Kafka broker而后重新启动集群。

蓝/绿升级

Intuit公司选择蓝/绿部署模式处理其工作负载,下面来看更多详细情况。

如果您能够构建起另一个独立的Kafka集群并对其进行升级,我们强烈建议您使用蓝/绿升级方案。在这种情况下,推荐大家使用最新Kafka版本以使集群保持最新。关于Kafka版本升级的更多详细信息,请参阅Kafka升级说明文档

下图所示,为蓝/绿升级模式的基本架构。

在这种情况下,升级的具体流程为:

  • 在AWS上创建一个新的Kafka集群。
  • 创建一个新的Kafka生产栈并指向新的Kafka集群。
  • 在新的Kafka集群上创建主题。
  • 端到端测试绿部署(合理性检查)。
  • 使用Amazon Route 53将AWS上的新Kafka生产栈指向之前创建的新绿Kafka环境。

回滚的具体流程为:

  • 使用Amazon Route 53将AWS上的旧Kafka生产线指向旧有Kafka环境。

关于使用Kafka蓝/绿部署架构的更多详细信息,请参阅re: Invent大会演示文稿《通过蓝/绿部署架构运用云资源》。

性能调优

大家可以在多个维度上实现Kafka的性能调优。下面来看部分性能优化最佳实践。

以下是部分常规性能调优方法:

  • 如果吞吐量低于网络容量,则尝试以下方法:
    • 添加更多线程
    • 添加批次大小
    • 添加更多生产实例
    • 添加更多分区
  • 要提高acks = -1时的延迟,请上调num.replica.fetches的值。
  • 对于跨可用区数据传输用例,请调整sockets与OS TCP的缓冲区设置。
  • 保证num.replica.fetches值大于Kafka专用磁盘的数量。
  • 根据生产者实例数量,消费者实例数量以及复制因子调整num.network.threads 的值。
  • 您的消息大小也会影响到网络传输带宽。要从Kafka集群中获得更高性能,请选择可提供10 Gb/s性能的实例类型。

要对Java及JVM进行性能调优,请尝试以下方法:

  • 使用Oracle JDK(使用新的G1垃圾优先收集器)最大程度减少GC暂停。
  • 尝试将Kafka堆大小保持在4 GB以下。

监控

我们需要随时了解Kafka集群在生产环境中是否保持正常运行。有时候我们只需要确保集群已经启动,但有时候还需要对Kafka应用程序中的诸多活动部分进行监控。接触过运维工作的朋友可能也有同感,我们往往很难准确分辨需要留意的重要内容与可以暂时搁置起来的内容。对项目的监控范围从总体流量到简单指标、再到生产者、消费者、代理、控制器、ZooKeeper、主题、分区乃至消息等等,可谓无所不包。

为了进行监控,Intuit公司使用到多种工具,包括Newrelec、Wavefront、Amazon CloudWatch以及AWS CloudTrail。我们建议大家使用以下监控方案。

在系统指标方面,我们建议监控以下几项:

  • CPU 负载
  • 网络指标
  • 文件句柄使用量
  • 磁盘空间
  • 磁盘I/O性能
  • 垃圾收集
  • ZooKeeper

在生产者方面,我们建议监控以下几项:

  • Batch-size-avg
  • Compression-rate-avg
  • Waiting-threads
  • Buffer-available-bytes
  • Record-queue-time-max
  • Record-send-rate
  • Records-per-request-avg

在消费者方面,我们建议监控以下几项:

  • Batch-size-avg
  • Compression-rate-avg
  • Waiting-threads
  • Buffer-available-bytes
  • Record-queue-time-max
  • Record-send-rate
  • Records-per-request-avg

安全性

与大多数分布式系统一样,Kafka也在各相关组件之间提供较为安全的数据传输机制。根据您的具体设置,安全性要素可能涵盖不同的服务,例如加密、Kerberos、传输层安全(TLS)证书以及高级访问控制列表(ACL)设置等。下文将详细介绍Intuit公司采取的方法。关于本节未提及的更多Kafka安全详细信息,请参阅Kafka说明文档

静态加密

对于采用EBS的EC2实例,大家可以使用启用加密功能的Amazon EBS存储卷实现静态数据加密。Amazon EBS使用AWS Key Management Service (AWS KMS) 实现加密功能。关于更多详细信息,请参阅EBS说明文档中的Amazon EBS加密。对于采用实例存储的EC2实例,大家可以使用Amazon EC2实例存储加密实现静态数据加密

传输加密

Kafka使用TLS对各客户端与节点间通信进行加密。

身份验证

由客户端(生产实例与消费实例)指向各代理以及各代理间的连接使用安全套接字层(SSL)或简单身份验证与安全层(SASL)实现身份验证。

Kafka支持Kerberos身份验证。如果您已经拥有Kerberos服务器,则可将Kafka添加至现有配置当中。

授权

在Kafka中,我们可以进行插入式授权,并与外部授权服务进行集成。

备份与恢复

我们在部署中使用的具体存储类型,决定了备份与恢复的实际策略。

在使用实例存储时,备份Kafka集群的最佳方法是设置另一个集群并使用MirrorMaker进行消息复制。Kafka的镜像功能可帮助用户轻松为现有Kafka集群维护一套副本。根据具体设置及要求,您的备份集群可以与主集群位于同一AWS区域之内,也可以位于其他集群当中。

对基于EBS的部署,大家可以启用EBS存储卷的自动快照功能以实现存储卷备份。我们可以利用这些快照轻松创建新的EBS存储卷以进行恢复。我们建议将备份文件存储在Amazon S3当中。

关于如何在Kafka中实现备份的更多详细信息,请参阅Kafka说明文档

总结

在本文中,我们将讨论了在AWS云中运行Kafka的几种常见模式。AWS还提供另一种托管解决方案,即 Amazon Kinesis Data Streams。该方案无需为服务器的管理或扩展而分神,大家可以在几秒钟之内扩展流式管道规模且无任何停机,跨可用区数据复制将自动执行,以开箱即用的方式享受良好的安全保障,Kinesis Data Stream与Lambda、Redshift、Elasticsearch等多种AWS服务以及Storm、Spark、Flink等开源框架紧密集成。大家还可以参考kafka-kinesis连接器的相关信息

如果大家有任何问题或建议,请在评论区中与我们交流。

扩展阅读

如果本文对您有所帮助,也建议大家参阅使用Amazon Kinesis Analytics实现无服务器日志分析以及使用Amazon Kinesis Analytics进行实时点击流异常检测

本篇作者

Prasad Alle

Prasad Alle 是 AWS 专业服务部的高级大数据顾问。他在领导和构建适合于 AWS 企业和战略客户的可扩展且可靠的大数据、机器学习、人工智能和物联网解决方案上投入了大量时间。他还对各种不同技术非常感兴趣,例如高级边缘计算、在边缘站点的机器学习等。在他的空余时间,他喜欢阅读和与家人在一起。