排查 Pod 横向自动扩缩问题

如果 Google Kubernetes Engine (GKE) 中的 Pod 横向自动扩缩未按预期运行,您的工作负载可能无法正确扩缩。此问题可能会阻碍应用处理负载,从而导致性能问题或服务中断。您可能会发现,尽管 CPU 使用率很高,但 Pod 数量并未增加;HorizontalPodAutoscaler 状态中的指标值显示为 <unknown>;或者根本没有进行扩缩操作。

您可以使用本文档来诊断和解决 Pod 横向自动扩缩的常见问题,范围从 HorizontalPodAutoscaler 对象中的初始配置错误,到指标流水线中更复杂的故障。按照这些问题排查步骤操作,有助于确保您的应用根据需求高效可靠地扩缩,从而有效利用 HorizontalPodAutoscaler 资源。

对于配置 HorizontalPodAutoscaler 对象并需要确保其应用正确扩缩的应用开发者,此信息非常重要。它还可以帮助平台管理员和运维人员排查影响所有自动扩缩的工作负载的指标流水线或集群配置问题。如需详细了解我们在 Google Cloud 内容中提及的常见角色和示例任务,请参阅常见的 GKE 用户角色和任务

准备工作

  • 请确保将 HorizontalPodAutoscaler 对象与可扩缩的工作负载(例如 Deployment 和 StatefulSet)搭配使用。您不能将 Pod 横向自动扩缩与无法扩缩的工作负载(例如 DaemonSet)搭配使用。
  • 如需获得在 GKE 中排查 Pod 横向自动扩缩问题(包括检查 HorizontalPodAutoscaler 对象和查看集群日志)所需的权限,请让管理员为您授予项目的以下 IAM 角色:

    如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限

    您也可以通过自定义角色或其他预定义角色来获取所需的权限。

  • 配置 kubectl 命令行工具以与您的 GKE 集群通信:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location LOCATION \
        --project PROJECT_ID
    

    替换以下内容:

    • CLUSTER_NAME:您的集群的名称。
    • LOCATION:集群的 Compute Engine 区域或可用区(例如 us-central1us-central1-a)。
    • PROJECT_ID:您的 Google Cloud 项目 ID。

诊断 HorizontalPodAutoscaler 问题

如需诊断 HorizontalPodAutoscaler 的问题,请使用 kubectl 命令或 Google Cloud 控制台检查状态和配置。

描述 HorizontalPodAutoscaler

如需查看实时计算结果和近期伸缩决策,请使用 kubectl describe hpa 命令:

kubectl describe hpa HPA_NAME -n NAMESPACE_NAME

替换以下内容:

  • HPA_NAME:HorizontalPodAutoscaler 对象的名称。
  • NAMESPACE_NAME:HorizontalPodAutoscaler 对象的命名空间。

输出类似于以下内容:

Name:                                                  php-apache-hpa
Namespace:                                             default
Reference:                                             Deployment/php-apache
Metrics: ( current / target )
  resource cpu on pods (as a percentage of request):   1% (1m) / 50%
Min replicas:                                          1
Max replicas:                                          10
Conditions:
  Type            Status  Reason              Message
  ----            ------  ------              -------
  AbleToScale     True    ReadyForNewScale    recommended size matches current size
  ScalingActive   True    ValidMetricFound    the HorizontalPodAutoscaler was able to successfully calculate a replica count
Events:
  Type     Reason              Age   From                       Message
  ----     ------              ----  ----                       -------
  Normal   SuccessfulRescale   39m   horizontal-pod-autoscaler  New size: 4; reason: cpu resource utilization...
  Normal   SuccessfulRescale   26m   horizontal-pod-autoscaler  New size: 1; reason: cpu resource utilization...

在输出中,以下三个部分可帮助您诊断问题:

  • Metrics:显示当前指标值与目标值的比较情况。<unknown> 指标值表示 HorizontalPodAutoscaler 尚未提取指标,或者指标流水线已中断。
  • Conditions:显示 HorizontalPodAutoscaler 是否可以提取指标 (AbleToScale) 并执行伸缩计算 (ScalingActive)。在任何这些情况下,如果状态为 False,则表示出现故障。
  • Events:记录来自 HorizontalPodAutoscaler 控制器的近期伸缩操作、警告和错误。您通常可以首先在此处查找特定错误消息或原因(例如 FailedGetScaleFailedGetResourceMetric)。

