配置精细资源限制

为了更有效地管理基础架构费用和配额,您可以为 Google Kubernetes Engine (GKE) 集群自动扩缩器定义资源上限。本文档介绍了如何使用 CapacityQuota 自定义资源为部分节点指定自动扩缩资源限制。与集群范围的资源限制不同,您可以使用 Kubernetes 标签选择器在 CapacityQuota 中选择特定节点。

本文档适用于管理集群伸缩和基础设施的平台管理员。您应熟悉 Kubernetes 节点标签和 GKE 集群自动扩缩器

CapacityQuota 资源限额的运作方式

CapacityQuota 是一种集群范围的 Kubernetes 自定义资源,您可以在清单中对其进行配置,然后将其应用到集群。您可以使用 CapacityQuota 规范中的以下字段来选择节点并指定资源限制:

  • selector:使用一个或多个标签选择器过滤特定节点。 例如,您可以选择特定 ComputeClass 的所有节点,也可以选择具有两个特定标签的节点。
  • limits:为与选择器匹配的节点指定最大资源限制。例如,您可以限制特定自定义 ComputeClass 可使用的 CPU 数量,也可以限制特定类型的 GPU 数量。

当扩容操作开始时,集群自动扩缩器会根据与节点标签匹配的所有 CapacityQuota 以及任何已配置的集群级资源限制来检查提议的节点。仅当节点未违反任何配置的资源限制时,GKE 才会创建该节点。

限制

  • GKE 会拒绝指定 node.kubernetes.io/instance-typebeta.kubernetes.io/instance-type 标签选择器的 CapacityQuota。如需限制使用特定机器类型的节点,请创建具有 machineType 优先级规则的自定义 ComputeClass,然后在 CapacityQuota 中选择该 ComputeClass。
  • 与集群范围的限制类似,CapacityQuotas 可能会阻止 ComputeClass 主动迁移。由于主动迁移是一种扩容操作,因此集群自动扩缩器会根据所有适用的 CapacityQuota 和集群级资源限制来检查潜在的新节点。如果新节点违反了上述任何限制,则 GKE 不会创建该节点,并且不会发生主动迁移。只有当 CapacityQuota 已达到或接近配置的限制时,才会出现这种情况。
  • CapacityQuota 限制并非严格的限制。在极少数情况下,您可能会发现 GKE 略微超出了配置的限制。
  • CapacityQuota 限制仅由集群自动扩缩器强制执行。您可以通过手动纵向扩容集群或将限值更改为低于当前使用量来超出限值。
  • 如果集群中的节点超出配置的 CapacityQuota 限制,集群自动扩缩器会阻止创建与超出的 CapacityQuota 匹配的新节点。集群自动扩缩器不会缩容与 CapacityQuota 匹配的现有节点。

准备工作

在开始之前,请确保您已执行以下任务:

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如果您要使用 Google Cloud CLI 执行此任务,请安装初始化 gcloud CLI。如果您之前安装了 gcloud CLI,请通过运行 gcloud components update 命令来获取最新版本。较早版本的 gcloud CLI 可能不支持运行本文档中的命令。
  • 确保您已有运行 1.36.2-gke.2064000 版或更高版本的 Autopilot 或 Standard 集群。如需创建新集群,请参阅创建 Autopilot 集群

在 CapacityQuota 中配置资源限制

您可以使用以下一种或两种方法来选择 CapacityQuota 所适用的节点:

  • 使用确切的节点标签选择节点:在 matchLabels 字段中指定一个或多个节点标签键值对。GKE 会查找具有您指定的所有标签的节点。此方法类似于在 Pod 规范中使用 nodeSelector 字段。

  • 使用表达式选择节点:通过指定标签键、运算符和值来指定一个或多个标签选择器表达式。此方法类似于在 Pod 规范中使用 nodeAffinity 字段。

使用节点标签选择节点

