Skip to Content
Kubernetes实践Pod管理Pod 常见故障处理

Pod 常见故障处理

在Kubernetes中发布应用时,我们经常会遇到Pod出现异常的情况,如Pod长时间处于Pending状态,或者反复重启,下面介绍下Pod 的各种异常状态及处理思路。

1. 常见错误

状态状态说明处理办法
ErrorPod 启动过程中发生错误。一般是由于容器启动命令、参数配置错误所致,请联系镜像制作者
NodeLostPod 所在节点失联。检查 Pod 所在节点的状态
UnkownPod 所在节点失联或其他未知异常。检查 Pod 所在节点的状态
PendingPod 等待被调度。资源不足等原因导致,通过 kubectl describe 命令查看 Pod 事件
TerminatingPod 正在被销毁。可增加 —fore参数强制删除
CrashLoopBackOff容器退出,Kubelet 正在将它重启。一般是由于容器启动命令、参数配置错误所致
ErrImageNeverPull策略禁止拉取镜像。拉取镜像失败,确认imagePullSecret是否正确
ImagePullBackOff正在重试拉取。镜像仓库与集群的网络连通性问题
RegistryUnavailable连接不到镜像仓库。联系仓库管理员
ErrImagePull拉取镜像出错。联系仓库管理员,或确认镜像名是否正确
RunContainerError启动容器失败。容器参数配置异常
PostStartHookError执行 postStart hook 报错。postStart 命令有误
NetworkPluginNotReady网络插件还没有完全启动。cni 插件异常,可检查cni状态

2. 常见命令

当我们发现 Pod 处于 上述状态时,可以使用以下命令来快速定位问题:

  1. 获取 Pod 状态
kubectl -n ${NAMESPACE} get pod -o wide
  1. 查看 Pod 的 yaml 配置
kubectl -n ${NAMESPACE} get pod ${POD_NAME} -o yaml
  1. 查看 Pod 事件
kubectl -n ${NAMESPACE} describe pod ${POD_NAME}
  1. 查看 Pod 日志
kubectl -n ${NAMESPACE} logs ${POD_NAME} ${CONTAINER_NAME}
  1. 登录 Pod
kubectl -n ${NAMESPACE} exec -it ${POD_NAME} /bin/bash

3. UK8S对Node上发布的容器有限制吗?如何修改?

UK8S 为保障生产环境 Pod 的运行稳定,每个 Node 限制了 Pod 数量为 110 个,用户可以通过登陆 Node 节点”vim /etc/kubernetes/kubelet.conf” 修改 maxpods:110,然后执行 systemctl restart kubelet 重启 kubelet 即可。

4. 为什么我的容器一起来就退出了?

  1. 查看容器log,排查异常重启的原因
  2. pod是否正确设置了启动命令,启动命令可以在制作镜像时指定,也可以在pod配置中指定
  3. 启动命令必须保持在前台运行,否则k8s会认为pod已经结束,并重启pod。

5. Docker 如何调整日志等级

  1. 修改/etc/docker/daemon.json 文件,增加一行配置”debug”: true
  2. systemctl reload docker 加载配置,查看日志
  3. 如果不再需要查看详细日志,删除debug配置,重新reload docker即可

6. 为什么节点已经异常了,但是 Pod 还处在 Running 状态

  1. 这是由于k8s的状态保护造成的,在节点较少或异常节点很多的情况下很容易出现
  2. 具体可以查看文档 https://kubernetes.io/zh/docs/concepts/architecture/nodes/#reliability

7. 节点宕机了 Pod 一直卡在 Terminating 怎么办

  1. 节点宕机超过一定时间后(一般为 5 分钟),k8s 会尝试驱逐 pod,导致 pod 变为 Terminating 状态
  2. 由于此时 kubelet 无法执行删除pod的一系列操作,pod 会一直卡在 Terminating
  3. 类型为 daemonset 的 pod,默认在每个节点都有调度,因此 pod 宕机不需要考虑此种类型 pod,k8s 也默认不会驱逐该类型的 pod
  4. 类型为 depolyment 和 replicaset 的 pod,当 pod 卡在 termanting 时,控制器会自动拉起对等数量的 pod
  5. 类型为 statefulset 的 pod,当 pod 卡在 termanting 时,由于 statefulset 下属的 pod 名称固定,必须等上一个 pod 彻底删除,对应的新 pod 才会被拉起,在节点宕机情况下无法自动拉起恢复
  6. 对于使用 udisk-pvc 的 pod,由于 pvc 无法卸载,会导致新起的 pod 无法运行,请按照本文 pvc 相关内容(#如何查看pvc对应的udisk实际挂载情况),确认相关关系

8. Pod 异常退出了怎么办?

  1. kubectl describe pods pod-name -n ns 查看 pod 的相关 event 及每个 container 的 status,是 pod 自己退出,还是由于 oom 被杀,或者是被驱逐
  2. 如果是 pod 自己退出,kubectl logs pod-name -p -n ns 查看容器退出的日志,排查原因
  3. 如果是由于 oom 被杀,建议根据业务重新调整 pod 的 request 和 limit 设置(两者不宜相差过大),或检查是否有内存泄漏
  4. 如果 pod 被驱逐,说明节点压力过大,需要检查时哪个 pod 占用资源过多,并调整 request 和 limit 设置
  5. 非 pod 自身原因导致的退出,需要执行dmesg查看系统日志以及journalctl -u kubelet查看 kubelet 相关日志。

9. 为什么在 K8S 节点 Docker 直接起容器网络不通

  1. UK8S 使用 TopnewCloud 自己的 CNI 插件,而直接用 Docker 起的容器并不能使用该插件,因此网络不通。
  2. 如果需要长期跑任务,不建议在 UK8S 节点用 Docker 直接起容器,应该使用 pod
  3. 如果只是临时测试,可以添加--network host 参数,使用 hostnetwork 的模式起容器

10. Pod的时区问题

在 Kubernetes 集群中运行的容器默认使用格林威治时间,而非宿主机时间。如果需要让容器时间与宿主机时间一致,可以使用 “hostPath” 的方式将宿主机上的时区文件挂载到容器中。

大部分linux发行版都通过 “/etc/localtime” 文件来配置时区,我们可以通过以下命令来获取时区信息:

# ls -l /etc/localtime lrwxrwxrwx. 1 root root 32 Oct 15 2015 /etc/localtime -> ../usr/share/zoneinfo/Asia/Shanghai

通过上面的信息,我们可以知道宿主机所在的时区为Asia/Shanghai,下面是一个Pod的yaml范例,说明如何将容器内的时区配置更改为Asia/Shanghai,和宿主机保持一致。

apiVersion: app/v1 kind: Pod metadata: name: nginx labels: name: nginx spec: containers: - name: nginx image: nginx imagePullPolicy: "IfNotPresent" resources: requests: cpu: 100m memory: 100Mi ports: - containerPort: 80 volumeMounts: - name: timezone-config mountPath: /etc/localtime volumes: - name: timezone-config hostPath: path: /usr/share/zoneinfo/Asia/Shanghai

如果容器之前已经创建了,只需要在 yaml 文件中加上 volumeMountsvolumes 参数,再使用 kubectl apply 命令更新即可。