使用命令排查 Kubernetes 问题
使用 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。查找不在 Running 或 Completed 状态的 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>
查找类似 MemoryPressure 或 DiskPressure 的条件。
配置和 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),或运行服务级命令(curl、ping 等)。
运行调试 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 环境。