如需使用 matchLabels 字段基于节点标签匹配构建 CapacityQuota,请按照以下步骤操作:

  1. 保存以下示例 CapacityQuota 之一,每个示例都适用于特定使用情形:

    • 通过指定 cloud.google.com/compute-class 标签,为整个自定义 ComputeClass 配置资源限制:

      apiVersion: autoscaling.x-k8s.io/v1beta1
      kind: CapacityQuota
      metadata:
        name: capacity-quota-compute-class
      spec:
        selector:
          matchLabels:
            cloud.google.com/compute-class: my-class
        limits:
          resources:
            cpu: 12
      

      此 CapacityQuota 将集群自动扩缩器的 CPU 数量限制为最多 12 个,这些 CPU 分配给 GKE 为 my-class ComputeClass 创建的所有节点。

    • 使用 cloud.google.com/gke-accelerator 标签和 nvidia.com/gpu 资源名称配置特定类型 GPU 的数量限制:

      apiVersion: autoscaling.x-k8s.io/v1beta1
      kind: CapacityQuota
      metadata:
        name: capacity-quota-gpu
      spec:
        selector:
          matchLabels:
            cloud.google.com/compute-class: my-gpu-class
            cloud.google.com/gke-accelerator: nvidia-tesla-t4
        limits:
          resources:
            nvidia.com/gpu: 16
      

      此 CapacityQuota 将集群自动扩缩器限制为在 my-gpu-class ComputeClass 中最多使用 16 个 NVIDIA Tesla T4 GPU。如果省略 ComputeClass 选择器,则相应限制将应用于集群中的所有 NVIDIA Tesla T4 GPU 节点。

    • 使用 topology.kubernetes.io/zone 标签和 nodes 资源名称,为 GKE 在特定可用区中创建的节点数量配置限制:

      apiVersion: autoscaling.x-k8s.io/v1beta1
      kind: CapacityQuota
      metadata:
        name: capacity-quota-zone
      spec:
        selector:
          matchLabels:
            topology.kubernetes.io/zone: us-central1-b
        limits:
          resources:
            nodes: 64
      

      此 CapacityQuota 将集群自动扩缩器限制为 us-central1-b 可用区中的 64 个节点。

  2. 创建 CapacityQuota:

    kubectl apply -f PATH_TO_MANIFEST_FILE
    

    PATH_TO_MANIFEST_FILE 替换为您创建的 CapacityQuota 清单文件的路径。

使用表达式选择节点

对于更复杂的定位,除了 matchLabels 字段之外,CapacityQuota 还支持定义 matchExpressions 字段。matchExpressions 支持 InNotInExistsDoesNotExist 等运算符。

  1. 创建使用 matchExpressions 字段的 CapacityQuota 清单。以下 CapacityQuota 示例通过使用 In 运算符对在特定高性能机器家族上运行的节点进行分组,从而对这些节点应用 CPU 和内存限制:

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityQuota
    metadata:
      name: capacity-quota-high-perf-machines
    spec:
      selector:
        matchExpressions:
          - key: cloud.google.com/machine-family
            operator: In
            values:
              - c2
              - c3
              - c3d
      limits:
        resources:
          cpu: 64
          memory: 128Gi
    
  2. 将清单应用到您的集群:

    kubectl apply -f PATH_TO_MANIFEST_FILE
    

    PATH_TO_MANIFEST_FILE 替换为您创建的 CapacityQuota 清单文件的路径。

验证 CapacityQuota 配置

