k8s pod 状态异常状态分析和处理方法

转自腾讯云原生架构师roc github博客

pod状态一般分为以下几种:
1、terminating 2、pending 3、containercreating或waiting 4、CrashloopBackoff 5、imagePullBackoff 6、imageinspectError 7、unknown 8、Error
9、Evicted
pod状态分析:

0、
Evicted代表当前节点上资源不足,被驱逐,调度不上,需要调去别的节点上的

1、一般处于imageinspectError通常指的是镜像文件损坏了,可以尝试删除损坏的镜像重新拉取。
2、Error状态说明pod在启动过程中发生了错误,常见可能原因包括依赖的configmap,secret或者PV等不存在,请求的资源超过了限制,比如超过了limitrange等。还有可能是违反了集群的安全策略等,比如违反了podsecurityPolicy等。容器无法操作集群内部的资源,
比如做了RBAC后,需要配置sa并为其配置角色绑定。
3、处于UNknown状态一般可能是节点失联,没有上报给apiserver,到达阈值后controller-manager认为节点失联并将其状态标记为unknown。
可能的原因有:节点高负载导致无法上报,节点宕机,节点被关机,网络不通。
4、处于terminating状态说明pod被删除,但是一直无法结束。
pod被删除的主要原因可能是:
1.用户主动删除的pod
2.工作负载在滚动更新,自动删除的pod
3.触发了节点驱逐,自动清理的pod。
4.节点长时间处于notready状态,pod被自动删除以便于被重新调度。

pod被删除流程中主要涉及到的组件有:apiserver,etcd,kubelet,dockerd或者containerd。既然能看到pod卡在terminating状态,说明apiserver能正常响应,也能正常从etcd中获取状态,
一般这两个组件不会有什么问题。有问题的主要是节点上的操作。

有时候也因为节点异常触发了内核bug。
用dmesg或者journalctl -k 来查看内核log分析。

5、pod状态如果一直pending,一般原因都是调度失败,通常我们可以describe一下来查看envent事件分析原因。
如何判断某个node节点资源是否足够?通过describe node查看node资源情况,主要关注以下信息:
Allocatable:表示该节点能够申请的资源总和
Allocated resources:表示该节点已经分配的资源(allocatable减去节点上所有的pod总的request)
这两者相减,可以计算出可剩余申请的资源,如果这个值小于pod的request,就不满足pod的资源请求,scheduler在predicates(预选)阶段就会剔除掉这个node,
也就不会在调度上去。

还有可能是节点亲和性或者污点导致无法调度。也有可能是kube-schuduler没有正常运行,需要取master节点上排查有没有正常运行,查看日志分析或者尝试重启修复

6、pod状态如果一直处于containercreating或者waiting可能得原因有以下几种:
镜像问题:
镜像名称错误,错误得镜像标签,错误得存储仓库,存储仓库需要身份认证。
依赖问题:
在pod启动之前kubelet会检查与其他k8s元素有没有依赖关系,如pvc,configmap,secret等。
挂载volume失败

7、pod如果一直处于CrashloopBackoff状态说明之前启动了,但是又异常退出了,只要pod得restartpolicy不是never就又会被重新拉起。
这时我们可以查看容器得异常退出码来缩小问题排查范围:
describe pod一下,查看last state字段,其中exitcode代表上次退出得状态码,如果不为0,则代表异常退出。
退出码范围必须在0-255之间:
0表示正常退出
外界中断进程退出码在129-255之间
程序自身中断一般在1-128之间(当然如果程序一定要用129-255也是可以的,这个可以用kubectl logs -p 查看容器重启前得标准输出)
假如程序代码指定了退出状态不在0-255之间,例如exit(-1),这个时候会自动转换,最终呈现出来的状态码还是在0-255之间,
我们把退出码标记为code,负数转换公式为 256 - (|code| % 256),当指定得退出码为正数,则转换公式为 code % 256

常见退出码为0和137,0为一般代表业务程序正常退出,或者是存活检测失败重启。 137一般代表oom退出或者被木马程序恶意杀死退出。

8、pod如果一直处于imagepullBackoff
一般原因为仓库需要认证没有添加ca,镜像损坏,镜像不存在,私有仓库认证失败,镜像拉取超时等因素

io爆满处理方法:
ps -eL -o lwp,pid,ppid,state,comm | grep -E " R|D "
check 节点负载,R表示CPU,D表示io,一般来讲loadavg大于cpu数量得2~3倍,就比较高了,当然也看业务敏感程度,不太敏感的大于4倍就算高负载了。

内存碎片化严重处理方法:
节点内存碎片化严重得解决办法:
周期性得或者在发现大块内存不足时,先进行drop_cache操作:
echo 3 > /proc/sys/vm/drop_caches

必要时进行内存整理,开销会比较大,会造成业务卡顿一段时间(慎用):

echo 1 > /proc/sys/vm/compact_memory

磁盘空间爆满处理方法:

节点磁盘空间爆满后,需要清理相关空间,可以通过清理docker log来进行清理空间:
cd /var/lib/docker/containers
du -sh * 找出最大目录
cd 进去
cat /dev/null > log 文件
注意这里使用cat /dev/null而不适用rm得原因,是因为rm清理空间后,docker进程可能并不会释放文件,空间也就不会释放。
log得后缀数字越大表示时间越久远,优先删除旧日志。

pid爆满处理方法:
如何判断pid已经爆满:
首先要检查机器全局pid限制,检查全局pid最大限制:
cat /proc/sys/kernel/pid_max
也检查下线程数限制:
cat /proc/sys/kernel/threads-max
接下来再检查当前用户是否还有ulimit限制最大进程数。
确认当前实际pid数量: ps -eLf | wc -l
如果发现实际pid数量接近最大限制说明pid就可能会爆满导致经常有进程无法启动,低版本内核可能报:cannot allocate memory,
这个报错信息可能不准确,高版本内核已经改进这个报错error了。

解决方法:
临时调大pid限制:
echo 65535 > /proc/sys/kernel/pid_max
echo 65535 > /proc/sys/kernel/threads-max

永久调大pid和进程数限制:
echo "kernel.pid_max=65535" >> /etc/sysctl.conf &&sysctl -p
echo "kernel.threads-max=65535" >> /etc/sysctl.conf && sysctl -p

 

posted @ 2023-06-15 10:25  tigergaonotes  阅读(2299)  评论(0编辑  收藏  举报