Pod异常状态排错

一、常用命令

首先列出Pod排查过程中的常用命令:

查看Pod状态:kubectl get pod podname -o wide

查看Pod的yaml配置:kubectl get pods podname -o yaml

查看pod事件:kubectl describe pods podname

查看容器日志:kubectl logs podsname -c container-name

二、Pod状态

  • Error:Pod 启动过程中发生错误
  • NodeLost : Pod 所在节点失联
  • Unkown : Pod 所在节点失联或其它未知异常
  • Waiting : Pod 等待启动
  • Pending : Pod 等待被调度
  • ContainerCreating : Pod 容器正在被创建
  • Terminating : Pod 正在被销毁
  • CrashLoopBackOff :容器退出,kubelet 正在将它重启
  • InvalidImageName :无法解析镜像名称
  • ImageInspectError :无法校验镜像
  • ErrImageNeverPull :策略禁止拉取镜像
  • ImagePullBackOff :正在重试拉取
  • RegistryUnavailable :连接不到镜像中心
  • ErrImagePull :通用的拉取镜像出错
  • CreateContainerConfigError :不能创建 kubelet 使用的容器配置
  • CreateContainerError :创建容器失败
  • RunContainerError :启动容器失败
  • PreStartHookError : 执行 preStart hook 报错
  • PostStartHookError :执行 postStart hook 报错
  • ContainersNotInitialized :容器没有初始化完毕
  • ContainersNotReady :容器没有准备完毕
  • ContainerCreating :容器创建中
  • PodInitializing :pod 初始化中
  • DockerDaemonNotReady :docker还没有完全启动
  • NetworkPluginNotReady :网络插件还没有完全启动

三、pod遇到的问题

1、pod一直处于Pending状态

Pending 状态说明 Pod 还没有被调度到某个节点上,需要看下 Pod 事件进一步判断原因,比如

  $ kubectl describe pod tikv-0 
     . ... 
       Events: 
        Type     Reason   Age     From   Message 
         ----    ------   ----    ----    ------- 
        Warning FailedScheduling 3m (x106 over 33m) default-scheduler 0/4 nodes are available: 1 node(s) had no available volume zone, 2 Insufficient cpu, 3 Insufficient memory.

下面是我遇到的一些原因:

  • 节点资源不够

节点资源不够有以下几种情况:

1、CPU负载过高

2、剩余可被分配的内存不足

3、剩余可用GPU数量不足

如果判断某个 Node 资源是否足够?通过下面的命令查看node资源情况,关注以下信息:

kubectl describe node nodename
  • Allocatable : 表示此节点能够申请的资源总和
  • Allocated resources : 表示此节点已分配的资源 (Allocatable 减去节点上
  • 所有 Pod 总 的 Request)

前者与后者相减,可得出剩余可申请的资源。如果这个值小于 Pod 的 request,就不满足 Pod 的 资源要求,Scheduler 在 Predicates (预选) 阶段就会剔除掉这个 Node,也就不会调度上去。

 

不满足 nodeSelector 与 affinity

如果节点上存在污点 (Taints),而 Pod 没有响应的容忍 (Tolerations),Pod 也将不会调度上 去。通过 describe node 可以看下 Node 有哪些 Taints:

$ kubectl describe nodes host1 
    ... 
    Taints: special=true:NoSchedule

污点既可以是手动添加也可以是被自动添加,下面可以看一下。

手动添加的污点:

通过类似以下方式可以给节点添加污点:

$ kubectl taint node host1 special=true:NoSchedule
   node "host1" tainted

另外,有些场景下希望新加的节点默认不调度 Pod,直到调整完节点上某些配置才允许调度,就给新加 的节点都加上node.kubernetes.io/unschedulable 这个污点。

自动添加的污点

如果节点运行状态不正常,污点也可以被自动添加,从 v1.12 开始, TaintNodesByCondition 特性进入 Beta 默认开启,controller manager 会检查 Node 的 Condition,如果命中条件 就自动为 Node 加上相应的污点,这些 Condition 与 Taints 的对应关系如下:

 Conditon Value Taints 
 -------- ----- ------
 OutOfDisk True node.kubernetes.io/out-of-disk
 Ready False node.kubernetes.io/not-ready
 Ready Unknown node.kubernetes.io/unreachable
 MemoryPressure True node.kubernetes.io/memory-pressure
 PIDPressure True node.kubernetes.io/pid-pressure
 DiskPressure True node.kubernetes.io/disk-pressure
 NetworkUnavailable True node.kubernetes.io/network-unavailable

解释下上面各种条件的意思:

  • OutOfDisk 为 True 表示节点磁盘空间不够了
  • Ready 为 False 表示节点不健康
  • Ready 为 Unknown 表示节点失联,在 node-monitor-grace-period 这
  • 么长的时间内没有 上报状态 controller-manager 就会将 Node 状态置
  • 为 Unknown (默认 40s)
  • MemoryPressure 为 True 表示节点内存压力大,实际可用内存很少
  • PIDPressure 为 True 表示节点上运行了太多进程,PID 数量不够用了
  • DiskPressure 为 True 表示节点上的磁盘可用空间太少了
  • NetworkUnavailable 为 True 表示节点上的网络没有正确配置,无法跟
  • 其它 Pod 正常通 信

另外,在云环境下,比如腾讯云 TKE,添加新节点会先给这个 Node 加上node.cloudprovider.kubernetes.io/uninitialized 的污点,等 Node 初始化成功后才自动移 除这个污点,避免 Pod 被调度到没初始化好的 Node 上。

  • kube-scheduler 没有正常运行