本部分介绍如何通过部署违反这些限制的示例工作负载来验证 CapacityQuota 是否主动强制执行限制。如需执行此验证,请按以下步骤操作:

  1. 将以下 ComputeClass 示例保存为 test-capacityquota-class.yaml

    apiVersion: cloud.google.com/v1
    kind: ComputeClass
    metadata:
      name: test-capacityquota-class
    spec:
      priorities:
      - machineFamily: n2
      nodePoolAutoCreation:
        enabled: true
    

    此 ComputeClass 可以自动创建使用 N2 机器系列的节点。

  2. 创建 ComputeClass:

    kubectl apply -f test-capacityquota-class.yaml
    
  3. 将以下 CapacityQuota 示例保存为 test-capacityquota.yaml

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityQuota
    metadata:
      name: test-capacityquota
    spec:
      selector:
        matchLabels:
          cloud.google.com/compute-class: test-capacityquota-class
      limits:
        resources:
          cpu: 8
    

    此 CapacityQuota 将自动扩缩器的 CPU 资源限制为 test-capacityquota-class ComputeClass 的 8 个。

  4. 创建 CapacityQuota:

    kubectl apply -f test-capacityquota.yaml
    
  5. 将以下 Deployment 保存为 test-capacityquota-workload.yaml

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: test-capacityquota-workload
    spec:
      replicas: 16
      selector:
        matchLabels:
          app: test-capacityquota-workload
      template:
        metadata:
          labels:
            app: test-capacityquota-workload
        spec:
          containers:
          - name: test
            image: gcr.io/google_containers/pause
            resources:
              limits:
                cpu: 500m
          nodeSelector:
            cloud.google.com/compute-class: test-capacityquota-class
    

    此 Deployment 会创建 16 个 Pod,每个 Pod 都请求 500 mCPU。由于节点会为系统组件预留一些 CPU,因此 GKE 必须创建的所有节点上的 CPU 资源总和大于 8,才能运行 16 个 Pod。

  6. 创建 Deployment:

    kubectl apply -f test-capacityquota-workload.yaml
    
  7. 等待大约两分钟,然后验证 Pod 调度状态:

    kubectl get pods -l app=test-capacityquota-workload
    

    集群自动扩缩器会将节点扩容到 CapacityQuota 限制(8 个 CPU)。达到此限制后,自动扩缩器不会再创建节点。因此,部署中的某些 Pod 仍处于 Pending 状态。

  8. 如需验证 CapacityQuota 是否导致了 Pending 状态,请描述其中一个处于等待状态的 Pod:

    kubectl describe pod PENDING_POD_NAME
    

    PENDING_POD_NAME 替换为卡在 Pending 状态的 Pod 的名称。

    输出类似于以下内容,表明 CapacityQuota 阻止了节点扩缩:

    Pod didn't trigger scale-up: 1 exceeded quota: "CapacityQuota/test-capacityquota", resources: cpu
    

    您还可以使用集群自动扩缩器可见性日志查看这些事件。检查 noScaleUp 事件,如以下示例所示:

    {
      "jsonPayload": {
        "noDecisionStatus": {
          "noScaleUp": {
            "skippedMigs": [
              {
                "reason": {
                  "parameters": [
                    "exceeded quota: \"CapacityQuota/test-capacityquota\", resources: cpu"
                  ],
                  "messageId": "no.scale.up.mig.skipped"
                },
                "mig": {
                  "name": "gke-test-grp",
                  "zone": "us-central1-f",
                  "nodepool": "nap-n2-highcpu-2-test"
                }
              }
            ]
          }
        }
      }
    }
    

检查 CapacityQuotas 的使用情况和有效性

CapacityQuota API 资源中的 status 字段提供有关与 CapacityQuota 匹配的节点的资源使用情况以及 CapacityQuota 规范有效性的信息。

如需检查 CapacityQuota 的状态,请运行以下命令:

kubectl describe capacityquota CAPACITY_QUOTA_NAME

CAPACITY_QUOTA_NAME 替换为您要检查的 CapacityQuota 的名称。

在输出中,检查以下字段:

  • 如需检查匹配节点的资源用量,请使用 status.used 字段:

    status:
      conditions:
      - lastTransitionTime: "2026-07-27T10:00:00Z"
        message: "CapacityQuota is valid"
        reason: "Valid"
        status: "True"
        type: "cluster-autoscaler.kubernetes.io/valid"
      used:
        resources:
          cpu: 32
          memory: 128Gi
    

    status.used 字段仅用于可观测性,集群自动调节程序不会使用它来强制执行限制。此字段仅在成功执行扩容操作后显示用量。集群自动扩缩器还会跟踪内部待处理的节点,并将这些待处理的节点纳入后续的纵向扩容评估中。这种内部跟踪有助于防止超出限制。

  • 如需检查 CapacityQuota 的有效性,请使用 status.conditions 字段:

    status:
      conditions:
      - lastTransitionTime: "2026-07-27T10:00:00Z"
        message: "CapacityQuota is valid"
        reason: "Valid"
        status: "True"
        type: "cluster-autoscaler.kubernetes.io/valid"
      used:
        resources:
          cpu: 32
          memory: 128Gi
    

    cluster-autoscaler.kubernetes.io/valid 条件用于验证 CapacityQuota 是否使用了有效的配置,例如格式正确的选择器。如果此条件的 status 字段中的值为 True,则 CapacityQuota 有效,并且系统会强制执行您的限制。不过,如果 status 字段中的值为 False,或者条件尚不存在,则不会强制执行限制。message 字段提供有关 CapacityQuota 无效原因的详细信息。

后续步骤