排查资源争用问题

本页面介绍如何识别和排查 Google Distributed Cloud 环境中的资源争用问题。

如果您需要其他帮助,请与 Cloud Customer Care 联系。

概览

有时,您的 Google Distributed Cloud 可能会遇到资源争用问题,导致容器变慢、性能不佳或终止。由于容器的 CPU 或内存消耗较高,可能会发生这种情况。

CPU 和内存管理的工作原理

  • CPU:

    • Pod 根据 Pod 中的容器指定的 CPU 请求被调度到节点。
    • Pod 中的容器使用的 CPU 数量不能超过容器指定的 CPU 数量限制
    • 容器的 CPU 使用率受到 CPU 限制的制约。
    • 如果 CPU 使用率在节点级别受到制约,则系统会根据请求数量向容器自动分配 CPU 周期。

    详细了解如何安排具有资源请求的 Pod

  • 内存:

    • Pod 根据 Pod 中的容器指定的内存请求被调度到节点。
    • 容器使用的内存不能超过容器指定的限制。
    • 如果未指定内存限制,则容器可能会消耗节点上的所有可用内存。然后,系统可能会触发 OOM-Killer(内存不足终止器),并逐出低优先级 Pod。

如需了解详情,请参阅 Kubernetes 中的分配 CPU 资源分配内存资源GKE Enterprise 指标

问题

容器变慢

CPU 争用问题可能会导致容器变慢。以下是一些可能的原因:

容器的 CPU 利用率较高:

如果容器未获得与 CPU 请求成比例的 CPU 周期,或者 CPU 请求设置为低于容器所需的数量,则容器可能会变慢。因此,请检查容器的 CPU 限制与 CPU 利用率的比率。

Google Cloud 控制台 > Monitoring > Metrics ExplorerMQL 编辑器中,运行以下查询:

  fetch k8s_container
  | metric 'kubernetes.io/anthos/container/cpu/limit_utilization'
  | group_by 1m, [value_limit_utilization_mean: mean(value.limit_utilization)]
  | filter resource.cluster_name == 'CLUSTER_NAME'
  | filter resource.container_name == 'CONTAINER_NAME'
  | filter resource.pod_name == 'POD_NAME'
  | filter resource.namespace_name == 'NAMESPACE_NAME'
  | every 1m

然后,执行以下操作之一:

节点上的 CPU 利用率较高

如果 Pod 的任何单个容器的 CPU 限制与利用率的比率不够高,则可能是节点没有足够的 CPU 周期来分配给节点上运行的容器集。因此,请按照以下步骤检查实际 CPU 使用率与节点上可分配的 CPU 的比率:

  1. 获取运行缓慢的 Pod 的节点:

    kubectl get pod –kubeconfig CLUSTER_KUBECONFIG --namespace NAMESPACE POD --output wide
    
  2. Google Cloud 控制台 > Monitoring > Metrics ExplorerMQL 编辑器中,运行以下查询:

    fetch k8s_node
    | metric 'kubernetes.io/anthos/node/cpu/allocatable_utilization'
    | group_by 1m,
        [value_allocatable_utilization_mean: mean(value.allocatable_utilization)]
    | filter resource.cluster_name == 'CLUSTER_NAME'
    | filter resource.node_name == 'NODE_NAME'
    | every 1m
    

    如果此比率较高 (>=0.8),则表示节点没有足够的 CPU 周期,并且被超额订阅。因此,请按照以下步骤检查该节点上所有其他 Pod 的 CPU 使用率,并调查是否有其他容器占用更多 CPU。

    1. 获取节点上的所有 Pod:
    kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=NODE_NAME
    
    1. 检查每个容器的 CPU 利用率:
    fetch k8s_container
    | metric 'kubernetes.io/anthos/container/cpu/limit_utilization'
    | group_by 1m, [value_limit_utilization_mean: mean(value.limit_utilization)]
    | filter resource.cluster_name == 'CLUSTER_NAME'
    | filter resource.container_name == 'CONTAINER_NAME'
    | filter resource.pod_name == 'POD_NAME'
    | filter resource.namespace_name == 'NAMESPACE_NAME'
    | every 1m
    

    如果节点上其他容器的 CPU 利用率较高,请增加缓慢容器的 CPU 请求和限制。这将在其他节点上重新创建 Pod 以获取所需的 CPU 周期。

