在 Kubernetes 中运行 Kafka 时如何管理页面缓存资源

Posted

技术标签:

【中文标题】在 Kubernetes 中运行 Kafka 时如何管理页面缓存资源【英文标题】:How to manage page cache resources when running Kafka in Kubernetes 【发布时间】:2018-07-14 13:35:01 【问题描述】:

我在 Kubernetes 上运行 Kafka 已经有一段时间了,没有出现任何重大问题;然而,我最近引入了一组 Cassandra pod,并开始遇到 Kafka 的性能问题。

尽管 Cassandra 不像 Kafka 那样使用页面缓存,但它确实会频繁写入磁盘,这可能会影响内核的底层缓存。

我了解 Kubernetes pod 是通过 cgroups 管理内存资源的,这可以通过在 Kubernetes 中设置内存请求和限制来进行配置,但我注意到 Cassandra 对页面缓存的利用会增加我的 Kafka pod 中的页面错误数量即使它们似乎没有竞争资源(即,它们的节点上有可用内存)。

在 Kafka 中,更多的页面错误会导致更多的磁盘写入,这会阻碍顺序 IO 的优势并损害磁盘性能。如果您使用 AWS 的 EBS 卷之类的东西,这最终会耗尽您的突增余额并最终导致整个集群发生灾难性故障。

我的问题是,是否可以在 Kubernetes 中隔离页面缓存资源,或者以某种方式让内核知道我的 Kafka pod 拥有的页面应该比我的 Cassandra pod 中的页面保留在缓存中的时间更长?

【问题讨论】:

撇开 k8s 不谈,我看不出问题中描述的那种精确的隔离可以通过编程或配置来合理地完成,是吗? mlock + mmap 将在 RAM 中保留不需要的页面。 Cgroups 可以限制这两个应用程序,但这真的不是人们想要的。将应用程序指向它们自己的 I/O 资源并不能缓解主机争用。通常一个人不会在单个主机上运行两个 i/O 饥饿服务。您可以使用污点将它们隔离到不同的节点组吗? 我现在正在使用 k8s 反关联规则将它们分开,但它似乎有限制。如果您确信没有办法做到这一点,请写一个详细说明原因的答案,我会奖励您。 【参考方案1】:

我认为这是一个有趣的问题,所以这是一些挖掘的结果。

最佳猜测:k8s OOB 无法做到这一点,但有足够的工具可用,因此它可能是研究和开发可部署为 DaemonSet 的调优和策略应用程序的富有成果的领域。

调查结果:

应用程序可以使用 fadvise() 系统调用向内核提供有关应用程序需要哪些文件支持的页面以及哪些不需要并且可以回收的指导。

http://man7.org/linux/man-pages/man2/posix_fadvise.2.html

应用程序也可以使用 O_DIRECT 来尝试在做 IO 时避免使用页面缓存:

https://lwn.net/Articles/457667/

有迹象表明 Cassandra 已经在尝试优化以减少其页面缓存占用空间的方式使用 fadvise:

http://grokbase.com/t/cassandra/commits/122qha309v/jira-created-cassandra-3948-sequentialwriter-doesnt-fsync-before-posix-fadvise

三星最近(2017 年 1 月)也进行了一些研究,在内核中修补 Cassandra 和 fadvise,以更好地利用多流 SSD:

http://www.samsung.com/us/labs/pdfs/collateral/Multi-stream_Cassandra_Whitepaper_Final.pdf

Kafka 支持页面缓存架构,尽管它似乎没有直接使用 fadvise。内核中可用的旋钮足以在专用主机上调整 Kafka:

vm.dirty* 获取有关何时将写入(脏)页返回磁盘的指导 vm.vfs_cache_pressure 获取有关如何积极地使用 RAM 进行页面缓存的指导

内核中对特定于设备的写回线程的支持可以追溯到 2.6 天:

https://www.thomas-krenn.com/en/wiki/Linux_Page_Cache_Basics

Cgroups v1 和 v2 专注于基于 pid 的 IO 节流,而不是基于文件的缓存调整:

https://andrestc.com/post/cgroups-io/

也就是说,旧的 linux-ftools 实用程序集有一个简单的命令行旋钮示例,用于在特定文件上使用 fadvise:

https://github.com/david415/linux-ftools

所以那里已经足够了。给定特定的 kafka 和 cassandra 工作负载(例如,重读与重写)、特定优先级(kafka 优于 cassandra,反之亦然)和特定 IO 配置(专用与共享设备),可能会出现特定的调优模型,而那些可能推广到政策模型中。

【讨论】:

谢谢,这是一个非常好的答案。我正在寻找关于 k8s 建议的通用页面缓存,它非常有帮助。

以上是关于在 Kubernetes 中运行 Kafka 时如何管理页面缓存资源的主要内容,如果未能解决你的问题,请参考以下文章

远程访问运行在 kubernetes 中的 Kafka

一旦在 Kubernetes/Minikube 中,Kafka 就无法访问

这是在 Kubernetes 上运行 Kafka 的好方法吗?

Kubernetes 集群中的 Kafka - 如何从 Kubernetes 集群外部发布/使用消息

如何为在 kubernetes 集群上运行的 Kafka Connect 配置 MongoDB 官方源连接器

使用 Kafka Avro Console Consumer 时如何为特定的 Schema 注册表传递参数?