×

ResourceQuota对象定义的资源配额提供限制,以限制每个项目的聚合资源消耗。它可以限制按类型在项目中可以创建的对象数量,以及该项目中资源可能消耗的计算资源和存储总量。

本指南介绍了资源配额的工作原理、集群管理员如何按项目设置和管理资源配额,以及开发人员和集群管理员如何查看它们。

配额管理的资源

以下描述了可以由配额管理的计算资源和对象类型集。

如果status.phase in (Failed, Succeeded)为真,则 Pod 处于终端状态。

表 1. 配额管理的计算资源
资源名称 描述

cpu

非终端状态下所有 Pod 的 CPU 请求总和不能超过此值。cpurequests.cpu的值相同,可以互换使用。

memory

非终端状态下所有 Pod 的内存请求总和不能超过此值。memoryrequests.memory的值相同,可以互换使用。

requests.cpu

非终端状态下所有 Pod 的 CPU 请求总和不能超过此值。cpurequests.cpu的值相同,可以互换使用。

requests.memory

非终端状态下所有 Pod 的内存请求总和不能超过此值。memoryrequests.memory的值相同,可以互换使用。

limits.cpu

非终端状态下所有 Pod 的 CPU 限制总和不能超过此值。

limits.memory

非终端状态下所有 Pod 的内存限制总和不能超过此值。

表 2. 配额管理的存储资源
资源名称 描述

requests.storage

任何状态下所有持久卷声明的存储请求总和不能超过此值。

persistentvolumeclaims

项目中可以存在的持久卷声明总数。

<storage-class-name>.storageclass.storage.k8s.io/requests.storage

任何状态下所有具有匹配存储类的持久卷声明的存储请求总和不能超过此值。

<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims

项目中可以存在的具有匹配存储类的持久卷声明总数。

ephemeral-storage

非终端状态下所有 Pod 的本地临时存储请求总和不能超过此值。ephemeral-storagerequests.ephemeral-storage的值相同,可以互换使用。

requests.ephemeral-storage

非终端状态下所有 Pod 的临时存储请求总和不能超过此值。ephemeral-storagerequests.ephemeral-storage的值相同,可以互换使用。

limits.ephemeral-storage

非终端状态下所有 Pod 的临时存储限制总和不能超过此值。

表 3. 配额管理的对象计数
资源名称 描述

pods

项目中可以存在的非终端状态 Pod 的总数。

replicationcontrollers

项目中可以存在的副本控制器总数。

resourcequotas

项目中可以存在的资源配额总数。

services

项目中可以存在的服务总数。

services.loadbalancers

项目中可以存在的LoadBalancer类型服务总数。

services.nodeports

项目中可以存在的NodePort类型服务总数。

secrets

项目中可以存在的密钥总数。

configmaps

项目中可以存在的ConfigMap对象总数。

persistentvolumeclaims

项目中可以存在的持久卷声明总数。

openshift.io/imagestreams

项目中可以存在的镜像流总数。

配额范围

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

向配额添加范围会限制该配额可以应用到的资源集。指定允许集之外的资源会导致验证错误。

范围

描述

BestEffort

匹配具有最佳努力服务质量的 Pod(cpumemory)。

NotBestEffort

匹配不具有最佳努力服务质量的 Pod(cpumemory)。

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

  • pods

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

  • pods

  • memory

  • requests.memory

  • limits.memory

  • cpu

  • requests.cpu

  • limits.cpu

配额执行

在为项目创建资源配额后,项目会限制创建任何可能违反配额约束的新资源的能力,直到它计算出更新的使用情况统计信息。

创建配额并更新使用情况统计信息后,项目将接受新内容的创建。创建或修改资源时,您的配额使用量会在创建或修改资源的请求后立即递增。

删除资源时,您的配额使用量将在项目配额统计信息的下次完整重新计算期间递减。可配置的时间量决定了将配额使用情况统计信息减少到当前观察到的系统值所需的时间。

如果项目修改超过配额使用限制,服务器将拒绝该操作,并向用户返回相应的错误消息,解释违反的配额约束以及系统中当前观察到的使用情况统计信息。

请求与限制

分配计算资源时,每个容器都可能为 CPU、内存和临时存储分别指定请求值和限制值。配额可以限制这些值中的任何一个。

如果配额为requests.cpurequests.memory指定了值,则它要求每个传入的容器都对这些资源发出明确的请求。如果配额为limits.cpulimits.memory指定了值,则它要求每个传入的容器都为这些资源指定明确的限制。

示例资源配额定义

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)
1 项目中可以存在的ConfigMap对象总数。
2 项目中可以存在的持久卷声明 (PVC) 的总数。
3 项目中可以存在的副本控制器的总数。
4 项目中可以存在的密钥总数。
5 项目中可以存在的服务总数。
6 项目中可以存在的LoadBalancer类型服务总数。
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)
    limits.cpu: "2" (4)
    limits.memory: 2Gi (5)
