Kubernetes怎么用命令排查故障?

文章导读
Previous Quiz Next 使用 Kubernetes 既令人兴奋又充满挑战。虽然它提供了强大的工具来管理容器化应用,但问题在所难免。无论是 pod 卡在 CrashLoopBackOff 状态,还是 service 无响应,掌握有效的排查方法都至关重要。
📋 目录
  1. 检查集群健康状态
  2. 排查 Pods
  3. 常见的 Pod 问题
  4. Service 和网络问题
  5. 节点级故障排除
  6. 配置和 Secret
  7. 事件和审计轨迹
  8. 高级调试
  9. 调试有状态应用
  10. 检查 DaemonSets 和 Jobs
A A

使用命令排查 Kubernetes 问题

Previous
Quiz
Next

使用 Kubernetes 既令人兴奋又充满挑战。虽然它提供了强大的工具来管理容器化应用,但问题在所难免。无论是 pod 卡在 CrashLoopBackOff 状态,还是 service 无响应,掌握有效的排查方法都至关重要。

在本章中,我们将介绍一些常见场景以及帮助诊断和解决问题的 kubectl 命令。

检查集群健康状态

在深入排查具体问题之前,确保集群健康是必不可少的。

查看集群节点

使用以下命令查看集群节点 -

$ kubectl get nodes

输出

NAME           STATUS   ROLES           AGE   VERSION
controlplane   Ready    control-plane   71m   v1.31.6
node01         Ready    <none>          71m   v1.31.6

此命令列出集群中的所有节点。我们应该看到所有节点处于 Ready 状态。如果有节点处于 NotReady 状态,则可能表示节点健康或连接性问题。

检查节点详情

使用以下命令检查节点详情 -

$ kubectl describe node <node-name>

它提供特定节点详细信息,包括资源使用情况、条件和事件。有助于识别磁盘压力或内存不足等问题。

排查 Pods

Pod 是 Kubernetes 中最小的可部署单元。当出现问题时,Pod 往往是首先检查的地方。

列出所有 Pods

使用以下命令列出所有 Pod -

$ kubectl get pods -A

输出

NAMESPACE      NAME                                    READY   STATUS    RESTARTS   AGE
kube-flannel   kube-flannel-ds-fbqdb                   1/1     Running   0          75m
kube-flannel   kube-flannel-ds-jln5p                   1/1     Running   0          75m
kube-system    coredns-7c65d6cfc9-4t6gh                1/1     Running   0          75m
kube-system    coredns-7c65d6cfc9-gprrn                1/1     Running   0          75m
kube-system    etcd-controlplane                       1/1     Running   0          75m
kube-system    hostpath-provisioner-5558658586-md76l   1/1     Running   0          75m

它列出所有 namespace 中的所有 Pod。查找不在 RunningCompleted 状态的 Pod。

描述 Pod

使用以下命令描述 Pod -

$ kubectl describe pod <pod-name> -n <namespace>

例如:

$ kubectl describe pod kube-flannel-ds-fbqdb -n kube-flannel

输出

Name:                 kube-flannel-ds-fbqdb
Namespace:            kube-flannel
Priority:             2000001000
Priority Class Name:  system-node-critical
Service Account:      flannel
Node:                 controlplane/172.16.8.5
Start Time:           Tue, 29 Apr 2025 11:15:04 +0000

它提供 Pod 的详细信息,包括事件,这些事件可以指示调度失败或 image 拉取错误等问题。

查看 Pod 日志

要查看 Pod 日志,使用以下命令 -

$ kubectl logs kube-flannel-ds-fbqdb -n kube-flannel

输出

I0429 11:15:25.762540       1 kube.go:139] Waiting 10m0s for node controller to sync
I0429 11:15:25.762636       1 kube.go:469] Starting kube subnet manager
I0429 11:15:25.769460       1 kube.go:490] Creating the node lease for IPv4. This is the n.Spec.PodCIDRs: [10.244.1.0/24]

它显示 Pod 主容器的日志。如果 Pod 有多个容器,请指定容器名称:

$ kubectl logs <pod-name> -c <container-name> -n <namespace>

常见的 Pod 问题

常见的 Pod 问题包括应用错误、配置错误的的环境变量或资源不足。让我们来探讨一些常见的与 Pod 相关的问题以及如何排查它们。

CrashLoopBackOff

$ kubectl get pods

输出

NAME            READY   STATUS             RESTARTS   AGE
crashloop-pod   0/1     CrashLoopBackOff   5          30s

此状态表示 Pod 正在反复崩溃。

描述 Pod 以查看最近的事件:

$ kubectl describe pod crashloop-pod

输出

