Docker容器实时迁移的再次尝试

出处:Tang’s blog – Docker容器实时迁移的再次尝试http://www.tangblog.com/2017/07/04/docker-container-live-migration.html。
早在今年过年的时候我就尝试过实现Docker Container Live Migration,但是当时由于各种限制无疾而终。主要是Docker自身对这个的支持不太行。这几天又把这个问题拿出来尝试再次解决,发现还是没有好的解决方法。

方案一:checkpoint/restore

这个是比较理想的解决方案,对于单个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

方案二:export/commit

这个解决方案就不太实时了。基本思想也简单,就是把容器导出为镜像,然后传输镜像,然后在新的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不起来了。这个问题暂时还没时间去解决,过几天我再看一下。

方案三:第三方

搜了下,主要有这么几个第三方做了些容器实时迁移的工作。

  1. flocker:https://clusterhq.com/flocker/introduction/
  2. jelastic:http://blog.jelastic.com/2016/01/14/live-migration-of-docker-containers-within-cloud-regions/
  3. http://docs.virtuozzo.com/virtuozzo_7_users_guide/managing-virtual-machines-and-containers/migrating-virtual-machines-and-containers.html

本想尝试下第一个flocker,奈何官方文档各种打不开。第二、第三个都需要使用他们特定的平台,暂时不考虑。

结语

上面说了几种方法,在单一host上都很容易实现,毫无问题。但是涉及跨host的迁移时,就会出现各种问题了。接下来我会尝试一下迁移一个nginx web server,看看用什么解决方案比较好。

你可能感兴趣的:(Docker)