配置容量缓冲区

容量缓冲区通过使用 Kubernetes CapacityBuffer 自定义资源定义 (CRD) 主动管理预配置、预配置容量的备用集群容量和暂停状态,来提高关键工作负载的响应能力和可靠性。使用容量缓冲区可让您明确定义集群中未使用的节点容量的具体数量。此预留容量有助于缩短 Pod 调度时间。

当高优先级工作负载需要快速扩容时,新工作负载可以立即使用空闲容量,而无需等待节点预配。这种方法可最大限度地减少延迟时间,并避免在需求突然激增时出现资源争用。

本页介绍了配置容量缓冲区的各种方法:固定副本缓冲区、资源限制缓冲区和基于百分比的缓冲区。

准备工作

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

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如果您要使用 Google Cloud CLI 执行此任务,请安装初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请通过运行 gcloud components update 命令来获取最新版本。较早版本的 gcloud CLI 可能不支持运行本文档中的命令。
  • 创建或有权访问版本为 1.35.2-gke.1842000 的 GKE 集群(用于活动缓冲区),以及版本为 1.36.0-gke.2253000 或更高版本的 GKE 集群(用于备用缓冲区)。
  • 在 Standard 集群上启用节点自动预配。在 Autopilot 集群中,节点自动预配功能已启用。节点自动预配功能是可选的,但建议用于有效缓冲区,并且必须用于备用缓冲区。

创建前提条件 Kubernetes 对象

如需配置 CapacityBuffer,您需要一个包含所有必需对象的命名空间(CapacityBuffer 本身以及 PodTemplate 或工作负载等其他资源)。PodTemplate 和 CapacityBuffer 必须位于同一命名空间中。您可以创建命名空间,也可以使用现有命名空间,包括 default 命名空间。

根据您配置的 CapacityBuffer 类型,您���需要以下其中一项:

  • PodTemplate:定义单个缓冲区容量单位的资源要求。在 CapacityBuffer 对象中指定的配置引用了 Pod 模板。
  • 工作负载:您在 CapacityBuffer 对象中引用的现有工作负载。本指南使用 Deployment 对象作为工作负载示例,但容量缓冲区支持以下任何资源类型:

    • 部署
    • ReplicaSet
    • StatefulSet
    • ReplicationController
    • 作业
    • 实现 scale 子资源的 CustomResourceDefinition (CRD)。

本部分提供了这些对象的示例。如果您已有要配置容量缓冲的工作负载,请继续应用容量缓冲

如需创建示例 Kubernetes 工作负载,请完成以下步骤:

  1. 将以下清单保存为 namespace.yaml

    apiVersion: v1
    kind: Namespace
    metadata:
      name: capacity-buffer-example
      labels:
        name: capacity-buffer-example
    

    此清单会创建一个名为 capacity-buffer-example 的命名空间。

  2. 可选:如需将容量缓冲区与自定义 ComputeClass 搭配使用,请将以下清单保存为 custom-compute-class.yaml

    apiVersion: cloud.google.com/v1
    kind: ComputeClass
    metadata:
      name: ccc-example
      namespace: capacity-buffer-example
    spec:
      # Buffers are also created according to these priorities
      priorities:
      - machineFamily: n4
      - machineFamily: n4d
      - machineFamily: c4
      - machineFamily: c4d
      nodePoolAutoCreation:
        enabled: true
    

    此清单会创建一个自定义 ComputeClass,用于定义和控制 GKE 配置的节点的计算优先级。如需了解详情,请参阅自定义 ComputeClass

  3. 将以下清单保存为 buffer-pod-template.yaml

    apiVersion: v1
    kind: PodTemplate
    metadata:
      name: buffer-unit-template
      namespace: capacity-buffer-example # the namespace must be the same namespace as the CapacityBuffer
    template:
      spec:
        terminationGracePeriodSeconds: 0
        containers:
        - name: buffer-container
          image: registry.k8s.io/pause:3.9
          resources:
            requests:
              cpu: "1"
              memory: "1Gi"
            limits:
              cpu: "1"
              memory: "1Gi"
        # Optional: Using buffers with a custom ComputeClass /
        # controls the properties of the provisioned nodes.
        nodeSelector:
          cloud.google.com/compute-class: ccc-example
    

    此清单创建了一个 PodTemplate,用于定义单个缓冲区容量单位(1 CPU 和 1Gi 内存)的资源要求。此配置用于指定 GKE 为缓冲区预配的容量单位的大小。例如,如果集群扩缩,对于此 PodTemplate,GKE 不会将可用资源少于 1 个 CPU 和 1Gi 的节点视为缓冲区的一部分。

  4. 将以下清单保存为 sample-workload-deployment.yaml

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: critical-workload-ref
      namespace: capacity-buffer-example # the namespace must be the same namespace as the CapacityBuffer
    spec:
      replicas: 10
      selector:
        matchLabels:
          app: critical-workload
      template:
        metadata:
          labels:
            app: critical-workload
        spec:
          containers:
          - name: busybox
            image: busybox
            command: ["sleep", "3600"]
            resources:
              requests:
                cpu: 100m
          # Optional: Using buffers with a custom ComputeClass /
          # controls the properties of the provisioned nodes.
          nodeSelector:
            cloud.google.com/compute-class: ccc-example
    

    此清单会创建一个包含 10 个副本的示例 Deployment,该 Deployment 是下一部分中基于百分比的缓冲区示例的参考对象。

  5. 将清单应用到您的集群:

    kubectl apply -f namespace.yaml -f custom-compute-class.yaml -f buffer-pod-template.yaml -f sample-workload-deployment.yaml
    
  6. 验证 GKE 是否已创建对象:

    kubectl get podtemplate -n capacity-buffer-example
    kubectl get deployment critical-workload-ref -n capacity-buffer-example
    

    输出类似于以下内容:

    NAME                   AGE
    buffer-unit-template   1m
    
    NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
    critical-workload-ref   10/10   10           10          1m
    

