资源配额

当多个用户或团队共享一个节点数量固定的集群时,他们可能会担心某个团队使用的资源会超过其应得的份额。

资源配额是管理员解决这个担忧的工具。

资源配额由一个 ResourceQuota 对象定义,它提供了限制每个命名空间总资源消耗的约束。它可以按类型限制可在命名空间中创建的对象数量,以及该命名空间中资源可能消耗的计算资源总量。

资源配额工作原理如下

  • 不同的团队在不同的命名空间中工作。这可以通过 RBAC 来强制执行。

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

  • 用户在命名空间中创建资源(Pod、Service 等),配额系统跟踪资源使用情况,以确保它不超过 ResourceQuota 中定义的硬性资源限制。

  • 如果创建或更新资源违反了配额约束,该请求将以 HTTP 状态码 403 FORBIDDEN 失败,并伴随一条消息解释被违反的约束。

  • 如果在命名空间中为 cpumemory 等计算资源启用了配额,用户必须为这些值指定请求或限制;否则,配额系统可能会拒绝 Pod 创建。提示:使用 LimitRanger 准入控制器为未提出计算资源需求的 Pod 强制设定默认值。

    参阅演练,了解如何避免此问题的示例。

ResourceQuota 对象的名称必须是合法的 DNS 子域名

可以使用命名空间和配额创建的策略示例如下:

  • 在一个容量为 32 GiB RAM 和 16 核的集群中,让团队 A 使用 20 GiB 和 10 核,团队 B 使用 10 GiB 和 4 核,并保留 2 GiB 和 2 核以备将来分配。
  • 将“testing”命名空间的资源使用限制为 1 核和 1 GiB RAM。允许“production”命名空间使用任意数量的资源。

在集群总容量小于命名空间配额总和的情况下,可能会出现资源争用。这种情况按照先到先得的原则处理。

资源争用和配额变更都不会影响已经创建的资源。

启用资源配额

对于许多 Kubernetes 发行版,ResourceQuota 支持默认是启用的。当 API 服务器--enable-admission-plugins= 标志的参数之一包含 ResourceQuota 时,该功能就被启用。

当命名空间中存在 ResourceQuota 对象时,资源配额在该特定命名空间中强制执行。

计算资源配额

你可以限制在给定命名空间中可以请求的计算资源总量。

支持以下资源类型:

资源名称描述
limits.cpu在所有非终止状态的 Pod 中,CPU limits 的总和不能超过此值。
limits.memory在所有非终止状态的 Pod 中,memory limits 的总和不能超过此值。
requests.cpu在所有非终止状态的 Pod 中,CPU requests 的总和不能超过此值。
requests.memory在所有非终止状态的 Pod 中,memory requests 的总和不能超过此值。
hugepages-<size>在所有非终止状态的 Pod 中,指定大小的 huge page 请求数量不能超过此值。
cpurequests.cpu 相同
memoryrequests.memory 相同

扩展资源的资源配额

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

由于扩展资源不允许过度承诺 (overcommit),因此在配额中为同一扩展资源同时指定 requestslimits 没有意义。因此,对于扩展资源,只允许带有 requests. 前缀的配额项。

以 GPU 资源为例,如果资源名称是 nvidia.com/gpu,并且你想将命名空间中请求的 GPU 总数限制为 4,可以按如下方式定义配额:

  • requests.nvidia.com/gpu: 4

参阅查看和设置配额了解更多详情。

存储资源配额

你可以限制在给定命名空间中可以请求的存储资源总量。

此外,你还可以根据相关的 StorageClass 限制存储资源的消耗。

资源名称描述
requests.storage在所有 PersistentVolumeClaim 中,存储请求的总和不能超过此值。
persistentvolumeclaims可在命名空间中存在的PersistentVolumeClaims 总数。
<storage-class-name>.storageclass.storage.k8s.io/requests.storage<storage-class-name> 相关的所有 PersistentVolumeClaim 中,存储请求的总和不能超过此值。
<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims<storage-class-name> 相关的所有 PersistentVolumeClaim 中,可在命名空间中存在的PersistentVolumeClaim 总数。

例如,如果你想将使用 gold StorageClass 的存储与使用 bronze StorageClass 的存储分开配额,可以按如下方式定义配额:

  • gold.storageclass.storage.k8s.io/requests.storage: 500Gi
  • bronze.storageclass.storage.k8s.io/requests.storage: 100Gi

在 1.8 版本中,对本地临时存储的配额支持作为 Alpha 特性添加

资源名称描述
requests.ephemeral-storage在命名空间中的所有 Pod 中,本地临时存储请求的总和不能超过此值。
limits.ephemeral-storage在命名空间中的所有 Pod 中,本地临时存储 limits 的总和不能超过此值。
ephemeral-storagerequests.ephemeral-storage 相同。

对象数量配额

可以使用以下语法为 Kubernetes API 中某个特定资源类型的对象总数设置配额:

  • count/<resource>.<group> 用于非核心组中的资源
  • count/<resource> 用于核心组中的资源

