问题

在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

}

引用

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

  1. Prometheus:监控与告警:10:Node Exporter的Grafana模版

    在前面的文章中介绍了,如何使用Prometheus Server搜集Node Exporter提供的指标数据,然后利用Grafana定制可视化监控的方式,而Grafana社区提供了类似的仪表盘的模版可 ...

  2. 会php学node要多久,php开发需要会node吗

    php开发需要会node吗 不需要.php作为后端开发语言完全够用,不需要额外学习使用nodejs技术. PHP PHP即"超文本预处理器",是一种通用开源脚本语言.PHP是在服务 ...

  3. 【鸿蒙 HarmonyOS】HarmonyOS 开发环境搭建 ( Node.js 安装 )

    文章目录 一.下载 Node.js® 安装包 二.安装 Node.js 三.验证 Node.js 鸿蒙 HarmonyOS 开发环境 DevEco Studio 安装 , 参考博客 : [鸿蒙 Har ...

  4. cs架构用什么语言开发_用Rust语言开发微信小程序

    由于stdweb已经好久没有更新了,本人又写了另外一篇: JiaYe:用Rust语言开发微信小程序:wasm-bindgen​zhuanlan.zhihu.com stdweb可以轻松将Rust代码编 ...

  5. 利用PHP语言开发手机app后台服务器的框架是什么?或者说开发流程是怎么样的?

    最近正在做一个手机APP的服务端API开发,虽然是基于Ruby on Rails的,做的也不太专业,不过大致相通,希望能够给你一些启发. 首先,如果是比较简单的手机APP,例如新闻客户端这样的 不会涉 ...

  6. Go语言开发学习笔记(持续更新中)

    Go语言开发学习笔记(持续更新中) 仅供自我学习 更好的文档请选择下方 https://studygolang.com/pkgdoc https://www.topgoer.com/go%E5%9F% ...

  7. 【学习OpenCV4】案例1:Windows OpenCV C++语言开发环境搭建

    本文的案例内容源自于图书**<学习OpenCV 4:基于Python的算法实战>**,该书是国内第一本完整介绍OpenCV4的图书,第一章有在各个平台搭建环境的介绍,后面每个章节都有对模块 ...

  8. 轻松玩转树莓派Pico之三、Windows+Ubuntu虚拟机模式下VSCode C语言开发环境搭建

    目录 1.VSCode下载与安装 2.VSCode基础插件安装 3.SSH连接与配置 4.SSH免密登录 5.Pico编译 工欲善其事,必先利其器.之前的介绍的Pico流程都是通过命令行编译,没有进行 ...

  9. 1 Go语言开发环境搭建详细教程+go常见bug合集【Go语言教程】

    Go语言开发环境搭建[Win.Linux.Mac] 1 SDK下载 官网地址:golang.org,因为一些原因国内可能无法访问.可以使用下面第二个链接. 国内地址访问:https://golang. ...

最新文章

  1. 一次图文并茂的***完整测试二
  2. 机器人3·15 | 赛迪「机器人国评中心」揭示机器人产品质量6大痛点!
  3. requests + BeautifulSoup + json
  4. WAF果真是个好东西
  5. [shell进阶]——shell多线程
  6. 转自把《编程珠玑》读薄
  7. 福禄克FI-3000光纤监测显微仪使用MPO检查摄像头?
  8. error C2440 “static_cast” 无法从“void (__thiscall CPppView )(void)”转换为“LRESULT (__thiscall
  9. [flask]gunicorn配置文件
  10. linux下解包bin二进制文件_linux下如何使用docker二进制文件安装_docker离线安装
  11. Git初学札记(六)————在远程新建本地Branch与在本地新建远程Branch
  12. 【转】详解GAN代码之逐行解析GAN代码
  13. Remoting Generic Async Queue (Release 2) override InitializeLifetimeService return null
  14. 关于Lambda表达式的简单语法理解,有参无参,有无返回值的格式的理解,仅限编程新手
  15. 《Windows程序设计》复习题
  16. 同志亦凡人第一季/全集BQueer As Folk 1迅雷下载
  17. 如何才能修炼成一名不可替代的程序员?
  18. 豆瓣top250-词云案例
  19. Y7000P 2020安装黑苹果教程
  20. php自我介绍50字,自我介绍50字

热门文章

  1. 【Vue 实战项目】后台管理系统登录页详解附源码
  2. 国密算法Go语言实现(详解)(九) ——SM2(椭圆曲线公钥密码算法)
  3. java 图片相似搜索_JAVA比较两张图片相似度的方法
  4. 安卓电池校正_都说苹果寿命长,2年前的iPhoneXR,相当于目前什么安卓手机?
  5. Junit新语法assertThat
  6. 2022杭电多校八 1011-Stormwind(贪心)
  7. pacemaker+corosync+pcs
  8. MySQL备份恢复-mysqldump/xbk
  9. MySQL——建表建库基本命令
  10. cv2.cvtColor(image,cv2.COLOR_RGB2BGR) opencv颜色空间的转换