应用容量缓冲

本部分提供了可应用于工作负载的不同类型的容量缓冲区的示例。

配置固定副本缓冲区

配置具有固定副本数的 CapacityBuffer 可指定您基于 PodTemplate 所需的确切缓冲区单元数。

如需创建具有固定副本数的缓冲区,请完成以下步骤:

  1. 将以下清单保存为 cb-fixed-replicas.yaml

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityBuffer
    metadata:
      name: fixed-replica-buffer
      namespace: NAMESPACE
    spec:
      podTemplateRef:
        name: POD_TEMPLATE
      replicas: 3
      provisioningStrategy: "STRATEGY"
    

    替换以下内容:

    • NAMESPACE:命名空间的名称,例如 capacity-buffer-example
    • POD_TEMPLATE:用于定义资源要求的 PodTemplate,例如 buffer-unit-template
    • STRATEGY:预配策略,为 "buffer.x-k8s.io/active-capacity"(默认)或 "buffer.gke.io/standby-capacity"

    此清单会创建一个 CapacityBuffer 资源,该资源引用一个 PodTemplate 来请求特定数量的缓冲区单元。

  2. 应用清单:

    kubectl apply -f cb-fixed-replicas.yaml
    
  3. 确认 GKE 已应用容量缓冲区:

    kubectl get capacitybuffer fixed-replica-buffer -n NAMESPACE
    

    状态中的 replicas 字段应显示 3,这反映了您在清单中定义的副本数量。STATUS 字段应显示 ReadyForProvisioning

配置资源限制缓冲区

您可以使用 limits 字段来定义缓冲区应消耗的最大资源量,该资源量是根据您的 PodTemplate 大小计算得出的。

如需创建资源限制缓冲区,请完成以下步骤:

  1. 将以下清单保存为 cb-resource-limits.yaml

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityBuffer
    metadata:
      name: resource-limit-buffer
      namespace: NAMESPACE
    spec:
      podTemplateRef:
        name: POD_TEMPLATE
      limits:
        cpu: "5"
        memory: "5Gi"
      provisioningStrategy: "STRATEGY"
    

    替换以下内容:

    • NAMESPACE:命名空间的名称,例如 capacity-buffer-example
    • POD_TEMPLATE:用于定义资源要求的 PodTemplate,例如 buffer-unit-template
    • STRATEGY:预配策略,为 "buffer.x-k8s.io/active-capacity"(默认)或 "buffer.gke.io/standby-capacity"

    此清单会创建一个 CapacityBuffer 资源,其总限制为 5 个 CPU 和 5 GiB 内存。如果您使用的是上一步中的 PodTemplate 示例,则将每个单元定义为 1 CPU 和 1Gi 内存,这应该会产生 5 个缓冲区单元。

  2. 应用清单:

    kubectl apply -f cb-resource-limits.yaml
    
  3. 确认 GKE 已应用容量缓冲区:

    kubectl get capacitybuffer resource-limit-buffer -n NAMESPACE
    

    检查 CapacityBuffer 状态。replicas 字段应显示根据您定义的限值得出的值。如果您使用的是上一部分中的 PodTemplate 示例,则应看到 5 个缓冲区单位,因为这是在定义的限制范围内可容纳的最大单位数。