以下是用户可能希望纳入对象数量配额控制的资源示例集:

  • count/persistentvolumeclaims
  • count/services
  • count/secrets
  • count/configmaps
  • count/replicationcontrollers
  • count/deployments.apps
  • count/replicasets.apps
  • count/statefulsets.apps
  • count/jobs.batch
  • count/cronjobs.batch

如果你通过这种方式定义配额,它适用于作为 API 服务器一部分的 Kubernetes API,以及由 CustomResourceDefinition 支持的任何自定义资源。如果你使用API 聚合来添加未定义为 CustomResourceDefinition 的额外自定义 API,核心 Kubernetes 控制平面不会对聚合的 API 强制执行配额。如果自定义 API 适合,则期望扩展 API 服务器提供配额强制执行。例如,要在 example.com API 组中对 widgets 自定义资源创建配额,请使用 count/widgets.example.com

使用这种资源配额(几乎适用于所有对象类型)时,如果对象类型在控制平面中存在(已定义),则该对象会被计入配额。这类配额对于防止存储资源耗尽非常有用。例如,考虑到 Secrets 的大小较大,你可能希望限制服务器中 Secrets 的数量。集群中过多的 Secrets 实际上会阻止服务器和控制器启动。你可以为 Job 设置配额,以防止配置不当的 CronJob。在命名空间中创建过多 Job 的 CronJob 可能导致拒绝服务。

还有另一种语法,仅用于为某些特定资源设置相同类型的配额。支持以下类型:

资源名称描述
configmaps可在命名空间中存在的 ConfigMaps 总数。
persistentvolumeclaims可在命名空间中存在的PersistentVolumeClaims 总数。
pods可在命名空间中存在的非终止状态的 Pod 总数。如果 .status.phase in (Failed, Succeeded) 为真,则 Pod 处于终止状态。
replicationcontrollers可在命名空间中存在的 ReplicationControllers 总数。
resourcequotas可在命名空间中存在的 ResourceQuotas 总数。
services可在命名空间中存在的 Services 总数。
services.loadbalancers可在命名空间中存在的类型为 LoadBalancer 的 Services 总数。
services.nodeports可在命名空间中存在的分配给类型为 NodePortLoadBalancer 的 Services 的 NodePort 总数。
secrets可在命名空间中存在的 Secrets 总数。

例如,pods 配额统计并强制执行单个命名空间中创建的非终止状态 pods 的最大数量。你可能希望对命名空间设置 pods 配额,以避免用户创建许多小型 Pod 并耗尽集群的 Pod IP 供应的情况。

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

配额范围

每个配额都可以有一组相关的 scopes。配额仅在匹配所列范围的交集时才会衡量资源的用量。

当一个范围被添加到配额中时,它将配额支持的资源数量限制在与该范围相关的那些资源上。在配额中指定的资源如果超出允许的集合,将导致验证错误。

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

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

  • pods

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

  • pods
  • cpu
  • memory
  • requests.cpu
  • requests.memory
  • limits.cpu
  • limits.memory

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

scopeSelectoroperator 字段中支持以下值:

  • In
  • NotIn
  • Exists
  • DoesNotExist

在定义 scopeSelector 时,如果使用以下值之一作为 scopeName,则 operator 必须是 Exists

  • Terminating
  • NotTerminating
  • BestEffort
  • NotBestEffort

如果 operatorInNotIn,则 values 字段必须至少包含一个值。例如:

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

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

每个 PriorityClass 的资源配额

特性状态: Kubernetes v1.17 [stable]

Pod 可以创建时指定优先级。你可以通过在配额规约中使用 scopeSelector 字段,根据 Pod 的优先级控制 Pod 对系统资源的消耗。

配额只有在配额规约中的 scopeSelector 选择了该 Pod 时才匹配并被消耗。

当使用 scopeSelector 字段将配额限制在优先级类范围时,配额对象仅限于跟踪以下资源:

  • 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 在故障域中被调度。

通过在此范围中创建一个 ResourceQuota 对象,将其范围设为 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 亲和性中使用 namespacesnamespaceSelector

每个 VolumeAttributesClass 的资源配额

特性状态: Kubernetes v1.31 [beta] (默认禁用)

PersistentVolumeClaim 可以创建时指定特定的卷属性类,并在创建后可能被修改。你可以通过在配额规约中使用 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

Requests 与 Limits 对比

在分配计算资源时,每个容器可以为 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 作为构建块来实现此类策略,具体方法是编写一个“控制器”,该控制器监控配额使用情况并根据其他信号调整每个命名空间的配额硬限制。

请注意,资源配额划分了集群总资源,但它对节点没有施加限制:来自多个命名空间的 Pods 可以运行在同一个节点上。

默认限制优先级类 (Priority Class) 的使用

可能需要,只有当存在一个匹配的配额对象时,才允许具有特定优先级(例如 "cluster-services")的 Pods 进入某个命名空间。

通过此机制,运维人员能够将某些高优先级类的使用限制在有限数量的命名空间内,并且默认情况下不是每个命名空间都能使用这些优先级类。

为了强制执行此操作,应使用 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 的命名空间中创建,则该请求将被拒绝。

下一步

最后修改于 太平洋标准时间 (PST) 2025 年 3 月 13 日下午 12:03: 按 VolumeAttributesClass 的资源配额 (f26e212868)