破案现场:Docker容器资源限制导致的oom问题
- 01 事故现场
- 02 问题定位
- 03 对症下药
- 04 后记
原文来自于微信公众号“运维之美”
https://mp.weixin.qq.com/s?__biz=MzA5NDY1MTM3MA==&mid=2247484902&idx=1&sn=8394aefd884ee09ea546fcd400dd233c&chksm=904a1363a73d9a759bb525771b3e8ebe17948f1820e2c70121fc1fb49e0f528de75030cd815a&token=798793277&lang=zh_CN#rd
01 事故现场
有同事反馈grafana监控大盘无法展示监控数据,prometheus界面一直在starting up状态
02 问题定位
从现象上感觉prometheus状态肯定不对,查看prometheus容器状态,可以看到prometheus在反复重启,验证了我们的猜想
[localhost@ ~]$ docker ps -a |grep prometheus
e2e973cc7e53 prometheus:v2.42.0 "/opt/bitnami/promet…" 4 days ago Up 1minutes prometheus
通过docker logs prometheus日志看到容器确实不断启动,但是没有明显的报错,想着看通过messages日志看看能不能找到什么证据
通过journalctl -p err查看系统日志,看到promethus出现“out of memory”内存溢出的报错
此时已经接近真相了,出现内存溢出,一般有2种情况
-
一种是主机物理内存不够了,根据优先级kill掉部分服务
-
另外一种就是容器有资源限制,超出了内存限制后被oom,防止影响其它服务
经过查看监控节点物理内存还有空余,看看第二种情况,可以从下边看到prometheus内存使用在不断增长
[root@localhost ~]# docker stats prometheusCONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
7ab16bd57127 prometheus 90.60% 7.507GiB / 8GiB 42.59% 0B / 0B 7.54GB / 82.4GB 63CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
7ab16bd57127 prometheus 96.60% 7.807GiB / 8GiB 42.59% 0B / 0B 7.54GB / 82.4GB 63
由于主机节点较多,监控指标越来越多,prometheus当初定义的内存已经不够使用了,那么解决方案要么是优化上报的数据,另外一个就是增加放宽内存限制
03 对症下药
登录监控节点,执行如下命令,修改内存为超过top命令或者docker stats观察到的最大值执行如下命令更新内存使用限制
注:update命令需要容器状态为up时才能更新成功
docker update --memory=15g prometheus
可能会出现如下报错
[localhost@02-2 ~]$ docker update --memory=20G prometheus
Error response from daemon: Cannot update container e2e973cc7e535201e121fcc5bcfe1dc12fa91e24fee9e6a0af1636ffd119f482: Memory limit should be smaller than already set memoryswap limit, update the memoryswap at the same time
命令修改为如下即可解决,上面报错是由于swap内存限制导致
docker update --memory=15g --memory-swap=15g prometheus
成功破案,问题解决,真的太棒了,后续可以优化业务上报的指标
04 后记
在docker中可以对容器应用程序的资源进行限制,通过cgroup来控制容器,以确保它们在运行时不会占用过多的系统资源。以下是一些常见的 Docker 资源限制选项
-
内存限制:可以使用 --memory 或 -m 选项来限制容器可以使用的内存。例如,–memory=1g 表示限制容器使用的内存为
1GB。超出限制的内存使用可能会导致容器被终止或无法正常运行。 -
CPU 限制:可以使用 --cpus 选项来限制容器可以使用的 CPU 核数。例如,–cpus=0.5 表示限制容器使用的 CPU
核心为 0.5 个。这个值可以是小数,表示分配的 CPU 资源的相对权重 -
CPU 调度策略:可以使用 --cpu-shares 选项来为容器分配 CPU 时间片的权重。这个值越高,容器获得的 CPU
时间越多。默认情况下,所有容器的 CPU 权重相等。 -
IO 限制:你可以使用 --blkio-weight 选项来设置容器对 IO 资源的相对权重。默认情况下,所有容器的 IO 权重相等。
-
网络带宽限制:可以使用 --network 选项来限制容器的网络带宽。例如,–network=none
表示容器没有网络访问权限,–network=host 表示容器与宿主机共享网络 -
使用方式
docker run --cpus 0.5 --memory 256M -d node_app
可以在启动时指定资源限制
当使用docker-compose的时候,通过resources资源标签来定义
version: '3'
services:web:image: nginx:latestports:- "8080:80"deploy:resources:limits:cpus: '0.5'memory: 256M
查看运行容器的资源限制
#方式一
docker stats
#方式二
docker inspect nginx | grep -i memory
放松时刻
最近,我们建立了一个技术交流微信群。有兴趣的同学可以加入和我们一起交流技术,在 「运维之美」 公众号直接回复 「加群」 邀请你入群。