出处:Tang’s blog – Docker容器实时迁移的再次尝试http://www.tangblog.com/2017/07/04/docker-container-live-migration.html。
早在今年过年的时候我就尝试过实现Docker Container Live Migration,但是当时由于各种限制无疾而终。主要是Docker自身对这个的支持不太行。这几天又把这个问题拿出来尝试再次解决,发现还是没有好的解决方法。
这个是比较理想的解决方案,对于单个host上来说,这个方案行之有效,可以很快的进行docker的checkpoint:
https://docs.docker.com/engine/reference/commandline/checkpoint/
和restore:
start --checkpoint checkpoint1 --checkpoint-dir=/tmp
参考:
https://docs.docker.com/engine/reference/commandline/start/
没有遇到任何问题。整个流程参考CRIU的文档:
https://criu.org/Docker
但是当我尝试将一个容器checkpoint之后,把checkpoint的文件传输到另外一个host,并提前在另外的host上创建容器,尝试将checkpoint的文件导入新的host上的新的容器时,发生了错误,百般查询后,发现确实是一个未解决的问题,问题参考:Docker Checkpoint & Restore on another host。
So I started using an Ubuntu 16.04 LTS host (kernel 4.4.0-75-generic). This allowed me to install CRIU 2.6 which got me past the ghost file issue and I was able to successfully dump my container. However I then ran into issues when attempting to restore a checkpointed container. I have mounted filesystems in my container which CRIU and Docker in particular were unable to restore. This is documented in Docker issue 3222711. The last 2 comments on that issue are pretty enlightening and if I knew Go, I’d fix it.
issues/32227里面给出了解释:
The problem is that after running docker create -v myVolume:/foo, myVolume is not actually mounted on /foo inside the container; Docker appears to lazily mount the volume, so this only occurs on the first docker start. After docker start has been run once, the volumes are mounted. When docker start --checkpoint ... is then run afterwards, the volume is mounted, CRIU can see the files, and the restore is successful.
This isn’t a CRIU bug, this is a bug caused by Docker’s lazy mounting of volumes causing CRIU to not be able to see the files.
就是说当create一个新的容器后,docker的机制并没有及时的mount the volume,导致CRIU并不知道新复制来的文件。
这里还有个相似的issue:
Docker restore doesn’t work on freshly created container
这里不得不再提另外一点,从docker 1.10开始,针对aufs文件系统的存储命名方式发生了变化。直接通过docker id去
/var/lib/docker/aufs/diff
下面找文件是找不到的,docker id 对应的mount id存放在了
/var/lib/docker/image/aufs/layerdb/mounts/<docker-id>/mount-id
可以通过cat查看。这个大坑花了我一晚上才找到,感谢国外网友。
至此在最新版本docker(17.06.0-ce)上尝试checkpoint/restore方案失败。
但是有一个修改版的docker其实是可以支持这个功能的:
https://github.com/boucher/docker/blob/cr-combined/experimental/checkpoint_restore.md
所以如果没有版本洁癖可以使用上面这个docker,具体实现过程参考:
https://circleci.com/blog/checkpoint-and-restore-docker-container-with-criu/
代码:
https://gist.github.com/kimh/79f7bcb195466acea39a
这个解决方案就不太实时了。基本思想也简单,就是把容器导出为镜像,然后传输镜像,然后在新的host上新建一个基于这个镜像的容器。如果涉及数据卷(data volume),还需要单独迁移数据卷。
主要过程参考这儿:
Easy Backup, Restore and Migrate Containers in Docker
以及官方的一些操作:
https://docs.docker.com/engine/reference/commandline/import/
但是我尝试了一下,把容器在host1上commit或者export后,迁移到host2上再import毫无问题,但是run就run不起来了。这个问题暂时还没时间去解决,过几天我再看一下。
搜了下,主要有这么几个第三方做了些容器实时迁移的工作。
本想尝试下第一个flocker,奈何官方文档各种打不开。第二、第三个都需要使用他们特定的平台,暂时不考虑。
上面说了几种方法,在单一host上都很容易实现,毫无问题。但是涉及跨host的迁移时,就会出现各种问题了。接下来我会尝试一下迁移一个nginx web server,看看用什么解决方案比较好。