资源配额
当多个用户或团队共享一个拥有固定数量节点的集群时,可能会出现一个团队使用超过其公平份额的资源的情况。
资源配额是管理员解决此问题的一种工具。
资源配额由 ResourceQuota 对象定义,它提供了限制每个命名空间中聚合资源消耗的约束。ResourceQuota 还可以限制按 API 类型在命名空间中可创建对象的数量,以及命名空间中 API 对象可能消耗的基础设施资源的总量。
注意
资源争用或配额的更改都不会影响已创建的资源。Kubernetes 资源配额如何工作
资源配额的工作原理如下:
集群管理员为每个命名空间至少创建一个 ResourceQuota。
- 为确保执行得到持续的强制执行,集群管理员还应限制删除或更新该 ResourceQuota 的访问权限;例如,通过定义验证准入策略。
用户在命名空间中创建资源(pod、service 等),配额系统会跟踪使用情况,以确保其不超过 ResourceQuota 中定义的硬资源限制。
您可以将范围应用于 ResourceQuota,以限制其适用范围。
如果创建或更新资源违反了配额约束,控制平面将以 HTTP 状态码
403 Forbidden
拒绝该请求。错误消息将解释将要违反的约束。如果在命名空间中为
cpu
和memory
等资源启用了配额,用户在定义 Pod 时必须指定这些值的请求或限制;否则,配额系统可能会拒绝 pod 创建。资源配额演练展示了如何避免此问题的示例。
注意
- 您可以定义一个LimitRange来强制对没有计算资源要求的 pod 应用默认值(这样用户就不必记住这样做)。
您通常不直接创建 Pod;例如,您通常会创建工作负载管理对象,如Deployment。如果您创建的 Deployment 试图使用比可用资源更多的资源,那么 Deployment(或其他工作负载管理对象)的创建将成功,但 Deployment 可能无法使其管理的所有 Pod 都存在。在这种情况下,您可以检查 Deployment 的状态,例如使用 kubectl describe
,以查看发生了什么。
- 对于
cpu
和memory
资源,ResourceQuotas 强制要求该命名空间中所有(新)pod 都为该资源设置限制。如果您在命名空间中为cpu
或memory
强制执行资源配额,您和其他客户端必须为每个新提交的 Pod 指定该资源的requests
或limits
。如果您不这样做,控制平面可能会拒绝该 Pod 的准入。 - 对于其他资源:ResourceQuota 会生效,并将忽略命名空间中没有为该资源设置限制或请求的 pod。这意味着,如果命名空间的临时存储配额受到限制,您可以创建一个新的 pod 而不设置临时存储的限制/请求。
您可以使用LimitRange来自动设置这些资源的默认请求。
ResourceQuota 对象的名称必须是有效的DNS 子域名。
可以使用命名空间和配额创建的策略示例包括:
- 在内存为 32 GiB,核心为 16 个的集群中,让 A 团队使用 20 GiB 和 10 个核心,B 团队使用 10 GiB 和 4 个核心,并保留 2 GiB 和 2 个核心用于未来分配。
- 将“testing”命名空间限制为使用 1 个核心和 1 GiB 内存。让“production”命名空间使用任意数量。
如果集群的总容量小于命名空间配额的总和,可能会出现资源争用。这种情况按先到先得的原则处理。
启用资源配额
资源配额支持在许多 Kubernetes 发行版中默认启用。当API 服务器的 --enable-admission-plugins=
标志将 ResourceQuota
作为其参数之一时,它会被启用。
当某个命名空间中有 ResourceQuota 时,该命名空间中的资源配额就会生效。
资源配额的类型
ResourceQuota 机制允许您强制执行不同类型的限制。本节介绍您可以强制执行的限制类型。
基础设施资源配额
您可以限制给定命名空间中可以请求的计算资源的总和。
支持以下资源类型:
资源名称 | 描述 |
---|---|
limits.cpu | 在所有非终结状态的 pod 中,CPU 限制的总和不能超过此值。 |
limits.memory | 在所有非终结状态的 pod 中,内存限制的总和不能超过此值。 |
requests.cpu | 在所有非终结状态的 pod 中,CPU 请求的总和不能超过此值。 |
requests.memory | 在所有非终结状态的 pod 中,内存请求的总和不能超过此值。 |
hugepages-<size> | 在所有非终结状态的 pod 中,指定大小的 huge page 请求数量不能超过此值。 |
cpu | 与 requests.cpu 相同 |
memory | 与 requests.memory 相同 |
扩展资源配额
除了上面提到的资源之外,在 1.10 版本中,还增加了对扩展资源的配额支持。
由于扩展资源不允许超额分配,因此在配额中为同一个扩展资源同时指定 requests
和 limits
没有意义。因此,对于扩展资源,只允许带有 requests.
前缀的配额项。
以 GPU 资源为例,如果资源名称是 nvidia.com/gpu
,并且您想将命名空间中请求的 GPU 总数限制为 4,则可以定义如下配额:
requests.nvidia.com/gpu: 4
有关更多详细信息,请参阅查看和设置配额。
存储配额
您可以限制给定命名空间中可以请求的卷存储的总和。
此外,您可以根据关联的StorageClass来限制存储资源的消耗。
资源名称 | 描述 |
---|---|
requests.storage | 在所有持久卷声明中,存储请求的总和不能超过此值。 |
persistentvolumeclaims | 命名空间中可以存在的PersistentVolumeClaims的总数。 |
<storage-class-name>.storageclass.storage.k8s.io/requests.storage | 在所有与 <storage-class-name> 关联的持久卷声明中,存储请求的总和不能超过此值。 |
<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims | 在所有与 <storage-class-name> 关联的持久卷声明中,命名空间中可以存在的持久卷声明的总数。 |
例如,如果您想单独对 gold
StorageClass 和 bronze
StorageClass 的存储进行配额,可以定义如下配额:
gold.storageclass.storage.k8s.io/requests.storage: 500Gi
bronze.storageclass.storage.k8s.io/requests.storage: 100Gi
本地临时存储配额
Kubernetes v1.8 [alpha]
资源名称 | 描述 |
---|---|
requests.ephemeral-storage | 在命名空间的所有 pod 中,本地临时存储请求的总和不能超过此值。 |
limits.ephemeral-storage | 在命名空间的所有 pod 中,本地临时存储限制的总和不能超过此值。 |
ephemeral-storage | 与 requests.ephemeral-storage 相同。 |
对象数量配额
您可以使用以下语法为 Kubernetes API 中一个特定资源类型设置配额:
count/<resource>.<group>
用于非核心 API 组的资源count/<resource>
用于核心 API 组的资源
例如,PodTemplate API 属于核心 API 组,因此如果您想限制命名空间中 PodTemplate 对象的数量,则使用 count/podtemplates
。
这类配额有助于防止控制平面存储耗尽。例如,您可能希望限制服务器中 Secret 的数量,因为它们的体积很大。集群中过多的 Secret 实际上会阻止服务器和控制器启动。您可以为 Jobs 设置配额,以防止配置错误的 CronJob。在命名空间中创建过多 Jobs 的 CronJobs 可能导致拒绝服务。
如果以这种方式定义配额,它将应用于 API 服务器的 Kubernetes API,以及由 CustomResourceDefinition 支持的任何自定义资源。例如,要对 example.com
API 组中的 widgets
自定义资源设置配额,请使用 count/widgets.example.com
。如果您使用API 聚合添加未定义为 CustomResourceDefinitions 的附加自定义 API,则核心 Kubernetes 控制平面不会强制执行对聚合 API 的配额。如果这对自定义 API 是合适的,扩展 API 服务器将负责提供配额强制执行。
通用语法
以下是您可能希望使用对象数量配额进行管理的常见对象类型的示例列表,按您将使用的配置字符串列出:
count/pods
count/persistentvolumeclaims
count/services
count/secrets
count/configmaps
count/deployments.apps
count/replicasets.apps
count/statefulsets.apps
count/jobs.batch
count/cronjobs.batch
专用语法
还有另一种语法,仅用于设置同一种类型的配额,该语法仅适用于某些 API 类型。支持以下类型:
资源名称 | 描述 |
---|---|
configmaps | 命名空间中可以存在的 ConfigMaps 的总数。 |
persistentvolumeclaims | 命名空间中可以存在的PersistentVolumeClaims的总数。 |
Pod(pods) | 命名空间中可以存在的非终结状态 Pod 的总数。如果 .status.phase in (Failed, Succeeded) 为 true,则 pod 处于终结状态。 |
replicationcontrollers | 命名空间中可以存在的 ReplicationControllers 的总数。 |
resourcequotas | 命名空间中可以存在的 ResourceQuotas 的总数。 |
服务(services) | 命名空间中可以存在的 Services 的总数。 |
services.loadbalancers | 命名空间中可以存在的 LoadBalancer 类型 Service 的总数。 |
services.nodeports | 分配给 NodePort 或 LoadBalancer 类型 Service 的 NodePorts 在命名空间中可用的总数。 |
secrets | 命名空间中可以存在的 Secrets 的总数。 |
例如,pods
配额计算并强制执行单个命名空间中创建的非终结 pod 的最大数量。您可能希望在命名空间上设置 pods
配额,以避免用户创建许多小型 pod 并耗尽集群的 Pod IP 供应。
您可以在查看和设置配额中找到更多示例。
配额范围
每个配额都可以关联一组 scopes
。只有当资源与枚举范围的交集匹配时,配额才会衡量该资源的用法。
当范围添加到配额时,它会将支持的资源数量限制为与该范围相关的资源。配额中指定的、超出允许范围的资源会导致验证错误。
范围 | 描述 |
---|---|
Terminating | 匹配 .spec.activeDeadlineSeconds >= 0 的 Pod |
NotTerminating | 匹配 .spec.activeDeadlineSeconds 为 nil 的 Pod |
BestEffort | 匹配具有最佳努力服务质量的 Pod。 |
NotBestEffort | 匹配不具有最佳努力服务质量的 Pod。 |
PriorityClass | 匹配引用指定优先级类的 Pod。 |
CrossNamespacePodAffinity | 匹配具有跨命名空间 Pod(反)亲和性项的 Pod。 |
VolumeAttributesClass | 匹配引用指定卷属性类的 PersistentVolumeClaims。 |
BestEffort
范围将配额限制为跟踪以下资源:
Pod(pods)
Terminating
、NotTerminating
、NotBestEffort
和 PriorityClass
范围将配额限制为跟踪以下资源:
Pod(pods)
cpu
memory
requests.cpu
requests.memory
limits.cpu
limits.memory
请注意,您不能在同一个配额中同时指定 Terminating
和 NotTerminating
范围,也不能在同一个配额中同时指定 BestEffort
和 NotBestEffort
范围。
scopeSelector
支持 operator
字段中的以下值:
In
NotIn
Exists
DoesNotExist
当使用以下值之一作为 scopeName
来定义 scopeSelector
时,operator
必须是 Exists
。
Terminating
NotTerminating
BestEffort
NotBestEffort
如果 operator
是 In
或 NotIn
,values
字段必须至少有一个值。例如:
scopeSelector:
matchExpressions:
- scopeName: PriorityClass
operator: In
values:
- middle
如果 operator
是 Exists
或 DoesNotExist
,则必须不指定 values
字段。
按优先级类划分的资源配额
Pod 可以以特定的优先级创建。您可以通过在配额规范中使用 scopeSelector
字段来根据 Pod 的优先级控制其系统资源消耗。
只有当配额规范中的 scopeSelector
选择该 Pod 时,才会匹配并消耗该配额。
当使用 scopeSelector
字段为优先级类设置配额范围时,配额对象仅限于跟踪以下资源:
Pod(pods)
cpu
memory
ephemeral-storage
limits.cpu
limits.memory
limits.ephemeral-storage
requests.cpu
requests.memory
requests.ephemeral-storage
此示例创建了一个配额对象,并将其与特定优先级的 Pod 匹配。示例工作如下:
- 集群中的 Pod 具有“low”、“medium”、“high”三个优先级类之一。
- 为每个优先级创建一个配额对象。
将以下 YAML 保存到名为 quota.yaml
的文件中。
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-high
spec:
hard:
cpu: "1000"
memory: "200Gi"
pods: "10"
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values: ["high"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-medium
spec:
hard:
cpu: "10"
memory: "20Gi"
pods: "10"
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values: ["medium"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-low
spec:
hard:
cpu: "5"
memory: "10Gi"
pods: "10"
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values: ["low"]
使用 kubectl create
应用 YAML。
kubectl create -f ./quota.yaml
resourcequota/pods-high created
resourcequota/pods-medium created
resourcequota/pods-low created
使用 kubectl describe quota
验证 Used
配额是否为 0
。
kubectl describe quota
Name: pods-high
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 1k
memory 0 200Gi
pods 0 10
Name: pods-low
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 5
memory 0 10Gi
pods 0 10
Name: pods-medium
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 10
memory 0 20Gi
pods 0 10
创建具有“high”优先级的 Pod。将以下 YAML 保存到名为 high-priority-pod.yaml
的文件中。
apiVersion: v1
kind: Pod
metadata:
name: high-priority
spec:
containers:
- name: high-priority
image: ubuntu
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello; sleep 10;done"]
resources:
requests:
memory: "10Gi"
cpu: "500m"
limits:
memory: "10Gi"
cpu: "500m"
priorityClassName: high
使用 kubectl create
应用。
kubectl create -f ./high-priority-pod.yaml
验证“high”优先级配额 pods-high
的“Used”统计信息已更改,而其他两个配额未更改。
kubectl describe quota
Name: pods-high
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 500m 1k
memory 10Gi 200Gi
pods 1 10
Name: pods-low
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 5
memory 0 10Gi
pods 0 10
Name: pods-medium
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 10
memory 0 20Gi
pods 0 10
跨命名空间 Pod 亲和性配额
Kubernetes v1.24 [stable]
操作员可以使用 CrossNamespacePodAffinity
配额范围来限制哪些命名空间允许具有跨命名空间亲和性项的 pod。具体来说,它控制哪些 pod 允许在 pod 亲和性项中设置 namespaces
或 namespaceSelector
字段。
阻止用户使用跨命名空间亲和性项可能是可取的,因为具有反亲和性约束的 pod 会阻止来自所有其他命名空间的 pod 在故障域中获得调度。
使用此范围,操作员可以通过在该命名空间中创建具有 CrossNamespacePodAffinity
范围和硬限制为 0 的资源配额对象来防止某些命名空间(如下例中的 foo-ns
)拥有使用跨命名空间 Pod 亲和性的 Pod。
apiVersion: v1
kind: ResourceQuota
metadata:
name: disable-cross-namespace-affinity
namespace: foo-ns
spec:
hard:
pods: "0"
scopeSelector:
matchExpressions:
- scopeName: CrossNamespacePodAffinity
operator: Exists
如果操作员希望默认情况下禁止使用 namespaces
和 namespaceSelector
,而只允许在特定命名空间中使用,则可以通过将 kube-apiserver 标志 --admission-control-config-file
设置为以下配置文件的路径来将 CrossNamespacePodAffinity
配置为受限资源:
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: "ResourceQuota"
configuration:
apiVersion: apiserver.config.k8s.io/v1
kind: ResourceQuotaConfiguration
limitedResources:
- resource: pods
matchScopes:
- scopeName: CrossNamespacePodAffinity
operator: Exists
使用上述配置,只有当 pod 创建所在命名空间具有 CrossNamespacePodAffinity
范围且硬限制大于或等于使用这些字段的 pod 数量的资源配额对象时,pod 才能使用 pod 亲和性中的 namespaces
和 namespaceSelector
。
按 VolumeAttributesClass 划分的资源配额
Kubernetes v1.34 [稳定]
(默认启用:true)PersistentVolumeClaims 可以使用特定的卷属性类创建,并且可以在创建后修改。您可以通过在配额规范中使用 scopeSelector
字段,根据关联的卷属性类来控制 PVC 对存储资源的消耗。
PVC 通过以下字段引用关联的卷属性类:
spec.volumeAttributesClassName
status.currentVolumeAttributesClassName
status.modifyVolumeStatus.targetVolumeAttributesClassName
只有当配额规范中的 scopeSelector
选择 PVC 时,才会匹配并消耗该配额。
当使用 scopeSelector
字段为卷属性类设置配额范围时,配额对象仅限于跟踪以下资源:
persistentvolumeclaims
requests.storage
此示例创建了一个配额对象,并将其与特定卷属性类的 PVC 匹配。示例工作如下:
- 集群中的 PVC 至少具有“gold”、“silver”、“copper”三个卷属性类之一。
- 为每个卷属性类创建一个配额对象。
将以下 YAML 保存到名为 quota-vac.yaml
的文件中。
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pvcs-gold
spec:
hard:
requests.storage: "10Gi"
persistentvolumeclaims: "10"
scopeSelector:
matchExpressions:
- operator: In
scopeName: VolumeAttributesClass
values: ["gold"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pvcs-silver
spec:
hard:
requests.storage: "20Gi"
persistentvolumeclaims: "10"
scopeSelector:
matchExpressions:
- operator: In
scopeName: VolumeAttributesClass
values: ["silver"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pvcs-copper
spec:
hard:
requests.storage: "30Gi"
persistentvolumeclaims: "10"
scopeSelector:
matchExpressions:
- operator: In
scopeName: VolumeAttributesClass
values: ["copper"]
使用 kubectl create
应用 YAML。
kubectl create -f ./quota-vac.yaml
resourcequota/pvcs-gold created
resourcequota/pvcs-silver created
resourcequota/pvcs-copper created
使用 kubectl describe quota
验证 Used
配额是否为 0
。
kubectl describe quota
Name: pvcs-gold
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
requests.storage 0 10Gi
Name: pvcs-silver
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
requests.storage 0 20Gi
Name: pvcs-copper
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
requests.storage 0 30Gi
创建一个具有“gold”卷属性类的 pvc。将以下 YAML 保存到名为 gold-vac-pvc.yaml
的文件中。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gold-vac-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: # change this to the name of the storage class you want to use
volumeAttributesClassName: gold
使用 kubectl create
应用。
kubectl create -f ./gold-vac-pvc.yaml
验证“gold”卷属性类配额 pvcs-gold
的“Used”统计信息已更改,而其他两个配额未更改。
kubectl describe quota
Name: pvcs-gold
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 1 10
requests.storage 2Gi 10Gi
Name: pvcs-silver
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
requests.storage 0 20Gi
Name: pvcs-copper
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
requests.storage 0 30Gi
PVC 绑定后,允许修改所需的卷属性类。让我们使用 kubectl patch 将其更改为“silver”。
kubectl patch pvc gold-vac-pvc --type='merge' -p '{"spec":{"volumeAttributesClassName":"silver"}}'
验证“silver”卷属性类配额 pvcs-silver
的“Used”统计信息已更改,pvcs-copper
未更改,而 pvcs-gold
可能未更改或已释放,具体取决于 PVC 的状态。
kubectl describe quota
Name: pvcs-gold
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 1 10
requests.storage 2Gi 10Gi
Name: pvcs-silver
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 1 10
requests.storage 2Gi 20Gi
Name: pvcs-copper
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
requests.storage 0 30Gi
让我们使用 kubectl patch 将其更改为“copper”。
kubectl patch pvc gold-vac-pvc --type='merge' -p '{"spec":{"volumeAttributesClassName":"copper"}}'
验证“copper”卷属性类配额 pvcs-copper
的“Used”统计信息已更改,pvcs-silver
和 pvcs-gold
可能未更改或已释放,具体取决于 PVC 的状态。
kubectl describe quota
Name: pvcs-gold
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 1 10
requests.storage 2Gi 10Gi
Name: pvcs-silver
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 1 10
requests.storage 2Gi 20Gi
Name: pvcs-copper
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 1 10
requests.storage 2Gi 30Gi
使用以下命令打印 PVC 的清单。
kubectl get pvc gold-vac-pvc -o yaml
它可能显示以下输出:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gold-vac-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: default
volumeAttributesClassName: copper
status:
accessModes:
- ReadWriteOnce
capacity:
storage: 2Gi
currentVolumeAttributesClassName: gold
phase: Bound
modifyVolumeStatus:
status: InProgress
targetVolumeAttributesClassName: silver
storageClassName: default
稍等片刻,卷修改完成后,再次验证配额。
kubectl describe quota
Name: pvcs-gold
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
requests.storage 0 10Gi
Name: pvcs-silver
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
requests.storage 0 20Gi
Name: pvcs-copper
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 1 10
requests.storage 2Gi 30Gi
请求与限制的比较
在分配计算资源时,每个容器都可以为 CPU 或内存指定请求和限制值。配额可以配置为配额任一值。
如果配额为 requests.cpu
或 requests.memory
指定了值,那么它要求每个传入的容器都明确请求这些资源。如果配额为 limits.cpu
或 limits.memory
指定了值,那么它要求每个传入的容器都明确指定这些资源的限制。
查看和设置配额
kubectl 支持创建、更新和查看配额。
kubectl create namespace myspace
cat <<EOF > compute-resources.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-resources
spec:
hard:
requests.cpu: "1"
requests.memory: "1Gi"
limits.cpu: "2"
limits.memory: "2Gi"
requests.nvidia.com/gpu: 4
EOF
kubectl create -f ./compute-resources.yaml --namespace=myspace
cat <<EOF > object-counts.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: object-counts
spec:
hard:
configmaps: "10"
persistentvolumeclaims: "4"
pods: "4"
replicationcontrollers: "20"
secrets: "10"
services: "10"
services.loadbalancers: "2"
EOF
kubectl create -f ./object-counts.yaml --namespace=myspace
kubectl get quota --namespace=myspace
NAME AGE
compute-resources 30s
object-counts 32s
kubectl describe quota compute-resources --namespace=myspace
Name: compute-resources
Namespace: myspace
Resource Used Hard
-------- ---- ----
limits.cpu 0 2
limits.memory 0 2Gi
requests.cpu 0 1
requests.memory 0 1Gi
requests.nvidia.com/gpu 0 4
kubectl describe quota object-counts --namespace=myspace
Name: object-counts
Namespace: myspace
Resource Used Hard
-------- ---- ----
configmaps 0 10
persistentvolumeclaims 0 4
pods 0 4
replicationcontrollers 0 20
secrets 1 10
services 0 10
services.loadbalancers 0 2
kubectl 还支持所有标准命名空间资源的对象数量配额,使用语法 count/<resource>.<group>
。
kubectl create namespace myspace
kubectl create quota test --hard=count/deployments.apps=2,count/replicasets.apps=4,count/pods=3,count/secrets=4 --namespace=myspace
kubectl create deployment nginx --image=nginx --namespace=myspace --replicas=2
kubectl describe quota --namespace=myspace
Name: test
Namespace: myspace
Resource Used Hard
-------- ---- ----
count/deployments.apps 1 2
count/pods 2 3
count/replicasets.apps 1 4
count/secrets 1 4
配额与集群容量
ResourceQuotas 与集群容量无关。它们以绝对单位表示。因此,如果您向集群添加节点,这不会自动使每个命名空间消耗更多资源的能力。
有时可能需要更复杂的策略,例如:
- 在多个团队之间按比例分配集群总资源。
- 允许每个租户按需增长资源使用量,但设置一个慷慨的限制以防止意外的资源耗尽。
- 检测一个命名空间的需求,添加节点,并增加配额。
这些策略可以作为构建块使用 ResourceQuotas
来实现,通过编写一个“控制器”来监视配额使用情况并根据其他信号调整每个命名空间的配额硬限制。
请注意,资源配额分割了集群的总资源,但它没有对节点施加限制:来自多个命名空间的 pod 可能会运行在同一个节点上。
默认限制优先级类消耗
可能需要允许特定优先级(例如“cluster-services”)的 pod 在某个命名空间中存在,前提是存在匹配的配额对象。
通过这种机制,操作员能够将某些高优先级类的使用限制为有限数量的命名空间,而不是每个命名空间默认都能消耗这些优先级类。
为实现此目的,应使用 kube-apiserver
标志 --admission-control-config-file
来传递以下配置文件的路径:
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: "ResourceQuota"
configuration:
apiVersion: apiserver.config.k8s.io/v1
kind: ResourceQuotaConfiguration
limitedResources:
- resource: pods
matchScopes:
- scopeName: PriorityClass
operator: In
values: ["cluster-services"]
然后,在 kube-system
命名空间中创建一个资源配额对象:
apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-cluster-services
spec:
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["cluster-services"]
kubectl apply -f https://k8s.io/examples/policy/priority-class-resourcequota.yaml -n kube-system
resourcequota/pods-cluster-services created
在这种情况下,pod 创建将被允许,如果:
- Pod 的
priorityClassName
未指定。 - Pod 的
priorityClassName
被指定为cluster-services
以外的值。 - Pod 的
priorityClassName
被设置为cluster-services
,它将在kube-system
命名空间中创建,并且它已通过资源配额检查。
如果 Pod 的 priorityClassName
被设置为 cluster-services
并且它将在 kube-system
以外的命名空间中创建,则 Pod 创建请求将被拒绝。
下一步
- 请参阅有关如何使用资源配额的详细示例。
- 阅读 ResourceQuota API 参考
- 了解LimitRanges
- 您可以阅读历史ResourceQuota 设计文档以获取更多信息。
- 您还可以阅读优先级类资源配额支持设计文档。