讲解如何从内核角度理解K8s CPU限流的原理

news/2025/2/26 0:04:28

在使用 Kubernetes(简称K8s) 时,通常会在同一台机器上部署多个 Pod。如果某个 Pod 中的服务出现问题(如出现死循环),将会导致占用大量的 CPU 时间,从而影响到其他 Pod 的正常运行。

为了解决这个问题,K8s 提供了一个限制 Pod 使用 CPU 资源的配置项,如下所示:

resources:
  limits:
    cpu: "0.5"

上述配置限制了 Pod 只能使用 0.5 个 CPU 资源。

K8s 通过使用 Linux 资源控制组(cgroup)中的 CPU子系统 来限制 Pod 对 CPU 资源的使用。

下面我们来分析一下 Linux 内核是如何限制进程对 CPU 资源的使用。

CPU限流原理

如果让我们来设计一个限制进程对 CPU 资源使用的算法(如限制进程 A 只能使用 10% 的 CPU 运行时间),应该如何实现呢?

最简单的方法是,将 CPU 的运行时间划分成一个个时间片段(称为 周期(period),如 100 毫秒)。由于进程 A 被限制为只能使用 10% 的 CPU 运行时间,所以在一个周期内,进程 A 只能获得 10 毫秒的运行时间。当进程 A 在一个周期内运行超过 10 毫秒后,将会被内核移除可运行队列。那么在当前周期内,进程 A 将不会被调度,从而实现 CPU限流 的目的。

当一个新的周期开始时,进程 A 将会重新获得 10% 的 CPU 运行时间。如下图所示:

进程在一个周期内能运行的时间被称为 配额(quota)

 

 资料直通车:Linux内核源码技术学习路线+视频教程内核源码

学习直通车:Linux内核源码内存调优文件系统进程管理设备驱动/网络协议栈

CPU限流实现

内核以 进程组 作为资源控制的主体,进程组使用 task_group 结构体来描述,其定义如下:

struct task_group {
    ...
    // 可运行队列,每个CPU一个
    struct cfs_rq **cfs_rq;
    ...
    // 用于限制进程组对CPU资源的使用
    struct cfs_bandwidth cfs_bandwidth;
};

可以看出,每个进程组都有一个可运行队列,可运行队列中包含了进程组中所有可以被调度的进程。

在多核环境下,每个 CPU 都有一个可运行队列,主要为了解决资源竞争问题。

另外,task_group 结构体中还有个类型为 cfs_bandwidth 的字段,用于控制进程组对 CPU 资源的使用。cfs_bandwidth 结构体的定义如下:

struct cfs_bandwidth {
    ...
    ktime_t period;
    u64 quota;
    u64 runtime;
    ...
    struct hrtimer period_timer;
};

下面介绍一下 cfs_bandwidth 结构体各个字段的作用:

  • period:就是上面介绍的周期,用户可以通过修改 cgroup 的 cpu.cfs_period_us 文件进行设置。
  • quota:进程组在周期内能够运行的时间,用户可以通过修改 cgroup 的 cpu.cfs_quota_us 文件进行设置。
  • runtime:进程组在周期内剩余的可运行时间。
  • period_timer:定时器,每隔一个周期执行一次,主要用于更新 runtime 字段的值。

runtime 字段用于保存进程组在当前周期内剩余的可运行时间,如果调度器选中了进程组中某个进程进行运行时,将会减少进程组的剩余可运行时间。如下图所示:

在上图中,进程组 A 中的进程 D 被调度器选中运行。如果进程组 A 原来的可运行时间为 50 毫秒,而进程 D 运行了 10 毫秒。那么,进程组 A 的可运行时间将从会减少 10 毫秒,从而变为 40 毫秒。

在一个周期内,当进程组的可运行时间变为 0 时,那么此进程组将会被限制运行(称为 CPU Throttling),直到下一个周期开始。

当进程组被限制运行时,进程组内的所有进程都不能被执行。

当进程组开启了 CPU 限流功能时(也就是设置了 period 和 quota 的值),内核将会为其启动一个定时器。定时器每隔一个周期触发一次,用于更新进程组的可运行时间,从而解除进程组被限制运行的情况。

定时器通过调用 __refill_cfs_bandwidth_runtime() 函数来更新进程组的可运行时间,其代码如下:

void __refill_cfs_bandwidth_runtime(struct cfs_bandwidth *cfs_b)
{
    ...
    cfs_b->runtime = cfs_b->quota;
    ...
}

上面的代码将 quota 字段的值赋给了 runtime 字段,所以进程组重新获得了可运行时间,从而解除被限制运行的状态。

 

 


http://www.niftyadmin.cn/n/200361.html

相关文章

Live800:“以客户为中心”,企业如何落地?

以客户为中心不是什么新鲜论断,现代管理学之父——彼得德鲁克旗帜鲜明地提出:“企业的唯一目的就是创造顾客。”“客户决定着企业是什么、企业生产什么、企业是否会兴旺。” 如何创造顾客?以客户为中心?产品和服务是连接企业与客户…

python零基础实现基于旋转特征的自监督学习(一)——算法思路解析以及数据集读取

系列文章目录 基于旋转特征的自监督学习(一)——算法思路解析 基于旋转特征的自监督学习(一)——算法思路解析系列文章目录前言算法概述数据加载基于旋转特征的自监督学习数据加载器监督学习数据加载器前言 在本专栏的第一个项目…

python 读取视频有多少帧并将视频转为GIF动态图

目录 1 python读取视频帧 2 python 将MP4格式视频前500帧转为动态图 3 python 将MP4格式视频第2688到2890帧转为动态图,并将gif图片的七分之一列和后七分之一列裁掉 4 python 将MP4格式视频第2688到2890帧转为动态图,并将gif图片的七分之一行和后七分…

h5|web页面嵌套iframe传参给cocosCreator

h5|web页面嵌套iframe传参给cocosCreator 目录 一、快速浏览 二、详细实现与项目代码 三、安全性评估——iframe 实现效果: 一、快速浏览 在h5页面中,使用JavaScript获取需要传递的参数,如下: var token ZHESHINIDETOKEN; var phone 11…

ld: library not found for -lcrt0.o

ld: library not found for -lcrt0.o 背景: Mac 系统编译的时候报错 语言:golang 原因: 代码使用了静态编译,-static。stack overflow 上说 This option will not work on Mac OS X unless all libraries (including libgcc.a…

自学大数据第16天~Pig安装与配置及其他

Pig简介: Apache Pig是一个用于分析大型数据集的平台,它由用于表达数据分析程序的高级语言以及用于评估这些程序的基础架构组成。 Pig程序的显着特性是它们的结构适合大量的并行化,这反过来使它们能够处理非常大的数据集。 基础设施层: 目前&#xff…

可替换STM23G031的32位单片机

灵动微MM32G系列MCU。基于Arm Cortex M0内核,封装型号均引脚兼容业界主流G系列,为用户提供更多的MM32 MCU选择。与MM32F系列相比,MM32G系列对产品的引脚布局进行了全面优化,在保证效率和可靠性的基础上,升级工艺、压缩…

TCP协议二:TCP状态转换(重要)

TCP状态转换分析https://www.bilibili.com/video/BV1iJ411S7UA?p44&spm_id_frompageDriver&vd_sourced239c7cf48aa4f74eccfa736c3122e65 TCP状态转换图 粗实线:主动端 虚线: 被动端 细实线:内核操作 状态分析 CLOSED&#xff1…