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,升级时会保留该值,节流继续按原来的方式工作。如果配置文件不包含该字段,kubelet 会使用新的 null 默认值,并停止设置 memory.high。这种情况下,如需继续节流,请显式添加 memoryThrottlingFactor:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
memoryThrottlingFactor: 0.9
如何在 v1.37 中配置 MemoryQoS
完整配置说明见 cgroup v2 下的 Memory QoS、配置内存预留以及系统要求。
仅启用内存节流
将 memoryThrottlingFactor 设置为 0 到 1 之间的值。kubelet 使用该系数计算 Burstable 和 BestEffort 容器的 memory.high。各 QoS 类别的计算方式见内存节流。
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。对容器而言,重启或调整大小等协调路径会将过期的 memory.high 重置为 max。
已知限制:内存预留作用于整个节点
memoryReservationPolicy 适用于节点上的每个 Pod。使用 TieredReservation 时,每个 Guaranteed Pod 获得 memory.min,每个 Burstable Pod 获得 memory.low;不能逐个 Pod 选择加入或退出。如果一个节点同时运行需要硬预留的工作负载和应保持可回收内存的工作负载,就必须为所有工作负载选择同一种策略。
硬预留还覆盖计入容器 cgroup 的所有内存,包括页缓存。因此,读取大文件的 Pod 可能持有内存,而这些内存原本可以被内核回收,用于服务同节点的其他 Pod。
SIG Node 在 kubernetes/kubernetes#140246 中跟踪这两个问题。如果它们影响你的工作负载,该议题是描述情况的最佳位置。
接下来可以期待什么
Memory QoS 的下一里程碑是升级为 GA。Beta 用户的反馈将影响在此之前仍需作出的调整。如果遇到问题,请在 kubernetes/kubernetes 提交缺陷报告。
如何进一步了解
- KEP-2570:Memory QoS
- Pod 服务质量类别
- cgroup v2 下的 Memory QoS
- 管理容器资源
- Kubernetes 对 cgroups v2 的支持
- Linux 内核 cgroups v2 文档
参与贡献
该功能由 SIG Node 推动。如果希望贡献或提供反馈,可以通过以下渠道联系:
- Slack:#sig-node
- 邮件列表
- SIG Node 会议











暂无评论内容