特性介绍

Pod CPU 优先级

rubik 支持业务 CPU 优先级配置,针对在/离线业务混合部署的场景,确保在线业务相对离线业务的 CPU 资源抢占。

前置条件

  • 建议使用 openEuler-22.03+的内核版本。内核支持针对 cgroup 的 cpu 优先级配置,cpu 子系统存在接口 cpu.qos_level。

CPU 优先级内核接口

  • /sys/fs/cgroup/cpu 目录下容器的 cgroup 中,如/sys/fs/cgroup/cpu/kubepods/burstable/<PodUID>/<container-longid>目录
    • cpu.qos_level:开启 CPU 优先级配置,默认值为 0, 有效值为 0 和-1。
      • 0:标识为在线业务
      • -1:标识为离线业务

CPU 优先级配置详解

rubik 会根据 Pod 的 yaml 文件中的注解volcano.sh/preemptable自动配置 cpu.qos_level, 默认为 false。

annotations:
    volcano.sh/preemptable: true
  • true:代表业务为离线业务
  • false:代表业务为在线业务

Pod 内存优先级

rubik 支持业务 memory 优先级配置,针对在/离线业务混合部署的场景,确保 OOM 时优先 kill 离线业务。

前置条件

  • 建议使用 openEuler-22.03+的内核版本。内核支持针对 cgroup 的 memory 优先级配置,memory 子系统存在接口 memory.qos_level。
  • 开启内存优先级支持:echo 1 > /proc/sys/vm/memcg_qos_enable

内存优先级内核接口

  • /proc/sys/vm/memcg_qos_enable:开启内存优先级特性,默认值为 0,有效值为 0 和 1。开启命令为:echo 1 > /proc/sys/vm/memcg_qos_enable

    • 0:表示关闭特性
    • 1:表示开启特性。
  • /sys/fs/cgroup/memory 目录下容器的 cgroup 中,如/sys/fs/cgroup/memory/kubepods/burstable/<PodUID>/<container-longid>目录

    • memory.qos_level:开启内存优先级配置,默认值为 0,有效值为 0 和-1。
      • 0:标识为在线业务
      • -1:标识为离线业务

内存优先级配置详解

rubik 会根据 Pod 的 yaml 文件中的注解volcano.sh/preemptable自动配置 memory.qos_level,参考CPU 优先级配置详解

dynCache 访存带宽和 LLC 限制

rubik 支持业务的 Pod 访存带宽(memory bandwidth)和 LLC(Last Level Cache)限制,通过限制离线业务的访存带宽/LLC 使用,减少其对在线业务的干扰。

前置条件

  • cache/访存限制功能仅支持物理机,不支持虚拟机。

    • X86 物理机,需要 OS 支持且开启 intel RDT 的 CAT 和 MBA 功能,内核启动项 cmdline 需要添加rdt=l3cat,mba
    • ARM 物理机,需要 OS 支持且开启 mpam 功能,内核启动项需要添加mpam=acpi
  • 由于内核限制,RDT mode 当前不支持 pseudo-locksetup 模式。

rubik 新增权限和目录

  • 挂载目录:/sys/fs/resctrl。 rubik 需要读取和设置/sys/fs/resctrl 目录下的文件,该目录需在 rubik 启动前挂载,且需保障在 rubik 运行过程中不被卸载。
  • 权限:SYS_ADMIN. 设置主机/sys/fs/resctrl 目录下的文件需要 rubik 容器被赋有 SYS_ADMIN 权限。
  • namepsace: pid namespace. rubik 需要获取业务容器进程在主机上的 pid,所以 rubik 容器需与主机共享 pid namespace。

rubik rdt 控制组

rubik 在 RDT resctrl 目录(默认为 /sys/fs/resctrl)下创建 5 个控制组,分别为 rubik_max、rubik_high、rubik_middle、rubik_low、rubik_dynamic。rubik 启动后,将水位线写入对应控制组的 schemata。其中,low、middle、high 的水位线可在 cacheConfig 中配置;max 控制组为默认最大值,dynamic 控制组初始水位线和 low 控制组一致。

离线业务 Pod 启动时通过注解volcano.sh/cache-limit设置其 cache level,并被加入到指定的控制组中,如下列配置的 Pod 将被加入 rubik_low 控制组:

annotations:
    volcano.sh/cache-limit: "low"

rubik dynamic 控制组

当存在 level 为 dynamic 的离线 Pod 时,rubik 通过采集当前节点在线业务 Pod 的 cache miss 和 llc miss 指标,调整 rubik_dynamic 控制组的水位线,实现对 dynamic 控制组内离线应用 Pod 的动态控制。

