TKE 标准集群指南

最佳实践

API 文档

诚邀爱技术、爱分享的你,成为文档内容共建者> HOT

为什么容器要设置 Request/Limit?

容器在运行时通常需要消耗 CPU/内存资源,假设没有任何配置的情况下,容器能使用的资源上限为当前所在的节点可被分配的资源量。

  • 一台节点通常会运行很多容器。
    假设一个节点上只有一个容器,那么这个容器在没有完全消耗节点资源的时间里,节点上空闲的资源被浪费了。现代一台普通的个人电脑通常可以运行数百个进程,同样的,一台节点通常会运行很多容器,但这引发了另外一个问题:容器之间可能抢夺资源,而节点本身的资源却是固定的。
  • 需要使用 Limit 控制容器资源使用上限。
    Kubernetes 的世界里,通过 Limit 来限定一个容器能使用的资源量上限,如果容器申请的资源量大于 Limit,它就会被压制用量甚至被驱逐到其它节点上。
  • 需要使用 Request 保证容器资源使用的下限。
    只设置 Limit 来控制容器资源使用上限就足够了吗?设想:如果一个10核的节点上运行了100个容器,但每个容器至少需要1核才能正常启动和运行,这时节点上的所有容器都无法正常运行。因此,Kubernetes 使用 Request 来保证容器最少的资源供给量。

总的来说,Kuberentes 使用 Request 和 Limit 来保证和限制一个容器使用的 CPU/内存的资源量。

CPU 和内存的单位是什么?

CPU

CPU 默认单位:核。您也可以使用带小数的 CPU 资源量。当您定义一个容器 CPU Request 为0.5时,所请求的 CPU 是请求1.0核 CPU 时的一半。同时,0.5等价于500m,可以看作 “500 millicpu”,读作“五百毫核”。

内存

内存默认单位:字节。您也可以使用普通的整数,或者带有 数量单位 后缀来表示内存。例如,以下表达式所代表的是大致相同的值:

128974848129e6、129M、128974848000m、123Mi

注意:

请注意后缀的大小写。例如,如果请求400m临时存储,实际上所请求的值是0.4字节。同理,如果申请400Mi字节(400Mi)或者400M字节,实际上所请求的值是0.4字节。

如何理解 Request/Limit?

Kubernetes 里的 Request/Limit 是通过 CPU Share 和 CPU Quota 技术实现的。

CPU Share

假设一个机器上运行多个容器,多个容器是如何分配资源的?您需要了解 CPU Shares 的概念。

CPU Shares 是属于一项 Linux Control Groups(cgroup)的特性,CPU Shares 控制容器中的进程可以使用的 CPU time。
CPU time 是 CPU 用于处理计算机程序或操作系统的指令的时间量,不是实际日常生活中的时间概念。例如进程进入中断、挂起、休眠等行为时,CPU time 不会增加,但进程恢复运行后 CPU time 会从中断前的时间点继续增加。

CPU Shares 特点

  1. CPU Shares 是相对的概念,不是绝对的含义。
    容器的 CPU Shares 是用于在不同容器之间调度 CPU time 的相对值。单独看 CPU Shares 的数字本身没有任何意义。例如,将一个容器 A 的 CPU Shares 设置为512,并不会提供有关容器将获得多少 CPU time 的信息。如果此时将另一个容器 B 的 CPU Shares 设置为1024,意味着 B 容器将获得两倍于 A 容器的 CPU time。也就是说,它仍然没有提供有关每个容器将获得的实际 CPU time 的信息,只有它们之间的相对量。如果 A、B 同时运行在一个3核的设备上,理论上每个时刻将分别获得1核和2核的 CPU。如果运行在6核的设备上,则分别获得2核和4核。如果运行在一个0.3核的设备上,则变成了0.1核和0.2核。
  2. CPU Shares 只有在资源竞争时才会发生。
    • 只有 A、B 容器期望在相同时间运行时,才会使用您设置的 CPU Shares 值去分配 CPU 核数。
    • 如果只有一个容器在运行,该容器可以用所有的 CPU。
    • 如果同时有多个容器在运行,则通过设置的 CPU Shares 值去分配节点上可分配的 CPU 核数。
    • 非运行中的容器即使配置 CPU Shares,也不会影响到运行中的容器关于 CPU time 的划分。
  3. CPU Shares 设计的目的在于最大化 CPU 资源的利用率。
    • 任何容器,不管 CPU Shares 值是多少,都有可能用到一台节点上的所有 CPU 资源。
    • 在 CPU 发生竞争时,可以通过 CPU Shares 值来判断每个容器到底该获得多少 CPU time。

CPU Quota

CPU Quota 是用来限制容器的资源使用上限,即使一个节点资源还有剩余量,但容器依旧无法使用超过 CPU Quota 的数值。

Kubernetes 中的 CPU Share

Kubernetes 的 Request/Limit 是由 CPU Share 和 CPU Quota 来实现的。但 Request 还有更多的含义:

  1. Request 是一个绝对值,不是相对值,保证一个容器的最小可用的资源量。
  2. Request 用来给调度器做判断,寻找集群可剩余调度资源量大于当前 Pod Request 的节点中,最优的节点用来调度当前 Pod。
  3. 在发生资源竞争时,会利用 CPU Share 的相对值概念,分配 CPU。

没有 Request 的 Pod

没有 Request 的 Pod 可以调度到任意节点,因为任意节点的剩余可调度资源都满足该 Pod 要求。但是在发生竞争时,它将不会获得任何的资源,此时 Pod 可能会无限期地缺乏资源。

实际应用

在终端里创建一个可以交互的 busybox Pod:

kubectl run -i --tty --rm busybox \
  --image=busybox \
  --restart=Never \
  --requests='cpu=50m,memory=50Mi' -- sh

在交互栏里使用如下命令让该 Pod 可以用满当前节点上空闲的 CPU 和内存:

while true; do true; done
dd if=/dev/zero of=/dev/shm/fill bs=1k count=1024k

在另一终端里查看当前 Pod 的资源用量

kubectl top pods
NAME      CPU(cores)   MEMORY(bytes)
busybox   460m         65Mi

可以看出,当前 busybox Pod 的 CPU 和内存的资源用量都大于 Request。但理论上因为 busybox 运行的是无限循环的程序,应该会把所有的 CPU 都消耗完才对,为什么只消耗了460m?因为此时集群中还有其他的 Pod 和进程,它们都会通过 CPU Share 彼此竞争集群中的 CPU 资源。

总结

  • Kubernetes 用 Request 保证容器对资源的最小用量。
  • Kubernetes 用 Limit 限制容器对资源的最大用量。
  • 输入数值的时候,要注意默认单位:CPU 默认单位:核;内存默认单位:字节。
  • 当发生资源竞争时,Kuberentes 根据不同容器对 Request 的申请量的比例分配资源。
目录