1 项目中可以存在的非终端状态 Pod 的总数。
2 在所有非终止状态的 Pod 中,CPU 请求的总和不能超过 1 个核心。
3 在所有非终止状态的 Pod 中,内存请求的总和不能超过 1Gi。
4 在所有非终止状态的 Pod 中,CPU 限制的总和不能超过 2 个核心。
5 在所有非终止状态的 Pod 中,内存限制的总和不能超过 2Gi。
besteffort.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: besteffort
spec:
  hard:
    pods: "1" (1)
  scopes:
  - BestEffort (2)
1 项目中可以存在的具有BestEffort 服务质量的非终止状态 Pod 的总数。
2 将配额限制为仅匹配那些对内存或 CPU 具有BestEffort 服务质量的 Pod。
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)
  scopes:
  - NotTerminating (4)
1 非终止状态的 Pod 的总数。
2 在所有非终止状态的 Pod 中,CPU 限制的总和不能超过此值。
3 在所有非终止状态的 Pod 中,内存限制的总和不能超过此值。
4 将配额限制为仅匹配spec.activeDeadlineSeconds设置为nil的 Pod。除非应用了RestartNever策略,否则构建 Pod 属于NotTerminating
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)
  scopes:
  - Terminating (4)
1 终止状态的 Pod 的总数。
2 在所有终止状态的 Pod 中,CPU 限制的总和不能超过此值。
3 在所有终止状态的 Pod 中,内存限制的总和不能超过此值。
4 将配额限制为仅匹配spec.activeDeadlineSeconds >=0的 Pod。例如,此配额会对构建或部署程序 Pod 收费,但不会对长期运行的 Pod(如 Web 服务器或数据库)收费。
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)
    requests.ephemeral-storage: 2Gi (8)
    limits.ephemeral-storage: 4Gi (9)
1 项目中持久卷声明的总数
2 项目中所有持久卷声明的存储请求总和不能超过此值。
3 项目中所有持久卷声明中,gold 存储类中请求的存储总和不能超过此值。
4 项目中所有持久卷声明中,silver 存储类中请求的存储总和不能超过此值。
5 项目中所有持久卷声明中,silver 存储类中的声明总数不能超过此值。
6 项目中所有持久卷声明中,bronze 存储类中请求的存储总和不能超过此值。当设置为0时,表示 bronze 存储类不能请求存储。
7 项目中所有持久卷声明中,bronze 存储类中请求的存储总和不能超过此值。当设置为0时,表示 bronze 存储类不能创建声明。
8 在所有非终止状态的 Pod 中,临时存储请求的总和不能超过 2Gi。
9 在所有非终止状态的 Pod 中,临时存储限制的总和不能超过 4Gi。

创建配额

您可以创建配额来限制给定项目中的资源使用情况。

步骤
  1. 在一个文件中定义配额。

  2. 使用该文件创建配额并将其应用于项目

    $ oc create -f <file> [-n <project_name>]

    例如

    $ oc create -f core-object-counts.yaml -n demoproject

创建对象计数配额

您可以为 OpenShift Container Platform 上所有标准命名空间资源类型(例如BuildConfigDeploymentConfig对象)创建对象计数配额。对象配额计数会对所有标准命名空间资源类型设置定义的配额。

使用资源配额时,创建对象后会将其计入配额。这些类型的配额可用于防止资源耗尽。只有当项目内有足够的剩余资源时,才能创建配额。

步骤

要为资源配置对象计数配额:

  1. 运行以下命令:

    $ 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

    此示例将列出的资源限制为集群中每个项目中的硬性限制。

  2. 验证配额已创建

    $ 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

为扩展资源设置资源配额

扩展资源不允许资源超额分配,因此必须在配额中为相同的扩展资源指定 requestslimits。目前,只有以 requests. 为前缀的配额项才允许用于扩展资源。以下是设置 GPU 资源 nvidia.com/gpu 资源配额的示例场景。

步骤
  1. 确定集群中节点上可用的 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 可用。

  2. 创建一个 ResourceQuota 对象以在 nvidia 命名空间中设置配额。在此示例中,配额为 1

    示例输出
    apiVersion: v1
    kind: ResourceQuota
    metadata:
      name: gpu-quota
      namespace: nvidia
    spec:
      hard:
        requests.nvidia.com/gpu: 1
  3. 创建配额

    # oc create -f gpu-quota.yaml
    示例输出
    resourcequota/gpu-quota created
  4. 验证命名空间是否已设置正确的配额

    # oc describe quota gpu-quota -n nvidia
    示例输出
    Name:                    gpu-quota
    Namespace:               nvidia
    Resource                 Used  Hard
    --------                 ----  ----
    requests.nvidia.com/gpu  0     1
  5. 定义一个请求单个 GPU 的 Pod。以下示例定义文件名为 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
  6. 创建 Pod

    # oc create -f gpu-pod.yaml
  7. 验证 Pod 是否正在运行

    # oc get pods
    示例输出
    NAME              READY     STATUS      RESTARTS   AGE
    gpu-pod-s46h7     1/1       Running     0          1m
  8. 验证配额 Used 计数器是否正确

    # oc describe quota gpu-quota -n nvidia
    示例输出
    Name:                    gpu-quota
    Namespace:               nvidia
    Resource                 Used  Hard
    --------                 ----  ----
    requests.nvidia.com/gpu  1     1
  9. 尝试在 nvidia 命名空间中创建第二个 GPU Pod。从技术上讲,这在节点上可用,因为它有 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

    由于您有 1 个 GPU 的配额,而此 Pod 尝试分配第二个 GPU,这超过了其配额,因此会出现此预期的禁止错误消息。

