配置精细资源限制

为了更有效地管理基础架构费用和配额,您可以为 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-type 和 beta.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 将集群自动扩缩器限制为在 GKE 为 my-class ComputeClass 创建的所有节点上最多使用 12 个 CPU。

    • 使用 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 支持 In、NotIn、Exists 和 DoesNotExist 等运算符。

  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 将自动扩缩器限制为最多为 test-capacityquota-class ComputeClass 提供 8 个 CPU 资源。

  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)。 达到此上限后,自动扩缩器不会创建节点。因此,Deployment 中的某些 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 无效原因的详细信息。

后续步骤