配置基于百分比的缓冲区

配置基于百分比的缓冲区会根据现有可伸缩工作负载的百分比动态调整缓冲区的大小。基于百分比的容量缓冲区仅适用于实现伸缩子资源的 Kubernetes 可伸缩对象,例如 Deployment、StatefulSet、ReplicaSet 或 Job。您无法为 Pod 模板定义基于百分比的缓冲区,因为它们没有 replicas 字段。

我们通常建议先采用固定副本或资源限制策略,而不是基于百分比的缓冲区。如果工作负载缩放到较低的数字或零,基于百分比的缓冲区对突然的扩缩响应速度会较慢,因为安全边际会按比例缩放活动 Pod。它们主要适用于永远不会缩减到极低副本数的大规模部署。

如需创建基于百分比的缓冲区,请完成以下步骤:

  1. 将以下清单保存为 cb-percentage-based.yaml

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityBuffer
    metadata:
      name: percentage-buffer
      namespace: NAMESPACE
    spec:
      scalableRef:
        apiGroup: apps
        kind: Deployment
        name: SCALABLE_RESOURCE_NAME
      percentage: 20
      provisioningStrategy: "STRATEGY"
    

    替换以下内容:

    • NAMESPACE:您的命名空间名称。
    • SCALABLE_RESOURCE_NAME:可伸缩资源的名称,例如 critical-workload-ref
    • STRATEGY:预配策略,为 "buffer.x-k8s.io/active-capacity"(默认)或 "buffer.gke.io/standby-capacity"

    此清单会创建一个 CapacityBuffer 资源,该资源请求的缓冲区空间大小相当于所引用资源的副本数的 20%。如果您使用的是上一部分中的部署示例,则副本值设置为 10

  2. 应用清单:

    kubectl apply -f cb-percentage-based.yaml
    
  3. 确认 GKE 已应用容量缓冲区:

    kubectl get capacitybuffer percentage-buffer -n NAMESPACE
    

    检查 CapacityBuffer 状态。replicas 字段应显示百分比计算得出的值。如果您使用的是上一部分中的部署示例,则应看到 2 个缓冲区单元,这相当于部署中定义的 10 个副本的 20%。

  4. 通过手动将部署扩缩到 20 个副本来测试动态伸缩:

    kubectl scale deployment critical-workload-ref -n NAMESPACE --replicas=20
    

    CapacityBuffer 控制器会做出反应,并自动将缓冲区扩缩为 4 个副本。

自定义待机缓冲区行为

您可以使用注释来自定义备用缓冲区的启动和刷新方式。将以下注解添加到 CapacityBuffer 资源的 metadata.annotations 字段:

  • buffer.gke.io/standby-capacity-init-time:节点在创建后到被暂停之前保持活动状态的时间量。格式为时长字符串(例如 5m1h)。默认值为 5m
  • buffer.gke.io/standby-capacity-refresh-frequency:刷新已暂停节点的频率。默认值为 1d

以下示例展示了一个包含这些可选字段的清单,用于自定义待机缓冲区的行为:

apiVersion: autoscaling.x-k8s.io/v1beta1
kind: CapacityBuffer
metadata:
  name: customized-standby-buffer
  namespace: my-namespace
  annotations:
    buffer.gke.io/standby-capacity-init-time: "15m"
    buffer.gke.io/standby-capacity-refresh-frequency: "12h"
spec:
  podTemplateRef:
    name: buffer-unit-template
  replicas: 3
  provisioningStrategy: "buffer.gke.io/standby-capacity"

在待机缓冲区中预加载图片

为了缩短备用节点恢复时的工作负载启动时间,您可以使用 DaemonSet 预加载容器映像。DaemonSet 在节点挂起之前的启动期间运行。

