Pod异常排错

本章介绍 Pod 运行异常的排错方法。一般来说,无论 Pod 处于什么异常状态,都可以执行以下命令来查看 Pod 的状态


  • kubectl get pod <pod-name> -o yaml 查看 Pod 的配置是否正确 
  • kubectl describe pod <pod-name> 查看 Pod 的事件
  • kubectl logs <pod-name> [-c <container-name>] 查看容器日志


这些事件和日志通常都会有助于排查 Pod 发生的问题。


处于Pending状态

Pending 说明 Pod 还没有调度到某个 Node 上面。可以通过 kubectl describe pod <pod-name> 命令查看到当前 Pod 的事件,进而判断为什么没有调度。如


$ kubectl describe pod mypod
...
Events:
Type Reason Age From Me
ssage
---- ------ ---- ---- -- -----
Warning FailedScheduling 12s (x6 over 27s) default-scheduler 0/ 4
nodes are available: 2 Insufficient cpu.

可能的原因包括


  • 资源不足,集群内所有的 Node 都不满足该 Pod 请求的 CPU、内存、GPU 或者临时存储空间等资源。解决方法是删除集群内不用的 Pod 或者增加新的 Node。 


HostPort 端口已被占用,通常推荐使用 Service 对外开放服务端口


Waiting和ContainerCreating状态

首先还是通过 kubectl describe pod <pod-name> 命令查看到当前 Pod 的事件。可能的原因包括


  • 镜像拉取失败,比如配置了镜像错误、Kubelet 无法访问镜像、私有镜像的**配置错误、镜像太大,拉取超时等。
  • CNI 网络错误,一般需要检查 CNI 网络插件的配置,比如无法配置 Pod 、无法分配 IP 地址。
  • 容器无法启动,需要检查是否打包了正确的镜像或者是否配置了正确的容器参数。


$ kubectl -n kube-system describe pod nginx-pod


ImagePullBackOff状态

这通常是镜像名称配置错误或者私有镜像的密钥配置错误导致。这种情况可以使用 docker pull <image> 来验证镜像是否可以正常拉取。 

搞懂Kubernetes Pod常见异常状态_排错

如果是私有镜像,需要首先创建一个 docker-registry 类型的 Secret


kubectl create secret docker-registry my-secret --docker-server=DOCKE R_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOC KER_PASSWORD --docker-email=DOCKER_EMAIL

然后在容器中引用这个 Secret


spec:
containers:
- name: private-reg-container
image: <your-private-image>
imagePullSecrets:
- name: my-secret


CrashLoopBackOff状态

CrashLoopBackOff 状态说明容器曾经启动了,但又异常退出了。此时 Pod RestartCounts 通常是大于 0 的,可以先查看一下容器的日志


kubectl describe pod <pod-name> 
kubectl logs <pod-name>
kubectl logs --previous <pod-name>

这里可以发现一些容器退出的原因,比如


  • 容器进程退出 
  • 健康检查失败退出 
  • OOMKilled


$ kubectl describe pod mypod
...
Containers:
sh:
Container ID: docker://3f7a2ee0e7e0e16c22090a25f9b6e42b5c06ec049 405bc34d3aa183060eb4906
Image: alpine Image ID: docker-pullable://alpine@sha256:7b848083f93822dd21 b0a2f14a110bd99f6efb4b838d499df6d04a49d0debf8b
Port: <none>
Host Port: <none>
State: Terminated
Reason: OOMKilled
Exit Code: 2
Last State: Terminated
Reason: OOMKilled
Exit Code: 2
Ready: False
Restart Count: 3
Limits:
cpu: 1
memory: 1G
Requests:
cpu: 100m
memory: 500M ...

如果此时如果还未发现线索,还可以到容器内执行命令来进一步查看退出原因



kubectl exec cassandra -- cat /var/log/cassandra/system.log

如果还是没有线索,那就需要 SSH 登录该 Pod 所在的 Node 上,查看 Kubelet 或者 Docker 的日志进一步排查了

# Query Node 
kubectl get pod <pod-name> -o wide
# SSH to Node
ssh <username>@<node-name>

Error状态

通常处于 Error 状态说明 Pod 启动过程中发生了错误。常见的原因包括


  • 依赖的 ConfigMapSecret 或者 PV 等不存在 
  • 请求的资源超过了管理员设置的限制,比如超过了 LimitRange 等 
  • 违反集群的安全策略,比如违反了 PodSecurityPolicy 等 
  • 容器无权操作集群内的资源,比如开启 RBAC 后,需要为 ServiceAccount 配置角 色绑定