问题


最近一段时间,因为业务增长飞速同时导致了服务器压力倍增,瞬时压力有时候上升到了100%,此时Node服务器开始变得极不稳定,系统进程频频被kill,甚至导致无法ssh远程登录。

原因


紧急定位问题,最终定位到有以下两点问题,导致内存不足时服务器不稳定。

(1)K8S和docker使用的cgroup 驱动和centos7.5系统守护进程使用的cgroup 驱动不一致

(2)没有为系统进程预留可用的内存

当 Pod 内存不足时,会触发OOM 把 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 等。

可以看到守护进程都是优先级最低的,但是为什么还是会被杀死呢?因为我们在安装Kubernetes和Docker定义cgroup驱动时定义为了cgroupfs,因为而centos系统的守护进程的用的是systemd做内存管理的,这两个相当于是两套管理器管理同一个内存资源,同时这两套之间没有通信,所以当高压力的情况cgroupfs会占用服务器的全部资源而不考虑系统进程,而systemd发现系统已经没内存的时候就会根据oom_score_adj 将系统进程給杀掉

cgroup 驱动

在 Linux 上,控制组(CGroup)用于限制分配给进程的资源。

kubelet 和底层容器运行时都需要对接控制组来强制执行 为 Pod 和容器管理资源 并为诸如 CPU、内存这类资源设置请求和限制。若要对接控制组,kubelet 和容器运行时需要使用一个 cgroup 驱动。 关键的一点是 kubelet 和容器运行时需使用相同的 cgroup 驱动并且采用相同的配置。

可用的 cgroup 驱动有两个: