第 5 章 配额
5.1. 项目的资源配额
资源配额由 ResourceQuota 对象定义,提供约束来限制各个项目的累计资源消耗。它可根据类型限制项目中创建的对象数量,以及该项目中资源可以消耗的计算资源和存储的总和。
本指南阐述了资源配额如何工作,集群管理员如何以项目为基础设置和管理资源配额,以及开发人员和集群管理员如何查看配额。
5.1.1. 配额管理的资源
下方描述了可通过配额管理的一系列计算资源和对象类型。
如果 status.phase in (Failed, Succeeded)
为 true,则 Pod 处于终端状态。
资源名称 | 描述 |
---|---|
|
非终端状态的所有 Pod 的 CPU 请求总和不能超过这个值。 |
|
非终端状态的所有 Pod 的内存请求总和不能超过这个值。 |
|
非终端状态的所有 Pod 的本地临时存储请求总和不能超过这个值。 |
|
非终端状态的所有 Pod 的 CPU 请求总和不能超过这个值。 |
|
非终端状态的所有 Pod 的内存请求总和不能超过这个值。 |
|
非终端状态的所有 Pod 的临时存储请求总和不能超过这个值。 |
| 非终端状态的所有 Pod 的 CPU 限值总和不能超过这个值。 |
| 非终端状态的所有 Pod 的内存限值总和不能超过这个值。 |
| 非终端状态的所有 Pod 的临时存储限值总和不能超过这个值。只有在您启用了临时存储技术预览时,此资源才可用。此功能默认为禁用。 |
资源名称 | 描述 |
---|---|
| 处于任何状态的所有持久性卷声明的存储请求总和不能超过这个值。 |
| 项目中可以存在的持久性卷声明的总数。 |
| 在处于任何状态且具有匹配存储类的所有持久性卷声明中,存储请求总和不能超过这个值。 |
| 项目中可以存在的具有匹配存储类的持久性卷声明的总数。 |
资源名称 | 描述 |
---|---|
| 项目中可以存在的处于非终端状态的 Pod 总数。 |
| 项目中可以存在的 ReplicationController 的总数。 |
| 项目中可以存在的资源配额总数。 |
| 项目中可以存在的服务总数。 |
|
项目中可以存在的 |
|
项目中可以存在的 |
| 项目中可以存在的 secret 的总数。 |
|
项目中可以存在的 |
| 项目中可以存在的持久性卷声明的总数。 |
| 项目中可以存在的镜像流的总数。 |
5.1.2. 配额范围
每个配额都有一组关联的范围。配额只在与枚举的范围交集匹配时才会测量资源的使用量。
为配额添加范围会限制该配额可应用的资源集合。指定允许的集合之外的资源会导致验证错误。
影响范围 | 描述 |
|
匹配 |
|
匹配 |
|
匹配 |
|
匹配 |
BestEffort
范围将配额仅限为限制以下资源:
-
pods
Terminating
、NotTerminating
和 NotBestEffort
范围将配额仅限为跟踪以下资源:
-
pods
-
memory
-
requests.memory
-
limits.memory
-
cpu
-
requests.cpu
-
limits.cpu
-
ephemeral-storage
-
requests.ephemeral-storage
-
limits.ephemeral-storage
只有在启用了临时存储技术预览功能时,才会应用临时存储请求和限值。此功能默认为禁用。
5.1.3. 配额强制
在项目中首次创建资源配额后,项目会限制您创建可能会违反配额约束的新资源,直到它计算了更新后的使用量统计。
在创建了配额并且更新了使用量统计后,项目会接受创建新的内容。当您创建或修改资源时,配额使用量会在请求创建或修改资源时立即递增。
在您删除资源时,配额使用量在下一次完整重新计算项目的配额统计时才会递减。可配置的时间量决定了将配额使用量统计降低到其当前观察到的系统值所需的时间。
如果项目修改超过配额使用量限值,服务器会拒绝该操作,并将对应的错误消息返回给用户,解释违反了配额约束,并说明系统中目前观察到的使用量统计。
5.1.4. 请求与限值
在分配计算资源时,每个容器可能会为 CPU、内存和临时存储各自指定请求和限制值。配额可以限制任何这些值。
如果配额具有为 requests.cpu
或 requests.memory
指定的值,那么它要求每个传入的容器都明确请求那些资源。如果配额具有为 limits.cpu
或 limits.memory
指定的值,那么它要求每个传入的容器为那些资源指定一个显性限值。
5.1.5. 资源配额定义示例
core-object-counts.yaml
apiVersion: v1 kind: ResourceQuota metadata: name: core-object-counts spec: hard: configmaps: "10" 1 persistentvolumeclaims: "4" 2 replicationcontrollers: "20" 3 secrets: "10" 4 services: "10" 5 services.loadbalancers: "2" 6
openshift-object-counts.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: openshift-object-counts
spec:
hard:
openshift.io/imagestreams: "10" 1
- 1
- 项目中可以存在的镜像流的总数。
compute-resources.yaml
apiVersion: v1 kind: ResourceQuota metadata: name: compute-resources spec: hard: pods: "4" 1 requests.cpu: "1" 2 requests.memory: 1Gi 3 requests.ephemeral-storage: 2Gi 4 limits.cpu: "2" 5 limits.memory: 2Gi 6 limits.ephemeral-storage: 4Gi 7
besteffort.yaml
apiVersion: v1 kind: ResourceQuota metadata: name: besteffort spec: hard: pods: "1" 1 scopes: - BestEffort 2
compute-resources-long-running.yaml
apiVersion: v1 kind: ResourceQuota metadata: name: compute-resources-long-running spec: hard: pods: "4" 1 limits.cpu: "4" 2 limits.memory: "2Gi" 3 limits.ephemeral-storage: "4Gi" 4 scopes: - NotTerminating 5
compute-resources-time-bound.yaml
apiVersion: v1 kind: ResourceQuota metadata: name: compute-resources-time-bound spec: hard: pods: "2" 1 limits.cpu: "1" 2 limits.memory: "1Gi" 3 limits.ephemeral-storage: "1Gi" 4 scopes: - Terminating 5
storage-consumption.yaml
apiVersion: v1 kind: ResourceQuota metadata: name: storage-consumption spec: hard: persistentvolumeclaims: "10" 1 requests.storage: "50Gi" 2 gold.storageclass.storage.k8s.io/requests.storage: "10Gi" 3 silver.storageclass.storage.k8s.io/requests.storage: "20Gi" 4 silver.storageclass.storage.k8s.io/persistentvolumeclaims: "5" 5 bronze.storageclass.storage.k8s.io/requests.storage: "0" 6 bronze.storageclass.storage.k8s.io/persistentvolumeclaims: "0" 7
5.1.6. 创建配额
您可以通过创建配额,来约束给定项目中的资源使用量。
流程
- 在一个文件中定义配额。
使用该文件创建配额,并将其应用到项目:
$ oc create -f <file> [-n <project_name>]
例如:
$ oc create -f core-object-counts.yaml -n demoproject
5.1.6.1. 创建对象数配额
您可以针对所有 OpenShift Container Platform 标准命名空间资源类型创建对象数配额,如 BuildConfig
和 DeploymentConfig
。对象配额数将定义的配额施加于所有标准命名空间资源类型。
在使用资源配额时,如果服务器存储中存在某一对象,则从其配额中扣减。这些类型的配额对防止耗尽存储资源很有用处。
流程
为资源配置对象数配额:
运行以下命令:
$ oc create quota <name> \ --hard=count/<resource>.<group>=<quota>,count/<resource>.<group>=<quota> 1
- 1
<resource>
是资源名称,<group>
则是 API 组(若适用)。使用oc api-resources
命令可以列出资源及其关联的 API 组。
例如:
$ oc create quota test \ --hard=count/deployments.extensions=2,count/replicasets.extensions=4,count/pods=3,count/secrets=4 resourcequota "test" created
本例将列出的资源限制为集群中各个项目的硬限值。
验证是否创建了配额:
$ oc describe quota test Name: test Namespace: quota Resource Used Hard -------- ---- ---- count/deployments.extensions 0 2 count/pods 0 3 count/replicasets.extensions 0 4 count/secrets 0 4
5.1.6.2. 为扩展资源设定资源配额
扩展资源不允许过量使用资源,因此您必须在配额中为相同扩展资源指定 requests
和 limits
。目前,扩展资源只允许使用带有前缀 requests.
配额项。以下是如何为 GPU 资源 nvidia.com/gpu
设置资源配额的示例场景。
流程
确定集群中某个节点中有多少 GPU 可用。例如:
# oc describe node ip-172-31-27-209.us-west-2.compute.internal | egrep 'Capacity|Allocatable|gpu' openshift.com/gpu-accelerator=true Capacity: nvidia.com/gpu: 2 Allocatable: nvidia.com/gpu: 2 nvidia.com/gpu 0 0
本例中有 2 个 GPU 可用。
在命名空间
nvidia
中设置配额。本例中配额为1
:# cat gpu-quota.yaml apiVersion: v1 kind: ResourceQuota metadata: name: gpu-quota namespace: nvidia spec: hard: requests.nvidia.com/gpu: 1
创建配额:
# oc create -f gpu-quota.yaml resourcequota/gpu-quota created
验证命名空间是否设置了正确的配额:
# oc describe quota gpu-quota -n nvidia Name: gpu-quota Namespace: nvidia Resource Used Hard -------- ---- ---- requests.nvidia.com/gpu 0 1
运行一个请求单个 GPU 的 Pod:
# oc create -f gpu-pod.yaml
apiVersion: v1 kind: Pod metadata: generateName: gpu-pod- namespace: nvidia spec: restartPolicy: OnFailure containers: - name: rhel7-gpu-pod image: rhel7 env: - name: NVIDIA_VISIBLE_DEVICES value: all - name: NVIDIA_DRIVER_CAPABILITIES value: "compute,utility" - name: NVIDIA_REQUIRE_CUDA value: "cuda>=5.0" command: ["sleep"] args: ["infinity"] resources: limits: nvidia.com/gpu: 1
验证 Pod 是否在运行:
# oc get pods NAME READY STATUS RESTARTS AGE gpu-pod-s46h7 1/1 Running 0 1m
验证配额计数器
Used
是否正确:# oc describe quota gpu-quota -n nvidia Name: gpu-quota Namespace: nvidia Resource Used Hard -------- ---- ---- requests.nvidia.com/gpu 1 1
尝试在
nvidia
命名空间中创建第二个 GPU Pod。从技术上讲,该节点支持 2 个 GPU,因为它有 2 个 GPU:# oc create -f gpu-pod.yaml Error from server (Forbidden): error when creating "gpu-pod.yaml": pods "gpu-pod-f7z2w" is forbidden: exceeded quota: gpu-quota, requested: requests.nvidia.com/gpu=1, used: requests.nvidia.com/gpu=1, limited: requests.nvidia.com/gpu=1
应该会显示此 Forbidden 错误消息,因为您有设为 1 个 GPU 的配额,但这一 Pod 试图分配第二个 GPU,而这超过了配额。
5.1.7. 查看配额
您可以在 Web 控制台导航到项目的 Quota 页面,查看与项目配额中定义的硬限值相关的使用量统计。
您还可以使用命令行来查看配额详情。
流程
获取项目中定义的配额列表。例如,对于名为
demoproject
的项目:$ oc get quota -n demoproject NAME AGE besteffort 11m compute-resources 2m core-object-counts 29m
描述您关注的配额,如
core-object-counts
配额:$ oc describe quota core-object-counts -n demoproject Name: core-object-counts Namespace: demoproject Resource Used Hard -------- ---- ---- configmaps 3 10 persistentvolumeclaims 0 4 replicationcontrollers 3 20 secrets 9 10 services 2 10
5.1.8. 要求显式配额来消耗资源
如果资源不受配额管理,用户可以消耗的资源量就不会有限制。例如,如果没有与金级存储类相关的存储配额,则项目可以创建的金级存储量没有限制。
对于高成本计算或存储资源,管理员可能要求赋予显式配额方可消耗资源。譬如,如果某个项目没有显式赋予与金级存储类有关的存储配额,则该项目的用户将无法创建该类型的存储。
流程
要求显式配额来消耗特定资源:
将以下小节添加到主控机配置中:
admissionConfig: pluginConfig: ResourceQuota: configuration: apiVersion: resourcequota.admission.k8s.io/v1alpha1 kind: Configuration limitedResources: - resource: persistentvolumeclaims 1 matchContains: - gold.storageclass.storage.k8s.io/requests.storage 2
在上例中,配额系统会拦截创建或更新
persistentVolumeClaim
的每个操作。它会检查将要消耗的配额理解哪些资源,如果项目中没有配额涵盖这些资源,则请求会被拒绝。在本例中,如果用户创建的
PersistentVolumeClaim
使用与金级存储类关联的存储,并且项目中没有匹配的配额,请求会被拒绝。
5.1.9. 配置配额同步周期
在删除一组资源后,但在恢复配额使用量前,用户在尝试重新使用这些资源时可能会遇到问题。资源同步时间表由 resource-quota-sync-period
设置决定,该设置可由集群管理员配置。
在使用自动化时,调整重新生成时间对创建资源和决定资源使用量很有帮助。
resource-quota-sync-period
设置旨在平衡系统性能。缩短同步周期可能会导致 master 遭遇重度负载。
流程
配置配额同步周期:
编辑 Kubernetes 控制器管理器。
$ oc edit kubecontrollermanager cluster
为
resource-quota-sync-period
字段指定时间量(以秒为单位),将unsupportedconfigOverrides
字段更改为具有下列设置:unsupportedConfigOverrides: extendedArguments: resource-quota-sync-period: - 60s