集群故障排查

调试常见的集群问题。

本篇文档是介绍集群故障排查的;我们假设对于你碰到的问题,你已经排除了是由应用程序造成的。 对于应用的调试,请参阅应用故障排查指南。 你也可以访问故障排查来获取更多的信息。

有关 kubectl 的故障排查, 请参阅 kubectl 故障排查

列举集群节点

调试的第一步是查看所有的节点是否都已正确注册。

运行以下命令:

  1. kubectl get nodes

验证你所希望看见的所有节点都能够显示出来,并且都处于 Ready 状态。

为了了解你的集群的总体健康状况详情,你可以运行:

  1. kubectl cluster-info dump

示例:调试关闭/无法访问的节点

有时在调试时查看节点的状态很有用 —— 例如,因为你注意到在节点上运行的 Pod 的奇怪行为, 或者找出为什么 Pod 不会调度到节点上。与 Pod 一样,你可以使用 kubectl describe nodekubectl get node -o yaml 来检索有关节点的详细信息。 例如,如果节点关闭(与网络断开连接,或者 kubelet 进程挂起并且不会重新启动等), 你将看到以下内容。请注意显示节点为 NotReady 的事件,并注意 Pod 不再运行(它们在 NotReady 状态五分钟后被驱逐)。

  1. kubectl get nodes
  1. NAME STATUS ROLES AGE VERSION
  2. kube-worker-1 NotReady <none> 1h v1.23.3
  3. kubernetes-node-bols Ready <none> 1h v1.23.3
  4. kubernetes-node-st6x Ready <none> 1h v1.23.3
  5. kubernetes-node-unaj Ready <none> 1h v1.23.3
  1. kubectl describe node kube-worker-1
  1. Name: kube-worker-1
  2. Roles: <none>
  3. Labels: beta.kubernetes.io/arch=amd64
  4. beta.kubernetes.io/os=linux
  5. kubernetes.io/arch=amd64
  6. kubernetes.io/hostname=kube-worker-1
  7. kubernetes.io/os=linux
  8. Annotations: kubeadm.alpha.kubernetes.io/cri-socket: /run/containerd/containerd.sock
  9. node.alpha.kubernetes.io/ttl: 0
  10. volumes.kubernetes.io/controller-managed-attach-detach: true
  11. CreationTimestamp: Thu, 17 Feb 2022 16:46:30 -0500
  12. Taints: node.kubernetes.io/unreachable:NoExecute
  13. node.kubernetes.io/unreachable:NoSchedule
  14. Unschedulable: false
  15. Lease:
  16. HolderIdentity: kube-worker-1
  17. AcquireTime: <unset>
  18. RenewTime: Thu, 17 Feb 2022 17:13:09 -0500
  19. Conditions:
  20. Type Status LastHeartbeatTime LastTransitionTime Reason Message
  21. ---- ------ ----------------- ------------------ ------ -------
  22. NetworkUnavailable False Thu, 17 Feb 2022 17:09:13 -0500 Thu, 17 Feb 2022 17:09:13 -0500 WeaveIsUp Weave pod has set this
  23. MemoryPressure Unknown Thu, 17 Feb 2022 17:12:40 -0500 Thu, 17 Feb 2022 17:13:52 -0500 NodeStatusUnknown Kubelet stopped posting node status.
  24. DiskPressure Unknown Thu, 17 Feb 2022 17:12:40 -0500 Thu, 17 Feb 2022 17:13:52 -0500 NodeStatusUnknown Kubelet stopped posting node status.
  25. PIDPressure Unknown Thu, 17 Feb 2022 17:12:40 -0500 Thu, 17 Feb 2022 17:13:52 -0500 NodeStatusUnknown Kubelet stopped posting node status.
  26. Ready Unknown Thu, 17 Feb 2022 17:12:40 -0500 Thu, 17 Feb 2022 17:13:52 -0500 NodeStatusUnknown Kubelet stopped posting node status.
  27. Addresses:
  28. InternalIP: 192.168.0.113
  29. Hostname: kube-worker-1
  30. Capacity:
  31. cpu: 2
  32. ephemeral-storage: 15372232Ki
  33. hugepages-2Mi: 0
  34. memory: 2025188Ki
  35. pods: 110
  36. Allocatable:
  37. cpu: 2
  38. ephemeral-storage: 14167048988
  39. hugepages-2Mi: 0
  40. memory: 1922788Ki
  41. pods: 110
  42. System Info:
  43. Machine ID: 9384e2927f544209b5d7b67474bbf92b
  44. System UUID: aa829ca9-73d7-064d-9019-df07404ad448
  45. Boot ID: 5a295a03-aaca-4340-af20-1327fa5dab5c
  46. Kernel Version: 5.13.0-28-generic
  47. OS Image: Ubuntu 21.10
  48. Operating System: linux
  49. Architecture: amd64
  50. Container Runtime Version: containerd://1.5.9
  51. Kubelet Version: v1.23.3
  52. Kube-Proxy Version: v1.23.3
  53. Non-terminated Pods: (4 in total)
  54. Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits Age
  55. --------- ---- ------------ ---------- --------------- ------------- ---
  56. default nginx-deployment-67d4bdd6f5-cx2nz 500m (25%) 500m (25%) 128Mi (6%) 128Mi (6%) 23m
  57. default nginx-deployment-67d4bdd6f5-w6kd7 500m (25%) 500m (25%) 128Mi (6%) 128Mi (6%) 23m
  58. kube-system kube-proxy-dnxbz 0 (0%) 0 (0%) 0 (0%) 0 (0%) 28m
  59. kube-system weave-net-gjxxp 100m (5%) 0 (0%) 200Mi (10%) 0 (0%) 28m
  60. Allocated resources:
  61. (Total limits may be over 100 percent, i.e., overcommitted.)
  62. Resource Requests Limits
  63. -------- -------- ------
  64. cpu 1100m (55%) 1 (50%)
  65. memory 456Mi (24%) 256Mi (13%)
  66. ephemeral-storage 0 (0%) 0 (0%)
  67. hugepages-2Mi 0 (0%) 0 (0%)
  68. Events:
  69. ...
  1. kubectl get node kube-worker-1 -o yaml
  1. apiVersion: v1
  2. kind: Node
  3. metadata:
  4. annotations:
  5. kubeadm.alpha.kubernetes.io/cri-socket: /run/containerd/containerd.sock
  6. node.alpha.kubernetes.io/ttl: "0"
  7. volumes.kubernetes.io/controller-managed-attach-detach: "true"
  8. creationTimestamp: "2022-02-17T21:46:30Z"
  9. labels:
  10. beta.kubernetes.io/arch: amd64
  11. beta.kubernetes.io/os: linux
  12. kubernetes.io/arch: amd64
  13. kubernetes.io/hostname: kube-worker-1
  14. kubernetes.io/os: linux
  15. name: kube-worker-1
  16. resourceVersion: "4026"
  17. uid: 98efe7cb-2978-4a0b-842a-1a7bf12c05f8
  18. spec: {}
  19. status:
  20. addresses:
  21. - address: 192.168.0.113
  22. type: InternalIP
  23. - address: kube-worker-1
  24. type: Hostname
  25. allocatable:
  26. cpu: "2"
  27. ephemeral-storage: "14167048988"
  28. hugepages-2Mi: "0"
  29. memory: 1922788Ki
  30. pods: "110"
  31. capacity:
  32. cpu: "2"
  33. ephemeral-storage: 15372232Ki
  34. hugepages-2Mi: "0"
  35. memory: 2025188Ki
  36. pods: "110"
  37. conditions:
  38. - lastHeartbeatTime: "2022-02-17T22:20:32Z"
  39. lastTransitionTime: "2022-02-17T22:20:32Z"
  40. message: Weave pod has set this
  41. reason: WeaveIsUp
  42. status: "False"
  43. type: NetworkUnavailable
  44. - lastHeartbeatTime: "2022-02-17T22:20:15Z"
  45. lastTransitionTime: "2022-02-17T22:13:25Z"
  46. message: kubelet has sufficient memory available
  47. reason: KubeletHasSufficientMemory
  48. status: "False"
  49. type: MemoryPressure
  50. - lastHeartbeatTime: "2022-02-17T22:20:15Z"
  51. lastTransitionTime: "2022-02-17T22:13:25Z"
  52. message: kubelet has no disk pressure
  53. reason: KubeletHasNoDiskPressure
  54. status: "False"
  55. type: DiskPressure
  56. - lastHeartbeatTime: "2022-02-17T22:20:15Z"
  57. lastTransitionTime: "2022-02-17T22:13:25Z"
  58. message: kubelet has sufficient PID available
  59. reason: KubeletHasSufficientPID
  60. status: "False"
  61. type: PIDPressure
  62. - lastHeartbeatTime: "2022-02-17T22:20:15Z"
  63. lastTransitionTime: "2022-02-17T22:15:15Z"
  64. message: kubelet is posting ready status. AppArmor enabled
  65. reason: KubeletReady
  66. status: "True"
  67. type: Ready
  68. daemonEndpoints:
  69. kubeletEndpoint:
  70. Port: 10250
  71. nodeInfo:
  72. architecture: amd64
  73. bootID: 22333234-7a6b-44d4-9ce1-67e31dc7e369
  74. containerRuntimeVersion: containerd://1.5.9
  75. kernelVersion: 5.13.0-28-generic
  76. kubeProxyVersion: v1.23.3
  77. kubeletVersion: v1.23.3
  78. machineID: 9384e2927f544209b5d7b67474bbf92b
  79. operatingSystem: linux
  80. osImage: Ubuntu 21.10
  81. systemUUID: aa829ca9-73d7-064d-9019-df07404ad448

查看日志

目前,深入挖掘集群需要登录相关机器。以下是相关日志文件的位置。 在基于 systemd 的系统上,你可能需要使用 journalctl 而不是检查日志文件。

控制平面节点

  • /var/log/kube-apiserver.log —— API 服务器,负责提供 API 服务
  • /var/log/kube-scheduler.log —— 调度器,负责制定调度决策
  • /var/log/kube-controller-manager.log —— 运行大多数 Kubernetes 内置控制器的组件,除了调度(kube-scheduler 处理调度)。

工作节点

  • /var/log/kubelet.log —— 负责在节点运行容器的 kubelet 所产生的日志
  • /var/log/kube-proxy.log —— 负责将流量转发到服务端点的 kube-proxy 所产生的日志

集群故障模式

这是可能出错的事情的不完整列表,以及如何调整集群设置以缓解问题。

故障原因

  • 虚拟机关闭
  • 集群内或集群与用户之间的网络分区
  • Kubernetes 软件崩溃
  • 持久存储(例如 GCE PD 或 AWS EBS 卷)的数据丢失或不可用
  • 操作员错误,例如配置错误的 Kubernetes 软件或应用程序软件

具体情况

  • API 服务器所在的 VM 关机或者 API 服务器崩溃
    • 结果
      • 不能停止、更新或者启动新的 Pod、服务或副本控制器
      • 现有的 Pod 和服务在不依赖 Kubernetes API 的情况下应该能继续正常工作
  • API 服务器的后端存储丢失

    • 结果
      • kube-apiserver 组件未能成功启动并变健康
      • kubelet 将不能访问 API 服务器,但是能够继续运行之前的 Pod 和提供相同的服务代理
      • 在 API 服务器重启之前,需要手动恢复或者重建 API 服务器的状态
  • Kubernetes 服务组件(节点控制器、副本控制器管理器、调度器等)所在的 VM 关机或者崩溃

    • 当前,这些控制器是和 API 服务器在一起运行的,它们不可用的现象是与 API 服务器类似的
    • 将来,这些控制器也会复制为多份,并且可能不在运行于同一节点上
    • 它们没有自己的持久状态
  • 单个节点(VM 或者物理机)关机
    • 结果
      • 此节点上的所有 Pod 都停止运行
  • 网络分裂

    • 结果
      • 分区 A 认为分区 B 中所有的节点都已宕机;分区 B 认为 API 服务器宕机 (假定主控节点所在的 VM 位于分区 A 内)。
  • kubelet 软件故障

    • 结果
      • 崩溃的 kubelet 就不能在其所在的节点上启动新的 Pod
      • kubelet 可能删掉 Pod 或者不删
      • 节点被标识为非健康态
      • 副本控制器会在其它的节点上启动新的 Pod
  • 集群操作错误
    • 结果
      • 丢失 Pod 或服务等等
      • 丢失 API 服务器的后端存储
      • 用户无法读取 API
      • 等等

缓解措施

  • 措施:对于 IaaS 上的 VM,使用 IaaS 的自动 VM 重启功能

    • 缓解:API 服务器 VM 关机或 API 服务器崩溃
    • 缓解:Kubernetes 服务组件所在的 VM 关机或崩溃
  • 措施: 对于运行 API 服务器和 etcd 的 VM,使用 IaaS 提供的可靠的存储(例如 GCE PD 或者 AWS EBS 卷)

    • 缓解:API 服务器后端存储的丢失
  • 措施:使用高可用性的配置

    • 缓解:主控节点 VM 关机或者主控节点组件(调度器、API 服务器、控制器管理器)崩溃
      • 将容许一个或多个节点或组件同时出现故障
    • 缓解:API 服务器后端存储(例如 etcd 的数据目录)丢失
      • 假定你使用了高可用的 etcd 配置
  • 措施:定期对 API 服务器的 PD 或 EBS 卷执行快照操作

    • 缓解:API 服务器后端存储丢失
    • 缓解:一些操作错误的场景
    • 缓解:一些 Kubernetes 软件本身故障的场景
  • 措施:在 Pod 的前面使用副本控制器或服务

    • 缓解:节点关机
    • 缓解:kubelet 软件故障
  • 措施:应用(容器)设计成容许异常重启

    • 缓解:节点关机
    • 缓解:kubelet 软件故障

接下来