当 Pod 里面内存不足时,会触发 Cgroup 把 Pod 里面的进程杀死;但当系统内存不足时,就有可能触发系统 OOM,导致整个虚拟机宕机。这时候根据 oom score 来确定优先杀死哪个进程,而 oom_score_adj 又是影响 oom score 的重要参数,其值越低,表示 oom 的优先级越低。
OOM 的优先级如下:
sshd 等 | K8S 管理进程 | guarantee pod | 其它进程 | best effort pod | |
---|---|---|---|---|---|
具体进程 | sshd/dmevented / systemd-udevd | kubelet / docker / journalctl | guarantee pod | 内核 init 进程等 | best effort pod |
oom_score_adj | -1000 | -999 | -998 | 0 | >0 |
best effort pod > 其它进程 > guarantee pod > kubelet/docker 等 > sshd 等,如果节点没有 best effort 类型的 pod,那么其它进程就有可能被 OOM,包括系统进程等,后果可想而知。所以,预留一定的资源给系统和 K8S 管理服务。
解决办法:
机器配置要高。(8核64G起)
CPU:作为可压缩资源,超配的后果是运行变慢,影响较小,为了充分发挥节点性能,CPU 不预留RAM:预留 4 GB,这是经验得出一个较为合理的值
kubelet --system-reserved=memory=4Gi
集群初始node节点较少,启动pod过多,pod request设置的较小,导致大量pod调度到单个节点上,打满了节点pid,docker异常,kubelet无法工作,节点也无法登陆。当服务器重启之后,有多余的pid被释放,此时节点可以登陆,但是docker已经挂掉,问题节点无法恢复正常工作,此时新加节点,会导致原节点上的pod集体迁移到新节点,导致新节点也因同样原因挂掉,造成集群雪崩效应,需要手动重启组件或节点才可恢复。
低版本内核可能报错: Cannot allocate memory,这个报错信息不准确,在内核 4.1 以后改进了--> https://github.com/torvalds/linux/commit/35f71bc0a09a45924bed268d8ccd0d3407bc476f
解决办法:
机器配置要高;(8核64G起)同时调大PID 和线程数限制。
临时调大 PID 和线程数限制:
echo 65535 > /proc/sys/kernel/pid_maxecho 65535 > /proc/sys/kernel/threads-max永久调大 PID 和线程数限制:
echo "kernel.pid_max=65535 " >> /etc/sysctl.conf && sysctl -pecho "kernel.threads-max=65535 " >> /etc/sysctl.conf && sysctl -p