检查 HorizontalPodAutoscaler 清单

通过 HorizontalPodAutoscaler 对象的 YAML 清单,您可以查看有关其配置和当前状态的信息。

如需查看 YAML 清单,请选择以下选项之一:

控制台

  1. 在 Google Cloud 控制台中,前往对象浏览器页面。

    转到对象浏览器

  2. 对象种类列表中,选中 HorizontalPodAutoscaler 复选框,然后点击确定

  3. 前往自动扩缩 API 组,然后点击 HorizontalPodAutoscaler 的展开箭头。

  4. 点击要检查的 HorizontalPodAutoscaler 对象的名称。

  5. 查看 YAML 部分,其中会显示 HorizontalPodAutoscaler 对象的完整配置。

kubectl

运行以下命令:

kubectl get hpa HPA_NAME -n NAMESPACE_NAME -o yaml

替换以下内容:

  • HPA_NAME:HorizontalPodAutoscaler 对象的名称。
  • NAMESPACE_NAME:HorizontalPodAutoscaler 对象的命名空间。

检索清单后,请查找以下关键部分:

  • spec(您的配置)
    • scaleTargetRef:HorizontalPodAutoscaler 配置为扩缩的工作负载(例如 Deployment)。
    • minReplicasmaxReplicas:副本数量下限和上限设置。
    • metrics:为伸缩配置的指标(例如,CPU 利用率或自定义指标)。
  • status(HorizontalPodAutoscaler 的有效状态)
    • currentMetrics:HorizontalPodAutoscaler 观察到的最近指标值。
    • currentReplicasdesiredReplicas:当前 Pod 数量以及 HorizontalPodAutoscaler 要扩缩到的数量。
    • conditions:显示 HorizontalPodAutoscaler 的健康状况:
      • AbleToScale:指示 HorizontalPodAutoscaler 是否可以找到其目标和指标。
      • ScalingActive:显示是否允许 HorizontalPodAutoscaler 计算和执行扩缩。
      • ScalingLimited:显示 HorizontalPodAutoscaler 是否想要扩缩,但受到 minReplicasmaxReplicas 设置限制。

查看事件日志

如需更深入了解 HorizontalPodAutoscaler 对象,请使用以下类型的日志:

  • 在 Cloud Logging 中查看 HorizontalPodAutoscaler 事件:使用日志过滤条件查找特定集群的所有 HorizontalPodAutoscaler 事件。 例如:

    1. 在 Google Cloud 控制台中,前往 Logs Explorer 页面。

      转到日志浏览器

    2. 在查询窗格中,输入以下查询:

      resource.type="k8s_cluster"
      resource.labels.cluster_name="CLUSTER_NAME"
      resource.labels.location="LOCATION"
      logName="projects/PROJECT_ID/logs/events"
      jsonPayload.involvedObject.kind="HorizontalPodAutoscaler"
      

      替换以下内容:

      • CLUSTER_NAME:HorizontalPodAutoscaler 所属集群的名称。
      • LOCATION:集群的 Compute Engine 区域或可用区(例如 us-central1us-central1-a)。
      • PROJECT_ID:您的项目 ID。
    3. 点击运行查询,然后查看输出。

  • 查看 Pod 横向自动扩缩事件:这些日志提供结构化的人类可读日志,其中说明 HorizontalPodAutoscaler 如何计算建议,从而详细了解其决策过程。

排查 HorizontalPodAutoscaler 配置错误

以下部分介绍了 HorizontalPodAutoscaler 清单中的错误配置,例如字段输入错误、指标目标值无效或配置冲突。

找不到目标工作负载

表现

Events 部分具有 FailedGetScale 条件,以及类似于以下内容的消息:

the HorizontalPodAutoscaler controller was unable to get the target's current scale: WORKLOAD_TYPE.apps "TARGET_WORKLOAD" not found

此输出包括以下值:

  • WORKLOAD_TYPE:工作负载的类型,例如 DeploymentStatefulSet
  • TARGET_WORKLOAD:工作负载的名称。

原因

HorizontalPodAutoscaler 控制器无法找到配置为要管理的工作负载(例如 Deployment 或 StatefulSet)。此问题是由 HorizontalPodAutoscaler 清单中 scaleTargetRef 字段的错误配置所导致的。指定的资源可能不存在、可能已删除,或者可能存在拼写错误。

解决方法

