配置容量缓冲区

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

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

本页面介绍了如何配置固定副本、资源限制和基于百分比的容量缓冲区,如何将缓冲区专用于特定工作负载,如何自定义备用缓冲区行为,以及如何预加载容器映像。

准备工作

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

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如需使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。如果您之前安装了 gcloud CLI,请通过运行 gcloud components update 命令来获取最新版本。较早版本的 gcloud CLI 可能不支持运行本文档中的命令。
  • 创建或有权访问运行 1.37.1-gke.3020000 版或更高版本的 GKE 集群。Autopilot 集群上的备用缓冲区需要自定义 ComputeClass。
  • 在 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
    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,它是下一部分中基于百分比的缓冲区示例的参考对象。

  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 成比例地减少。
  • 备用节点在暂停前的初始化期间会产生计算费用。随着工作负载波动动态伸缩备用缓冲区会浪费计算资源,因此请改为对备用缓冲区使用固定副本或资源限制。
  • 基于百分比的缓冲区主要适用于大型部署中的活跃缓冲区,这些部署永远不会缩减到较低的副本数。

如需在引用的工作负载缩容时保持最小缓冲区空间,请同时设置 replicas 字段和 percentage 字段。GKE 会使用可产生更多缓冲区单元的字段。如需限制缓冲区空间,还需设置 limits 字段。

例如,假设有一个包含 percentage: 20 和 replicas: 3 的缓冲区,它引用了具有 10 个副本的 Deployment。由于 10 个副本的 20% 为 2,小于 replicas 值 3,因此 GKE 会预配 3 个缓冲区单元。如果 Deployment 扩缩到 20 个副本,则缓冲区会增加到 4 个单元。如需了解详情,请参阅 CapacityBuffer 参考文档。

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

  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%。如果您使用的是上一部分中的 Deployment 示例,则副本值会设置为 10。

  2. 应用清单:

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

    kubectl get capacitybuffer percentage-buffer -n NAMESPACE
    

    检查 CapacityBuffer 状态。replicas 字段应显示百分比计算结果。如果您使用的是上一部分中的 Deployment 示例,则应该会看到 2 个缓冲区单元,即 Deployment 中定义的 10 个副本的 20%。

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

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

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

为特定工作负载分配专用容量缓冲区

默认情况下,任何与缓冲区节点的调度限制条件匹配的待处理 Pod 都可以声明缓冲区容量。当多个工作负载共享一个自定义 ComputeClass 或节点池时,请使用工作负载分离为特定工作负载预留容量缓冲区。此方法需要节点池自动创建,或 Standard 集群上活跃缓冲区的专用节点池。

避免为许多单独的工作负载分配单独的容量缓冲区。每个专用缓冲区都需要自己的节点池,这会增加预配和重新填充缓冲区的时间。如需了解建议的缓冲区数量,请参阅可伸缩性。

如需将容量缓冲区专用于特定工作负载,请完成以下步骤:

  1. 在工作负载清单(例如创建前提条件 Kubernetes 对象中的 sample-workload-deployment.yaml)中,向 Pod 规范添加自定义容忍度和节点选择器:

    spec:
      tolerations:
      - key: KEY
        operator: Equal
        value: "VALUE"
        effect: NoSchedule
      nodeSelector:
        KEY: "VALUE"
        cloud.google.com/compute-class: ccc-example
    

    替换以下内容:

    • KEY:污点和节点标签的自定义键,例如 group。如需了解受限键前缀,请参阅工作负载隔离的限制。
    • VALUE:用于标识工作负载的自定义值,例如 critical-workload。

    在 Autopilot 集群上,请在 nodeSelector 字段中保留自定义 ComputeClass 或硬件选择器,以便缓冲区使用基于节点的结算模式,而不是不受支持的基于 Pod 的结算模式。

  2. 将 CapacityBuffer 配置为使用相同的调度限制条件:

    • 如果您的 CapacityBuffer 使用 scalableRef 字段,请在 spec.scalableRef 字段中引用工作负载。缓冲区会自动继承工作负载的 tolerations 和 nodeSelector 字段。
    • 如果 CapacityBuffer 使用 podTemplateRef 字段,请将相同的 tolerations 和 nodeSelector 字段添加到 PodTemplate 清单中,例如 buffer-pod-template.yaml。
  3. 应用清单并创建 CapacityBuffer。如需查看相关说明,请参阅应用容量缓冲区。如果您在备用缓冲区上预加载映像,请同时向预加载 DaemonSet 添加自定义容忍设置,以便它可以在专用缓冲区节点上进行调度。如果缓冲区使用自定义 ComputeClass,则 DaemonSet 还需要容忍 ComputeClass 污点:

    tolerations:
    - key: "buffer.gke.io/standby-capacity-node-suspended"
      operator: "Exists"
    - key: KEY
      operator: Equal
      value: "VALUE"
      effect: NoSchedule
    - key: cloud.google.com/compute-class
      operator: Equal
      value: ccc-example
      effect: NoSchedule
    
  4. 在集群自动扩缩器预配缓冲区节点后,验证这些节点是否具有专用节点标签和节点污点:

    kubectl get nodes -l KEY=VALUE \
        -o custom-columns='NAME:.metadata.name,TAINTS:.spec.taints[*].key'
    

    输出中的每个节点都会列出 KEY 污点键。如果缓冲区使用自定义 ComputeClass,则节点还会列出 cloud.google.com/compute-class 污点键。备用缓冲区节点也具有 GKE 管理的污点,例如暂停节点上的 buffer.gke.io/standby-capacity-node-suspended。当工作负载扩容时,运行 kubectl get pods -n NAMESPACE -o wide 并确认 NODE 列列出了此输出中的专用节点名称。