检查 maser 上的 kube-scheduler 是否运行正常,异常的话可以尝试重启临时恢复。

3、Pod 处于 CrashLoopBackOff 状态

Pod 如果处于 CrashLoopBackOff 状态说明之前是启动了,只是又异常退出了,只要 Pod 的 restartPolicy不是 Never 就可能被重启拉起,此时 Pod 的 RestartCounts 通常是大于 0 的,可以先看下容器进程的退出状态码来缩小问题范围

容器进程主动退出:

如果是容器进程主动退出,退出状态码一般在 0-128 之间,除了可能是业务程序 BUG,还有其它许 多可能原因

系统OOM

如果发生系统 OOM,可以看到 Pod 中容器退出状态码是 137,表示被 SIGKILL 信号杀死,同时 内核会报错: Out of memory: Kill process … 。大概率是节点上部署了其它非 K8S 管理的进 程消耗了比较多的内存,或者 kubelet 的 --kube-reserved 和 --system-reserved 配的 比较小,没有预留足够的空间给其它非容器进程,节点上所有 Pod 的实际内存占用总量不会超过 /sys/fs/cgroup/memory/kubepods 这里 cgroup 的限制,这个限制等于 capacity - "kube- reserved" - "system-reserved" ,如果预留空间设置合理,节点上其它非容器进程(kubelet, dockerd, kube-proxy, sshd 等) 内存占用没有超过 kubelet 配置的预留空间是不会发生系统 OOM 的,可以根据实际需求做合理的调整。

系统OOM

如果是 cgrou OOM 杀掉的进程,从 Pod 事件的下 Reason 可以看到是 OOMKilled ,说明 容器实际占用的内存超过 limit 了,同时内核日志会报: ``。可以根据需求调整下 limit。

节点内存碎片化

如果节点上内存碎片化严重,缺少大页内存,会导致即使总的剩余内存较多,但还是会申请内存失败,

健康检查失败

2、Pod 一直处于 ContainerCreating 或 Waiting 状 态

Pod 配置错误

  • 检查是否打包了正确的镜像
  • 检查配置了正确的容器参数

 

挂载 Volume 失败

  • Volume 挂载失败也分许多种情况,先列下我这里目前已知的。
  • limit 设置太小或者单位不对

如果 limit 设置过小以至于不足以成功运行 Sandbox 也会造成这种状态,常见的是因为 memory limit 单位设置不对造成的 limit 过小,比如误将 memory 的 limit 单位像 request 一样设 置为小 m ,这个单位在 memory 不适用,会被 k8s 识别成 byte, 应该用 Mi 或M

拉取镜像失败

  • 镜像拉取失败也分很多情况,这里列举下:
  • 配置了错误的镜像
  • Kubelet 无法访问镜像仓库(比如默认 pause 镜像在 gcr.io 上,国内环境访问需要特殊处 理)
  • 拉取私有镜像的 imagePullSecret 没有配置或配置有误
  • 镜像太大,拉取超时

3. Pod 一直处于 Terminating 状态

  • 磁盘爆满

如果 docker 的数据目录所在磁盘被写满,docker 无法正常运行,无法进行删除和创建操作,所以 kubelet 调用 docker 删除容器没反应,看 event 类似这样:

  • 存在 Finalizers

k8s 资源的 metadata 里如果存在 finalizers ,那么该资源一般是由某程序创建的,并且在其 创建的资源的 metadata 里的 finalizers 加了一个它的标识,这意味着这个资源被删除时需要 由创建资源的程序来做删除前的清理,清理完了它需要将标识从该资源的 finalizers 中移除,然 后才会最终彻底删除资源。比如 Rancher 创建的一些资源就会写入 finalizers 标识。

处理建议:kubectl edit 手动编辑资源定义,删掉 finalizers ,这时再看下资源,就会发现 已经删掉了

4、Pod 一直处于 Unknown 状态

通常是节点失联,没有上报状态给 apiserver,到达阀值后 controller-manager 认为节点失联 并将其状态置为 Unknown

可能原因:

  • 节点高负载导致无法上报
  • 节点宕机
  • 节点被关机
  • 网络不通

5、Pod 一直处于 Error 状态

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

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

6、Pod 一直处于 ImagePullBackOff 状态

  • http 类型 registry,地址未加入到 insecure- registry

dockerd 默认从 https 类型的 registry 拉取镜像,如果使用 https 类型的 registry,则 必须将它添加到 insecure-registry 参数中,然后重启或 reload dockerd 生效。

  • https 自签发类型 resitry,没有给节点添加 ca 证书

如果 registry 是 https 类型,但证书是自签发的,dockerd 会校验 registry 的证书,校验 成功才能正常使用镜像仓库,要想校验成功就需要将 registry 的 ca 证书放置到/etc/docker/certs.d/<registry:port>/ca.crt 位置

  • 私有镜像仓库认证失败

如果 registry 需要认证,但是 Pod 没有配置 imagePullSecret,配置的 Secret 不存在或者 有误都会认证失败。

  • 镜像文件损坏

如果 push 的镜像文件损坏了,下载下来也用不了,需要重新 push 镜像文件。

  • 镜像拉取超时

如果节点上新起的 Pod 太多就会有许多可能会造成容器镜像下载排队,如果前面有许多大镜像需要下 载很长时间,后面排队的 Pod 就会报拉取超时。

  • 镜像不存在

镜像配置错误或者镜像不存在会导致拉取超时。

 

posted @   david_cloud  阅读(105)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)
点击右上角即可分享
微信分享提示