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.high、memory.min 或 memory.low 值。

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

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

默认 memoryThrottlingFactor 改为 null

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

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

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

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

如何在 v1.37 中配置 MemoryQoS

有关配置 Memory QoS 的完整细节,请参阅 Memory QoS with cgroup v2、Configuring memory reservation 和 System 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 以外的任何值,或者 memoryReservationPolicy 为 TieredReservation,kubelet 会拒绝该配置,因此如果你设置过这些字段,请删除或调整它们。

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

当特性门控关闭,或 memoryReservationPolicy 不是 TieredReservation 时,kubelet 会在 cgroup v2 节点启动时重置残留的保护配置:根 kubepods cgroup 上的 memory.min=0 和 memory.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← 返回首页