ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Volcano 内存 QoS 设计解析:基于 Cgroup V2 的混部内存隔离与保护机制

Volcano 内存 QoS 设计解析:基于 Cgroup V2 的混部内存隔离与保护机制 Volcano 内存 QoS 设计解析基于 Cgroup V2 的混部内存隔离与保护机制【免费下载链接】volcanoA Cloud Native Batch System (Project under CNCF)项目地址: https://gitcode.com/GitHub_Trending/vol/volcano导读在 Volcano 混部Colocation场景中在线online与离线offline工作负载共享同一节点以提升资源利用率但离线负载的过度内存占用会冲击在线业务造成性能抖动甚至 OOM Kill。本文基于 docs/design/colocation/memory-qos-design.md 设计文档系统讲解 Volcano 基于 Cgroup V2 的内存 QoS 方案通过memory.high、memory.low、memory.min三个内核接口为高优负载提供内存保障、限制低优负载的内存占用。读完本文你将掌握ColocationConfigurationCRD 的完整配置方法、Controller 与 Volcano-Agent 的协同工作流程、cgroup 接口文件的计算规则以及配置失效时的重置语义。背景混部场景下的内存干扰问题在传统的单业务集群中节点资源往往存在大量闲置。混部Colocation将高优先级在线业务与低优先级离线业务部署在同一节点上从而显著提升资源利用率。但代价是资源隔离的复杂性离线负载可能无节制地申请内存挤压在线负载的可用内存当节点内存压力升高时内核回收机制可能误杀在线业务的关键进程导致服务不可用。Volcano 的内存 QoS 机制正是为了解决这一问题而设计利用 Cgroup V2 提供的内存接口为在线负载建立可保障的内存访问同时限制离线负载的内存使用从 cgroup 层面实现内存的隔离与保护。约束条件该机制的核心约束是仅支持 Cgroup V2。这意味着运行节点需使用 Cgroup V2 文件系统Linux 内核 5.4 且已启用cgroup v2挂载这是使用memory.high/memory.low/memory.min接口的前提。Cgroup V2 内存接口基础方案依赖的 Cgroup V2 内存接口及其语义如下接口文件语义在本方案中的作用memory.high内存使用超过该值后内核将加大回收力度并对页面分配施加压力throttle属于软限制限制离线负载内存增长防止其挤压在线负载memory.low在系统内存压力下cgroup 的内存使用在低于该值时不会被回收优先级保护保护在线负载的内存不被回收memory.mincgroup 的内存使用在低于该值时绝对不会被回收即使回收其他 cgroup 内存也无法满足为在线负载提供绝对内存保障三个接口从防止占用过多high到回收优先级保护low再到绝对不可回收min构成由松到严的三级内存保护体系。CRD 定义ColocationConfiguration内存 QoS 配置通过自定义资源ColocationConfigurationAPI 组config.volcano.sh/v1alpha1下发。以下为设计文档给出的完整示例apiVersion: config.volcano.sh/v1alpha1 kind: ColocationConfiguration metadata: name: colo-config1 spec: selector: matchLabels: app: offline-test memoryQos: highRatio: 100 # Memory throttling ratio; default100, range: 0~100 lowRatio: 0 # Memory priority protection ratio; default0, range: 0~100 minRatio: 0 # Absolute memory protection ratio; default0, range: 0~100配置字段详解从 API 类型定义 staging/src/volcano.sh/apis/pkg/apis/config/v1alpha1/types.go 可以看到完整的字段结构与校验规则spec.selector标准metav1.LabelSelector用于匹配目标 PodColocationConfigurationSpec.Selector。spec.memoryQos内存 QoS 配置块包含三个整型字段highRatio内存限流throttling比例。默认100取值范围0~100kubebuilder:validation:Minimum0/Maximum100/default100。memory.high由该比例乘以容器内存 Limit 计算得出。lowRatio内存优先级保护比例。默认0取值范围0~100。memory.low由该比例乘以容器内存 Request 计算得出。minRatio绝对内存保护比例。默认0取值范围0~100。memory.min由该比例乘以容器内存 Request 计算得出。配置语义小结highRatio决定能占多少内存基于 LimitlowRatio与minRatio决定内存多受保护基于 Request。将离线负载的highRatio调低即可限制其内存占用将在线负载的lowRatio/minRatio调高即可强化其内存保障。Configuration结构体中MemoryQos字段带json:memoryQos,omitempty标签MemoryQos三个比例字段使用omitempty未配置时由 kubebuilder 默认值填充100/0/0。架构与整体工作流程如上图所示内存 QoS 的执行链路贯穿API Server → Controller → Pod Annotation → Volcano-Agent → 节点 cgroup五个环节用户Actor通过 API Server 提交ColocationConfiguration与工作负载PodController 监听ColocationConfiguration与 Pod 事件将匹配的 Pod 放入工作队列工作队列线程处理 Pod查找匹配的配置并更新 Pod 注解volcano.sh/colocation-config回写 API ServerPod 更新事件携带新注解被节点上的 Volcano-Agent 接收Volcano-Agent 解析注解中的配置在节点上修改对应 cgroup 接口文件完成内存 QoS 落地。该链路中 Controller 只负责把配置翻译成注解真正的内核落地动作由节点代理完成两者职责分离、解耦清晰。Controller 侧实现配置到注解的翻译Controller 的完整实现位于 pkg/controllers/colocationconfig核心逻辑如下。注解键约定从 staging/src/volcano.sh/apis/pkg/apis/config/v1alpha1/labels.go 可看到三个关键常量const ( ColocationConfigNameKey volcano.sh/colocation-config-name ColocationConfigKey volcano.sh/colocation-config ColocationConfigReset {} )volcano.sh/colocation-config-name记录匹配到的ColocationConfiguration名称volcano.sh/colocation-configJSON 格式的配置内容格式与ColocationConfiguration.spec保持一致即Configuration结构体含memoryQos字段ColocationConfigReset {}用于表示需要重置 cgroup的空配置值。事件处理与入队在 colocation_config_controller_handler.go 中podHandler/podUpdateHandlerPod 创建、更新时将其入队colocationConfigurationHandler/colocationConfigurationUpdateHandlerColocationConfiguration创建、更新时调用enqueueRelatedPods将更新前后匹配到的所有 Pod 重新入队见设计文档要求selector 更新时必须同时入队更新前后匹配的 Pod。enqueueRelatedPods将 LabelSelector 转换为selector后通过podLister列出匹配 Pod并逐个AddAfter(key, time.Second)入队processPodQueue消费工作队列失败时AddRateLimited限速重试。syncPod匹配、更新与重置syncPodcolocation_config_controller_handler.go#L180-L221是核心处理逻辑列出命名空间下所有ColocationConfiguration按 CreationTimestamp 降序排序新创建的配置优先遍历配置若 Pod 标签匹配某个配置的 selector则调用updateColocationConfigToPod将配置序列化为 JSON 写入 Pod 注解并返回若没有任何配置匹配则调用resetColocationConfigForPod执行重置逻辑。getModifiedPod通过比较ColocationConfigNameKey与反序列化后的Configuration是否相等equality.Semantic.DeepEqual判断是否需要更新避免无意义的重复写操作。重置语义保留键、清空值设计文档明确要求当 Pod 带有volcano.sh/colocation-config注解但找不到匹配的ColocationConfiguration时应清空注解值但保留注解键其目的是保留键以标识该 Pod 曾经被混部配置管理过Agent 看到空值配置后会执行 cgroup 重置动作把memory.high/low/min恢复为默认值避免 Pod 残留旧的 cgroup 限制。resetColocationConfigForPodcolocation_config_controller_handler.go#L284将volcano.sh/colocation-config置为{}ColocationConfigReset同时移除配置名注解。Volcano-Agent 侧实现注解到 cgroup 的落地Agent 端的内存 QoS 处理器实现在 pkg/agent/events/handlers/memoryqosv2/memoryqosv2_linux.go通过handlers.RegisterEventHandleFunc(string(framework.PodEventName), NewMemoryQoSV2Handle)注册为 Pod 事件处理器。处理流程MemoryQoSV2Handle.Handle的执行步骤从 Pod Lister 获取最新 Pod校验 UID 与事件一致读取注解volcano.sh/colocation-config为空则跳过parseColocationConfig将 JSON 反序列化为Configuration若MemoryQos缺失则填充默认值HighRatio100, LowRatio0, MinRatio0即重置语义通过cgroupMgr.GetPodCgroupPath获取 Pod 的 cgroup v2 路径按 QoSClass 与 UID 定位遍历 Pod 的每个容器逐容器设置memory.high/memory.low/memory.min。cgroup 接口文件计算规则设计文档给出的核心计算公式如下memory.high resources.limits[memory] * highRatio % memory.low resources.requests[memory] * lowRatio % memory.min resources.requests[memory] * minRatio %对应的源码实现memoryqosv2_linux.go#L117-L153中有一个值得注意的细节memory.high若quantity.IsZero()容器未声明内存 Limit或HighRatio 100则直接设置为MemoryUnlimited即max不施加限流memory.low/memory.min分别取Requests中内存量乘以对应比例比例计算为整数乘法除法quantity.Value() * int64(cfg.HighRatio) / 100。扩展资源内存的支持getMemoryQuantitymemoryqosv2_linux.go#L163-L170会根据 Pod 的 QoS 级别判断是否优先使用扩展内存资源apis.GetExtendResourceMemory()当 QoS 级别允许使用扩展资源extension.AllowedUseExtRes(qosLevel)且容器声明了该资源时优先以扩展内存资源作为计算基数否则回退到标准ResourceMemory。重置动作当 Pod 注解volcano.sh/colocation-config存在但值为空或解析后MemoryQos缺失时Agent 按以下规则重置 cgroupmemory.high max memory.low 0 memory.min 0即取消全部内存限制与保护恢复内核默认行为。源码中的parseColocationConfig注释// TODO: adapt feature gate MemoryQoS表明若 Kubernetes 特性门控MemoryQoS已启用重置值应按 Kubernetes 官方Quality-of-Service for Memory Resources方案计算该方案将memory.high设为容器内存 Limit将memory.min设为 Request 并按一定比例折算具体以 Kubernetes 文档为准。当前仓库实现中这一适配尚在演进中重置路径目前采用统一的max/0/0策略。特性开关与启用前提内存 QoS V2 属于 Volcano-Agent 的可选能力受特性开关与 Agent 配置双重控制特性门控features.MemoryQoSV2Feature见 pkg/agent/features/feature_gate.go。Enabled(key, cfg)的判定逻辑为节点混部或超卖开关NodeColocationEnable/NodeOverSubscriptionEnable任一开启且Agent 配置中MemoryQosV2Config.Enable为 trueAgent 配置结构在 pkg/agent/config/api/types.go 中ColocationConfig.MemoryQosV2Config对应memoryQosV2Config配置项MemoryQos.Enable控制是否启用运行时校验Supported通过cfg.IsFeatureSupported判断该特性是否被当前构建的 Agent 支持不支持的场景下 Agent 会跳过处理。因此完整启用内存 QoS 需要同时满足节点为 Cgroup V2、节点开启混部/超卖、Agent 配置启用MemoryQoSV2并存在匹配 Pod 的ColocationConfiguration。测试验证行为即契约仓库为上述两个核心组件均提供了单元测试可直接作为行为契约参考Controller 侧pkg/controllers/colocationconfig/colocation_config_controller_test.go 覆盖了 5 个关键场景Pod 不匹配任何配置不更新Pod 匹配配置写入配置名与 JSON 配置注解Pod 已携带相同配置跳过更新幂等Pod 匹配多个配置最新创建CreationTimestamp 最大者生效Pod 曾有配置但当前无匹配置为ColocationConfigReset{}执行重置。Agent 侧pkg/agent/events/handlers/memoryqosv2/memoryqosv2_linux_test.go 验证了核心计算逻辑例如HighRatio80时memory.high 内存Limit * 80 / 100LowRatio20时memory.low 内存Request * 20 / 100MinRatio10时memory.min 内存Request * 10 / 100与设计文档公式完全一致。总结与最佳实践建议Volcano 的内存 QoS 方案以配置 CRD → Controller 翻译注解 → Agent 落盘 cgroup三段式流水线在混部场景中实现了内存的隔离与保护为离线负载设置较小的highRatio如 50~80限制其内存占用上限防止挤占在线业务为在线负载设置较大的lowRatio/minRatio如 80~100确保内存压力下其内存优先被保护避免被误回收或 OOM修改ColocationConfiguration.spec.selector时Controller 会自动重新入队前后匹配的所有 Pod无需人工干预配置删除或 Pod 不再匹配时Agent 自动将 cgroup 重置为max/0/0不留脏状态。需要注意的是该方案依赖 Cgroup V2 与 KubernetesMemoryQoS特性门控的后续适配仓库中仍有 TODO实际生产使用前应确认节点内核、容器运行时与 Volcano-Agent 版本的兼容性。延伸阅读本文对应设计文档位于 docs/design/colocation/memory-qos-design.md混部整体设计背景可参考同目录下的 Overview.mdAgent 的 Cgroup V2 适配细节见 docs/design/agent-cgroup-v2-adaptation.md。【免费下载链接】volcanoA Cloud Native Batch System (Project under CNCF)项目地址: https://gitcode.com/GitHub_Trending/vol/volcano创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表