dynCache 内核接口

  • /sys/fs/resctrl: 在该目录下创建 5 个控制组目录,并修改其 schemata 和 tasks 文件。

dynCache 配置详解

dynCache 功能相关的配置在cacheConfig中:

"cacheConfig": {
        "enable": false,
        "defaultLimitMode": "static",
        "adjustInterval": 1000,
        "perfDuration": 1000,
        "l3Percent": {
            "low": 20,
            "mid": 30,
            "high": 50
        },
        "memBandPercent": {
            "low": 10,
            "mid": 30,
            "high": 50
        }
    },
  • l3Percent 和 memBandPercent: 通过 l3Percent 和 memBandPercent 配置 low, mid, high 控制组的水位线。

    比如当环境的rdt bitmask=fffff, numa=2时,rubik_low 的控制组将根据 l3Percent low=20 和 memBandPercent low=10 两个参数,将为/sys/fs/resctrl/rubik_low 控制组配置:

    L3:0=f;1=f
    MB:0=10;1=10
    
  • defaultLimitMode: 如果离线 Pod 未指定volcano.sh/cache-limit注解,将根据 cacheConfig 的 defaultLimitMode 来决定 Pod 将被加入哪个控制组:

    • defaultLimitMode 为 static 时,Pod 将被加入到 rubik_max 控制组
    • defaultLimitMode 为 dynamic 时,Pod 将被加入到 rubik_dynamic 控制组
  • adjustInterval: dynCache 动态调整 rubik_dynamic 控制组的间隔时间,单位 ms,默认 1000ms

  • perfDuration: dynCache 性能 perf 执行时长,单位 ms,默认 1000ms

dynCache 注意事项

  • dynCache 仅针对离线 Pod,对在线业务不生效。
  • 若业务容器运行过程中被手动重启(容器 ID 不变但容器进程 PID 变化),针对该容器的 dynCache 无法生效。
  • 业务容器启动并已设置 dynCache 级别后,不支持对其限制级别进行修改。
  • 动态限制组的调控灵敏度受到 rubik 配置文件内 adjustInterval、perfDuration 值以及节点在线业务 Pod 数量的影响,每次调整(若干扰检测结果为需要调整)间隔在区间【adjustInterval+perfDuration, adjustInterval+perfDuration*Pod 数量】内波动,用户可根据灵敏度需求调整配置项。

blkio

Pod 的 blkio 的配置以volcano.sh/blkio-limit注解的形式,在 Pod 创建的时候配置,或者在 Pod 运行期间通过 kubectl annotate 进行动态的修改,支持离线和在线 Pod。

配置内容为 4 个列表:

说明
device_read_bps用于设定设备执行“读”操作字节的上限。该配置为 list,可以对多个 device 进行配置,device 指定需要限制的块设备,value 限定上限值,单位为 byte
device_read_iops用于设定设备执行“读”操作次数的上限。该配置为 list,可以对多个 device 进行配置,device 指定需要限制的块设备
device_write_bps用于设定设备执行 “写” 操作次数的上限。该配置为 list,可以对多个 device 进行配置,device 指定需要限制的块设备,value 限定上限值,单位为 byte
device_write_iops用于设定设备执行“写”操作字节的上限。该配置为 list,可以对多个 device 进行配置,device 指定需要限制的块设备

blkio 内核接口

  • /sys/fs/cgroup/blkio 目录下容器的 cgroup 中,如/sys/fs/cgroup/blkio/kubepods/burstable/<PodUID>/<container-longid>目录:
    • blkio.throttle.read_bps_device
    • blkio.throttle.read_iops_device
    • blkio.throttle.write_bps_device
    • blkio.throttle.write_iops_device

配置的 key:value 和 cgroup 的 key:value 的配置规则一致:

  • 写入时会转换成环境 page size 的倍数
  • 只有 minor 为 0 的 device 配置才会生效
  • 如果取消限速,可将值设为 0

blkio 配置详解

rubik 开启关闭 blkio 功能:

rubik 提供 blkio 配置功能的开关,在blkioConfig

"blkioConfig": {
        "enable": true
}
  • enable: IO 控制模块使能开关, 默认为 false

Pod 配置样例:

通过 Pod 的注解配置时可提供四个列表,分别是 write_bps, write_iops, read_bps, read_iops, read_byte.

  • 创建时:在 yaml 文件中

    volcano.sh/blkio-limit: '{"device_read_bps":[{"device":"/dev/sda1","value":"10485760"}, {"device":"/dev/sda","value":"20971520"}],
                    "device_write_bps":[{"device":"/dev/sda1","value":"20971520"}],
                    "device_read_iops":[{"device":"/dev/sda1","value":"200"}],
                    "device_write_iops":[{"device":"/dev/sda1","value":"300"}]}'
    
  • 修改 annotation: 可通过 kubectl annotate 动态修改,如: kubectl annotate --overwrite pods <podname> volcano.sh/blkio-limit='{"device_read_bps":[{"device":"/dev/vda", "value":"211715200"}]}'

