资源配额

当多个用户或团队共享一个拥有固定数量节点的集群时,可能会出现一个团队使用超过其公平份额的资源的情况。

资源配额是管理员解决此问题的一种工具。

资源配额由 ResourceQuota 对象定义,它提供了限制每个命名空间中聚合资源消耗的约束。ResourceQuota 还可以限制按 API 类型在命名空间中可创建对象的数量,以及命名空间中 API 对象可能消耗的基础设施资源的总量。

Kubernetes 资源配额如何工作

资源配额的工作原理如下:

  • 不同的团队在不同的命名空间中工作。这种分离可以通过RBAC或任何其他授权机制来强制执行。

  • 集群管理员为每个命名空间至少创建一个 ResourceQuota。

    • 为确保执行得到持续的强制执行,集群管理员还应限制删除或更新该 ResourceQuota 的访问权限;例如,通过定义验证准入策略
  • 用户在命名空间中创建资源(pod、service 等),配额系统会跟踪使用情况,以确保其不超过 ResourceQuota 中定义的硬资源限制。

    您可以将范围应用于 ResourceQuota,以限制其适用范围。

  • 如果创建或更新资源违反了配额约束,控制平面将以 HTTP 状态码 403 Forbidden 拒绝该请求。错误消息将解释将要违反的约束。

  • 如果在命名空间中为 cpumemory资源启用了配额,用户在定义 Pod 时必须指定这些值的请求或限制;否则,配额系统可能会拒绝 pod 创建。

    资源配额演练展示了如何避免此问题的示例。

您通常不直接创建 Pod;例如,您通常会创建工作负载管理对象,如Deployment。如果您创建的 Deployment 试图使用比可用资源更多的资源,那么 Deployment(或其他工作负载管理对象)的创建将成功,但 Deployment 可能无法使其管理的所有 Pod 都存在。在这种情况下,您可以检查 Deployment 的状态,例如使用 kubectl describe,以查看发生了什么。

  • 对于 cpumemory 资源,ResourceQuotas 强制要求该命名空间中所有(新)pod 都为该资源设置限制。如果您在命名空间中为 cpumemory 强制执行资源配额,您和其他客户端必须为每个新提交的 Pod 指定该资源的 requestslimits。如果您不这样做,控制平面可能会拒绝该 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 请求数量不能超过此值。
cpurequests.cpu 相同
memoryrequests.memory 相同

扩展资源配额

除了上面提到的资源之外,在 1.10 版本中,还增加了对扩展资源的配额支持。

由于扩展资源不允许超额分配,因此在配额中为同一个扩展资源同时指定 requestslimits 没有意义。因此,对于扩展资源,只允许带有 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-storagerequests.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分配给 NodePortLoadBalancer 类型 Service 的 NodePorts 在命名空间中可用的总数。
secrets命名空间中可以存在的 Secrets 的总数。

例如,pods 配额计算并强制执行单个命名空间中创建的非终结 pod 的最大数量。您可能希望在命名空间上设置 pods 配额,以避免用户创建许多小型 pod 并耗尽集群的 Pod IP 供应。

您可以在查看和设置配额中找到更多示例。

配额范围

每个配额都可以关联一组 scopes。只有当资源与枚举范围的交集匹配时,配额才会衡量该资源的用法。

当范围添加到配额时,它会将支持的资源数量限制为与该范围相关的资源。配额中指定的、超出允许范围的资源会导致验证错误。

范围描述
Terminating匹配 .spec.activeDeadlineSeconds >= 0 的 Pod
NotTerminating匹配 .spec.activeDeadlineSecondsnil 的 Pod
BestEffort匹配具有最佳努力服务质量的 Pod。
NotBestEffort匹配不具有最佳努力服务质量的 Pod。
PriorityClass匹配引用指定优先级类的 Pod。
CrossNamespacePodAffinity匹配具有跨命名空间 Pod(反)亲和性项的 Pod。
VolumeAttributesClass匹配引用指定卷属性类的 PersistentVolumeClaims。

BestEffort 范围将配额限制为跟踪以下资源:

  • Pod(pods)

TerminatingNotTerminatingNotBestEffortPriorityClass 范围将配额限制为跟踪以下资源:

  • Pod(pods)
  • cpu
  • memory
  • requests.cpu
  • requests.memory
  • limits.cpu
  • limits.memory

请注意,您不能在同一个配额中同时指定 TerminatingNotTerminating 范围,也不能在同一个配额中同时指定 BestEffortNotBestEffort 范围。

scopeSelector 支持 operator 字段中的以下值:

  • In
  • NotIn
  • Exists
  • DoesNotExist

当使用以下值之一作为 scopeName 来定义 scopeSelector 时,operator 必须是 Exists

  • Terminating
  • NotTerminating
  • BestEffort
  • NotBestEffort

如果 operatorInNotInvalues 字段必须至少有一个值。例如:

  scopeSelector:
    matchExpressions:
      - scopeName: PriorityClass
        operator: In
        values:
          - middle

如果 operatorExistsDoesNotExist,则必须不指定 values 字段。

按优先级类划分的资源配额

功能状态: `Kubernetes v1.17 [稳定]`

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 亲和性项中设置 namespacesnamespaceSelector 字段。

阻止用户使用跨命名空间亲和性项可能是可取的,因为具有反亲和性约束的 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

如果操作员希望默认情况下禁止使用 namespacesnamespaceSelector,而只允许在特定命名空间中使用,则可以通过将 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 亲和性中的 namespacesnamespaceSelector

按 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-silverpvcs-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.cpurequests.memory 指定了值,那么它要求每个传入的容器都明确请求这些资源。如果配额为 limits.cpulimits.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 创建将被允许,如果:

  1. Pod 的 priorityClassName 未指定。
  2. Pod 的 priorityClassName 被指定为 cluster-services 以外的值。
  3. Pod 的 priorityClassName 被设置为 cluster-services,它将在 kube-system 命名空间中创建,并且它已通过资源配额检查。

如果 Pod 的 priorityClassName 被设置为 cluster-services 并且它将在 kube-system 以外的命名空间中创建,则 Pod 创建请求将被拒绝。

下一步

最后修改日期:2025 年 8 月 13 日下午 1:13 PST:更新资源配额文档链接 (47b7523d29)