如何理解Kubernetes资源限制CPU


这篇文章将为大家详细讲解有关如何理解Kubernetes资源限制CPU,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。Requests 和 Limits 之间的区别,其中Requests用于在调度时通知调度器 Pod 需要多少资源才能调度,而Limits用来告诉 Linux 内核什么时候你的进程可以为了清理空间而被杀死。我会继续仔细分析 CPU 资源限制。正如我在上一篇文章中提到的,CPU资源限制比内存资源限制更复杂,原因将在下文详述。幸运的是CPU资源限制和内存资源限制一样都是由cgroup控制的,上文中提到的思路和工具在这里同样适用,我们只需要关注他们的不同点就行了。首先,让我们将 CPU 资源限制添加到之前示例中的 yaml:Copy单位后缀m表示千分之一核,也就是说1 Core = 1000m。因此该资源对象指定容器进程需要50/1000核(5%)才能被调度,并且允许最多使用100/1000核(10%)。同样,2000m表示两个完整的 CPU 核心,你也可以写成2或者2.0。为了了解 Docker 和 cgroup 如何使用这些值来控制容器,我们首先创建一个只配置了 CPUrequests的 Pod:Copy通过 kubectl 命令我们可以验证这个 Pod 配置了50m的 CPU requests:Copy我们还可以看到 Docker 为容器配置了相同的资源限制:Copy这里显示的为什么是51,而不是50?这是因为 Linux cgroup 和 Docker 都将 CPU 核心数分成了1024个时间片(shares),而 Kubernetes 将它分成了1000个 shares。shares 用来设置 CPU 的相对值,并且是针对所有的 CPU(内核),默认值是 1024,假如系统中有两个 cgroup,分别是 A 和 B,A 的 shares 值是 1024,B 的 shares 值是 512,那么 A 将获得 1024/(1204+512)=66% 的 CPU 资源,而 B 将获得 33% 的 CPU 资源。shares 有两个特点:如果 A 不忙,没有使用到 66% 的 CPU 时间,那么剩余的 CPU 时间将会被系统分配给 B,即 B 的 CPU 使用率可以超过 33%。如果添加了一个新的 cgroup C,且它的 shares 值是 1024,那么 A 的限额变成了 1024/(1204+512+1024)=40%,B 的变成了 20%。
从上面两个特点可以看出:在闲的时候,shares 基本上不起作用,只有在 CPU 忙的时候起作用,这是一个优点。由于 shares 是一个绝对值,需要和其它 cgroup 的值进行比较才能得到自己的相对限额,而在一个部署很多容器的机器上,cgroup 的数量是变化的,所以这个限额也是变化的,自己设置了一个高的值,但别人可能设置了一个更高的值,所以这个功能没法精确的控制 CPU 使用率。与配置内存资源限制时 Docker 配置容器进程的内存 cgroup 的方式相同,设置 CPU 资源限制时 Docker 会配置容器进程的cpu,cpuacctcgroup:CopyDocker 容器的HostConfig.CpuShares属性映射到 cgroup 的cpu.shares属性,可以验证一下:Copy你可能会很惊讶,设置了 CPU requests 竟然会把值传播到cgroup,而在上一篇文章中我们设置内存 requests 时并没有将值传播到 cgroup。这是因为内存的soft limit内核特性对 Kubernetes 不起作用,而设置了cpu.shares却对 Kubernetes 很有用。后面我会详细讨论为什么会这样。现在让我们先看看设置 CPUlimits时会发生什么:Copy再一次使用 kubectl 验证我们的资源配置:Copy查看对应的 Docker 容器的配置:Copy可以明显看出,CPU requests 对应于 Docker 容器的HostConfig.CpuShares属性。而 CPU limits 就不太明显了,它由两个属性控制:HostConfig.CpuPeriodHostConfig.CpuQuota。Docker 容器中的这两个属性又会映射到进程的cpu,couacctcgroup 的另外两个属性:cpu.cfs_period_uscpu.cfs_quota_us。我们来看一下:Copy如我所说,这些值与容器配置中指定的值相同。但是这两个属性的值是如何从我们在 Pod 中设置的100mcpu limits 得出的呢,他们是如何实现该 limits 的呢?这是因为 cpu requests 和 cpu limits 是使用两个独立的控制系统来实现的。Requests 使用的是 cpushares系统,cpu shares 将每个 CPU 核心划分为1024个时间片,并保证每个进程将获得固定比例份额的时间片。如果总共有 1024 个时间片,并且两个进程中的每一个都将cpu.shares设置为512,那么它们将分别获得大约一半的 CPU 可用时间。但 cpu shares 系统无法精确控制 CPU 使用率的上限,如果一个进程没有设置 shares,则另一个进程可用自由使用 CPU 资源。大约在 2010 年左右,谷歌团队和其他一部分人注意到了这个问题。为了解决这个问题,后来在 linux 内核中增加了第二个功能更强大的控制系统:CPU 带宽控制组。带宽控制组定义了一个周期,通常为1/10秒(即 100000 微秒)。还定义了一个配额,表示允许进程在设置的周期长度内所能使用的 CPU 时间数,两个文件配合起来设置CPU的使用上限。两个文件的单位都是微秒(us),cfs_period_us的取值范围为 1 毫秒(ms)到 1 秒(s),cfs_quota_us的取值大于 1ms 即可,如果 cfs_quota_us 的值为-1默认值),表示不受 CPU 时间的限制。下面是几个例子:Copy在本例中我们将 Pod 的 cpu limits 设置为100m,这表示100/1000个 CPU 核心,即100000微秒的 CPU 时间周期中的10000。所以该 limits 翻译到cpu,cpuacctcgroup 中被设置为cpu.cfs_period_us=100000cpu.cfs_quota_us=10000。顺便说一下,其中的cfs代表Completely Fair Scheduler(绝对公平调度),这是 Linux 系统中默认的 CPU 调度算法。还有一个实时调度算法,它也有自己相应的配额值。现在让我们来总结一下:在 Kubernetes 中设置的 cpu requests 最终会被 cgroup 设置为cpu.shares属性的值, cpu limits 会被带宽控制组设置为cpu.cfs_period_uscpu.cfs_quota_us属性的值。与内存一样,cpu requests 主要用于在调度时通知调度器节点上至少需要多少个 cpu shares 才可以被调度。与 内存 requests 不同,设置了 cpu requests 会在 cgroup 中设置一个属性,以确保内核会将该数量的 shares 分配给进程。cpu limits 与 内存 limits 也有所不同。如果容器进程使用的内存资源超过了内存使用限制,那么该进程将会成为oom-killing的候选者。但是容器进程基本上永远不能超过设置的 CPU 配额,所以容器永远不会因为尝试使用比分配的更多的 CPU 时间而被驱逐。系统会在调度程序中强制进行 CPU 资源限制,以确保进程不会超过这个限制。如果你没有在容器中设置这些属性,或将他们设置为不准确的值,会发生什么呢?与内存一样,如果只设置了 limits 而没有设置 requests,Kubernetes 会将 CPU 的 requests 设置为 与 limits 的值一样。如果你对你的工作负载所需要的 CPU 时间了如指掌,那再好不过了。如果只设置了 CPU requests 却没有设置 CPU limits 会怎么样呢?这种情况下,Kubernetes 会确保该 Pod 被调度到合适的节点,并且该节点的内核会确保节点上的可用 cpu shares 大于 Pod 请求的 cpu shares,但是你的进程不会被阻止使用超过所请求的 CPU 数量。既不设置 requests 也不设置 limits 是最糟糕的情况:调度程序不知道容器需要什么,并且进程对 cpu shares 的使用是无限制的,这可能会对 node 产生一些负面影响。最后我还想告诉你们的是:为每个 pod 都手动配置这些参数是挺麻烦的事情,kubernetes 提供了LimitRange资源,可以让我们配置某个 namespace 默认的 request 和 limit 值。通过上文的讨论大家已经知道了忽略资源限制会对 Pod 产生负面影响,因此你可能会想,如果能够配置某个 namespace 默认的 request 和 limit 值就好了,这样每次创建新 Pod 都会默认加上这些限制。Kubernetes 允许我们通过LimitRange资源对每个命名空间设置资源限制。要创建默认的资源限制,需要在对应的命名空间中创建一个LimitRange资源。下面是一个例子:Copy这里的几个字段可能会让你们有些困惑,我拆开来给你们分析一下。l 香港云主机imits字段下面的default字段表示每个 Pod 的默认的limits配置,所以任何没有分配资源的 limits 的 Pod 都会被自动分配100Milimits 的内存和100mlimits 的 CPU。defaultRequest字段表示每个 Pod 的默认requests配置,所以任何没有分配资源的 requests 的 Pod 都会被自动分配50Mirequests 的内存和50mrequests 的 CPU。maxmin字段比较特殊,如果设置了这两个字段,那么只要这个命名空间中的 Pod 设置的limitsrequests超过了这个上限和下限,就不会允许这个 Pod 被创建。我暂时还没有发现这两个字段的用途,如果你知道,欢迎在留言告诉我。LimitRange中设定的默认值最后由 Kubernetes 中的准入控制器LimitRanger插件来实现。准入控制器由一系列插件组成,它会在 API 接收对象之后创建 Pod 之前对 Pod 的Spec字段进行修改。对于LimitRanger插件来说,它会检查每个 Pod 是否设置了 limits 和 requests,如果没有设置,就给它配置LimitRange中设定的默认值。通过检查 Pod 中的annotations注释,你可以看到LimitRanger插件已经在你的 Pod 中设置了默认值。例如:关于如何理解Kubernetes资源限制CPU就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

相关推荐: python列表基本使用方法是什么

这篇“python列表基本使用方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“python列表基本使用方法是什么”文章吧。1、列表是写在…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

Like (0)
Donate 微信扫一扫 微信扫一扫
Previous 08/12 16:02
Next 08/12 16:02

相关推荐