自定义待机缓冲区行为

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

  • buffer.gke.io/standby-capacity-init-time:节点在创建后保持活跃状态的时长,超过该时长后 GKE 会将其暂停。指定时长字符串,例如 5m 或 1h。默认值为 5m。
  • buffer.gke.io/standby-capacity-refresh-frequency:GKE 刷新暂停节点的频率。指定时长字符串,例如 12h 或 24h,最长为 120h(5 天)。默认值为 24h。

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

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-capacity-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。

    此清单包含 buffer.gke.io/standby-capacity-node-suspended 容忍度,以便在 GKE 暂停备用节点后,DaemonSet 仍会调度到这些节点上。

  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 监控性能

如需监控容量缓冲区对扩容时间的端到端影响,请使用 Google Cloud 控制台中的启动延迟时间信息中心。您可以使用 Pod 启动延迟时间分布情况和 Pod 首次就绪延迟时间图表来跟踪从 Pod 创建到就绪的 kubernetes.io/pod/latencies/pod_first_ready 指标。您还可以在 Cloud Logging 中查询 Scheduled 事件,以衡量 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

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

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

缓冲区 Pod 不会在由自定义 ComputeClass 预配的节点上调度

如果您的 CapacityBuffer 配置依赖项(例如 PodTemplate)选择自定义 ComputeClass,您可能会遇到缓冲区 Pod 未在新预配的节点上调度的问题。此问题会导致集群自动扩缩器在删除空闲节点时重复创建冗余节点池和节点。

如果自定义 ComputeClass 预配的节点具有污点或特定运行时要求,而您的缓冲区 Pod(或它们所依赖的 PodTemplate)没有匹配的容忍设置或设置,就会出现此问题。

如需解决此问题,请更新 CapacityBuffer 配置,以指定所需的容忍设置、节点选择器或运行时类。例如,如果您的依赖项选择了配置了 GKE Sandbox 的自定义 ComputeClass,请更新依赖项以执行以下操作之一:

  • 指定 spec.runtimeClassName: gvisor 字段。
  • 为 sandbox.gke.io/runtime=gvisor:NoSchedule 污点添加显式容忍设置。

如需了解详情,请参阅自定义 ComputeClass 文档。

备用缓冲区节点无法恢复

由于以下原因之一,暂停的备用缓冲区节点可能无法恢复:

  • 如需恢复已暂停的备用节点,该可用区中必须有可用的 Compute Engine 容量,以支持该节点的机器类型和特定 CPU 平台代系(例如 E2 或 N2 机器系列)。如果可用区没有足够的计算容量来支持该确切配置,则节点无法恢复。如需了解详情,请参阅 Compute Engine 挂起和恢复限制。
  • 如果您的自定义 ComputeClass 启用了主动迁移到优先级更高的节点 (activeMigration.optimizeRulePriority: true),并且将 Spot 虚拟机的优先级设置为高于按需虚拟机,则 GKE 会随着时间的推移将按需备用节点迁移到 Spot 虚拟机。由于 Spot 虚拟机更容易受到容量限制,并且暂停的 Spot 虚拟机在恢复时无法转换为按需虚拟机,因此这些限制可能会阻止这些备用节点恢复。
  • 恢复节点会超出项目的 Compute Engine 配额。如需了解详情,请参阅由于配额限制,容量缓冲区无法预配。

如需确定备用节点未能恢复的原因,请在 Logs Explorer 中查询 Compute Engine 审核日志,查找 compute.instances.resume 操作中的 ZONE_RESOURCE_POOL_EXHAUSTED 或 QUOTA_EXCEEDED 错误。

