诊断集群问题

本文档介绍如何使用 gkectl diagnose 诊断集群中的问题。

概览

gkectl 工具有两个用于排查集群问题的命令:gkectl diagnose clustergkectl diagnose snapshot。这两个命令适用于管理员集群和用户集群。

gkectl diagnose cluster

对集群执行健康检查并报告错误。对以下组件运行健康检查:

  • VCenter
    • 凭据
    • DRS
    • 反亲和性群组
    • 网络
    • 版本
    • 数据中心
    • 数据存储区
    • ResourcePool
    • 文件夹
    • 网络
  • 负载平衡器(F5、Seesaw、手动)
  • 用户集群和节点池
  • 集群对象
  • 用户集群的 Konnectivity 服务器就绪性
  • 机器对象和相应的集群节点
  • kube-system 和 gke-system 命名空间中的 Pod
  • 控制平面
  • 集群中的 vSphere 永久卷
  • 用户和管理员集群的 vCPU(虚拟 CPU)和内存争用信号
  • 用户和管理员集群 ESXi 预配置主机 CPU 使用率和内存用量警报
  • 时段 (TOD)
  • 启用了 Dataplane V2 的集群的节点网络政策
  • Dataplane V2 节点代理的整体健康状况

gkectl diagnose snapshot

此命令会将集群的状态、配置和日志压缩成 tar 压缩文件。如果您运行 gkectl diagnose snapshot,该命令会自动在进程中运行 gkectl diagnose cluster,并将输出文件放在快照中名为 /diagnose-report 的新文件夹中。

gkectl diagnose snapshot 命令的默认配置还会捕获集群的以下信息:

  • Kubernetes 版本

  • kubenetes 资源在 kube-system 和 gke-system 命名空间中的状态:集群、机器、节点、服务、端点、ConfigMap、ReplicaSet、CronJob、Pod 以及这些 Pod 的所有者,包括 Deployment、DaemonSet 和 StatefulSet

  • 控制平面的状态

  • 有关每个节点配置的详细信息,包括 IP 地址、iptables 规则、装载点、文件系统、网络连接,以及正在运行的进程

  • 管理员集群的控制平面节点的容器日志(当 Kubernetes API 服务器不可用时)

  • vSphere 信息,包括虚拟机对象及其基于资源池的事件。与虚拟机关联的数据中心、集群、网络和 Datastore 对象

  • F5 BIG-IP 负载均衡器信息,包括虚拟服务器、虚拟地址、池、节点和监控器

  • 来自 gkectl diagnose snapshot 命令的日志

  • 预检作业的日志

  • 根据情景位于命名空间中的容器的日志

  • 快照文件中关于管理员集群 Kubernetes 证书失效时间的信息 /nodes/<admin_master_node_name>/sudo_kubeadm_certs_check-expiration

  • 快照中所有文件的 HTML 索引文件

  • (可选)用于安装和升级具有 --config 标志的集群的管理员集群配置文件。

在创建 tarball 之前,将移除凭据(包括 vSphere 和 F5 凭据)。

获取帮助

如需获取有关可用命令的帮助,请运行以下命令:

gkectl diagnose --help

诊断管理员集群

如需诊断管理员集群,请运行以下命令:

gkectl diagnose cluster --kubeconfig=ADMIN_CLUSTER_KUBECONFIG

ADMIN_CLUSTER_KUBECONFIG 替换为管理员集群 kubeconfig 文件的路径。

输出示例:

Preparing for the diagnose tool...
Diagnosing the cluster......DONE

- Validation Category: Admin Cluster Connectivity
Checking VMs TOD (availability)...SUCCESS
Checking Konnectivity Server (readiness)...SUCCESS

- Validation Category: Admin Cluster F5 BIG-IP
Checking f5 (credentials, partition)...SUCCESS

- Validation Category: Admin Cluster VCenter
Checking Credentials...SUCCESS
Checking DRS enabled...SUCCESS
Checking Hosts for AntiAffinityGroups...SUCCESS
Checking Version...SUCCESS
Checking Datacenter...SUCCESS
Checking Datastore...SUCCESS
Checking Resource pool...SUCCESS
Checking Folder...SUCCESS
Checking Network...SUCCESS

