c语言开发exporter,cadvisor node-exporter引发的容器文件系统泄漏

问题

在2017年底,我们对自己的产品添加了监控功能,监控组件包括prometheus、grafana、cadvisor、node-exporter。监控功能集成进产品后,经过一段时间的使用,在卸载产品(主要是停止并删除各应用对应的docker容器)时经常会出现如下的错误信息:

Error response from daemon: Unable to remove filesystem for e1f4db20d043e73b997375c1db06c72127f22b5fa9b0163e98b311532fbbb257: remove /var/lib/docker/containers/e1f4db20d043e73b997375c1db06c72127f22b5fa9b0163e98b311532fbbb257/shm: device or resource busy

被删除失败的容器即刻变为Dead状态

上述错误信息可知,被删除的容器的shm文件系统一直被占用导致删除容器失败

cadvisor容器启动参数

docker run -itd --name cadvisor --network host --restart always -v /:/rootfs:ro -v /var/run:/var/run:rw -v /sys:/sys:ro -v /var/lib/docker:/var/lib/docker:ro -v /dev/disk:/dev/disk:ro -v /etc/localtime:/etc/localtime:ro cadvisor:v0.27.2 -port 8090

node-exporter容器启动参数

docker run -itd --name node-exporter --network host --restart always -v /proc:/host/proc -v /sys:/host/sys -v /:/rootfs -v /etc/localtime:/etc/localtime:ro node-exporter:v0.14.0 -collector.procfs /host/proc -collector.sysfs /host/sys -collector.filesystem.ignored-mount-points "^/(sys|proc|dev|host|etc)($|/)"

解决问题的过程

考虑到是因为添加了监控组件才导致卸载失败的问题,因此首先把注意力放在了四个组件的停止、删除操作上。处理的方法是:先停止四个监控组件的容器服务,其次删除四个监控组件的容器服务,最后停止并删除各应用的容器服务。经过大量的测试验证得知:此问题已经得到解决(服务停止正常、容器卸载正常、存储空间释放正常)。但心里还是想彻底地弄清楚错误提示device or resource busy产生的根本原因,因此开始了进一步的研究

于是开始把注意力放在了docker的存储引擎devicemapper上面,之前在使用devicemapper的时候偶尔也会出现device or resource busy的错误,主要是因为docker的devicemapper存储引擎自身所导致。因此想到了替换docker的存储引擎devicemapper为overlay(之前的一次分享会上学习到Centos7.2系统存储引擎devicemapper的坑要比overlay多一些)。实践更改docker的存储引擎为overlay后发现device or resource busy的错误依然存在,可见此解决方案又失败了

调整注意力到docker自身上,浏览docker官网文档的Troubleshoot一栏,里面确实提到了遇到的这个问题,但按照提示的做法并没有解决问题,这一思路又行不通了

再一次调整注意力到四个监控组件的容器服务上,考虑到:产品是因为引入了四个监控组件的容器后才出现的卸载失败的错误,所以问题肯定是由引入的监控组件所导致,于是开始采用对四个组件容器进行一一排查的策略。经过实践排查发现,一旦引入cadvisor与node-exporter两个中的任一个,均会出现上述错误。于是开始对cadvisor、node-exporter两个容器进行深入研究,以cadvisor研究为例:首先确定容器的启动参数设置正确;然后开始停止并删除测试容器的操作,查找导致device or resource busy的shm文件系统,确定宿主机上没有进程占用此shm文件系统;于是开始尝试进入cadvisor容器内查看挂载信息,发现cadvisor容器内挂载了自身与其他容器的存储文件系统与shm文件系统;开始实践查找此处的shm文件系统的挂载与产生device or resource busy错误的关系,最终发现确实是由于cadvisor容器内的shm文件系统的挂载导致的上述错误。node-exporter的问题与cadvisor一样,此时终于找到了卸载失败的原因

于是开始浏览github上cadvisor、docker的相关issues,想要找到彻底的解决方案。阅读完所有的issues后得出:一、这是一个文件系统泄漏的问题(内核<=3.10);二、Centos7.3的版本提供了解决方案;三、Centos7.4新版本的内核会尝试解决这个问题。由于我们当前用的是Centos7.2,内核是3.10,因此这里无法找到彻底的解决方案