memory

rubik 中支持多种内存策略。针对不同场景使用不同的内存分配方案,以解决多场景内存分配。

dynlevel 策略:基于内核 cgroup 的多级别控制。通过监测节点内存压力,多级别动态调整离线业务的 memory cgroup,尽可能地保障在线业务服务质量。

fssr 策略:基于内核 cgroup 的动态水位线控制。memory.high 是内核提供的 memcg 级的水位线接口,rubik 动态检测内存压力,动态调整离线应用的 memory.high 上限,实现对离线业务的内存压制,保障在线业务的服务质量。

memory dynlevel 策略内核接口

  • /sys/fs/cgroup/memory 目录下容器的 cgroup 中,如/sys/fs/cgroup/memory/kubepods/burstable/<PodUID>/<container-longid>目录。dynlevel 策略会依据当前节点的内存压力大小,依次调整节点离线应用容器的下列值:

    • memory.soft_limit_in_bytes
    • memory.force_empty
    • memory.limit_in_bytes
    • /proc/sys/vm/drop_caches

memory dynlevel 策略配置详解

rubik 提供 memory 的指定策略和控制间隔,在memoryConfig

"memoryConfig": {
        "enable": true,
        "strategy": "none",
        "checkInterval": 5
   }
  • enable 为是否打开该配置的开关

  • strategy 为 memory 的策略名称,现支持 dynlevel/fssr/none,默认为 none。

    • none: 即不设置任何策略,不会对内存进行调整。
    • dynlevel: 动态分级调整策略。
    • fssr: 快压制慢恢复策略。1)rubik 启动时,默认配置所有离线的 memory.high 为总内存的 80%。2)当内存压力增加,可用内存 freeMemory < reservedMemory(预留内存,totalMemory * 5%) 时认为内存紧张,此时压缩所有离线的 memory.high, 压缩量为总内存的 10%,即最新的 memory.high=memory.high-totalMemory * 10%。3)当持续一段时间总内存比较富裕,即可用内存 freeMemory > 3 * reservedMemory(totalMemory * 5%)时认为内存富裕,此时释放总内存的 1%给离线应用,memory.high=memory.high+totalMemory * 1%, 直到 memory free 介于 reservedMemory 与 3 * reservedMemory 之间。
  • checkInterval 为策略的周期性检查的时间,单位为秒,默认为 5。

memory fssr 策略内核接口

  • /sys/fs/cgroup/memory 目录下容器的 cgroup 中,如/sys/fs/cgroup/memory/kubepods/burstable/<PodUID>/<container-longid>目录。fssr 策略会依据当前节点的内存压力大小,依次调整节点离线应用容器的下列值:
  • memory.high

memory fssr 策略配置详解

rubik 提供 memory 的指定策略和控制间隔,在memoryConfig

"memoryConfig": {
        "enable": true,
        "strategy": "fssr",
        "checkInterval": 5
   }
  • enable 为是否打开该配置的开关

  • strategy 为 memory 的策略名称,现支持 dynlevel/fssr/none 两个选项,默认为 none。

    • none: 即不设置任何策略,不会对内存进行调整。
    • dynlevel: 动态分级调整策略。
    • fssr: 快压制慢恢复策略。1)rubik 启动时,默认配置所有离线的 memory.high 为总内存的 80%。2)当内存压力增加,可用内存 freeMemory < reservedMemory(预留内存,totalMemory * 5%) 时认为内存紧张,此时压缩所有离线的 memory.high, 压缩量为总内存的 10%,即最新的 memory.high=memory.high-totalMemory * 10%。3)当持续一段时间总内存比较富裕,即可用内存 freeMemory > 3 * reservedMemory(totalMemory * 5%)时认为内存富裕,此时释放总内存的 1%给离线应用,memory.high=memory.high+totalMemory * 1%, 直到 memory free 介于 reservedMemory 与 3 * reservedMemory 之间。
  • checkInterval 为策略的周期性检查的时间,单位为秒,默认为 5。

quota burst

Pod 的 quota burst 的配置以volcano.sh/quota-burst-time注解的形式,在 Pod 创建的时候配置,或者在 Pod 运行期间通过 kubectl annotate 进行动态的修改,支持离线和在线 Pod。

Pod 的 quota burst 默认单位是 microseconds, 其允许容器的 cpu 使用率低于 quota 时累积 cpu 资源,并在 cpu 利用率超过 quota 时,使用容器累积的 cpu 资源。