如需解决或缓解此问题,请执行以下一项或多项操作:

  • 使用区域级集群,以便集群自动扩缩器可以跨多个可用区预配或恢复节点。
  • 在自定义 ComputeClass 的 spec.priorities 列表中配置多个机器家族。如果暂停的节点无法恢复,集群自动扩缩器可以回退到根据其他优先级规则创建新节点。这些新节点需要比恢复的备用节点更长的时间才能准备就绪。此配置无法帮助暂停的节点恢复,因为暂停的节点只能使用其原始机器类型恢复。
  • 将专用自定义 ComputeClass 与按需虚拟机搭配使用,或将备用缓冲区使用的 ComputeClass 的 activeMigration.optimizeRulePriority 字段设置为 false。
  • 将备用缓冲区与小型活跃缓冲区搭配使用,以吸收即时流量高峰。

由于配额限制,容量缓冲区无法预配

如果容量缓冲区超出 Kubernetes ResourceQuota 或 Compute Engine 配额,则预配的副本数量可能会少于请求的数量,或者无法扩容。

如需确定是哪项配额限制了缓冲区,请检查以下一项或多项配额:

  • 检查命名空间中的 Kubernetes ResourceQuota 是否限制了缓冲区:

    kubectl describe capacitybuffer \
        CAPACITY_BUFFER_NAME \
        -n NAMESPACE
    

    在 status.conditions 输出中,查找状态为 True 的 LimitedByQuotas 条件。活跃和备用缓冲单元(包括由暂停的备用节点支持的单元)都会计入命名空间 ResourceQuota 限制,就像缓冲 Pod 正在运行一样。当缓冲区超出命名空间配额时,GKE 会限制 status.replicas 字段,使其不超过可用配额。

  • 检查 Compute Engine 项目配额是否阻止了节点预配。在 Logs Explorer 中,搜索 container.googleapis.com/cluster-autoscaler-visibility 日志以查找 no.scale.up.nap.quota.exceeded 事件,或搜索 Compute Engine 审核日志以查找 QUOTA_EXCEEDED 错误。

    检查备用缓冲区的 Compute Engine 配额时,除了 vCPU 和内存配额之外,还要验证以下两项配额:

    • 暂停的备用节点会保留其内部和外部 IP 地址,这会消耗使用中的 IP 地址配额。
    • 暂停备用虚拟机时,Compute Engine 会将节点的内存写入磁盘,这会消耗与节点内存大小成正比的 Persistent disk standard (GB) 磁盘配额。

如需解决配额限制问题,请执行以下某项操作:

  • 增加缓冲区命名空间中的 Kubernetes ResourceQuota。
  • 申请 Compute Engine 配额调整。
  • 减少 CapacityBuffer 清单中的 replicas、limits 或 percentage 值。

备用节点恢复后,DaemonSet Pod 停止接收数据

在暂停的备用缓冲区节点恢复后,该节点上的 DaemonSet Pod 可能会停止通过在节点暂停之前打开的长连接接收数据。Pod 不会记录任何错误,也不会重新连接。

当 DaemonSet Pod 充当只接收客户端(例如,对于流式 HTTP 响应、WebSocket 连接、服务器发送事件或 gRPC 服务器流式调用)时,会出现此问题。当备用节点暂停时,服务器或中间网络设备会超时并关闭连接。当节点恢复时,Pod 的网络栈仍会将连接视为打开状态。由于 Pod 不发送任何数据,因此它永远不会检测到连接已关闭,并会无限期等待数据。

如需解决此问题,请在 DaemonSet Pod 中配置客户端应用,以检测已关闭的连接并重新连接,方法是执行以下操作之一:

  • 在 Pod 的应用中配置客户端 TCP keepalive(仅在服务器上启用 keepalive 不会通知 Pod)。如需详细了解 TCP keepalive 参数,请参阅空闲连接。
    1. 在客户端库或语言运行时中启用 SO_KEEPALIVE 套接字选项,例如 Node.js 中的 socket.setKeepAlive(true, initialDelay) 或 Go 中的 net.Dialer.KeepAlive。某些运行时默认停用 TCP 保持连接。
    2. 配置较短的 keepalive 空闲时间 (TCP_KEEPIDLE)(例如几秒钟),而不是依赖于操作系统默认值。
    3. 更新您的应用,以便在 keepalive 探测失败时捕获连接错误(例如连接重置或超时),并打开新连接。
  • 在客户端中配置应用级心跳信号或读取超时,例如 WebSocket ping 和 pong 帧或 gRPC keepalive ping,并更新应用以在发生超时时重新连接。

后续步骤