如果系统 Pod 运行缓慢,请与 Google 支持联系。

vSphere 级层的 CPU 超额订阅

如果节点或 Pod 上的 CPU 使用率不高,但容器仍然运行缓慢,则虚拟机可能在 vSphere 级层被超额订阅。因此,节点无法从底层虚拟化获取预期的 CPU 周期。

按照这些步骤检查虚拟机是否被超额订阅。如果检测到超额订阅,请尝试以下操作:

  • 将一些虚拟机迁移到其他主机。
  • 评估主机的每个虚拟机的 vCPU 数量,并减少该数量。
  • 为 GKE Enterprise 虚拟机分配更多资源。
  • 提高容器的 CPU 请求和限制。这将在其他节点上重新创建 Pod 以获取所需的 CPU 周期。

Pod 因内存不足而终止

Pod 可能会因内存泄漏或容器上的内存请求和限制配置错误而终止。以下是一些可能的原因:

容器上的内存用量较高

如果 Pod 中的任何容器过渡耗用了已分配的总内存,则 Pod 可能会终止。因此,请检查内存请求与容器的内存限制的比率。

Google Cloud 控制台 > Monitoring > Metrics ExplorerMQL 编辑器中,运行以下查询:

fetch k8s_container
| metric 'kubernetes.io/anthos/container/memory/limit_utilization'
| filter (metric.memory_type == 'non-evictable')
| group_by 1m, [value_limit_utilization_mean: mean(value.limit_utilization)]
| filter resource.cluster_name == 'CLUSTER_NAME'
| filter resource.container_name == 'CONTAINER_NAME'
| filter resource.pod_name == 'POD_NAME'
| filter resource.namespace_name == 'NAMESPACE_NAME'
| every 1m

然后,执行以下操作之一:

节点上的内存用量较高

如果节点上运行的所有 Pod 的内存用量超过可用内存,则 Pod 可能会终止。因此,请检查节点上的 MemoryPressure 条件是否为 True

  1. 运行以下命令并检查 Conditions 部分:

    kubectl describe nodes --kubeconfig CLUSTER_KUBECONFIG NODE-NAME
    
  2. 如果 MemoryPressure 条件为 True,则检查节点上的内存利用率:

    fetch k8s_node
    | metric 'kubernetes.io/anthos/node/memory/allocatable_utilization'
    | filter (metric.memory_type == 'non-evictable')
    | group_by 1m,
        [value_allocatable_utilization_mean: mean(value.allocatable_utilization)]
    | filter resource.cluster_name == 'CLUSTER_NAME'
    | filter resource.node_name = 'NODE_NAME'
    | every 1m
    

    如果此比率较高 (>= 0.8),则表示节点没有足够的内存来分配给 Pod,这可能是因为某些进程或其他 Pod 占用大量内存。

  3. Google Cloud 控制台 > Monitoring > Metrics ExplorerMQL 编辑器中,运行以下查询以检查节点上容器的内存用量:

    fetch k8s_node
    | metric 'kubernetes.io/anthos/container_memory_usage_bytes'
    | filter resource.cluster_name == 'CLUSTER_NAME'
    | filter resource.node_name == 'NODE_NAME'
    | group_by 1m,
        [value_container_memory_usage_bytes_mean:
          mean(value.container_memory_usage_bytes)]
    | every 1m
    

    如果存在占用大量内存的容器,请调查容器运行状况,或根据需要为容器增加内存请求

如果系统 Pod 占用了大量内存,请与 Google 支持联系。

此外,您还可以在 Google Distributed Cloud 中启用自动扩缩功能,以便根据工作负载需求对节点池自动进行扩容和缩容。

了解如何启用自动扩缩器

etcd 问题

有时,由于 etcd 服务器问题,Anthos Clusters on VMware 可能会遇到容器故障,您可能会观察到以下情况:

  • 重复的 API 服务器日志,格式为:

    etcdserver: request timed outetcdserver: leader changed

  • 重复的 etcd 日志,格式为:

    W | wal: sync duration of 2.466870869s, expected less than 1sW | etcdserver: read-only range request * took too long

以下是一些可能的原因:

CPU 节流

由于 etcd 服务器 Pod 和/或运行 etcd 服务器的节点上的 CPU 节流,etcd 服务器可能会变慢。请参阅容器变慢部分中的步骤,检查是否存在任何 CPU 争用问题。

如果在 ectd 服务器 pod 或节点上检测到 CPU 争用,请将 CPU 添加到用户集群的控制平面节点。使用 gkectl update 修改用户集群配置文件中的 cpus 字段。

Etcd Pod 因内存不足而终止

由于资源争用问题,etcd pod 可能会因内存不足而终止。请参阅 Pod 因内存不足而终止部分,检查 etcd 服务器 Pod 和/或运行 etcd 服务器的节点是否存在任何内存争用问题。

如果检测到 etcd pod 因内存不足而终止,请增加用户集群的控制平面节点可用的内存。使用 gkectl update 修改用户集群配置文件中的 memoryMB 字段。

磁盘运行缓慢

如果 etcd 服务器 Pod 或节点上的 CPU 或内存消耗量没有问题,则当底层数据存储区运行缓慢或受到限制时,etcd 可能会变慢。

检查是否存在以下问题:

  • 要检查 etcd 服务器对底层磁盘的读写时间是否太长,请执行以下操作:

    1. 提取 etcd 日志:

      kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG logs -n ETCD_POD_NAMESPACE ETCD_POD
      
    2. 查找以下模式的条目以检测 etcd 是否使用过长时间从磁盘读取:

      W | etcdserver: read-only range request "key:\"/registry/configmaps/default/clusterapi-vsphere-controller-manager-leader-election\" " with result "range_response_count:1 size:685" took too long (6.893127339s) to execute

    3. 查找以下模式的条目以检测 etcd 是否使用过长时间写入磁盘:

      W | wal: sync duration of 2.466870869s, expected less than 1s

    如果上述任一日志模式或上述两个日志模式在 etcd 日志中频繁出现,则表示磁盘运行缓慢。然后,检查数据存储区和磁盘的性能

  • 如需查看 etcd 指标,请执行以下操作:

    1. 提取 etcd wal 同步延迟时间:

      Google Cloud 控制台 > Monitoring > Metrics ExplorerMQL 编辑器中,运行以下查询:

      fetch k8s_container::kubernetes.io/anthos/etcd_disk_wal_fsync_duration_seconds
      | every 1m
      | filter resource.cluster_name == 'CLUSTER_NAME'
      | filter resource.pod_name == 'POD_NAME'
      | filter resource.namespace_name == 'NAMESPACE_NAME'
      | percentile 99
      
    2. 提取 etcd 写入延迟时间:

      Google Cloud 控制台 > Monitoring > Metrics ExplorerMQL 编辑器中,运行以下查询:

      fetch k8s_container::kubernetes.io/anthos/etcd_disk_backend_commit_duration_seconds
      | every 1m
      | filter resource.cluster_name == 'CLUSTER_NAME'
      | filter resource.pod_name == 'POD_NAME'
      | filter resource.namespace_name == 'NAMESPACE_NAME'
      | percentile 99
      

    如果 etcd_disk_wal_fsync_duration_secondsp99 持续超过 10 毫秒,并且/或者 etcd_disk_backend_commit_duration_secondsp99 持续超过 25 毫秒,则表示磁盘运行缓慢。然后,检查数据存储区和磁盘的性能

虚拟机磁盘的读写延迟时间

请按照以下步骤检查虚拟机虚拟磁盘上的读/写延迟时间

  1. 确定较慢 etcd Pod 的节点:

    kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG get pods -n ETCD_POD_NAMESPACE ETCD_POD -owide
    
  2. 登录 vSphere 并选择上一步中标识的虚拟机:在 vSphere 中,转到 Monitor(监控)> Performance(性能)> Advanced(高级),然后选择 View(查看)部分中的 Virtual Disk(虚拟磁盘),以了解虚拟磁盘的读写延迟时间。

    如果虚拟磁盘的读/写延迟时间较长:

    • 检查数据存储区上运行的其他虚拟机,以检查较高的每秒输入/输出操作数 (IOPS) 使用情况。如果任何虚拟机显示 IOPS 峰值,请评估该虚拟机的运行情况。
    • 请咨询您的实验室/基础架构团队,确保读写带宽在任何时间点均不会受到限制。
    • 请咨询您的实验室/基础架构团队,以确定磁盘性能存储性能问题(如果有)。

