最近遇到一个问题,我们的程序在k8s环境中运行会有异常退出的情况,一开始以为是程序产生了crash,于是查看log打印,唯一一个异常点就是每次退出的时候进程的占用内存都在一个差不多的水平,因此怀疑是内存占用过高被系统kill,后来根据反馈,程序退出时也没有产生core_dump文件,更加证实了我们的猜想(由于我们在启动脚本里已经设置了ulimit -c unlimited,如果是发生异常crash应该会产生core文件)
然后开始搭环境验证,一开始用的是物理机,由于物理机的资源比较充足,虽然后面内存稳定后超过之前异常退出时的内存仍没有出问题。后来又想着搭建k8s去复现问题,因为k8s仅仅是一个container编排工具,最终出问题的环境是最底层的container,所以简化成在container内部去重现问题,按照container的文档描述,将memory限制在一个比较低的值: docker run -m 2048m , 运行一段时间后,可以复现异常退出问题。退出时虽然物理内存还剩很多,但是container内部消耗的内存已经超过了limit设置。
使用以下命令行可以查看系统日志:
sudo egrep -i -r 'killed process' /var/log 或者 dmesg -e | grep -i kill
/var/log/messages:Sep 20 07:38:17 ip-xxx-xx-xx-180 kernel: [<ffffffff9bbcd3f5>] oom_kill_process+0x2d5/0x4a0test
/var/log/messages:Sep 20 07:38:17 ip-xxx-xx-xx-180 kernel: Memory cgroup out of memory: Kill process 29830 (testProg) score 512 or sacrifice child
/var/log/messages:Sep 20 07:38:17 ip-xxx-xx-xx-180 kernel: Killed process 24128 (testProg), UID 0, total-vm:15512476kB, anon-rss:2191512kB, file-rss:13320kB, shmem-rss:0kB
退出原因:
Running out of memory can lead to the “Out Of Memory Exception (OOME)”. Docker adjusts the OOM priority and reduces the risk of it being killed but individual containers are at risk.
解决方法:
调整k8s资源配置:
pods/resource/memory-request-limit-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
namespace: mem-example
spec:
containers:
- name: memory-demo-ctr
image: polinux/stress
resources:
requests:
memory: "2Gi"
limits:
memory: "4Gi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
为了后续方便定位问题,我们在日志中增加了对container资源使用情况相关跟踪日志,主要读取以下几个系统文件:
cat /sys/fs/cgroup/memory/memory.limit_in_bytes
cat /sys/fs/cgroup/memory/memory.memsw.limit_in_bytes
cat /sys/fs/cgroup/memory/memory.memsw.usage_in_bytes
cat /sys/fs/cgroup/memory/memory.usage_in_bytes
Reference:
Resource constraints | Docker Docs
Assign Memory Resources to Containers and Pods | Kubernetes