Events:
  Type     Reason     Age   From               Message
  ----     ------     ----  ----               -------
  Normal   Scheduled  30s   default-scheduler  Successfully assigned default/crashloop-pod to node1
  Normal   Pulled     30s   kubelet, node1     Container image "busybox" already present on machine
  Warning  BackOff    5s    kubelet, node1     Back-off restarting failed container
  Normal   Killing    5s    kubelet, node1     Killing container with id docker://crashloop-container:container has runAsNonRoot and image has non-numeric user (busybox), cannot find user busybox in /etc/passwd

检查 Pod 的日志以查看错误消息:

$ kubectl logs crashloop-pod

输出

sh: nonexistent-command: not found

当 container 尝试运行无效命令时,就会出现此错误。我们可以通过以下方式排查此问题:

  • 通过设置有效的命令或从 YAML 文件中移除无效命令来修复它。
  • 进行更改后删除并重新创建 Pod。
  • 确保 Pod 的状态为 Running,并检查日志以验证修复是否成功。

ImagePullBackOff / ErrImagePull

当 Kubernetes 无法拉取 container image 时,就会出现此错误,通常是由于认证问题或 image 名称不正确导致。

描述 Pod 以获取错误详情:

$ kubectl describe pod <pod-name> -n <namespace>

验证 deployment 配置中的 image 名称和标签。确保指定的 registry 中存在该 image,并且 Kubernetes 有权访问它。私有 registry 的认证问题是常见原因。

Pending Pods

如果 Pod 卡在 Pending 状态,通常意味着它尚未被调度到节点上,可能是由于资源限制或节点选择器导致。

描述 Pod 以查看调度事件:

$ kubectl describe pod <pod-name> -n <namespace>

检查可能阻止调度的资源限制或节点选择器。集群资源不足或配置错误的 affinity 规则可能导致此问题。

Service 和网络问题

Service 将运行在 pod 上的应用程序暴露出来。网络问题可能阻止 service 和 pod 之间的通信。

列出 Service

使用以下命令列出 service -

$ kubectl get svc -A

输出

NAMESPACE     NAME                   TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)                  AGE
default       kubernetes             ClusterIP   10.96.0.1     <none>        443/TCP                  50m
kube-system   kube-dns               ClusterIP   10.96.0.10    <none>        53/UDP,53/TCP,9153/TCP   50m
kube-system   kubelet-csr-approver   ClusterIP   10.107.94.7   <none>        8080/TCP                 50m

它会列出所有 namespace 中的 service。

描述 Service

使用以下命令描述 service -

$ kubectl describe svc kubelet-csr-approver -n kube-system

输出

Type:                     ClusterIP
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.107.94.7
IPs:                      10.107.94.7
Port:                     metrics  8080/TCP
TargetPort:               metrics/TCP
Endpoints:                10.244.1.3:8080,10.244.1.6:8080
Session Affinity:         None
Internal Traffic Policy:  Cluster
Events:                   <none>

它提供了 service 配置和 endpoints 的详细信息。

测试 Service 连通性

使用 port forwarding 测试 service 访问:

$ kubectl port-forward svc/kubelet-csr-approver 8080:8080 -n kube-system

输出

Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080
Handling connection for 8080
Handling connection for 8080

然后,在 http://localhost:8080 访问该 service。

DNS 解析

如果 pod 无法解析 service 名称,请检查 DNS 配置:

$ kubectl exec -it <pod-name> -n <namespace> -- nslookup <service-name>

确保 CoreDNS pod 正在运行且健康。

节点级故障排除

有时,问题源于节点本身。

检查节点状态

使用以下命令检查节点状态 -

$ kubectl get nodes

输出

NAME           STATUS   ROLES           AGE     VERSION
controlplane   Ready    control-plane   6m37s   v1.31.6
node01         Ready    <none>          6m23s   v1.31.6

节点应处于 Ready 状态。

描述节点

如果需要获取节点的描述信息,则使用以下命令 -

$ kubectl describe node <node-name>

查找类似 MemoryPressureDiskPressure 的条件。

配置和 Secret

配置错误的 ConfigMap 或 Secret 可能导致应用程序失败。

列出 ConfigMap

使用以下命令列出 ConfigMap -

$ kubectl get configmaps -n dev

输出

NAME               DATA   AGE
app-config         3      25m
env-settings       2      25m

描述 ConfigMap

使用以下命令描述 ConfigMap -

$ kubectl describe configmap app-config -n dev

输出

Name:         app-config
Namespace:    dev
Data
====
PORT:         80
DB_HOST:      db-service
DB_PORT:      not-a-number

在这个例子中,DB_PORT 值被错误设置为 not-a-number>,但它应该是一个整数(一个有效的(一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个一个

事件和审计轨迹

事件提供了集群中重要事件的 timeline。

查看事件

使用以下命令查看事件 -

$ kubectl get events -A --sort-by='.metadata.creationTimestamp'

输出

kube-system    15m         Normal    Pulled
pod/metrics-server-54bf7cdd6-7khch           Successfully pulled image
"registry.k8s.io/metrics-server/metrics-server:v0.7.2" in 2.458s 
(2.458s including waiting). Image size: 19494617 bytes.
kube-system    15m         Normal    Created
pod/metrics-server-54bf7cdd6-7khch   Created container: metrics-server
kube-system    15m         Normal    Started
pod/metrics-server-54bf7cdd6-7khch   Started container metrics-server

它列出了所有 namespace 中的事件,按时间排序。事件可以揭示诸如挂载失败、调度问题或 image pull 错误等问题。

高级调试

对于更复杂的问题,可以使用额外的工具和命令来帮助。

在 Pod 中执行命令

如果需要在 Pod 中执行命令,则使用以下命令 -

$ kubectl exec -it <pod-name> -n <namespace> -- /bin/bash

示例:进入 Pod

$ kubectl exec -it my-app-5f4d8c6f6c-rm87x -n dev -- /bin/bash

它会在 pod 内部打开一个 shell。使用此 shell 检查配置文件、测试 DNS(nslookup),或运行服务级命令(curlping 等)。

运行调试 Pod

部署一个带有调试工具的临时 pod:

$ kubectl run debug-pod --rm -i --tty --image=busybox -- /bin/sh

这对于测试网络连接或 DNS 解析非常有用。

调试有状态应用

对于 StatefulSets 或 persistent volumes,请检查 Persistent Volume Claims (PVCs):

$ kubectl get pvc -n dev

输出

NAME            STATUS   VOLUME  CAPACITY   ACCESS MODES
data-my-db-0    Pending                                                   

描述 PVC

使用以下命令描述 PVC -

$ kubectl describe pvc data-my-db-0 -n dev

输出

Events:
  Type    Reason                Message
  ----    ------                -------
Warning ProvisioningFailed   no persistent volumes available for this claim

对于此问题,请检查是否存在兼容的 StorageClass 和 PV。如果缺少,则创建一个,或者更新 PVC 以使用可用的 class。检查 storage class 或 volume binding 问题。

检查 DaemonSets 和 Jobs

如果 DaemonSets 和 Jobs 配置不当,常常会导致集群级问题。

检查 DaemonSet 状态

使用以下命令检查 DaemonSet 状态 -

$ kubectl get ds -n kube-system

输出

NAME         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
kube-proxy   2         2         2       2            2           kubernetes.io/os=linux   39m

检查 Job 状态

要检查 Job 的状态,使用以下命令 -

$ kubectl get jobs -n dev

输出

NAME               COMPLETIONS   DURATION   AGE
my-job             1/1           2s         10m
failed-job         0/1           1m         15m

它显示了已发生的所需 job completions 数量。1/1 表示已成功完成;0/1 表示尚未完成或已失败。

对于失败的 Jobs,请检查 pod logs 或 events:

$ kubectl logs <pod-name>
$ kubectl describe job <job-name>

对于 DaemonSets:

  • 确保所有应运行 DaemonSet 的节点都有 pods。
  • 如果 pods 未创建,请检查 taints 或 node selectors。

检查 RBAC 权限

当应用或用户无法访问资源时,可能是由于 Role-Based Access Control (RBAC) 引起的。

验证权限:

$ kubectl auth can-i create deployments --as=dev-user

输出

no

这意味着 dev-user 没有在集群中创建 deployments 的必要权限。

要修复此问题,请更新 Role-Based Access Control (RBAC) 配置,为 dev-user 授予创建 deployments 的必要权限。

使用 Sidecar 调试 Container

我们可以向现有 pod 添加一个 sidecar container 来帮助调试、检查共享 volume、网络或文件系统,而不会中断主应用程序。

$ kubectl debug pod/my-app -n dev --image=busybox --target=main-container

输出

Pod "my-app-debug" created.

要使用 sidecar container,请运行:

$ kubectl exec -it my-app-debug -n dev -- /bin/sh

此命令使用 busybox image 创建一个 sidecar container,并将其附加到 dev namespace 中的现有 my-app pod。它将与 main-container(pod 中的主 container)并行运行,并允许在不影响主 container 的情况下进行调试。

我们现在可以使用 kubectl exec 获取到新调试 container 的 shell,并开始调查问题。这允许进行交互式调试而不影响主 container。

利用外部工具

第三方工具可以增强您的故障排除能力:

  • k9s: 用于管理 Kubernetes 集群的终端 UI。
  • Lens: 具有实时指标的 Kubernetes 仪表板。
  • Prometheus/Grafana: 用于高级监控和告警。

结论

排查 Kubernetes 问题涉及检查资源、分析日志和测试连接性的组合。通过掌握这些命令行技术,我们可以高效诊断和解决集群中的问题。

请记住,关键步骤包括:

  • 检查 pod、deployment 和 service。
  • 分析日志中的错误消息。
  • 测试组件之间的网络连接。
  • 监控资源使用情况以识别瓶颈。

有了这些工具和策略,我们就完全有能力维护健康且弹性的 Kubernetes 环境。