请尝试按以下解决方法操作:

  1. 验证 HorizontalPodAutoscaler 清单的 scaleTargetRef 字段:确保 scaleTargetRef 字段中 namekindapiVersion 的值与目标工作负载的相应元数据完全一致。如果工作负载名称不正确,请更新 HorizontalPodAutoscaler 的 scaleTargetRef 字段,使其指向正确的名称。
  2. 确认工作负载存在:验证目标工作负载与 HorizontalPodAutoscaler 位于同一命名空间中。您可以使用 kubectl get deployment DEPLOYMENT_NAME 等命令来检查此内容。如果您有意删除了工作负载,请删除相应的 HorizontalPodAutoscaler 对象以清理集群。如果您需要重新创建工作负载,HorizontalPodAutoscaler 会在工作负载可用后自动找到它,随后错误便会得到解决。
  3. 检查 HorizontalPodAutoscaler 和工作负载是否位于同一命名空间中:HorizontalPodAutoscaler 及其目标工作负载必须位于同一命名空间中。如果您在使用 kubectl 命令创建对象时忘记指定命名空间,Kubernetes 会将该对象放置在 default 命名空间中。如果您的 HorizontalPodAutoscaler 位于 default 命名空间中,而工作负载位于另一个命名空间中,或者情况相反,则此行为可能会导致不匹配。检查两个对象的命名空间,并验证它们是否一致。

HorizontalPodAutoscaler 成功找到其目标后,条件 AbleToScale 会变为 True,并且消息会更改为:the HorizontalPodAutoscaler controller was able to get the target's current scale

无效指标

表现

如果 HorizontalPodAutoscaler 因配置问题而无法计算所需的副本数量,则其 Events 部分会显示 FailedComputeMetricsReplicas 原因,并显示类似于以下内容的消息:

invalid metrics (1 invalid out of 1)

原因

此错误通常表示指标 type 与您在 HorizontalPodAutoscaler 清单中定义的 target 之间存在不匹配。例如,您可能指定 typeUtilization,但提供的目标值是 averageValue 而不是 averageUtilization

解决方法

更正 HorizontalPodAutoscaler 清单,使 target 字段的值与指标 type 一致:

  • 如果 typeUtilization,则 target 字段中的值必须为 averageUtilization
  • 如果 typeAverageValue,则 target 字段中的值必须为 averageValue

不允许使用指标标签

表现

您会注意到以下错误:

unable to fetch metrics from external metrics API: googleapi: Error 400: Metric label: 'LABEL_NAME' is not allowed

在此输出中,LABEL_NAME 是错误标签的名称。

原因

HorizontalPodAutoscaler 清单在 metric.selector.matchLabels 部分中指定了无效的标签键,而 Cloud Monitoring 无法识别或不允许将此键用于指标。

解决方法

如需解决此问题,请执行以下操作:

  1. 在错误消息中确定不允许使用的标签名称。
  2. 在 HorizontalPodAutoscaler 清单的 metric.selector.matchLabels 部分中移除或更正此标签键。
  3. 请参阅相应指标的 Cloud Monitoring 文档,找到有效的可过滤标签键。

多个 HorizontalPodAutoscaler 以同一工作负载为目标

表现

HorizontalPodAutoscaler 的状态中没有直接指示此冲突的特定 ConditionReason。不过,您可能会观察到以下症状:

  • 工作负载的副本数量可能会意外波动。
  • 扩缩决策似乎不与任何单个 HorizontalPodAutoscaler 中定义的指标对应。
  • 查看事件时,您可能会看到来自不同 HorizontalPodAutoscaler 对象的交替或矛盾的 SuccessfulRescale 事件。

原因

出现此问题的原因是,同一命名空间中的多个 HorizontalPodAutoscaler 对象在 spec.scaleTargetRef 字段中指定了完全相同的工作负载。每个 HorizontalPodAutoscaler 都会独立计算副本数量,并尝试根据自身的一组指标和目标来扩缩工作负载。Kubernetes 不会阻止此配置,但会导致扩缩调整不稳定,因为 HorizontalPodAutoscaler 会相互竞争。

解决方法