如需使用 DaemonSet 预加载映像,请完成以下步骤:

  1. 将以下清单保存为 image-puller-daemonset.yaml

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: image-prefetch-daemonset
      namespace: NAMESPACE
    spec:
      selector:
        matchLabels:
          name: image-prefetch
      template:
        metadata:
          labels:
            name: image-prefetch
        spec:
          tolerations:
          - key: "buffer.gke.io/standby-node-suspended"
            operator: "Exists"
          initContainers:
          - name: image-puller
            image: IMAGE_NAME
            command: ["sh", "-c", "true"]
          containers:
          - name: pause
            image: registry.k8s.io/pause:3.9
    

    替换以下内容:

    • NAMESPACE:DaemonSet 的命名空间,例如 capacity-buffer-example
    • IMAGE_NAME:要预加载的映像的名称,例如 your-app-image:latest
  2. 将 DaemonSet 清单应用到您的集群:

    kubectl apply -f image-puller-daemonset.yaml
    
  3. 验证 DaemonSet 是否已创建:

    kubectl get daemonset image-prefetch-daemonset -n NAMESPACE
    
  4. 验证容量缓冲区是否已创建并可用于配置:

    kubectl get capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE
    

    查看状态。STATUS 字段应显示 ReadyForProvisioning

监控容量缓冲状态和性能

您可以使用 kubectl 命令和 Cloud Monitoring 指标监控容量缓冲区的状态和健康状况。

验证 CapacityBuffer 资源状态

如需检查容量缓冲区的健康状况并验证它们是否已准备好接收工作负载,请完成以下步骤:

  1. 获取整个集群中所有容量缓冲区的状态:

    kubectl get capacitybuffer -A
    
  2. 检查特定缓冲区的详细状态、条件和事件日志:

    kubectl describe capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE
    

识别已暂停的备用缓冲区节点

备用缓冲虚拟机已预先配置,但会保持在暂停状态,以帮助降低费用。您可以识别这些已暂停的节点,因为它们具有自定义条件。如需审核已暂停的节点实例,请运行以下命令:

kubectl get nodes -o custom-columns='NAME:.metadata.name,SUSPENDED:.status.conditions[?(@.type=="Suspended")].status'

状态为 True 表示备用虚拟机已暂停。状态为 False<none> 表示节点处于活跃运行状态。

使用 Cloud Monitoring 监控性能

为了帮助您监控容量缓冲区的性能,请在 Cloud Monitoring 中监控以下资源:

  • 响应延迟时间 (cluster_autoscaler/reaction_time_milliseconds):跟踪集群自动伸缩器根据 CapacityBuffer 待处理需求做出伸缩决策的持续时间。
  • 集群自动扩缩器日志:搜索类似 "Capacity pod processor injecting ..." 的日志条目,以观察活跃的缓冲区 Pod 替换事件。

移除容量缓冲

如果您不再需要为工作负载提供容量缓冲,请删除 CapacityBuffer 对象。这样会移除占位 Pod,并允许集群自动扩缩器缩容节点。

kubectl delete capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE

CAPACITY_BUFFER_NAME 替换为您要删除的 CapacityBuffer 的名称。

问题排查

以下部分包含有关解决容量缓冲区的常见问题的信息。

由于结算模式,容量缓冲尚未准备就绪

如果您为使用基于 Pod 的结算模式(按 Pod 付费)的工作负载创建 CapacityBuffer,则容量缓冲区将无法用于预配。

如需确定此问题,请检查 CapacityBuffer 状态:

kubectl describe capacitybuffer BUFFER_NAME -n NAMESPACE

查找类型为 ReadyForProvisioning 且状态为 False 的条件。

如需解决此问题,请确保您的 CapacityBuffer 引用的是与基于节点的结算兼容的工作负载或 PodTemplate。

自定义可伸缩资源的权限错误

如果您配置 CapacityBuffer 以使用自定义可伸缩对象(使用 scalableRef 字段),则集群自动伸缩器可能会因缺少必要的权限而无法伸缩缓冲区。

如需解决此问题,请手动授予所需权限,方法是创建 ClusterRoleClusterRoleBinding,如以下示例所示:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: custom-scale-getter
rules:
- apiGroups: ["api.example.com"]
  resources: ["customreplicatedresources/scale"]
  verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: ca-custom-scale-getter
subjects:
- kind: User
  name: "system:cluster-autoscaler"
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: custom-scale-getter

如需详细了解如何配置 RBAC,请参阅 Kubernetes RBAC 文档

后续步骤