CFS

CFS(Completely Fair Scheduler)调度器谋求的是对所有过程的全面偏心,实际上它的做法就是在一个特定的调度周期内,保障所有待调度的过程都能被执行一遍

过程的运行工夫计算公式为:过程运行工夫 = 调度周期 * 过程权重 / 所有过程权重之和
vruntime = 过程运行工夫 * NICE_0_LOAD / 过程权重 = (调度周期 * 过程权重 / 所有过程总权重) * NICE_0_LOAD / 过程权重 = 调度周期 * NICE_0_LOAD / 所有过程总权重 

罕用参数阐明

  • sysctl_sched_latency:示意一段时间内,sched_entity必定会被调度到一次,也就是一个sched_entity调度的最大的延时,2.6.35.13内核中默认是6ms。
  • sysctl_sched_min_granularity:示意调度的最小粒度,如果调度的工夫距离小于这个时间段,内核是不会筛选其余sched_entity进行调度,这个2.6.35.13内核中默认是2ms。
  • nr_latency:示意在下面的那段最大调度提早中,最多解决的sched_entity。

CPU cgroup 配置阐明
/sys/fs/cgroup

  • cpu.sched_latency_ns: 调度周期
  • cpu.cfs_period_us:示意一个cpu带宽,单位为微秒。零碎总CPU带宽: cpu外围数 * cfs_period_us
  • cpu.cfs_quota_us:示意Cgroup能够应用的cpu的带宽,单位为微秒。cfs_quota_us为-1,示意应用的CPU不受cgroup限度。cfs_quota_us的最小值为1ms(1000),最大值为1s。
  • cpu.shares:cpu.shares以绝对比例限度cgroup的cpu,例如:两个工作再cgroup中share设置都为1,他们有雷同的cpu工夫;如果一个share值设置为2,那么能够应用cpu的工夫就是设置为1的2倍。(通过cfs_period_us和cfs_quota_us能够以相对比例限度cgroup的cpu应用,即cfs_quota_us/cfs_period_us 等于过程能够利用的cpu cores,不能超过这个数值。)

cpu.stat
蕴含了上面三项统计后果

  • nr_periods: 示意过来了多少个cpu.cfs_period_us外面配置的工夫周期
  • nr_throttled: 在下面的这些周期中,有多少次是受到了限度(即cgroup中的过程在指定的工夫周期中用光了它的配额)
  • throttled_time: cgroup中的过程被限度应用CPU继续了多长时间(纳秒

调度阐明

有如下系统配置状况:

  • CFS调度周期为10ms,失常负载状况下,过程ready队列外面的过程在每10ms的距离内都会保障被执行一次
  • CFS重调配周期为100ms,用于保障一个过程的limits设置会被反映在每100ms的重调配周期内能够占用的CPU工夫数,在多核零碎中,limit最大值能够是 CFS重调配周期*CPU核数
  • 该执行过程队列只有过程A和过程B两个过程
  • 过程A和B定义的CPU share占用都一样,所以在系统资源缓和的时候能够保障A和B过程都能够占用可用CPU资源的一半
  • 定义的CFS重调配周期都是100ms
  • 过程A在100ms内最多占用50ms,过程B在100ms内最多占用20ms

阐明

  • 在后面的4个CFS调度周期内,过程A和B因为share值是一样的,所以每个CFS调度内(10ms),过程A和B都会占用5ms
  • 在第4个CFS调度周期完结的时候,在本CFS重调配周期内,过程B曾经占用了20ms,在剩下的8个CFS调度周期即80ms内,过程B都会被限流,始终到下一个CFS重调配周期内,过程B才能够持续占用CPU
  • 在第5-7这3个CFS调度周期内,因为过程B被限流,所以过程A能够齐全领有这3个CFS调度的CPU资源,占用30ms的执行工夫,这样在本CFS重调配周期内,过程A曾经占用了50ms的CPU工夫,在前面剩下的3个CFS调度周期即前面的30ms内,过程A也会被限流,始终到下一个CFS重调配周期内,过程A才能够持续占用CPU

kubernetes基于CFS进行CPU治理

假如pod的资源定义为

    resources:      limits:        cpu: 500m        memory: 512Mi      requests:        cpu: 200m        memory: 100Mi

查看pod对应的cgroup信息

  • 通过docker确定对应的id

    85cb54d5b4-9c6kv 为pod中的关键字段docker ps |grep  85cb54d5b4-9c6kv {        "Id": "38abd5a4414774a87e6c509913b03694411ad921f5b6ee8901fd7dfcf0afebd7",        "Created": "2021-11-17T07:22:44.873699016Z",        xxxxx       "CgroupParent": "/kubepods/burstable/pod3b5332a9-b208-4236-b07b-da447f9fff8c",}

    其中Id和CgroupParent是查找cgroup的要害信息
    下面得悉CgroupParent=/kubepods/burstable/pod3b5332a9-b208-4236-b07b-da447f9fff8c。那么在宿主机上的cgroup目录为/sys/fs/cgroup/cpu/kubepods/${CgroupParent}

  • 查看宿主机目录

    ls /sys/fs/cgroup/cpu/kubepods/burstable/pod3b5332a9-b208-4236-b07b-da447f9fff8c38abd5a4414774a87e6c509913b03694411ad921f5b6ee8901fd7dfcf0afebd7  cgroup.procs   cpuacct.usage_all         cpuacct.usage_percpu_user  cpu.cfs_period_us  cpu.rt_runtime_us  notify_on_releasea2a521da5284c7ad9a0aca61bf470454f4d71b0d1ce18ea64dbab8ac107c9f06  cpuacct.stat   cpuacct.usage_percpu      cpuacct.usage_sys          cpu.cfs_quota_us   cpu.shares         taskscgroup.clone_children                                             cpuacct.usage  cpuacct.usage_percpu_sys  cpuacct.usage_user         cpu.rt_period_us   cpu.stat

    下面为pod级别的cgroup文件,但一个pod是至多有两个个容器一个利用容器和pause容器,所以外面有两个文件夹,文件夹名称为docker inspect xxxx里看到的第一行id字段,就是下面的38abd5a4414774a87e6c509913b03694411ad921f5b6ee8901fd7dfcf0afebd7

  • 查看cgroup信息

    cat cpu.cfs_period_us100000cat cpu.shares204cat cpu.cfs_quota_us50000
    1. limits次要用以申明应用的最大的CPU核数。通过设置cfs_quota_us和cfs_period_us。比方limits.cpu=500m,则cfs_quota_us=50000(cfs_period_us值个别都应用默认的100000),cfs_quota_us/cpu.cfs_period_us = 0.5
    2. request则次要用以申明最小的CPU核数。一方面则体现在设置cpushare上。比方request.cpu=200m,则cpushare=1024*0.2=204.8

CPU限流问题

告警主题: CPUThrottlingHigh告警级别: warning告警类型: CPUThrottlingHigh故障实例: 告警详情: 27% throttling of CPU in namespace kube-system for container kube-proxy in pod kube-proxy-9pj9j.触发工夫: 2020-05-08 17:34:17

揣测起因: 某些特定的CFS重调配周期内,kube-proxy的CPU占用率超过了给它调配的limits
比方:
假如pod的资源定义为

    resources:      requests:        memory: "512Mi"        cpu: "200m"      limits:        memory: "512Mi"        cpu: "200m"

limits配置只有200ms,这就意味着在默认的100ms的CFS重调度周期内,它只能占用20ms,所以在特定忙碌场景会有问题;解决方案就是将CPU limits进步