本页面介绍如何识别和排查 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 Explorer 的 MQL 编辑器中,运行以下查询:
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
然后,执行以下操作之一:
- 如果此比率较高 (>=0.8),则表示容器上的 CPU 限制较低,并且 Kubernetes 会限制容器的 CPU 周期,将 CPU 使用率保持在限制范围内。如需解决此问题,请提高容器的 CPU 限制。
- 如果此比率不高(<0.8),请检查节点上的 CPU 利用率是否较高。
节点上的 CPU 利用率较高
如果 Pod 的任何单个容器的 CPU 限制与利用率的比率不够高,则可能是节点没有足够的 CPU 周期来分配给节点上运行的容器集。因此,请按照以下步骤检查实际 CPU 使用率与节点上可分配的 CPU 的比率:
获取运行缓慢的 Pod 的节点:
kubectl get pod –kubeconfig CLUSTER_KUBECONFIG --namespace NAMESPACE POD --output wide
在 Google Cloud 控制台 > Monitoring > Metrics Explorer 的 MQL 编辑器中,运行以下查询:
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。
- 获取节点上的所有 Pod:
kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=NODE_NAME
- 检查每个容器的 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 Explorer 的 MQL 编辑器中,运行以下查询:
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
然后,执行以下操作之一:
- 如果此比率较高 (>= 0.8),则提高容器的内存限制。
- 如果此比率不高(<0.8),请检查节点上的内存使用率是否较高。
节点上的内存用量较高
如果节点上运行的所有 Pod 的内存用量超过可用内存,则 Pod 可能会终止。因此,请检查节点上的 MemoryPressure
条件是否为 True
。
运行以下命令并检查
Conditions
部分:kubectl describe nodes --kubeconfig CLUSTER_KUBECONFIG NODE-NAME
如果
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 占用大量内存。
在 Google Cloud 控制台 > Monitoring > Metrics Explorer 的 MQL 编辑器中,运行以下查询以检查节点上容器的内存用量:
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 out
和etcdserver: leader changed
重复的 etcd 日志,格式为:
W | wal: sync duration of 2.466870869s, expected less than 1s
和W | 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 服务器对底层磁盘的读写时间是否太长,请执行以下操作:
提取 etcd 日志:
kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG logs -n ETCD_POD_NAMESPACE ETCD_POD
查找以下模式的条目以检测 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
查找以下模式的条目以检测 etcd 是否使用过长时间写入磁盘:
W | wal: sync duration of 2.466870869s, expected less than 1s
如果上述任一日志模式或上述两个日志模式在 etcd 日志中频繁出现,则表示磁盘运行缓慢。然后,检查数据存储区和磁盘的性能。
如需查看 etcd 指标,请执行以下操作:
提取 etcd wal 同步延迟时间:
在 Google Cloud 控制台 > Monitoring > Metrics Explorer 的 MQL 编辑器中,运行以下查询:
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
提取 etcd 写入延迟时间:
在 Google Cloud 控制台 > Monitoring > Metrics Explorer 的 MQL 编辑器中,运行以下查询:
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_seconds
的p99
持续超过 10 毫秒,并且/或者etcd_disk_backend_commit_duration_seconds
的p99
持续超过 25 毫秒,则表示磁盘运行缓慢。然后,检查数据存储区和磁盘的性能。
虚拟机磁盘的读写延迟时间
请按照以下步骤检查虚拟机虚拟磁盘上的读/写延迟时间
确定较慢 etcd Pod 的节点:
kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG get pods -n ETCD_POD_NAMESPACE ETCD_POD -owide
登录 vSphere 并选择上一步中标识的虚拟机:在 vSphere 中,转到 Monitor(监控)> Performance(性能)> Advanced(高级),然后选择 View(查看)部分中的 Virtual Disk(虚拟磁盘),以了解虚拟磁盘的读写延迟时间。
如果虚拟磁盘的读/写延迟时间较长:
如需了解详情,请参阅扩缩资源的最佳做法。
API 服务器问题
如果 Google Distributed Cloud 中的容器在与 API 服务器通信时遇到延迟,或者 Kubectl 命令失败或响应时间过长,则可能表示 API 服务器存在问题。
以下是一些可能的原因:
大量 API 请求
如果请求的频率和数量过高,API 服务器的响应速度可能较慢。即使在 API 服务器开始限制请求后,响应速度也可能仍然很慢。因此,请检查 API 服务器上的 API 请求速率。
在 Google Cloud 控制台 > Monitoring > Metrics Explorer 的 MQL 编辑器中,运行以下查询:
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 timedout
或 etcdserver: leader changed
),请按照 Etcd 问题中的步骤解决任何与磁盘相关的问题。