devicemapper设置direct-lvm踩坑记
Apr 11, 2017
这是一篇碎碎念,想到哪儿就写到哪儿。。
官网上说:Docker hosts running the devicemapper storage driver default to a configuration mode known as loop-lvm. This mode uses sparse files to build the thin pool used by image and container snapshots. The mode is designed to work out-of-the-box with no additional configuration. However, production deployments should not run under loop-lvm mode.
所有的资料都说生产环境中建议用direct-lvm进行存储。网上说优点是便于扩容,备份和数据的迁移,还有的说性能更好。
扩容,备份和数据易迁移是使用外挂硬盘的优点,并不能解释为什么devicemapper用direct-lvm存储模式被官方强烈推荐。甚至在第一次启动docker的时候如果devicemapper不是用direct-lvm还会被警告:
WARNING: Usage of loopback devices is strongly discouraged for production use. Either use –storage-opt dm.thinpooldev or use –storage-opt dm.no_warn_on_loop_devices=true to suppress this warning.
性能好这个优点有一定道理,网上有人对此做过性能的测试http://blog.csdn.net/gushenbusi/article/details/49494629,得出结论“direct-lvm直接使用dm-thin内核模块,直接使用raw分区,在高负载和高密度下具有性能优势。”可能我没有在高负载高密度下使用docker的需求,所以使用direct-lvm的性能优势对我作用也不大。
在实际使用过程中碰到的问题是:在centos7.1下使用docker1.8.1,devicemapper的loop-lvm模式。某天发现容器的空间被占满了,于是便将文件清掉。然后发现了奇怪的情况:删除容器内的文件,宿主机并不会释放空间,容器空间依然是被占满的。在对精简池(thin pool),宿主机磁盘,和容器限制大小进行了改变,并在docker1.8.2和docker1.12.6下分别进行实验,发现有以下情况:
在centos7.1下,docker1.8.2和1.12.6容器内文件的变化对宿主机存储空间的影响基本一致:
- 容器内内生成文件,再删除,宿主机不会释放空间,需要删除容器才会释放空间。
- 容器内生成文件,再删除,宿主机不会释放空间,再生成文件,宿主机重新可能会重新分配空间;也可能不会重新分配空间。
- docker1.8.2下:
资源池预设空间小于宿主机磁盘大小,在容器中生成文件大于容器预设大小时,无法写入文件,但容器不会崩。
资源池预设空间大于宿主机磁盘大小,在容器中生成文件大于容器预设大小时,无法写入文件,但容器崩,退出后将无法再启动容器。
docker1.12.6下,当容器中生成文件大于容器预设大小时,无法写入文件,且容器崩溃。- 当资源池和宿主机的预设空间大于宿主机空间,在容器中生成文件大于容器预设大小时,宿主机提示磁盘空间占满,docker1.8.2导致了宿主机崩溃,docker1.12.6则不会导致宿主机崩溃,但删除容器后不会释放空间,需要删除devicemapper文件夹。
http://www.cnblogs.com/Andrew-XinFei/p/6245330.html这篇文章中提到:
devicemapper + loop-lvm 还有一个缺陷,因为它是稀疏文件,所以它会不断增长。用户在使用过程中会注意到 /var/lib/docker/devicemapper/devicemapper/data 不断增长,而且无法控制。很多人会希望删除镜像或者可以解决这个问题,结果发现效果并不明显。原因就是这个稀疏文件的空间释放后基本不进行垃圾回收的问题。因此往往会出现即使删除了文件内容,空间却无法回收,随着使用这个稀疏文件一直在不断增长。所以:对于 CentOS/RHEL 的用户来说,在没有办法使用 UnionFS 的情况下,一定要配置 direct-lvm 给 devicemapper,无论是为了性能,稳定性还是空间利用率。
感觉这段话是解决了上述问题。于是便千辛万苦申请了磁盘,设置之后发现情况并没有改变,删除文件磁盘依然不会释放空间,可能对上述文章理解有误吧,总之改成direct-lvm模式也没有解决我的问题。如果容器内有持续增长的文件,比如日志文件这种,撑爆容器是迟早的事情针对这种情况,目前想到的方法是将这些文件外挂到宿主机上,不知道还有没有别的方法。
上文说到千辛万苦挂磁盘,也想说一下。对于设置direct-lvm模式,官网讲得很清楚:https://docs.docker.com/engine/userguide/storagedriver/device-mapper-driver/#configure-docker-with-devicemapper,过了英语四级的小伙伴就不要犯懒了。总之我犯了个懒,还用了百度,百度了中文安装方法。还是上述文章,里面的步骤写的很清楚,但是我运行老是报错,我的环境是centos7.3,docker1.12.6,出现的问题,在起容器的时候会有:
/usr/bin/docker-current: Error response from daemon: shim error: docker-runc not installed on system.
在给容器映射端口的时候有:
/usr/bin/docker-current: Error response from daemon: driver failed programming external connectivity on endpoint stoic_wright (35ded5c721d0ccde517d932e54c4062197a84252a72b951de4fd66fbe6f01d88): exec: “docker-proxy”: executable file not found in $PATH.
仔细对照官网,发现官网在添加direct-pool信息的时候,是将其直接写入配置文件:
而上述文章采用了drop-in方法(官网也有提及),修改了daemon.conf和daemon.json
不同在于ExecStart,原始配置文件启动的是/usr/bin/dockerd-current,而drop-in的方法启动的是/usr/bin/dockerd。
进入/usr/libexec/docker/文件夹,确实没有docker-runc和docker-proxy存在,有的是docker-runc-current和docker-proxy-current。加上两个软连接,问题解决:
|
|
使用配置文件本来是件好事,比如修改配置不必重启服务,只需发送SIGHUP信号即可。
但是目前在dockerd中使用配置文件会有一些问题:例如无法得知具体哪项生效了,启动日志以及docker info,还有ps -ef都不会给出生效配置,这对于排障很不方便。
当 dockerd的参数和daemon.json文件中的配置有所重复或者冲突,会直接导致引擎启动失败。因此在这些问题解决前,先使用修改docker.service这类做法来实现。
https://blog.lab99.org/post/docker-2016-07-14-faq.html这篇文章解决了我的很多疑惑,对初学者很有意义。
