Kubernetes v1.37:内存 QoS 升级至 Beta

Kubernetes v1.37 的 Memory QoS 晋升 Beta 并默认启用,但 memoryThrottlingFactor 默认改为 null,升级不会改变现有集群行为。

中文
复制

Memory QoS 已在 Kubernetes v1.37 中晋升为 Beta,并默认启用。在运行 cgroup v2 的 Linux 节点上,该特性借助内存控制器,让内核能更好地判断该如何对待容器内存。它最早在 v1.22 以 Alpha 形式引入,并在 v1.36 中通过分层内存预留得到扩展。

本文介绍 v1.37 中的变化、Beta 晋升对集群运维人员意味着什么,以及如何配置该特性。

v1.37 中的变化

Memory QoS 进入 Beta 并默认启用

MemoryQoS 特性门控在 v1.37 中已进入 Beta。这意味着每个 v1.37 kubelet 无需任何配置改动就已开启该特性门控。默认开启是安全的,因为默认的 kubelet 配置不会启用内存限流或内存预留。除非你显式配置,否则不会向 cgroup 写入任何 memory.highmemory.minmemory.low 值。

你可以通过 kubelet 配置字段选择启用特定行为:

  1. 设置 memoryThrottlingFactor(例如 0.9)以对 Burstable 和 BestEffort 容器启用 memory.high 限流。默认值为 null,即不限流。
  2. memoryReservationPolicy 设为 TieredReservation,通过 memory.minmemory.low 启用分层内存保护。默认值为 None,即不做内存预留。

默认 memoryThrottlingFactor 改为 null

在更早的 Alpha 版本中,memoryThrottlingFactor 默认为 0.9,也就是说只要开启特性门控,kubelet 就会在容器上设置 memory.high。在 v1.37 中,默认值变为 null,因此除非你配置了取值,kubelet 不会设置 memory.high

做出这一改动的原因是:特性门控如今默认开启,自动设置 memory.high 可能会让原本不限流的工作负载被限流。将其设为 null 可确保升级到 v1.37 不会改变现有集群的运行时行为。

如果你的 kubelet 配置文件中已经显式包含 memoryThrottlingFactor 值,该值会在升级过程中保留,限流也照常生效。如果配置文件中没有 memoryThrottlingFactorkubelet 会采用新的 null 默认值,不再设置 memory.high。这种情况下若要保留限流,请显式添加 memoryThrottlingFactor

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
memoryThrottlingFactor: 0.9

如何在 v1.37 中配置 MemoryQoS

有关配置 Memory QoS 的完整细节,请参阅 Memory QoS with cgroup v2Configuring memory reservationSystem requirements

仅启用内存限流

memoryThrottlingFactor 设为 0 到 1 之间的值。kubelet 会用这个系数为 Burstable 和 BestEffort 容器计算 memory.high。各 QoS 等级下 memory.high 的计算方式见 Memory throttling

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
memoryThrottlingFactor: 0.9

同时启用内存限流和分级预留

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
memoryThrottlingFactor: 0.9
memoryReservationPolicy: TieredReservation

仅启用分级预留,不限流

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
memoryReservationPolicy: TieredReservation

完全禁用 Memory QoS

升级后如需禁用该特性,请将特性门控设为 false,并确保 kubelet 配置兼容。如果 memoryThrottlingFactor 被设为原默认值 0.9 以外的任何值,或者 memoryReservationPolicyTieredReservationkubelet 会拒绝该配置,因此如果你设置过这些字段,请删除或调整它们。

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
featureGates:
 MemoryQoS: false

当特性门控关闭,或 memoryReservationPolicy 不是 TieredReservation 时,kubelet 会在 cgroup v2 节点启动时重置残留的保护配置:根 kubepods cgroup 上的 memory.min=0memory.low=0,以及 Burstable QoS cgroup 上的 memory.low=0。对于容器,重启或 resize 等调和路径上残留的 memory.high 值会被重置为 max

已知限制:内存预留是节点级别的

memoryReservationPolicy 作用于节点上的所有 Pod。启用 TieredReservation 后,每个 Guaranteed Pod 都会获得 memory.min,每个 Burstable Pod 都会获得 memory.low,无法让单个 Pod 选择加入或退出。如果一个节点上既有需要硬预留的工作负载,又有应当保持可回收的工作负载,只能为它们统一选择一种策略。

硬预留还会覆盖计入容器 cgroup 的所有内容,包括页缓存,因此读取大文件的 Pod 可能占住内存,而内核本可以回收这些内存来服务它的邻居。

SIG Node 正在 kubernetes/kubernetes#140246 中跟进这两个问题。如果这影响到了你,那个 issue 是描述你的工作负载的最佳去处。

接下来会怎样

Memory QoS 的下一个里程碑是晋升至 GA。Beta 用户的反馈将决定在这一步之前还需要做哪些调整。如果遇到问题,请在 kubernetes/kubernetes 提交 bug。

如何了解更多?

参与其中

该特性由 SIG Node 推动。如果你有兴趣贡献或想提供反馈,可以通过以下方式联系我们:

来源: Kubernetes Blog← 返回首页