官方文档: 资源配额
资源配额 ResourceQuota
资源配额,通过 ResourceQuota 对象来定义,对每个 NameSpace 的资源消耗总量提供限制。它可以限制 NameSpace 中某种类型的对象的总数目上限,也可以限制 NameSpace 中的 Pod 可以使用的计算资源的总上限。
资源配额的工作方式如下:
- 不同的团队可以在不同的命名空间下工作,目前这是非约束性的,在未来的版本中可能会通过 ACL (Access Control List 访问控制列表) 来实现强制性约束。
- 集群管理员可以为每个命名空间创建一个或多个 ResourceQuota 对象。
- 当用户在 NameSpace 下创建资源(如 Pod、Service 等)时,Kubernetes 的 ResourceQuota 会跟踪集群的资源使用情况,以确保使用的资源用量不超过 ResourceQuota 中定义的硬性资源限额。
- 如果资源创建或者更新请求违反了配额约束,那么该请求会报错(HTTP 403 FORBIDDEN),并在消息中给出有可能违反的约束。
- 如果 NameSpace 下的计算资源(如 cpu 和 memory)的配额被启用,则用户必须为这些资源设定请求值(request)和约束值(limit),否则配额系统将拒绝 Pod 的创建。(提示: 可使用 LimitRanger 准入控制器来为没有设置计算资源需求的 Pod 设置默认值。)
在集群容量小于各命名空间配额总和的情况下,可能存在资源竞争。资源竞争时,Kubernetes 系统会遵循先到先得的原则。
不管是资源竞争还是配额的修改,都不会影响已经创建的资源使用对象。
启用资源配额
ResourceQuota 的支持在很多 Kubernetes 版本中是默认启用的。当 API 服务器的命令行标志 --enable-admission-plugins=
中包含 ResourceQuota
时,资源配额会被启用。
当 NameSpace 中存在一个 ResourceQuota 对象时,对于该命名空间而言,资源配额就是开启的。
计算 ResourceQuota
用户可以对给定 NameSpace 下的可被请求的 计算资源
总量进行限制。配额机制所支持的资源类型:
资源名称 | 描述 |
---|---|
limits.cpu | 所有非终止状态的 Pod,其 CPU 限额总量不能超过该值。 |
limits.memory | 所有非终止状态的 Pod,其内存限额总量不能超过该值。 |
requests.cpu | 所有非终止状态的 Pod,其 CPU 需求总量不能超过该值。 |
requests.memory | 所有非终止状态的 Pod,其内存需求总量不能超过该值。 |
hugepages-<size> | 对于所有非终止状态的 Pod,针对指定尺寸的巨页请求总数不能超过此值。 |
cpu | 与 requests.cpu 相同。 |
memory | 与 requests.memory 相同。 |
存储 ResourceQuota
用户可以对给定 NameSpace 下的存储资源总量进行限制。此外,还可以根据相关的存储类(Storage Class)来限制存储资源的消耗。
资源名称 | 描述 |
---|---|
requests.storage | 所有 PVC,存储资源的需求总量不能超过该值。 |
persistentvolumeclaims | 在该 NameSpace 中所允许的 PVC 总量。 |
<storage-class-name>.storageclass.storage.k8s.io/requests.storage | 在所有与 <storage-class-name> 相关的持久卷申请中,存储请求的总和不能超过该值。 |
<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims | 在与 <storage-class-name> 相关的所有持久卷申请中,NameSpace 中可以存在的持久卷申领总数。 |
例如,如果一个操作人员针对 gold 存储类型与 bronze 存储类型设置配额, 操作人员可以定义如下配额:
gold.storageclass.storage.k8s.io/requests.storage: 500Gi
bronze.storageclass.storage.k8s.io/requests.storage: 100Gi
其他扩展资源限制
在 Kubernetes 1.10 版本中,还添加了对 扩展资源 的支持。由于扩展资源不可超量分配,因此没有必要在配额中为同一扩展资源同时指定 requests 和 limits。对于扩展资源而言,目前仅允许使用前缀为 requests. 的配额项。以 GPU 拓展资源为例,如果资源名称为 nvidia.com/gpu
,并且要将 NameSpace 中请求的 GPU 资源总数限制为 4,则可以如下定义配额:
requests.nvidia.com/gpu: 4
ResourceQuota 配置示例
以下是一个基础的 ResourceQuota 配置示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21apiVersion: v1
kind: ResourceQuota # 资源类型
metadata:
name: resource-test # 资源配额的名称
labels:
app: resourcequota
spec:
hard:
pods: 50
requests.cpu: 0.5
requests.memory: 512Mi
limits.cpu: 5
limits.memory: 16Gi
configmaps: 20
requests.storage: 40Gi
persistentvolumeclaims: 20
replicationcontrollers: 20
secrets: 20
services: 50
services.loadbalancers: "2"
services.nodeports: "10"- pods: 限制最多启动Pod的个数
- requests.cpu: 限制最高的 CPU 请求数
- requests.memory: 限制最高内存的请求数
- limits.cpu: 限制最高CPU的limit上限
- limits.memory: 限制最高内存的limit上限
- configmaps: 限制最多创建的 ConfigMap 个数
- requests.storage: 限制存储的最大使用容量
- persistentvolumeclaims: 限制最多申请的 PVC 个数
限制范围 LimitRange
默认情况下,Kubernetes 集群上的容器运行使用的计算资源没有限制。使用 ResourceQuota ,集群管理员可以以 NameSpace 为单位,限制其资源的使用与创建。在 NameSpace 中,一个 Pod 或 Container 最多能够使用 NameSpace 的资源配额所定义的 CPU 和内存用量。LimitRange
是在 NameSpace 内限制资源的分配的策略,可以防止一个 Pod 或者 Container 使用所有的可用资源。
LimitRange 能够对以下对象进行限制:
- 在一个 NameSpace 中对每个 Pod 或 Container 使用内存和 CPU 的最小和最大值进行限制;
- 在一个 NameSpace 中对每个 PVC 能申请的最小和最大存储空间大小进行限制;
- 在一个 NameSpace 中对一种资源的 requests 值和 limits 值的控制;
- 设置一个 NameSpace 中对计算资源的默认 requests/limits,并且在运行时自动注入到多个 Container 中。
启用 LimitRange
Kubernetes 1.10 版本后默认启用对 LimitRange 的支持。LimitRange 支持在很多 Kubernetes 发行版本中也是默认启用的。
LimitRange 的总览
- 管理员在一个 NameSpace 内创建一个 LimitRange 对象。
- 用户在 NameSpace 内创建 Pod, Container 和 PersistentVolumeClaim 等资源。
- LimitRanger 准入控制器对所有没有设置计算资源需求的 Pod 和 Container 设置默认值与限制值,并跟踪其使用量以保证没有超出 NameSpace 中存在的任意 LimitRange 对象中的最小、最大资源使用量以及使用量比值。
- 若创建或更新资源(Pod、Container、PersistentVolumeClaim)时违反了 LimitRange 的约束,向 API 服务器的请求会失败,并返回 HTTP 状态码 403 FORBIDDEN 与描述哪一项约束被违反的消息。
- 若 NameSpace 中的 LimitRange 启用了对 cpu 和 memory 的限制,那么用户必须指定这些值的 requests 使用量与 limits 使用量。否则系统将会拒绝创建Pod。
- LimitRange 的验证仅在 Pod 准入阶段进行,不对正在运行的 Pod 进行验证。
LimitRange 配置示例
LimitRange 配置示例: 配置默认的 requests 和 limits
1
2
3
4
5
6
7
8
9
10
11
12
13apiVersion: v1
kind: LimitRange
metadata:
name: cpu-mem-limit-range
spec:
limits:
- default:
cpu: 1
memory: 512Mi
defaultRequest:
cpu: 0.5
memory: 256Mi
type: Container- default:默认 limits 配置
- defaultRequest: 默认 requests 配置
LimitRange 配置示例: requests 和 limits 的配置范围
1
2
3
4
5
6
7
8
9
10
11
12
13apiVersion: v1
kind: LimitRange
metadata:
name: cpu-min-max-demo-lr
spec:
limits:
- max:
cpu: "800m"
memory: 1Gi
min:
cpu: "200m"
memory: 500Mi
type: Container- max: 内存CPU的最大配置
- min: 内存CPU的最小配置
LimitRange配置示例: 限制申请存储空间的大小
1
2
3
4
5
6
7
8
9
10
11apiVersion: v1
kind: LimitRange
metadata:
name: storagelimits
spec:
limits:
- type: PersistentVolumeClaim
max:
storage: 2Gi
min:
storage: 1Gi- max: 最大PVC的空间
- min: 最小PVC的空间
服务质量 QoS
Kubernetes 使用 QoS 类来决定 Pod 的调度和驱逐策略,这里介绍怎么配置 Pod 的服务质量(QoS)类。
QoS 的类型
Kubernetes 创建 Pod 时就给它指定了下面的一种 QoS 类:
Guaranteed: 最高服务质量,当宿主机内存不够时,会先 kill 掉 QoS 为
BestEffort
和Burstable
的 Pod,如果内存还是不够,才会 kill 掉 QoS 为Guaranteed
的 Pod,该级别 Pod 的资源占用量一般比较明确,即requests
的 cpu 和 memory 和limits
的 cpu 和 memory 配置的一致。Burstable: 服务质量低于
Guaranteed
,当宿主机内存不够时,会先 kill 掉 QoS 为BestEffort
的 Pod,如果内存还是不够之后就会 kill 掉 QoS 级别为Burstable
的 Pod,用来保证 QoS 质量为Guaranteed
的 Pod,该级别 Pod 一般知道最小资源使用量,但是当机器资源充足时,还是想尽可能的使用更多的资源,即limits
字段的 cpu 和 memory 大于requests
的 cpu 和 memory 的配置。BestEffort: 当宿主机内存不够时,首先 kill 的就是该 QoS 的 Pod,用以保证
Burstable
和Guaranteed
级别的Pod正常运行。对于 QoS 类为BestEffort
的 Pod,Pod 中的容器必须没有设置内存和 CPU 限制或请求。
QoS 配置示例
创建一个命名空间 qos-example,以便练习以下示例
1
2# kubectl create ns qos-example
namespace/qos-example created
创建一个 QoS 类为 Guaranteed 的 Pod
对于 QoS 类为 Guaranteed 的 Pod:
- Pod 中的每个容器,包含初始化容器,必须指定内存请求和内存限制,并且两者要相等。
- Pod 中的每个容器,包含初始化容器,必须指定 CPU 请求和 CPU 限制,并且两者要相等。
下面是包含一个容器的 Pod 配置文件。容器设置了内存请求和内存限制,值都是 200 MiB。设置了 CPU 请求和 CPU 限制,值都是 700milli CPU:
创建 qos-pod.yaml 文件,内容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16apiVersion: v1
kind: Pod
metadata:
name: qos-demo
namespace: qos-example
spec:
containers:
- name: qos-demo-ctr
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "700m"
requests:
memory: "200Mi"
cpu: "700m"创建 Pod
1
2# kubectl create -f qos-pod.yml -n qos-example
pod/qos-demo created查看 Pod 详情
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21# kubectl get pod -n qos-example qos-demo -oyaml
apiVersion: v1
kind: Pod
metadata:
name: qos-demo
namespace: qos-example
spec:
containers:
- image: nginx
...
resources:
limits:
cpu: 700m
memory: 200Mi
requests:
cpu: 700m
memory: 200Mi
...
status:
...
qosClass: Guaranteed
创建一个 QoS 类为 Burstable 的 Pod
如果满足下面条件,将会指定 Pod 的 QoS 类为 Burstable:
- Pod 不符合 Guaranteed QoS 类的标准。
- Pod 中至少一个容器具有内存或 CPU 请求。
下面是包含一个容器的 Pod 配置文件。 容器设置了内存限制 200 MiB 和内存请求 100 MiB。
创建一个 qos-pod-2.yml 文件,内容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14apiVersion: v1
kind: Pod
metadata:
name: qos-demo-2
namespace: qos-example
spec:
containers:
- name: qos-demo-2-ctr
image: nginx
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"创建 Pod
1
2# kubectl create -f qos-pod-2.yml -n qos-example
pod/qos-demo-2 created查看 Pod 详情
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# kubectl get pod -n qos-example qos-demo-2 -oyaml
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-2
namespace: qos-example
spec:
containers:
...
resources:
limits:
memory: 200Mi
requests:
memory: 100Mi
...
status:
...
qosClass: Burstable
创建一个 QoS 类为 BestEffort 的 Pod
对于 QoS 类为 BestEffort 的 Pod,Pod 中的容器必须没有设置内存和 CPU 限制或请求。
创建一个 qos-pod-3.yaml 文件,内容如下:
1
2
3
4
5
6
7
8
9apiVersion: v1
kind: Pod
metadata:
name: qos-demo-3
namespace: qos-example
spec:
containers:
- name: qos-demo-3-ctr
image: nginx创建 Pod
1
2# kubectl create -f qos-pod-3.yaml -n qos-example
pod/qos-demo-3 created查看 Pod 详情
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# kubectl get pods -n qos-example qos-demo-3 -o yaml
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-3
namespace: qos-example
spec:
containers:
- image: nginx
...
resources: {}
...
status:
...
qosClass: BestEffort