- Validation Category: Admin Cluster
Checking cluster object...SUCCESS
Checking machine deployment...SUCCESS
Checking machineset...SUCCESS
Checking machine objects...SUCCESS
Checking kube-system pods...SUCCESS
Checking anthos-identity-service pods...SUCCESS
Checking storage...SUCCESS
Checking resource...SUCCESS
Checking virtual machine resource contention...SUCCESS
Checking host resource contention...SUCCESS
All validation results were SUCCESS.
Cluster is healthy!

如果目标集群中的虚拟 IP 地址(VIP 地址)出现问题,请使用 --config 标志提供管理员集群配置文件。这可为您提供更多调试信息。

gkectl diagnose cluster --kubeconfig ADMIN_CLUSTER_KUBECONFIG --config CLUSTER_CONFIG

CLUSTER_CONFIG 替换为管理员集群或用户集群配置文件的路径。

输出示例:

Failed to access the api server via LB VIP "...": ...
Try to use the admin master IP instead of problematic VIP...
Reading config with version "[CONFIG_VERSION]"
Finding the admin master VM...
Fetching the VMs in the resource pool "[RESOURCE_POOL_NAME]"...
Found the "[ADMIN_MASTER_VM_NAME]" is the admin master VM.
Diagnosing admin|user cluster "[TARGET_CLUSTER_NAME]"...
...

诊断用户集群

要获取用户集群的名称,请运行以下命令:

kubectl get cluster --kubeconfig=USER_CLUSTER_KUBECONFIG

USER_CLUSTER_KUBECONFIG 替换为用户集群 kubeconfig 文件的路径。

如需诊断用户集群,请运行以下命令:

gkectl diagnose cluster --kubeconfig=ADMIN_CLUSTER_KUBECONFIG \
    --cluster-name=USER_CLUSTER_NAME

USER_CLUSTER_NAME 替换为用户集群的名称。

输出示例:

Preparing for the diagnose tool...
Diagnosing the cluster......DONE

Diagnose result is saved successfully in 

- Validation Category: User Cluster Connectivity
Checking Node Network Policy...SUCCESS
Checking VMs TOD (availability)...SUCCESS
Checking Dataplane-V2...Success

- Validation Category: User Cluster F5 BIG-IP
Checking f5 (credentials, partition)...SUCCESS

- Validation Category: User Cluster VCenter
Checking Credentials...SUCCESS
Checking DRS enabled...SUCCESS
Checking Hosts for AntiAffinityGroups...SUCCESS
Checking VSphere CSI Driver...SUCCESS
Checking Version...SUCCESS
Checking Datacenter...SUCCESS
Checking Datastore...SUCCESS
Checking Resource pool...SUCCESS
Checking Folder...SUCCESS
Checking Network...SUCCESS

- Validation Category: User Cluster
Checking user cluster and node pools...SUCCESS
Checking cluster object...SUCCESS
Checking machine deployment...SUCCESS
Checking machineset...SUCCESS
Checking machine objects...SUCCESS
Checking control plane pods...SUCCESS
Checking kube-system pods...SUCCESS
Checking gke-system pods...SUCCESS
Checking gke-connect pods...SUCCESS
Checeking anthos-identity-service pods...SUCCESS
Checking storage...SUCCESS
Checking resource...SUCCESS
Checking virtual machine resource contention...SUCCESS
Checking host resource contention...SUCCESS
All validation results were SUCCESS.
Cluster is healthy!

排查诊断出的集群问题

运行 gkectl diagnose cluster 时,如果您遇到以下问题,请考虑以下解决方法。

问题可能的原因解决方法
管理员集群或用户集群无法连接到 Kubernetes API 服务器。 检查虚拟机运行状况 OOB(开箱)内存延迟图表,理想情况下内存延迟时间应接近零。内存争用也会增加 CPU 争用,CPU 就绪情况图表可能会出现峰值,因为会执行交换。 增大物理内存。如需了解其他选项,请参阅 VMware 问题排查建议
创建 Nodepool 时超时。 VMDK 的读/写延迟时间较长。检查虚拟机运行状况 OOB 以了解是否存在虚拟磁盘读写延迟。根据 VMware 报道,总延迟时间超过 20 毫秒表示存在问题。 请参阅磁盘性能问题的 VMware 解决方案

捕获集群状态

如果 gkectl diagnose cluster 发现错误,您应该捕获集群的状态并将信息提供给 Google。您可以使用 gkectl diagnose snapshot 命令执行此操作。

gkectl diagnose snapshot 有一个可选标志 --config。除了收集有关集群的信息之外,此标志还收集用于创建或升级集群的 GKE on VMware 配置文件。

捕获管理员集群状态

要捕获管理员集群的状态,请运行以下命令,其中 --config 是可选的:

gkectl diagnose snapshot --kubeconfig=[ADMIN_CLUSTER_KUBECONFIG] --config

输出包括文件列表和 tarball 文件的名称:

Taking snapshot of admin cluster "[ADMIN_CLUSTER_NAME]"...
   Using default snapshot configuration...
   Setting up "[ADMIN_CLUSTER_NAME]" ssh key file...DONE
   Taking snapshots...
       commands/kubectl_get_pods_-o_yaml_--kubeconfig_...env.default.kubeconfig_--namespace_kube-system
       commands/kubectl_get_deployments_-o_yaml_--kubeconfig_...env.default.kubeconfig_--namespace_kube-system
       commands/kubectl_get_daemonsets_-o_yaml_--kubeconfig_...env.default.kubeconfig_--namespace_kube-system
       ...
       nodes/[ADMIN_CLUSTER_NODE]/commands/journalctl_-u_kubelet
       nodes/[ADMIN_CLUSTER_NODE]/files/var/log/startup.log
       ...
   Snapshot succeeded. Output saved in [TARBALL_FILE_NAME].tar.gz.
要将 tarball 文件解压到目录中,请运行以下命令:
tar -zxf TARBALL_FILE_NAME --directory EXTRACTION_DIRECTORY_NAME

要查看快照生成的文件列表,请运行以下命令:

cd EXTRACTION_DIRECTORY_NAME/EXTRACTED_SNAPSHOT_DIRECTORY
ls kubectlCommands
ls nodes/NODE_NAME/commands
ls nodes/NODE_NAME/files

要查看特定操作的详细信息,请打开其中一个文件。

指定管理员集群的 SSH 密钥

获取管理员集群的快照时,gkectl 会自动查找管理员集群的私有 SSH 密钥。您还可以使用 --admin-ssh-key-path 参数显式指定密钥。

按照使用 SSH 连接到集群节点中的说明下载 SSH 密钥。

然后在 gkectl diagnose snapshot 命令中,将 --admin-ssh-key-path 设置为已解码的密钥文件路径:

gkectl diagnose snapshot --kubeconfig=ADMIN_CLUSTER_KUBECONFIG \
    --admin-ssh-key-path=PATH_TO_DECODED_KEY

捕获用户集群状态

要捕获用户集群的状态,请运行以下命令:

gkectl diagnose snapshot --kubeconfig=ADMIN_CLUSTER_KUBECONFIG \
    --cluster-name=USER_CLUSTER_NAME

输出包括文件列表和 tarball 文件的名称:

Taking snapshot of user cluster "[USER_CLUSTER_NAME]"...
Using default snapshot configuration...
Setting up "[USER_CLUSTER_NAME]" ssh key file...DONE
    commands/kubectl_get_pods_-o_yaml_--kubeconfig_...env.default.kubeconfig_--namespace_user
    commands/kubectl_get_deployments_-o_yaml_--kubeconfig_...env.default.kubeconfig_--namespace_user
    commands/kubectl_get_daemonsets_-o_yaml_--kubeconfig_...env.default.kubeconfig_--namespace_user
    ...
    commands/kubectl_get_pods_-o_yaml_--kubeconfig_.tmp.user-kubeconfig-851213064_--namespace_kube-system
    commands/kubectl_get_deployments_-o_yaml_--kubeconfig_.tmp.user-kubeconfig-851213064_--namespace_kube-system
    commands/kubectl_get_daemonsets_-o_yaml_--kubeconfig_.tmp.user-kubeconfig-851213064_--namespace_kube-system
    ...
    nodes/[USER_CLUSTER_NODE]/commands/journalctl_-u_kubelet
    nodes/[USER_CLUSTER_NODE]/files/var/log/startup.log
    ...
Snapshot succeeded. Output saved in [FILENAME].tar.gz.

快照场景

gkectl diagnose snapshot 命令支持用户集群的两种场景。如需指定场景,请使用 --scenario 标志。以下列表显示了可能的值:

  • 系统(默认):收集受支持系统命名空间中包含日志的快照。

  • 所有:收集所有命名空间(包括用户定义的命名空间)中包含日志的快照

以下示例展示了一些可能性。

如需创建管理员集群的快照,则无需指定场景:

gkectl diagnose snapshot \
    --kubeconfig=ADMIN_CLUSTER_KUBECONFIG

要使用 system 场景创建用户集群的快照,请执行以下操作:

gkectl diagnose snapshot \
    --kubeconfig=ADMIN_CLUSTER_KUBECONFIG \
    --cluster-name=USER_CLUSTER_NAME \
    --scenario=system

要使用 all 场景创建用户集群的快照,请执行以下操作:

gkectl diagnose snapshot \
    --kubeconfig=ADMIN_CLUSTER_KUBECONFIG \
    --cluster-name=USER_CLUSTER_NAME \
    --scenario=all

使用 --log-since 来限制快照

您可以使用 --log-since 标志将日志收集限制为最近的时间段。例如,您可以仅收集过去两天或过去三小时的日志。默认情况下,diagnose snapshot 会收集所有日志。

要限制日志收集的时间段,请执行以下操作:

gkectl diagnose snapshot --kubeconfig=ADMIN_CLUSTER_KUBECONFIG \
    --cluster-name=CLUSTER_NAME \
    --scenario=system \
    --log-since=DURATION

DURATION 替换为时间值,如 120m48h

备注:

  • kubectljournalctl 日志支持 --log-since 标志。
  • 自定义快照配置中不允许使用 --log-since 等命令标志。

对快照执行试运行

您可以使用 --dry-run 标志来显示要执行的操作和快照配置。

要在管理员集群上执行试运行,请输入以下命令:

gkectl diagnose snapshot --kubeconfig=ADMIN_CLUSTER_KUBECONFIG \
    --cluster-name=ADMIN_CLUSTER_NAME \
    --dry-run

要在用户集群上执行试运行,请输入以下命令:

gkectl diagnose snapshot --kubeconfig=ADMIN_CLUSTER_KUBECONFIG \
    --cluster-name=USER_CLUSTER_NAME \
    --dry-run

使用快照配置

如果这四种场景都不能满足您的需求,您可以使用 --snapshot-config 标志传入快照配置文件来创建自定义快照:

gkectl diagnose snapshot --kubeconfig=ADMIN_CLUSTER_KUBECONFIG \
    --cluster-name=USER_CLUSTER_NAME \
    --snapshot-config=SNAPSHOT_CONFIG_FILE

生成快照配置

您可以通过传入 --scenario--dry-run 标志为给定场景生成快照配置。例如,要查看用户集群的默认场景 (system) 的快照配置,请输入以下命令:

gkectl diagnose snapshot \
    --kubeconfig=ADMIN_CLUSTER_KUBECONFIG \
    --cluster-name=USER_CLUSTER_NAME \
    --scenario=system
    --dry-run

输出类似于以下内容:

numOfParallelThreads: 10
excludeWords:
- password
kubectlCommands:
- commands:
  - kubectl get clusters -o wide
  - kubectl get machines -o wide
  - kubectl get clusters -o yaml
  - kubectl get machines -o yaml
  - kubectl describe clusters
  - kubectl describe machines
  namespaces:
  - default
- commands:
  - kubectl version
  - kubectl cluster-info
  - kubectl get nodes -o wide
  - kubectl get nodes -o yaml
  - kubectl describe nodes
  namespaces: []
- commands:
  - kubectl get pods -o wide
  - kubectl get deployments -o wide
  - kubectl get daemonsets -o wide
  - kubectl get statefulsets -o wide
  - kubectl get replicasets -o wide
  - kubectl get services -o wide
  - kubectl get jobs -o wide
  - kubectl get cronjobs -o wide
  - kubectl get endpoints -o wide
  - kubectl get configmaps -o wide
  - kubectl get pods -o yaml
  - kubectl get deployments -o yaml
  - kubectl get daemonsets -o yaml
  - kubectl get statefulsets -o yaml
  - kubectl get replicasets -o yaml
  - kubectl get services -o yaml
  - kubectl get jobs -o yaml
  - kubectl get cronjobs -o yaml
  - kubectl get endpoints -o yaml
  - kubectl get configmaps -o yaml
  - kubectl describe pods
  - kubectl describe deployments
  - kubectl describe daemonsets
  - kubectl describe statefulsets
  - kubectl describe replicasets
  - kubectl describe services
  - kubectl describe jobs
  - kubectl describe cronjobs
  - kubectl describe endpoints
  - kubectl describe configmaps
  namespaces:
  - kube-system
  - gke-system
  - gke-connect.*
prometheusRequests: []
nodeCommands:
- nodes: []
  commands:
  - uptime
  - df --all --inodes
  - ip addr
  - sudo iptables-save --counters
  - mount
  - ip route list table all
  - top -bn1
  - sudo docker ps -a
  - ps -edF
  - ps -eo pid,tid,ppid,class,rtprio,ni,pri,psr,pcpu,stat,wchan:14,comm,args,cgroup
  - sudo conntrack --count
nodeFiles:
- nodes: []
  files:
  - /proc/sys/fs/file-nr
  - /proc/sys/net/nf_conntrack_max
seesawCommands: []
seesawFiles: []
nodeCollectors:
- nodes: []
f5:
  enabled: true
vCenter:
  enabled: true
  • numOfParallelThreads:用于截取快照的并行线程数。

  • excludeWords:要从快照中排除的字词列表(不区分大小写)。系统会从快照结果中移除包含这些字词的行。无论您是否指定“password”,都始终会将其排除。

  • kubectlCommands:要运行的 kubectl 命令列表。系统会保存结果。这些命令将针对相应的命名空间运行。对于 kubectl logs 命令,系统会自动添加相应命名空间中的所有 Pod 和容器。支持使用正则表达式指定命名空间。如果未指定命名空间,则假定为 default 命名空间。

  • nodeCommands:要在相应节点上运行的命令列表。系统会保存结果。未指定节点时,将考虑目标集群中的所有节点。

  • nodeFiles:要从相应节点收集的文件列表。系统会保存这些文件。未指定节点时,将考虑目标集群中的所有节点。

  • seesawCommands:要运行以收集 Seesaw 负载均衡器信息的命令列表。如果集群使用 Seesaw 负载平衡器,则会保存结果。

  • seesawFiles:要为 Seesaw 负载均衡器收集的文件列表。

  • nodeCollectors:为 Cilium 节点运行以收集 eBPF 信息的收集器。

  • f5:此标志用于启用收集与 F5 BIG-IP 负载均衡器相关的信息。

  • vCenter:此标志用于启用收集与 vCenter 相关的信息。

  • prometheusRequests:Prometheus 请求列表。系统会保存结果。

将快照上传到 Cloud Storage 存储桶

为了更轻松地保存、分析和存储,您可以将特定集群的所有快照上传到 Cloud Storage 存储桶。如果您需要 Cloud Customer Care 的帮助,则此操作特别有用。