如需避免冲突,请在单个 HorizontalPodAutoscaler 对象中定义所有扩缩指标。每个 HorizontalPodAutoscaler 都会根据自己的 spec.metrics 字段计算扩缩需求,因此合并它们可让所选的 HorizontalPodAutoscaler 对象同时考虑所有因素,例如 CPU 和每秒请求次数:

  1. 如需确定哪些 HorizontalPodAutoscaler 以同一工作负载为目标,请获取每个 HorizontalPodAutoscaler 对象的 YAML 清单。请密切注意输出中的 spec.scaleTargetRef 字段。

    kubectl get hpa -n NAMESPACE_NAME -o yaml
    

    NAMESPACE_NAME 替换为您的 HorizontalPodAutoscaler 对象的命名空间。

    查找不同的 HorizontalPodAutoscaler 资源在其 scaleTargetRef 字段中具有相同的 apiVersionkindname 值的所有实例。

  2. 将指标整合到单个 HorizontalPodAutoscaler 对象中:

    1. 选择一个要保留的 HorizontalPodAutoscaler 对象。这是您要修改的 HorizontalPodAutoscaler。
    2. 在以同一工作负载为目标的其他每个 HorizontalPodAutoscaler 对象的清单中检查 spec.metrics 部分。
    3. 从重复 HorizontalPodAutoscaler 对象的 spec.metrics 部分中复制要保留的指标定义。
    4. 将复制的这些指标定义粘贴到您决定保留的 HorizontalPodAutoscaler 的 spec.metrics 数组中。
  3. 如需应用更改,请运行以下命令:

    kubectl apply -f MANIFEST_NAME
    

    MANIFEST_NAME 替换为您决定保留的 HorizontalPodAutoscaler 清单的名称。

  4. 删除以同一工作负载为目标的其他 HorizontalPodAutoscaler 对象:

    kubectl delete hpa DUPLICATE_MANIFEST_NAME -n NAMESPACE_NAME
    

    DUPLICATE_MANIFEST_NAME 替换为您要删除的冗余 HorizontalPodAutoscaler 对象的名称。

排查工作负载和服务错误

以下部分将介绍由目标工作负载或其关联的服务(而非 HorizontalPodAutoscaler 对象本身)导致的错误。

缺少用于计算伸缩的资源请求

表现

ScalingActive 条件为 FalseReasonFailedGetResourceMetric。您通常还会看到类似如下内容的消息:

the HorizontalPodAutoscaler was unable to compute the replica count

原因

HorizontalPodAutoscaler 需要以百分比形式计算资源利用率来扩缩工作负载,但它无法执行此计算,因为 Pod 规范中至少有一个容器对相应资源(cpumemory)缺少 resources.requests 定义。

解决方法

如需解决此问题,请更新 Deployment、StatefulSet 或其他控制器中的 Pod 清单,针对 HorizontalPodAutoscaler 尝试扩缩的资源(cpumemory)添加 resources.requests 字段,以用于 Pod 中的所有容器。例如:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
# Multiple lines are omitted here
spec:
  containers:
  - name: example-container
    resources:
      requests:
        cpu: "100m"
        memory: "128Mi"

无法提取 Pod 指标

表现

您会看到类似如下内容的持续性消息:

unable to fetch pod metrics for pod

当指标服务器启动时,暂时看到此消息是正常现象。

原因

如需根据资源利用率百分比(例如 cpumemory)进行扩缩,作为 HorizontalPodAutoscaler 对象目标的 Pod 中的每个容器都必须为该特定资源定义 resources.requests 字段。否则,HorizontalPodAutoscaler 无法执行所需的计算,也不会执行与该指标相关的操作。

解决方法

如果这些错误消息持续存在,并且您发现 Pod 未针对您的工作负载进行伸缩,请验证您是否已为工作负载中的每个容器指定资源请求

多个服务选择同一目标

表现

您会注意到以下错误:

multiple services selecting the same target of HPA_NAME: SERVICE_NAME

此输出包括以下值:

  • HPA_NAME:HorizontalPodAutoscaler 的名称。
  • SERVICE_NAME:Service 的名称。

原因

已配置基于流量的自动扩缩,但有多个 Kubernetes Service 以 HorizontalPodAutoscaler 的 scaleTargetRef 字段为目标。基于流量的自动扩缩仅支持 Service 与自动扩缩工作负载之间的一对一关系。

解决方法