quota burst 内核接口

  • /sys/fs/cgroup/cpu 目录下容器的 cgroup 中,如/sys/fs/cgroup/cpu/kubepods/burstable/<PodUID>/<container-longid>目录,注解的值将被写入下列文件中:

    • cpu.cfs_burst_us
  • 注解volcano.sh/quota-burst-time的值和 cpu.cfs_burst_us 的约束一致:

    • 当 cpu.cfs_quota_us 不为-1,需满足 cpu.cfs_burst_us + cpu.cfs_quota_us <= 2^44-1 且 cpu.cfs_burst_us <= cpu.cfs_quota_us
    • 当 cpu.cfs_quota_us 为-1,cpu.cfs_burst_us 最大没有限制,取决于系统最大可设置的值

Pod 配置样例

  • 创建时:在 yaml 文件中

    metadata:
      annotations:
        volcano.sh/quota-burst-time : "2000"
    
  • 修改 annotation: 可通过 kubectl annotate 动态修改,如:

    kubectl annotate --overwrite pods <podname> volcano.sh/quota-burst-time='3000'

基于 iocost 的 io 权重控制

依赖说明

rubik 支持通过在 cgroup v1 下的 iocost 控制不同 Pod 的 io 权重分配。因此需要内核支持如下特性:

  • 内核支持 cgroup v1 blkcg iocost
  • 内核支持 cgroup v1 writeback

rubik 实现说明

步骤如下

  • 部署 rubik 时,rubik 解析配置并设置 iocost 相关参数
  • rubik 注册检测事件到 k8s api-server
  • Pod 被部署时将 Pod 配置信息等回调到 rubik
  • rubik 解析 Pod 配置信息,并根据 qos level 配置 Pod iocost 权重

rubik 协议说明

"nodeConfig": [
        {
            "nodeName": "slaver01",
            "iocostEnable": true,
            "iocostConfig": [
                {
                    "dev": "sda",
                    "enable": false,
                    "model": "linear",
                    "param": {
                        "rbps": 174610612,
                        "rseqiops": 41788,
                        "rrandiops": 371,
                        "wbps": 178587889,
                        "wseqiops": 42792,
                        "wrandiops": 379
                    }
                }
            ]
        }
    ]
配置项类型说明
nodeConfig数组node 节点配置信息
nodeNamestring要配置的节点名称
iocostEnablebool该 node 节点是否使用 iocost
iocostConfig数组针对不同物理磁盘的配置数组,当 iocostEnable 为 true 时会被读取
devstring物理磁盘名称
enablebool该物理磁盘是否启用 iocost
modelstringiocost 的模型名称,linear 为内核自带线性模型
paramobject该参数针对 model 参数配置,当 model 为 linear 时,下面的参数都是 linear 相关参数
r(w)bpsint64该物理块设备最大读(写)带宽
r(w)seqiopsint64该物理块设备最大顺序读(写)iops
r(w)randiopsint64该物理块设备最大随机读(写)iops

其他

  • iocost linear 模型相关参数可以通过 iocost_coef_gen.py 脚本获取,可以从link获得。

  • 在 blkcg 根系统文件下存在blkio.cost.qosblkio.cost.model两个文件接口。实现方式和接口说明可以访问 openEuler 内核文档。

文档捉虫

“有虫”文档片段

问题描述

提交类型 issue
有点复杂...
找人问问吧。
PR
小问题,全程线上修改...
一键搞定!
问题类型
规范和低错类

● 错别字或拼写错误;标点符号使用错误;

● 链接错误、空单元格、格式错误;

● 英文中包含中文字符;

● 界面和描述不一致,但不影响操作;

● 表述不通顺,但不影响理解;

● 版本号不匹配:如软件包名称、界面版本号;

易用性

● 关键步骤错误或缺失,无法指导用户完成任务;

● 缺少必要的前提条件、注意事项等;

● 图形、表格、文字等晦涩难懂;

● 逻辑不清晰,该分类、分项、分步骤的没有给出;

正确性

● 技术原理、功能、规格等描述和软件不一致,存在错误;

● 原理图、架构图等存在错误;

● 命令、命令参数等错误;

● 代码片段错误;

● 命令无法完成对应功能;

● 界面错误,无法指导操作;

风险提示

● 对重要数据或系统存在风险的操作,缺少安全提示;

内容合规

● 违反法律法规,涉及政治、领土主权等敏感词;

● 内容侵权;

您对文档的总体满意度

非常不满意
非常满意
提交
根据您的反馈,会自动生成issue模板。您只需点击按钮,创建issue即可。