在运行该命令之前,请确保已满足这些设置要求。

  • 舰队宿主项目中启用 storage.googleapis.com。虽然您可以使用其他项目,但建议使用舰队宿主项目。

    gcloud services enable --project=FLEET_HOST_PROJECT_ID storage.googleapis.com
    
  • roles/storage.admin 授予其父项目的服务账号,并使用 --service-account-key-file 参数传入服务账号 json 密钥文件。您可以使用任何服务账号,但建议使用连接注册服务账号。如需了解详情,请参阅服务账号

    gcloud projects add-iam-policy-binding FLEET_HOST_PROJECT_ID \
      --member "serviceAccount:CONNECT_REGISTER_SERVICE_ACCOUNT" \
      --role "roles/storage.admin"
    

    CONNECT_REGISTER_SERVICE_ACCOUNT 替换为连接注册服务账号。

  • 按照说明创建 Google Cloud 服务账号(如果您尚未创建),并与 Google Cloud 支持团队共享对该存储桶的访问权限

满足这些要求后,您现在可以使用以下命令上传快照:

gkectl diagnose snapshot --kubeconfig=ADMIN_CLUSTER_KUBECONFIG \
    --cluster-name CLUSTER_NAME \
    --upload-to BUCKET_NAME  \
    --service-account-key-file SERVICE_ACCOUNT_KEY_FILE \
    --share-with GOOGLE_SUPPORT_SERVICE_ACCOUNT

SERVICE_ACCOUNT_KEY_FILE 替换为服务账号密钥文件名。

--share-with 标志可以接受服务账号名称列表。将 GOOGLE_SUPPORT_SERVICE_ACCOUNT 替换为 Google 支持团队提供的 Google 支持服务账号以及 Google 支持团队提供的任何其他服务账号。

如果使用可选的 share-with 标志,它必须与 --upload-to--service-account-file 一起使用,以便先将快照上传到 Cloud Storage,然后再共享读取权限。

输出示例:

Using "system" snapshot configuration...
Taking snapshot of user cluster CLUSTER_NAME...
Setting up CLUSTER_NAME ssh key...DONE
Using the gke-connect register service account key...
Setting up Google Cloud Storage bucket for uploading the snapshot...DONE
Taking snapshots in 10 thread(s)...
   ...
Snapshot succeeded.
Snapshots saved in "SNAPSHOT_FILE_PATH".
Uploading snapshot to Google Cloud Storage......  DONE
Uploaded the snapshot successfully to gs://BUCKET_NAME/CLUSTER_NAME/xSNAPSHOT_FILE_NAME.
Shared successfully with service accounts:
GOOGLE_SUPPORT_SERVICE_ACCOUNT

已知问题

BundleUnexpectedDiff 个错误

由 GKE on VMware 软件包管理的 Kubernetes Cluster API 资源可能会被意外修改,这可能会导致系统组件故障或集群升级或更新失败。

在 GKE on VMware 1.13 版中,onprem-user-cluster-controller 会定期检查对象的状态,并通过日志和事件报告与预期状态的任何意外差异。这些对象包括用户集群控制平面和插件(例如 Service 和 DaemonSet)。

下面是一个事件示例:

 Type     Reason                 Age    From                              Message
 ----     ------                 ----   ----                              -------
 Warning  BundleUnexpectedDiff   13m    onpremusercluster/ci-bundle-diff  Detected unexpected difference of user control plane objects: [ConfigMap/istio], please check onprem-user-cluster-controller logs for more details.

下面是 onprem-user-cluster-controller 生成的日志示例:

2022-08-06T02:54:42.701352295Z W0806 02:54:42.701252       1 update.go:206] Detected unexpected difference of user addon object(ConfigMap/istio), Diff:   map[string]string{
2022-08-06T02:54:42.701376406Z -    "mesh": (
2022-08-06T02:54:42.701381190Z -        """
2022-08-06T02:54:42.701385438Z -        defaultConfig:
2022-08-06T02:54:42.701389350Z -          discoveryAddress: istiod.gke-system.svc:15012
...
2022-08-06T02:54:42.701449954Z -        """
2022-08-06T02:54:42.701453099Z -    ),
2022-08-06T02:54:42.701456286Z -    "meshNetworks": "networks: {}",
2022-08-06T02:54:42.701459304Z +    "test-key":     "test-data",
2022-08-06T02:54:42.701462434Z   }

事件和日志不会阻止集群操作。如果对象与其预期状态存在意外差异,则该对象将在下一次集群升级中被覆盖。