查看配额

您可以通过在 Web 控制台中导航到项目的配额页面来查看与项目配额中定义的任何硬性限制相关的使用情况统计信息。

您也可以使用 CLI 查看配额详细信息。

步骤
  1. 获取项目中定义的配额列表。例如,对于名为 demoproject 的项目

    $ oc get quota -n demoproject
    示例输出
    NAME                           AGE    REQUEST                                                                                                      LIMIT
    besteffort                     4s     pods: 1/2
    compute-resources-time-bound   10m    pods: 0/2                                                                                                    limits.cpu: 0/1, limits.memory: 0/1Gi
    core-object-counts             109s   configmaps: 2/10, persistentvolumeclaims: 1/4, replicationcontrollers: 1/20, secrets: 9/10, services: 2/10
  2. 描述您感兴趣的配额,例如 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

配置显式资源配额

在项目请求模板中配置显式资源配额,以便在新项目中应用特定的资源配额。

先决条件
  • 以具有 cluster-admin 角色的用户身份访问集群。

  • 安装 OpenShift CLI(oc)。

步骤
  1. 将资源配额定义添加到项目请求模板

    • 如果集群中不存在项目请求模板

      1. 创建一个引导项目模板并将其输出到名为 template.yaml 的文件中

        $ oc adm create-bootstrap-project-template -o yaml > template.yaml
      2. 将资源配额定义添加到 template.yaml。以下示例定义了一个名为“storage-consumption”的资源配额。此定义必须添加到模板中的 parameters: 部分之前

        - apiVersion: v1
          kind: ResourceQuota
          metadata:
            name: storage-consumption
            namespace: ${PROJECT_NAME}
          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)
        1 项目中持久卷声明的总数。
        2 项目中所有持久卷声明的存储请求总和不能超过此值。
        3 项目中所有持久卷声明中,gold 存储类中请求的存储总和不能超过此值。
        4 项目中所有持久卷声明中,silver 存储类中请求的存储总和不能超过此值。
        5 项目中所有持久卷声明中,silver 存储类中的声明总数不能超过此值。
        6 在项目中的所有持久卷声明中,在青铜存储类中请求的存储总和不能超过此值。当此值设置为 0 时,青铜存储类无法请求存储。
        7 在项目中的所有持久卷声明中,在青铜存储类中请求的存储总和不能超过此值。当此值设置为 0 时,青铜存储类无法创建声明。
      3. openshift-config 命名空间中修改后的 template.yaml 文件创建项目请求模板

        $ oc create -f template.yaml -n openshift-config

        要将配置作为 kubectl.kubernetes.io/last-applied-configuration 注解包含在内,请向 oc create 命令添加 --save-config 选项。

        默认情况下,模板名为 project-request

    • 如果集群中已存在项目请求模板

      如果您使用配置文件声明式或命令式地管理集群中的对象,请通过这些文件编辑现有的项目请求模板。

      1. 列出 openshift-config 命名空间中的模板

        $ oc get templates -n openshift-config
      2. 编辑现有的项目请求模板

        $ oc edit template <project_request_template> -n openshift-config
      3. 将资源配额定义(例如前面的 storage-consumption 示例)添加到现有模板中。此定义必须添加到模板中的 parameters: 部分之前。

  2. 如果您创建了项目请求模板,请在集群的项目配置资源中引用它

    1. 访问项目配置资源以进行编辑

      • 使用 Web 控制台

        1. 导航到管理集群设置页面。

        2. 单击配置以查看所有配置资源。

        3. 找到项目的条目,然后单击编辑 YAML

      • 使用 CLI

        1. 编辑 project.config.openshift.io/cluster 资源

          $ oc edit project.config.openshift.io/cluster
    2. 更新项目配置资源的 spec 部分以包含 projectRequestTemplatename 参数。以下示例引用默认项目请求模板名称 project-request

      apiVersion: config.openshift.io/v1
      kind: Project
      metadata:
      #  ...
      spec:
        projectRequestTemplate:
          name: project-request
  3. 验证创建项目时是否应用了资源配额

    1. 创建一个项目

      $ oc new-project <project_name>
    2. 列出项目的资源配额

      $ oc get resourcequotas
    3. 详细描述资源配额

      $ oc describe resourcequotas <resource_quota_name>