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 配置字段选择启用特定行为:
- 设置
memoryThrottlingFactor(例如0.9)以对 Burstable 和 BestEffort 容器启用memory.high限流。默认值为null,即不限流。 - 将
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。
如何了解更多?
- KEP-2570: Memory QoS
- Pod 服务质量等级
- cgroup v2 下的 Memory QoS
- 管理容器的资源
- Kubernetes 对 cgroups v2 的支持
- Linux 内核 cgroups v2 文档
参与其中
该特性由 SIG Node 推动。如果你有兴趣贡献或想提供反馈,可以通过以下方式联系我们:
- Slack:#sig-node
- 邮件列表
- SIG Node 会议