徐蓓,腾讯云专家工程师,深耕云计算、Kubernetes、离在线混部领域,Kubernetes 社区积极贡献者。
背景
随着云原生进入深水区,很多用户希望通过业务混部提升集群利用率。但由于 kernel 限制,部分资源隔离性不强,会导致业务受损。在这种背景下,腾讯云 TKE 团队向 Kubernetes 社区提交了KEP-2570: Support Memory QoS with cgroups v2【https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2570-memory-qos】,以希望解决内存隔离和服务质量问题。该提案和实现代码已被社区接受,计划在 Kubernetes v1.22 发布 alpha 版。
原理
在原有方案中,Kubernetes 通过 cgroups v1 实现 CPU 和 Memory 隔离。CPU 属于可压缩资源,通过 cpuset.cpus / cpu.cfs_period_us / cpu.cfs_quota_us / cpu.shares
实现绑核、分核与权重等隔离。在节点 CPU 紧张时,任务只会被 throttle,不至于被 kill,影响范围可控。但 Memory 这类不可压缩资源,在节点内存不足时会触发 OOM Killer,通过 oom_socre_adj
做 kill 操作。这对部分 Burstable Pod 是不可接受的。而且某些内存消耗型 Pod 在创建和运行中会短时申请大量内存,导致节点内存瞬间飙升。节点内存紧张可能会导致内存高敏 Pod 在申请内存时触发慢路径,从而影响服务质量。cgroups v1 无法解决此类 Memory QoS 问题。
但幸运的是,cgroups v2 memory controller 为我们提供了丰富的参数用于实现内存预留与分配限速。
在我们提交的 KEP 中,主要使用 memory.min / memory.high
实现容器 / Pod / Burstable QoS 的内存保留与分配限速。
内存保留
-
对于容器,我们通过
memory.min=pod.spec.containers[i].resources.requests[memory]
为容器保留申请内存 -
对于 Pod,我们通过
memory.min=sum(pod.spec.containers[i].resources.requests[memory]
为 Pod 保留申请内存 -
对于 Burstable QoS,我们通过
memory.min=sum(pod[i].spec.containers[j].resources.requests[memory])
为 Burstable Pods 保留申请内存
分配限速
-
若容器设置
limits.memory
,我们通过memory.high=pod.spec.containers[i].resources.limits[memory] * memory throttling factor
为容器超申请内存做分配限速 -
若容器未设置
limits.memory
,我们通过memory.high=node allocatable memory * memory throttling factor
为容器超申请内存做分配限速
更多设计细节可查阅:【https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2570-memory-qos】
目前实现代码已合入社区,详情见:
-
Feature: add unified on CRI to support cgroup v2 [1]
-
Feature: Support memory qos with cgroups v2 [2]
展望
随着 Linux cgroups v2 成熟和普及,以及 Kubernetes cgroups v2 支持进入 alpha,我们相信未来 Kubernetes 的资源 QoS 会逐渐 offload 到内核,资源隔离更多依赖内核进行强隔离。只有在这种趋势下,基于 Kubernetes 的大规模资源混部才会真正普及。
参考资料
[1]Feature: add unified on CRI to support cgroup v2:【 https://github.com/kubernetes/kubernetes/pull/102578】
[2]Feature: Support memory qos with cgroups v2:【 https://github.com/kubernetes/kubernetes/pull/102970】
猜你喜欢: