背景
某我的项目 kubernetes 环境某个利用每隔 20 分钟左右就会重启一次,工夫不固定,但在容器事件外面没有任何记录。
排查
首先狐疑是健康检查没过导致容器主动重启,以下是健康检查的配置
依照该配置,查看距离 30s,不衰弱阈值 60,也就是 1800s=30 分钟后会标记为不衰弱,但很快就排除该猜想,理由是
- 手动调用健康检查是 ok 的
- 后盾有健康检查的记录,记录显示也都是通过的
- 如果是健康检查不过的话,事件外面会有记录,这里找不到记录
失常状况下如果 kubernetes 重启 pod 那会在事件里记录重启的起因,但事件外面没有任何记录,所以可能不是 kubernetes 重启的,那么很容易想到一个可能性就是 OOM,也就是过程因为内存应用超过限度触发 OOM 操作系统将其 kill 掉,查看操作系统日志 /var/log/messages
发现以下日志
May 11 15:01:36 k8s-node-prod-3 kernel: [17094.020710] oom_kill_process.cold.30+0xb/0x1cf
May 11 15:01:36 k8s-node-prod-3 kernel: [17094.020788] [pid] uid tgid total_vm rss pgtables_bytes swapents oom_score_adj name
May 11 15:01:36 k8s-node-prod-3 kernel: [17094.109707] oom_reaper: reaped process 25929 (java), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
May 11 15:29:12 k8s-node-prod-3 kernel: [18750.337581] java invoked oom-killer: gfp_mask=0x6000c0(GFP_KERNEL), nodemask=(null), order=0, oom_score_adj=969
May 11 15:29:12 k8s-node-prod-3 kernel: [18750.337621] oom_kill_process.cold.30+0xb/0x1cf
May 11 15:29:12 k8s-node-prod-3 kernel: [18750.337709] [pid] uid tgid total_
果然有 OOM 的记录,而且几次 kill 的事件也正合乎利用重启的工夫,再查看其余 java 过程的 oom_score,居然高达 1000 多有很大危险会被再次 kill 掉,因而罪魁祸首就是 OOM,那为什么会导致 OOM 呢,此时操作系统的残余内存还是很短缺,留神到容器利用的启动参数配置的内存是 4096M
JAVA_OPTS="$JAVA_OPTS -server -Xms4096M -Xmx4096M -Xss512k ..."
而容器给的内存限额是 4500M,也就是说一台 4500M 的主机运行了一台须要 4096M 的程序,程序占了大比例主机内存,当然很容易被零碎 kill 掉
OOM killer 是 Linux 内核的一个个性,会查看占用内存过大的过程将其杀掉,操作系统会依据过程的内存应用状况打分,分数保留在 /proc/{过程 PID}/oom_score 中,分数越大越容易被 kill 掉
解决
因为在启动命令里限度了内存,就没必要在 kubernetes 上再对内存进行限度,因而去掉 kubernetes 的内存限度问题解决。
经验总结
问题虽小,但造成的影响十分大,因为该客户为跨国团体,业务波及多个国家,因而全天的交易量都十分大,从该问题能够总结以下教训
- 如果 kubernetes 没有事件记录,很可能是操作系统级别的问题,应该从操作系统动手排查
- 实际才是测验真谛的唯一标准,在出事之前,所有人都感觉这么配置很正当,都没想到会被 OOM,出了问题才焕然大悟