如需解决此问题,请确保只有一个 Service 的标签选择器与工作负载的 Pod 匹配:

  1. 查找工作负载的 Pod 标签:

    kubectl get deployment HPA_TARGET_DEPLOYMENT \
        -n NAMESPACE \
        -o jsonpath='{.spec.template.metadata.labels}'
    

    替换以下内容:

    • HPA_TARGET_DEPLOYMENT:作为 HorizontalPodAutoscaler 目标的 Deployment 的名称。
    • NAMESPACE:Deployment 的命名空间。

    输出类似于以下内容:

    {"app":"my-app", "env":"prod"}
    
  2. 通过查看命名空间中所有 Service 的 spec.selector 字段,找到与这些标签匹配的所有 Service。

    kubectl get services -n NAMESPACE -o yaml
    

    确定选择器与上一步中的标签匹配的每个 Service。例如,{"app": "my-app"}{"app": "my-app", "env": "prod"} 都会与示例 Pod 标签匹配。

  3. 选择以下选项之一来解决冲突:

    • 通过向 Deployment 的 spec.template.metadata.labels 字段添加新的唯一标签,使预期 Service 的选择器具有唯一性。然后,更新一个预期 Service 的 spec.selector 字段以包含此新标签。
    • 通过更改所有其他冲突 Service 的 spec.selector 字段,使其他 Service 选择器限制更严格,从而不再与工作负载的 Pod 匹配。
  4. 如需应用更改,请运行以下命令:

    kubectl apply -f MANIFEST_NAME
    

    MANIFEST_NAME 替换为包含更新后的 Service 或 Deployment 清单的 YAML 文件的名称。

排查指标 API 和数据可用性问题

以下部分将帮助您解决 HorizontalPodAutoscaler 尝试与指标 API 通信或查询指标后端时发生的错误。

排查自定义指标和外部指标方面的问题

当 HorizontalPodAutoscaler 依赖于来自默认 CPU 或内存以外的来源的指标时,自定义或外部指标流水线中可能会出现问题。此流水线由 HorizontalPodAutoscaler 控制器、Kubernetes 指标 API 服务器、指标适配器和指标来源(例如 Cloud Monitoring 或 Prometheus)组成,如下图所示:

显示以下组件的 HPA 指标流水线:HPA 控制器、Kubernetes API 服务器、指标适配器和指标来源。

表现

指标流水线出现问题的最常见症状如下所示:

  • 指标值显示为 <unknown>
  • HorizontalPodAutoscaler 事件显示 FailedGetExternalMetricFailedGetCustomMetric 等错误。

原因

自定义或外部指标流水线中存在问题。

解决方法

请按照以下步骤调试流水线:

  1. 检查指标适配器是否已注册并可用:指标适配器必须向主 Kubernetes API 服务器注册自身才能传送指标。此操作是查看适配器是否正在运行且可供 API 服务器访问的最直接方式:

    kubectl get apiservice | grep -E 'NAME|metrics.k8s.io'
    

    在输出中,您应该会看到 v1beta1.custom.metrics.k8s.iov1beta1.external.metrics.k8s.io 条目,以及 Available 列中的值为 True。例如:

    NAME                   SERVICE                      AVAILABLE   AGE
    v1beta1.metrics.k8s.io kube-system/metrics-server   True        18d
    
    • 如果 Available 列中的值为 False 或缺失,则您的适配器可能已崩溃或配置错误。在 kube-systemcustom-metrics 命名空间中适配器的 Pod 日志中检查是否存在与权限、与指标来源的网络连接相关的错误,或指示找不到指标的消息。

    • 如果值为 True,请继续执行下一步。

  2. 直接查询指标 API:如果适配器可用,则绕过 HorizontalPodAutoscaler 并直接向 Kubernetes API 请求指标。此命令会测试整个流水线(从 API 服务器到指标适配器再到数据源)。

    如需查询外部指标,请运行以下命令:

    kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/namespaces/NAMESPACE_NAME/METRIC_NAME" | jq .
    

    如需查询自定义 Pod 指标,请运行以下命令:

    kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/NAMESPACE_NAME/pods/*/METRIC_NAME" | jq .
    

    替换以下内容:

    • NAMESPACE_NAME:Pod 在其中运行的命名空间。
    • METRIC_NAME:您尝试查询的自定义指标或外部指标的名称。例如 requests_per_secondqueue_depth
  3. 分析命令输出:上一个命令的结果会告知您发生问题的位置。请选择与您的输出相符的场景:

    • 包含值的成功 JSON 响应:指标流水线正常运行。问题很可能是 HorizontalPodAutoscaler 清单中存在配置问题。检查指标名称中是否存在拼写错误或 matchLabels 是否不正确。
    • Error: Error from server (Service Unavailable):此错误通常表示存在网络连接问题,这在使用网络隔离的集群中通常是防火墙问题。

      1. 确定指标适配器 Service。它通常位于 custom-metricskube-system 命名空间中:

        kubectl get service -n custom-metrics,kube-system | grep -E 'adapter|metrics'
        
      2. 找到适配器正在监听的端口:

        kubectl get service ADAPTER_SERVICE -n ADAPTER_NAMESPACE -o yaml
        

        替换以下内容:

        • ADAPTER_SERVICE:与您部署的指标适配器关联的 Kubernetes Service 的名称。此 Service 是您在上一步中找到的 Service。此 Service 将适配器的功能公开给集群的其他部分,包括 Kubernetes API 服务器。
        • ADAPTER_NAMESPACE:适配器 Service 所在的命名空间(例如 custom-metricskube-system)。
      3. 查找集群控制平面的入站防火墙规则:

        gcloud compute firewall-rules list \
            --filter="name~gke-CLUSTER_NAME-[0-9a-z]*-master"
        

        CLUSTER_NAME 替换为您的集群名称。

      4. 将适配器的 targetPort 添加到规则中:

        1. 描述当前规则以查看现有的允许端口:

          gcloud compute firewall-rules describe FIREWALL_RULE_NAME
          

          FIREWALL_RULE_NAME 替换为用于管理流向 Kubernetes 集群控制平面的网络流量的防火墙规则的名称。

        2. 更新规则以将适配器端口添加到列表中:

          gcloud compute firewall-rules update FIREWALL_RULE_NAME \
              --allow tcp:443,tcp:10250,tcp:ADAPTER_PORT
          

          ADAPTER_PORT 替换为指标适配器正在监听的网络端口。

      5. 确保 Kubernetes 网络政策不会阻止流向指标适配器 Pod 的流量:

        kubectl get networkpolicy -n custom-metrics,kube-system
        

        检查所有政策,验证它们是否允许从控制平面或 API 服务器到 ADAPTER_PORT 上的 ADAPTER_SERVICE 的入站流量。

    • 空列表 []:此输出表示适配器正在运行,但无法检索特定指标,这表明适配器的配置或指标来源本身存在问题。

      • 适配器 Pod 问题:在指标适配器 Pod 或多个 Pod 的日志中检查是否存在与 API 调用、身份验证或指标提取相关的错误。如需检查日志,请执行以下操作:

        1. 找到适配器 Pod 的名称:

          kubectl get pods -n ADAPTER_NAMESPACE
          
        2. 查看其日志:

          kubectl logs ADAPTER_POD_NAME \
              -n ADAPTER_NAMESPACE
          

          替换以下内容:

          • ADAPTER_POD_NAME:您在上一步中确定的适配器 Pod 的名称。
          • ADAPTER_NAMESPACE:适配器 Pod 所在的命名空间(例如 custom-metricskube-system)。
      • 来源中没有数据:源系统中可能不存在相应指标。使用监控工具(例如 Metrics Explorer)确认相应指标存在,并且具有正确的名称和标签。

未找到指标版本或适配器不可用

表现

您会注意到以下错误:

unable to fetch metrics from custom metrics API: no known available metric versions found

原因

此错误表明集群内存在通信故障,而不是指标来源(例如 Cloud Monitoring)存在问题。常见原因包括:

  • Kubernetes API 服务器暂时不可用(例如,在集群升级或控制平面修复期间)。
  • 指标适配器 Pod(例如 custom-metrics-stackdriver-adapter)健康状况不佳、未运行或未正确注册到 API 服务器。

解决方法

此问题通常是暂时性的。如果问题持续存在,请尝试以下解决方案:

  1. 检查 Kubernetes 控制平面的健康状况

    1. 在 Google Cloud 控制台中,查看集群的健康状况和状态。

      1. 转到 Kubernetes 集群页面

        转到 KUBERNETES 集群

    2. 查看集群的状态通知列。

    3. 点击 通知,查找任何正在进行的操作,例如升级或修复。在这些时间段内,API 服务器可能会暂时无法使用。

    4. 查看 Cloud Audit Logs 中是否存在与控制平面组件相关的任何错误。如需了解如何查看这些日志,请参阅 GKE 审核日志记录信息

  2. 检查指标适配器 Pod 的健康状况和日志:确保指标适配器 Pod 处于 Running 状态,并且最近没有重启:

    kubectl get pods -n custom-metrics,kube-system -o wide
    

    如果 Pod 的状态不是 Running,或者其重启次数较多,请调查 Pod 以找出根本原因。如需了解问题排查提示,请参阅 Kubernetes 文档中的调试 Pod

  3. 验证指标 API 是否已注册并可用

    kubectl get apiservice | grep metrics.k8s.io
    

    如果指标 API 健康状况良好,则输出类似于以下内容:

    NAME                            SERVICE                                             AVAILABLE   AGE
    v1beta1.custom.metrics.k8s.io   custom-metrics/custom-metrics-stackdriver-adapter   True        18d
    v1beta1.external.metrics.k8s.io custom-metrics/custom-metrics-stackdriver-adapter   True        18d
    v1beta1.metrics.k8s.io          kube-system/metrics-server                          True        18d
    

    如果 AVAILABLE 列的值为 False,则完整 APIService 清单中的 Message 列可能会提供更多详细信息。

    您可以使用以下命令查看完整清单:

    kubectl get apiservice API_SERVICE_NAME -o yaml
    

    API_SERVICE_NAME 替换为 APIService 对象的名称,例如 v1beta1.custom.metrics.k8s.io

指标查询未返回任何时序

表现

您会注意到以下错误:

unable to fetch metrics from custom or external metrics API: googleapi: Error
400: The supplied filter [...] query will not return any time series

原因

发送到 Cloud Monitoring 的查询有效,但未返回任何数据。这意味着不存在与您的过滤条件匹配的数据点(这与找到值为 0 的指标不同)。此问题最可能的原因是,负责生成自定义指标的应用或工作负载在报告错误的时间段内未向 Cloud Monitoring 写入数据。

解决方法

请尝试按以下解决方法操作:

  1. 验证配置:确保 HorizontalPodAutoscaler 对象中的指标名称和标签与应用发出的指标名称和标签完全一致。
  2. 检查权限:确认应用已正确配置了必要的权限和 API 端点,以便将指标发布到 Cloud Monitoring。
  3. 确认应用活动:验证负责提供指标的应用在出现 HorizontalPodAutoscaler 警告的时间段内是否正常运行并尝试向 Cloud Monitoring 发送数据。
  4. 调查是否存在错误:检查同一时间段内的应用日志中是否存在与指标发出相关的任何明确错误,例如连接失败、凭证无效或格式问题。

排查健康但意外的伸缩行为

以下部分介绍了 HorizontalPodAutoscaler 配置有效且指标可用,但伸缩操作未按预期发生的情况。

HorizontalPodAutoscaler 健康状况良好,但未扩缩

表现

HorizontalPodAutoscaler 看似健康状况良好,其条件报告 True,并且其事件中未显示任何错误。但是,它仍未执行任何扩缩操作。

原因

多种因素可能会导致此预期行为:

  • 副本限制:当前副本数量已达到 HorizontalPodAutoscaler 配置中 minReplicasmaxReplicas 字段设置的边界。
  • 容忍度窗口:Kubernetes 使用默认的 10% 容忍度窗口来防止因指标的小幅波动而进行扩缩。仅当当前指标与目标指标的比率超出 0.9 到 1.1 的范围时,才会进行扩缩。例如,如果目标 CPU 使用率为 85%,而当前使用率为 93%,则比率约为 1.094 (93/85≈1.094)。由于此值小于 1.1,因此 HorizontalPodAutoscaler 不会进行扩容。
  • 未就绪的 Pod:HorizontalPodAutoscaler 仅在其伸缩计算中包含状态为 Ready 的 Pod。卡在 Pending 状态或未变为 Ready 状态(由于健康检查失败或资源问题)的 Pod 会被忽略,可能会阻碍扩缩。
  • 同步周期延迟时间:HorizontalPodAutoscaler 控制器会定期检查指标。指标超出阈值与开始执行扩缩操作之间存在 15-30 秒的延迟时间是正常现象。
  • 新指标延迟时间:当 HorizontalPodAutoscaler 首次使用新的自定义指标时,您可能会看到几分钟的一次性延迟时间。出现此延迟时间的原因是,监控系统(例如 Cloud Monitoring)必须在写入第一个数据点时创建新时序。
  • 多指标计算:配置多个指标时,HorizontalPodAutoscaler 会单独计算每个指标所需的副本数量,然后选择计算出的最高值作为最终的副本数量。由于这种行为,您的工作负载进行扩缩是为了满足需求最高的指标的需求。例如,如果 CPU 指标计算出需要 9 个副本,但每秒请求次数指标计算出需要 15 个副本,则 HorizontalPodAutoscaler 会将 Deployment 扩缩到 15 个副本。

解决方法

请尝试按以下解决方法操作:

  • 副本限制:检查 HorizontalPodAutoscaler 清单或 kubectl describe 命令输出中的 minReplicasmaxReplicas 值。如果这些限制阻碍了必要的扩缩,请调整这些限制。
  • 容忍度窗口:如果需要在默认容忍度范围内进行伸缩,请配置其他容忍度值。否则,请等待指标超出 0.9 至 1.1 的比率范围。
  • 未就绪的 Pod:调查 Pod 为 Pending 或不为 Ready 的原因,并解决底层问题(例如资源限制条件、就绪性探测失败)。如需了解问题排查提示,请参阅 Kubernetes 文档中的调试 Pod
  • 同步周期延迟时间和新指标延迟时间:这些延迟时间属于正常情况。等待同步周期完成或新的自定义指标时序创建完成。
  • 多指标计算:这是预期行为。如果扩容是根据某个指标(例如每秒请求次数)进行的,那么它会正确地替换另一个指标的较低计算结果(例如 CPU)。

HorizontalPodAutoscaler 无法缩容

表现

HorizontalPodAutoscaler 可成功扩容工作负载,但即使在 CPU 利用率等指标较低时,也无法缩容。

原因

此行为旨在防止快速扩容或缩容,或基于不完整的信息进行缩容。主要原因如下:

  • 使用多个指标:HorizontalPodAutoscaler 会根据需要最多副本数量的指标进行扩缩。如果您有多个指标,除非所有指标都表明需要减少副本数量,否则工作负载不会缩容。即使其他指标较低,如果有一个指标需要大量副本,也会阻止缩容。
  • 不可用的指标:如果任何指标变为不可用(通常显示为 <unknown>),HorizontalPodAutoscaler 会保守地拒绝缩容工作负载。它无法确定指标缺失是因为使用量确实为零,还是因为指标流水线中断。此问题在基于速率的自定义指标(例如 messages_per_second)中很常见,当没有活动时,这些指标可能会停止报告数据,导致 HorizontalPodAutoscaler 将相应指标视为不可用并停止缩容操作。
  • 来自扩缩政策的缩容延迟时间:HorizontalPodAutoscaler 的 behavior 字段可让您配置扩缩政策。默认的缩容政策包含 300 秒(5 分钟)的稳定时长。在此时长内,即使指标值已降至目标阈值以下,HorizontalPodAutoscaler 也不会减少副本数量。此时长可防止快速波动,但可能会导致缩容速度低于预期。

解决方法

请尝试按以下解决方法操作:

  1. 对于多个指标和不可用的指标,请诊断导致问题的指标:

    kubectl describe hpa HPA_NAME -n NAMESPACE_NAME
    

    在输出中,查看 Metrics 部分中是否存在任何状态为 <unknown> 的指标,以及 Events 部分中是否存在 FailedGetCustomMetricFailedGetExternalMetric 等警告。如需详细了解流水线调试,请参阅排查自定义指标和外部指标方面的问题部分。

  2. 对于不可用指标,如果某个指标在低流量期间变为不可用(基于速率的指标通常会这样),请尝试以下解决方案之一:

    • 尽可能使用基于衡量的指标,而不是基于速率的指标。例如,队列中的消息总数(例如 subscriptionnum_undelivered_messages)等衡量指标会持续报告一个值,即使该值为 0,也使 HorizontalPodAutoscaler 能够可靠地进行伸缩决策。
    • 确保您的指标来源报告零值。如果您控制自定义指标,请将其配置为在不活动期间发布 0,而不是完全不发送任何数据。
  3. 对于来自伸缩政策的缩容延迟时间,如果默认的 5 分钟缩容稳定时长过长,请自定义该时长。检查 HorizontalPodAutoscaler 清单的 spec.behavior.scaleDown 部分。您可以降低 stabilizationWindowSeconds,以便自动扩缩器在指标下降后更快地进行缩容。如需详细了解如何配置这些政策,请参阅 Kubernetes 文档中的扩缩政策

后续步骤