如需了解详情,请参阅扩缩资源的最佳做法

API 服务器问题

如果 Google Distributed Cloud 中的容器在与 API 服务器通信时出现延迟,或者 Kubectl 命令失败或响应时间过长,则可能表示 API 服务器存在问题。

以下是一些可能的原因:

大量 API 请求

如果请求的频率和数量过高,API 服务器的响应速度可能较慢。即使在 API 服务器开始限制请求后,响应速度也可能仍然很慢。因此,请检查 API 服务器上的 API 请求速率。

Google Cloud 控制台 > Monitoring > Metrics ExplorerMQL 编辑器中,运行以下查询:

fetch k8s_container::kubernetes.io/anthos/apiserver_request_total
| filter resource.cluster_name == 'CLUSTER_NAME'
| filter resource.pod_name == 'APISERVER_POD_NAME'
| filter resource.namespace_name == 'NAMESPACE_NAME'
| align rate(1m)
| every 1m
| group_by [metric.verb]

如果 API 请求意外增加,请使用 Cloud Audit Logging 识别可能过于频繁地查询 API 服务器的 Pod。

  • 如果是系统 Pod,请与 Google 支持联系。
  • 如果是用户 Pod,请进一步调查以确定 API 请求是否符合预期。

CPU 节流

API 服务器上的请求速率过高可能会导致 CPU 节流。然后,由于 API 服务器 Pod 和/或节点上出现 CPU 争用,API 服务器的速度可能会变慢。

请参阅容器变慢部分,检查 Pod 和/或节点是否存在任何 CPU 争用问题。

API 服务器 Pod 因内存不足而终止

由于资源争用问题,API 服务器 Pod 可能会因内存不足而终止。请参阅 Pod 因内存不足而终止部分,检查 Pod 和/或节点是否存在任何内存争用问题。

etcd 响应缓慢

API 服务器依靠与 etcd 集群的通信来为客户端提供读/写请求。如果 etcd 缓慢或无响应,API 服务器也会变慢。

提取 API 服务器的日志,以检查 API 服务器是否因 etcd 问题而变慢:

kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG logs -n APISERVER_NAMESPACE APISERVER_POD_NAME

如果您发现周期性日志(如 etcdserver: request timedoutetcdserver: leader changed),请按照 Etcd 问题中的步骤解决任何与磁盘相关的问题。

如果您的集群未导出指标

本文档前面所述的技术依赖于将指标从集群导出到 Google Cloud 项目。

如果您的集群未导出指标,您可以使用命令行来调查资源争用情况。以下是您可以在管理员工作站上运行的一些命令,用于查看指标。

查看节点的指标:

kubectl --kubeconfig CLUSTER_KUBECONFIG get --raw \
    /apis/metrics.k8s.io/v1beta1/nodes/NODE_NAME | jq

替换以下内容:

  • CLUSTER_KUBECONFIG:集群 kubeconfig 文件的路径
  • NODE_NAME:节点的名称

查看 Pod 的指标:

kubectl --kubeconfig CLUSTER_KUBECONFIG get --raw \
    /apis/metrics.k8s.io/v1beta1/namespaces/NAMESPACE/pods/POD_NAME | jq

替换以下内容:

  • NAMESPACE:Pod 的命名空间
  • POD_NAME:Pod 的名称

查看所有节点的指标:

kubectl --kubeconfig CLUSTER_KUBECONFIG top node

查看命名空间中所有 Pod 的指标:

kubectl --kubeconfig CLUSTER_KUBECONFIG top pod --namespace NAMESPACE

查看命名空间中所有 Pod 中的容器的指标:

kubectl --kubeconfig CLUSTER_KUBECONFIG top pod --containers --namespace NAMESPACE

如需了解详情,请参阅 kubectl top podkubectl top node

您还可以从在节点上运行的容器内运行 top 命令。

在容器内运行命令有两种方式:

后续步骤

如果您需要其他帮助,请与 Cloud Customer Care 联系。