特性
通过配置运行在集群内容器的CPU请求和限制,可以有效的利用集群上可用的CPU资源。把Pod CPU请求保持在较低的水平,可以使Pod更有机会被调度。通过使CPU限制大于CPU请求,可以完成两件事。
- Pod 可能会有突发性的活动,它可以利用碰巧可用的 CPU 资源。
- Pod 在突发负载期间可以使用的 CPU 资源数量仍被限制为合理的数量。
如果不指定CPU限制,有可能发生以下情况之一:
- 容器在可以使用的 CPU 资源上没有上限。因而可以使用所在节点上所有的可用 CPU 资源。
- 容器在具有默认 CPU 限制的名字空间中运行,系统会自动为容器设置默认限制。 集群管理员可以使用 LimitRange 指定 CPU 限制的默认值。
如果设置了CPU限制未设置CPU请求,Kubernetes 会自动设置CPU请求为限制的一样的值。
CPU 的单位
CPU 资源以 CPU 单位度量。Kubernetes 中的一个 CPU 等同于:
- 1 个 AWS vCPU
- 1 个 GCP核心
- 1 个 Azure vCore
- 裸机上具有超线程能力的英特尔处理器上的 1 个超线程
小数值是可以使用的。一个请求 0.5 CPU 的容器保证会获得请求 1 个 CPU 的容器的 CPU 的一半。 你可以使用后缀 m
表示毫。例如 100m
CPU、100 milliCPU 和 0.1 CPU 都相同。 精度不能超过 1m。
CPU 请求只能使用绝对数量,而不是相对数量。0.1 在单核、双核或 48 核计算机上的 CPU 数量值是一样的。
比如 500m 等同于 0.5 CPU。所以以后在资源清单中看见CPU的书写为 1 CPU 或 1000m 的时候要知道它们是相等的。
最佳实践
创建一个名为 cpu-example
的 namespace,在此空间下创建的资源与集群的其余部分资源隔离。
kubectl create namespace cpu-example
要为容器指定CPU请求与限制只需要在 resources.requests
与 resource.limits
中增加 cpu
清单即可。以下的例子将创建一个Pod并请求0.5CPU并最多限制1CPU。
cpu-request-limit.yaml
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo
namespace: cpu-example
spec:
containers:
- name: cpu-demo-ctr
image: ghcr.io/colinianking/stress-ng
resources:
limits:
cpu: "1"
requests:
cpu: "0.5"
command:
- stress-ng
args:
- --cpu
- "2"
可以看在启动参数中 --cpu
尝试使用 2CPU。猜想下会发生什么呢?
- Pod 无法调度?
- 虽然尝试使用 2CPU 但限制了最多 1CPU ,所以最终结果应该是 1CPU 左右。
创建Pod
kubectl create -f cpu-request-limit.yaml
查看Pod的运行状态
kubectl get pods -n cpu-example
查看关于Pod的详细信息
kubectl get pod cpu-demo --output=yaml -n cpu-example
输出显示 Pod 中的一个容器的 CPU 请求为 500 milliCPU,并且 CPU 限制为 1 个 CPU。
resources:
limits:
cpu: "1"
requests:
cpu: 500m
使用 kubectl top
命令来获取该 Pod 的指标:
kubectl top pod cpu-demo -n cpu-example
输出显示 Pod 使用的是 1000 milliCPU,与我们配置限制 1CPU是相符合的。
NAME CPU(cores) MEMORY(bytes)
cpu-demo 1000m 9Mi
说明:
CPU 使用率低于 1.0 的另一种可能的解释是,节点可能没有足够的 CPU 资源可用。
删除 Pod
kubectl delete -f cpu-request-limit.yaml
如果设置请求CPU大于节点的所拥有的CPU资源会发生什么?
猜想:
- Pod 无法进行调度?
- Pod运行后会全部占用该节点所有的CPU资源?
CPU 请求和限制与都与容器相关, Pod 对 CPU 用量的请求等于 Pod 中所有容器的请求数量之和。 同样,Pod 的 CPU 资源限制等于 Pod 中所有容器 CPU 资源限制数之和。
Pod 调度是基于资源请求值来进行的。 仅在某节点具有足够的 CPU 资源来满足 Pod CPU 请求时。创建以下例子来进行验证:
cpu-request-limit1.yaml
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo-1
namespace: cpu-example
spec:
containers:
- name: cpu-demo-ctr
image: ghcr.io/colinianking/stress-ng
resources:
limits:
cpu: "100"
requests:
cpu: "100"
command:
- stress-ng
args:
- --cpu
- "2"
创建Pod
kubectl create -f cpu-request-limit1.yaml
查看Pod的运行状态
kubectl get pods -n cpu-example
#Output:
NAME READY STATUS RESTARTS AGE
cpu-demo-1 0/1 Pending 0 5s
查看有关 Pod 的详细信息,包含事件:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 3m39s default-scheduler 0/3 nodes are available: 1 node(s) had untolerated taint {node-role.kubernetes.io/control-plane: }, 2 Insufficient cpu. preemption: 0/3 nodes are available: 1 Preemption is not helpful for scheduling, 2 No preemption victims found for incoming pod..
输出显示Pod处于Pending状态是无法进行调度的。因为当前节点只有4CPU,而请求 100 CPU远远大于 4CPU。从而导致Pod无法进行调度。
清理资源
kubectl delete namespace cpu-example
清理 namespace 会清理掉该空间下的所有资源。