Kubernetes容器资源要求-第1部分:内存

了解请求,限制

Kubernetes容器资源要求-第1部分:内存

为了让Kubernetes(K8)可靠地分配您的组件运行所需的资源并充分利用其所在的基础架构,您应该指定容器资源要求。 当前,您可以为两种类型的容器资源(内存和CPU)指定两种类型的需求,请求和限制。 本文旨在解释这两种需求的含义以及Docker容器运行时内存的含义。

内存的意义

内存在这里到底是什么意思? 简而言之,它是容器的总驻留集大小(RSS)和页面缓存使用情况。 在纯Docker中,该数字通常包含交换,但是K8会永久代表您禁用交换。

RSS是进程在任何给定时间使用的RAM数量。 对于Java进程,这可以包括多个区域,包括本机堆/非堆区域,线程堆栈和本机内存分配。 RSS受JVM线程配置,线程数和组件行为的影响。

页缓存是用于从磁盘缓存块的RAM区域。 出于性能原因,所有I / O通常都通过此缓存执行。 每当您的组件从文件中读取或写入文件时,都可以期望将相关的块缓存在此处。 您读取或写入的文件越多,要求就越高。 请注意,内核会将可用的备用内存用于页面缓存,但是如果其他地方需要,它将回收它-这意味着如果没有足够的空间,组件的性能可能会受到影响(取决于其对页面缓存的性能依赖)。 这里有一个潜在的难题-Docker的overlayfs存储驱动程序启用页面缓存共享,这意味着访问同一文件的同一节点上的多个容器共享该文件的相同页面缓存条目(例如索引或其他共享的内容)。 Docker文档指出:

计算页面缓存中的内存非常复杂。 如果不同控制组中的两个进程都读取同一文件(最终依赖于磁盘上的相同块),则将在控制组之间分配相应的内存费用。 很好,但这也意味着当一个cgroup终止时,它可能会增加另一个cgroup的内存使用量,因为它们不再为这些内存页面分配费用了。

…因此请注意,每个容器的页面缓存使用情况可能会有所不同,具体取决于与同一节点上运行的其他容器共享哪些文件。

内存请求和限制以字节为单位,但是您可以指定多个后缀。 JVM内存配置使用二进制前缀来表示(例如Xmx1g为1024³字节),因此使用等效的K8s后缀(Gi)作为容器规范的基础是有意义的。

请求与限制

定义Pod时,可以为其容器指定两个类别的内存和CPU要求-请求和限制:

<code>

resources

:

requests

:

memory

:

"8Gi"

cpu

:

"4"

limits

:

memory

:

"8Gi"

cpu

:

"4"

/<code>

请求是K8s的概念,用于在底层基础架构中调度容器:"将容器的容器放置在有足够资源容纳它们的地方"。 限制是可用于容器的资源的硬性上限,这些资源会传播到基础容器运行时,我们在这里假设Docker。 超出限制会导致节流,或者在最坏的情况下会导致容器终止。

您可能会问是否有理由将限制设置为高于要求。 如果您的组件具有稳定的内存占用空间,则可能不应该这样做,因为当容器超出其请求时,如果工作节点遇到内存不足的情况,则很可能将其驱逐。 对于CPU,如果请求和限制之间没有其他容器正在使用的资源,则可以适当地清除请求和限制之间的其他资源。 Burstable QoS类(请参阅下文)允许潜在地更有效地利用基础资源,但具有更大的不可预测性-例如,与CPU绑定的组件的延迟可能会受到同一工作节点上其他容器的瞬时共置的影响。 如果您不熟悉K8,最好通过设置与请求相同的限制来从"保证的QoS"类入手。

如果省略了对容器的请求,则默认为限制。 如果未设置限制,则默认为0(无界)。

根据请求的存在/配置和限制(从此处开始)采用QoS类:

如果为所有容器中的所有资源设置了限制和可选的请求(不等于0)并且它们相等,则将容器分类为保证。 这些容器被认为是优先级最高的容器,并保证在它们超过其限制之前或者系统处于内存压力下并且没有可以撤出的优先级较低的容器时才被杀死。

如果为一个或多个容器中的一个或多个资源设置了请求和可选的限制(不等于0),但请求和限制不相等,则将pod划分为Burstable。 如果未指定限制,则默认为节点容量。 这些Pod具有某种形式的最小资源保证,但是在可用时可以使用更多资源。 在系统内存压力下,一旦这些容器超出了它们的请求,并且不存在尽力而为的容器,它们很可能被杀死。

如果未针对所有容器的所有资源设置请求和限制,则该容器被分类为"尽力而为"。 这些Pod将被视为最低优先级。 如果系统内存不足,这些Pod中的进程将首先被杀死。 这些容器可以在节点中使用任何数量的可用内存。

内存限制?

内存限制在K8s看来被认为是不可压缩的,这意味着它不能被限制。 如果您的容器遇到内存压力,内核将积极删除页面缓存条目以满足需求,并且最终可能会被Linux内存不足(OOM)杀手杀死。 由于K8s禁用了交换功能(通过将memory-swappiness = 0传递给Docker),因此对于错误配置而言,这是一个非常宽容的环境。

您应凭经验确定组件的内存要求,以创建良好的配置; 如果您的组件依赖于良好的页面缓存效率,请通过容器的资源要求留出适当的开销。 当然,情况会发生变化,您的组件内存需求将始终如一地-将内存统计信息进行监视和警报作为正常操作功能的一部分。


(本文翻译自Will Tomlin的文章《Kubernetes Container Resource Requirements — Part 1: Memory》,参考:
https://medium.com/expedia-group-tech/kubernetes-container-resource-requirements-part-1-memory-a9fbe02c8a5f)


分享到:


相關文章: