前言

Kubernetes中资源管理保障机制:

  • 通过资源限额来确保不同的Pod只能占用指定的资源。
  • 允许集群的资源被超额分配,以提高集群的资源利用率。
  • 不同等级的Pod有不同的服务质量(QoS),资源不足时,低等级Pod会被优先清理,以确保高等级Pod稳定运行。

程序使用的 CPU 与 Memory 是一个动态的量。负载增减时,CPU 和 MEM 的使用量会相应的增减。因此最准确的说法是:某个进程 CPU 使用量为 0.1个CPU~1个CPU,内存占用为 500MB~1GB 。

对应到 Kubernetes 的 Pod 容器上,是4个参数:

  • spec.container[].resources.requests.cpu
  • spec.container[].resources.limits.cpu
  • spec.container[].resources.requests.memory
  • spec.container[].resources.limits.memory

基于Requests和Limits的Pod调度机制:

kubelet 在启动 Pod 的某个容器时,会将容器的 Requests 和 Limits 值转化为相应的容器启动参数传递给容器执行器。

当一个Pod创建后,Kubernetes调度器(Scheduler)会为此Pod选择运行节点。调度器在调度时,首先要确保调度后该节点上所有Pod的 CPU 和 MEM 的 Requests 总和不超过该节点能提供对应资源的最大容量值。

资源配置范围管理(LimitRange)

前言

默认情况下 Kubernetes 不会对 Pod 加上 CPU 和 MEM 限制,通过配置 Requests 和 Limits 可限制其资源使用。对于集群管理员而言,每个 Pod 都配置 Requests 和 Limits 是烦琐的,故可对集群内 Requests 和 Limits 配置做全局限制。

常见全局配置场景:

  • 集群由两个团队共享,分别运行生产环境和开发环境。生产环境上运行的服务限额 8GB,开发环境上运行的服务限额 512MB。集群管理员可以为两个环境创建不同的命名空间,并为每个命名空间设置不同的限制
  • 用户创建Pod时使用的资源可能会刚好比整个机器资源的上限稍小,而恰好剩下的资源大小非常尴尬:不足以运行其他任务但整个集群加起来又非常浪费。因此,集群管理员希望设置每个Pod都必须至少使用集群平均资源值(CPU和内存)的20%,这样集群能够提供更好的资源一致性的调度,从而减少了资源浪费。

针对这些需求,Kubernetes提供了LimitRange机制。

示例

创建LimitRange

1、创建一个Namespace
# kubectl create ns limit-example

2、设置LimitRange

  1. apiVersion: v1
  2. kind: LimitRange
  3. metadata:
  4. name: mylimits
  5. spec:
  6. limits:
  7. - max:
  8. cpu: "4"
  9. memory: 2Gi
  10. min:
  11. cpu: 200m
  12. memory: 6Mi
  13. maxLimitRequestRatio:
  14. cpu: 3
  15. memory: 2
  16. type: Pod
  17. - default:
  18. cpu: 300m
  19. memory: 200Mi
  20. defaultRequest:
  21. cpu: 200m
  22. memory: 100Mi
  23. max:
  24. cpu: "2"
  25. memory: 1Gi
  26. min:
  27. cpu: 100m
  28. memory: 3Mi
  29. maxLimitRequestRatio:
  30. cpu: 5
  31. memory: 4
  32. type: Container

3、创建
# kubectl apply -f limits.yaml —namespace=limit-example

4、查看

# kubectl describe limits mylimits -n limit-example
Name:       mylimits
Namespace:  limit-example
Type        Resource  Min   Max  Default Request  Default Limit  Max Limit/Request Ratio
----        --------  ---   ---  ---------------  -------------  -----------------------
Pod         memory    6Mi   2Gi  -                -              2
Pod         cpu       200m  4    -                -              3
Container   cpu       100m  2    200m             300m           5
Container   memory    3Mi   1Gi  100Mi            200Mi          4

配置说明:

  • 在 LimitRange 中,对于 CPU 和 MEM ,Pod 和 Container 都可以设置 Min、Max 和 Max Limit、Requests Ratio参数。Container还可以设置 Default Request 和 Default Limit 参数,而Pod不能。
  • 参数解释:
    • Container 的 Min(100m和3Mi)是Pod中所有容器的 Requests 值下限,Max(2和1Gi)是Pod中所有容器的 Limits 值上限
    • Container 的 Default Request(200m和100Mi)是Pod中所有未指定 Requests 值的容器的默认 Requests 值;Default Limit(300m和200Mi)同理
    • Pod 的 Min(200m和6Mi)是Pod中所有容器的 Requests 值的总和下限,Max(4和2Gi)是Pod中所有容器的 Limits 值的总和上限。
    • Container 的 Max Limit/Requests Ratio(5和4)限制 Pod 中所有容器的 Limits 值与 Requests 值的比例上限
    • Pod 的 Max Limit/Requests Ratio(3和2)限制 Pod 中所有容器的 Limits 值总和与 Requests 值总和的比例上限
  • 若设置了 Container 的 Max,则所有容器必须设置 Limits,否则无法成功创建。当 Pod 内的容器未配置 Limits 时,将使用 Default Limit 值(300m 200MiB)。若 Default Limit 也未配置,Pod 无法成功创建。Container 的 Min 同理。
  • 信息显示:
    • Pod 中所有容器的 Requests 总和必须大于或等于 6MiB,且所有容器的 Limits 总和必须小于或等于 1GiB;同理,所有容器的 CPU Requests 总和必须大于或等于 200m,且所有容器的 CPU Limits 总和必须小于或等于 2 。
    • Pod 中的所有容器的 Limits 与 Requests 的比例都不能超过 Container 的 Max Limit/Requests Ratio 值;Pod 中所有容器的 Limits 总和与 Requests 总和的比例不能超过 Pod 的 Max Limit/Requests Ratio 值。

Pod装备LimitRange限制

命名空间中 LimitRange 仅在 Pod 创建或更新时执行检查。当修改 LimitRange 值时,已经在该命名空间中创建好的 Pod 不会生效。当配置的资源值超过了 LimitRange 的限制,该创建过程会报错。

展示 Pod 配置默认限制流程:

场景一:创建 Pod 不配置资源限额,其将使用 namespace limit-example 中的默认定义值

创建
# kubectl run nginx —image=nginx —replicas=1 -n limit-example

查看
# kubectl get pods -n limit-example
image.png
# kubectl get pods nginx-6db489d4b7-rnfwh -n limit-example -o yaml | grep resources -C5
image.png

场景二:创建超出资源限制的 Pod

apiVersion: v1
kind: Pod
metadata:
  name: invalid-pod
spec:
  containers:
  - name: busybox
    image: busybox
    resources:
      limits:
        cpu: "3"
        memory: 100Mi
# 创建Pod时出现报错,原因是超过资源限制
$ kubectl create -f invalid-pod.yaml -n limit-example
Error from server (Forbidden): error when creating "invalid-pod.yaml": pods "invalid-pod" is forbidden: maximum cpu usage per Container is 2, but limit is 3

场景三:展示 LimitRange 对 maxLimitRequestRatio 的限制过程

apiVersion: v1
kind: Pod
metadata:
  name: limit-test-nginx
  namespace: limit-example
  labels:
    name: limit-test-nginx
spec:
  containers:
  - name: limit-test-nginx
    image: nginx
    resources:
      limits:
        cpu: "1"
        memory: 512Mi
      requests:
        cpu: "0.8"
        memory: 250Mi
$ kubectl apply -f limit-test-nginx.yaml
Error from server (Forbidden): error when creating "limit-test-nginx.yaml": pods "limit-test-nginx" is forbidden: memory max limit to request ratio per Pod is 2, but provided ratio is 2.048000

Pod 内存 Limits 总和与 Requests 总和比例为 512∶250,大于在 LimitRange 中定义的Pod的最大比率2(maxLimitRequestRatio.memory),故创建失败。

资源服务质量管理(Resource QoS)

在 Kubernetes 资源服务质量控制(QoS)体系中,要保证高可靠性的 Pod 可以申请可靠资源,而一些不需要高可靠性的 Pod 可以申请可靠性较低或者不可靠的资源。

Pod 的 Requests 和 Limits 资源配置特点:

  • 若Pod配置的Requests值等于Limits值,那么该Pod可以获得的资源是完全可靠的。
  • 若Pod的Requests值小于Limits值,该Pod获得的资源可分成两部分:
    • 完全可靠的资源,资源量的大小等于Requests值
    • 不可靠的资源,资源量最大等于Limits与Requests的差额,能够申请到多少取决于当时主机上容器可用资源的余量

通过这种机制,Kubernetes 可以实现节点资源的超售。比如在 CPU 完全充足的情况下,某机器共有 32GiB 内存可提供给容器使用,容器配置 Requests 值 1GiB,Limits 值为 2GiB,那么在该机器上最多可以同时运行 32 个容器,每个容器最多可以使用 2GiB 内存,如果这些容器的内存使用峰值能错开,那么所有容器都可以正常运行。

超售机制能有效提高资源的利用率,同时不会影响容器申请的完全可靠资源的可靠性。

服务质量等级(QoS Classes)

在一个超用(Over Committed,容器Limits总和大于系统容量上限)系统中,由于容器负载的波动可能导致操作系统的资源不足,最终可能导致部分容器被杀掉。在这种情况下,会优先杀掉那些不太重要的容器,那么如何衡量重要程度呢?

Kubernetes 将容器划分成三个 QoS 等级:

  • Guaranteed(完全可靠)
  • Burstable(弹性波动、较可靠)
  • BestEffort(尽力而为、不太可靠)

当节点资源不足时, Pods 被 kill 掉的顺序如下:

  • Best-Effort Pods:该类型 Pods 会最先被 kill 掉
  • Burstable Pods:没有 Best-Effort 类型容器可以被 kill 时,该类型的 Pods 会被 kill 掉
  • Guaranteed Pods:没有 Burstable 与 Best-Effort 类型的容器可以被 kill 时,该类型的 pods 会被 kill 掉

Guaranteed

若 Pod 中所有容器对所有资源类型都定义 Limits 和 Requests ,且 Limits 值和 Requests 值相等(且都不为0),则此 Pod 的 QoS 级别是Guaranteed。

在这种情况下,容器可以不定义 Requests,因为 Requests 值在未定义时默认等于 Limits 。

示例
image.png

Burstable

Burstable 级别的 Pod 包括两种情况:

  • Pod中部分容器定义了 Requests 和 Limits(都不为0),且 Requests 值小于 Limits 值
  • Pod中部分容器未定义 Requests 和 Limits

示例:容器 foo 的 CPU Requests 不等于 Limits
image.png

BestEffort

若 Pod 中未定义 Requests 和 Limits ,该 Pod 的 QoS 级别是 BestEffort 。

资源配额管理(Resource Quotas)

当一个 Kubernetes 集群被多个用户或多个团队共享时,通过 Resource Quota 对象可以定义资源配额,可以限制不同命名空间中某种类型对象的总数目上限,也可以设置 Pod 能用的计算资源的总上限。

资源配额使用场景:

  • 不同的团队工作在不同的命名空间下
  • 集群中的每个命名空间都创建资源配额项
  • 当启用命名空间中的资源配额,用户必须为相应的资源类型设置Requests或Limits,否则Pod创建会失败。可使用LimitRange机制为没有配置资源限额的Pod提供默认配置

资源配额可以通过在 kube-apiserver 的 —admission-control 参数值中添加 ResourceQuota 参数进行开启。一个命名空间可以有多个 ResourceQuota 配置项。

1)计算资源配额(Compute Resource Quota)
image.png

2)存储资源配额(Volume Count Quota)
image.png

3)对象数量配额(Object Count Quota)
image.png