将注意力调整到cadvisor容器启动的参数上,思路:cadvisor将其他容器的文件系统一并挂载的原因是因为在创建cadvisor容器的时候,将包含docker存储的根路径(默认为/var/lib/docker)作为容器的映射卷映射到了cadvisor的容器中,因此想要深入研究一下cadvisor的实现,在确保cadvisor正常功能的基础上绕开docker存储根路径的映射,对cadvisor容器的启动采用细粒度的挂载方式。花了大把的时间研究cadvisor的源码得知cadvisor实现的监控功能必须要映射docker存储的根路径,否则关于容器的监控信息将全部丢失,因此采用细粒度映射的思路又是行不通的

对于当前Centos7.2+Docker1.12.6的环境,最终采用shell脚本的方式对创建完成的cadvisor与node-exporter两个容器将其他容器的文件系统进行卸载操作。安装脚本(install.sh)会在安装完所有容器服务后进行文件系统的卸载操作;卸载脚本(uninstall.sh)会在卸载之前进行文件系统的卸载操作。依靠这种方式解决了device or resource busy的问题

卸载cadvisor、node-exporter容器文件系统的脚本

cadvisor与node-exporter容器的操作方式一样,这里以cadvisor为例说明,因为要在容器中做umount文件系统的操作因此这里需要对cadvisor、node-exporter容器添加--privileged参数,代码段如下:

function exec_cadvisor_container

{

cadvisor_container='cadvisor'

docker_root_dir='/var/lib/docker'

cadvisor_container_id=`docker ps --no-trunc -q --filter "name=${cadvisor_container}"`

for container_id in `docker ps --no-trunc -a -q | grep -v ${cadvisor_container_id}`

do

container_mount_id=`cat ${docker_root_dir}/image/devicemapper/layerdb/mounts/${container_id}/mount-id`

for container_fs in `docker exec ${cadvisor_container} cat /proc/mounts | awk '{print $2}' | grep -E "${container_id}|${container_mount_id}"`

do

if [ -n $container_fs ]

then

docker exec ${cadvisor_container} umount $container_fs

fi

done

done

}

引用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你想使用podman部署node-exporter,可以按照以下步骤进行操作: 1. 创建一个名为node-exporter的目录,用于存放node-exporter的配置文件和数据。使用以下命令创建: ``` mkdir node-exporter ``` 2. 创建一个名为node-exporter.service的systemd服务单元文件,用于启动node-exporter服务。使用以下命令创建: ``` sudo vi /etc/systemd/system/node-exporter.service ``` 将以下内容复制粘贴到文件中: ``` [Unit] Description=Node Exporter [Service] Restart=always ExecStartPre=podman rm node-exporter ExecStart=/usr/bin/podman run --name node-exporter --net=host --pid=host --privileged=true -v /proc:/host/proc:ro -v /sys:/host/sys:ro -v /:/rootfs:ro -v /etc/node-exporter:/etc/node-exporter:z quay.io/prometheus/node-exporter [Install] WantedBy=multi-user.target ``` 保存并退出文件。 3. 创建一个名为node-exporter的配置文件目录,用于存放node-exporter的配置文件。使用以下命令创建: ``` sudo mkdir /etc/node-exporter ``` 4. 创建一个名为node-exporter.yml的node-exporter配置文件,用于指定node-exporter的参数和监控对象。使用以下命令创建: ``` sudo vi /etc/node-exporter/node-exporter.yml ``` 将以下内容复制粘贴到文件中: ``` global: scrape_interval: 15s scrape_configs: - job_name: 'node' metrics_path: /metrics static_configs: - targets: ['localhost:9100'] ``` 保存并退出文件。 5. 重新加载systemd守护程序并启动node-exporter服务。使用以下命令执行: ``` sudo systemctl daemon-reload sudo systemctl enable node-exporter sudo systemctl start node-exporter ``` 6. 确认node-exporter服务已经成功启动。使用以下命令查看服务状态: ``` sudo systemctl status node-exporter ``` 如果服务状态显示为“active (running)”则表示服务已经启动成功。 希望以上步骤能够帮助你成功部署node-exporter服务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值