CRIU的热迁移

服务器-电脑一:192.168.229.134
客户端-电脑二:192.168.229.133

两台电脑的操作系统选择Ubuntu18.04.5 Desktop(64-bit)
docker使用版本 17.06.0~ce-0。
CRIU的版本选择3.14。

CRIU(Checkpoint/Restore In Userspace)是Linux上的一个软件。它可以用来暂停运行中的容器或者是进程,根据CRIU暂停生成的文件从断点恢复容器或者是进程,然后继续执行。

实验涉及两台电脑(虚拟机)因此两台电脑间的通信使用NFS(network file system)。

1. 安装NFS
  • 服务器端(电脑一:192.168.229.134)
    首先说明服务器端安装nfs的过程。使用apt-get下载完成nfs-kernel-server之后,将要挂载到客户端的目录添加到/etc/exports文件中。
# config host network
sudo apt-get install nfs-kernel-server -y
# config NFS
sudo gedit /etc/exports
# 在 exports file添加下行:
# /home       192.168.229.133(rw,sync,no_root_squash,no_subtree_check)
# Then restart nfs-kernel-server service
sudo systemctl restart nfs-kernel-server

在实验过程中根据需要,在服务器exports文件中加入了/home/proc和/home/container目录,分别储存进程迁移、容器迁移的相关文件。

完成上述配置之后,对防火墙进行配置。其中要允许客户端(IP为192.168.229.133)的访问。如下:

# config firewall
# First, check firewall status
sudo ufw status
 #状态:不活动
 #If ufw is inactive, use the below command to enable ufw:
sudo ufw enable
在系统启动时启用和激活防火墙
# Make ufw allow incoming and outgoing:
sudo ufw default allow incoming
#默认的 incoming 策略更改为 “allow”
#(请相应地更新你的防火墙规则)
sudo ufw default allow outgoing
#默认的 outgoing 策略更改为 “allow”
#(请相应地更新你的防火墙规则)
# Make client server can access host server
sudo ufw allow from 192.168.229.133 to any port nfs
#规则已添加
  • 配置客户端的代码如下。
    其中只挂载了/home目录,其他的目录挂载可以根据需要调整。
#!/bin/bash
# install nfs  

sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
sudo rm -f /etc/apt/sources.list
sudo cp ./sources.txt /etc/apt/sources.list    #这个没找到
echo "finish changing source"
sudo apt update
sudo apt upgrade -y -f

# config host network
sudo apt-get install nfs-common -y
# mount the host /home
sudo mkdir -p /nfs/home
sudo mount 192.168.229.134:/home /nfs/home
# 返回 mount.nfs: access denied by server while mounting 192.168.229.134:/home
# check mount status
sudo df -h

客户端输入sudo df -h 后返回

root@yqq2-HP-Pro-3348-MT:~# df -h
文件系统               容量  已用  可用 已用% 挂载点
udev                   1.9G     0  1.9G    0% /dev
tmpfs                  383M  1.6M  381M    1% /run
/dev/sda2              457G  8.6G  426G    2% /
tmpfs                  1.9G  144M  1.8G    8% /dev/shm
tmpfs                  5.0M  4.0K  5.0M    1% /run/lock
tmpfs                  1.9G     0  1.9G    0% /sys/fs/cgroup
/dev/sda1              511M  6.2M  505M    2% /boot/efi
tmpfs                  383M   60K  383M    1% /run/user/1000
/dev/loop0              30M   30M     0  100% /snap/snapd/8542
/dev/loop1              56M   56M     0  100% /snap/core18/1885
/dev/loop2              63M   63M     0  100% /snap/gtk-common-themes/1506
/dev/loop3             256M  256M     0  100% /snap/gnome-3-34-1804/36
/dev/loop4             2.5M  2.5M     0  100% /snap/gnome-calculator/748
/dev/loop5             384K  384K     0  100% /snap/gnome-characters/550
/dev/loop6             1.0M  1.0M     0  100% /snap/gnome-logs/100
/dev/loop7             2.3M  2.3M     0  100% /snap/gnome-system-monitor/148
tmpfs                  383M     0  383M    0% /run/user/0
/dev/loop8              56M   56M     0  100% /snap/core18/1932
/dev/loop9              32M   32M     0  100% /snap/snapd/10492
/dev/loop10            384K  384K     0  100% /snap/gnome-characters/570
/dev/loop11            2.5M  2.5M     0  100% /snap/gnome-calculator/826
/dev/loop12             65M   65M     0  100% /snap/gtk-common-themes/1514
/dev/loop13            218M  218M     0  100% /snap/gnome-3-34-1804/60
192.168.229.134:/home  457G  8.5G  426G    2% /nfs/home
2.安装docker

(1)docker同样使用apt安装,而非源码编译。首先将docker(和CRIU)所需要的支持软件全部安装好,如下:

#build dependent
sudo apt install build-essential -f -y
sudo apt install pkg-config -f -y
sudo apt install libnet-dev python-yaml libaio-dev -f -y
sudo apt install libprotobuf-dev libprotobuf-c-dev protobuf-c-compiler protobuf-compiler python-protobuf libnl-3-dev libcap-dev libbsd-dev -f -y
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common -y -f

(2)之后将docker加入sources.list,并且下载对应版本的docker。此处下载的docker版本为17.06.0,下载旧版本的docker是为了保证checkpoint不出现bug(使用apt-cache madison docker-ce指令查看全部可下载版本)。

如果成功下载hello-world并且运行则说明安装成功。

# install docker
# remove docker
sudo apt-get remove docker docker-engine docker.io containerd runc 
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# add repo
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
# update and install 
sudo apt-get update
sudo apt-get install docker-ce=17.06.0~ce-0~ubuntu -y
# check 
sudo docker run hello-world
  • docker 17.06.0的下载方式。
    如使用apt-cache madison docker-ce找不到要下载的docker版本,执行下面五条命令可以解决:
sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable"
sudo apt-get install docker-ce=17.06.0~ce-0~ubuntu -y

(3)安装完成docker之后需要开启experiment属性,代码如下:

# add experiment to docker
sudo echo "{\"experimental\": true}" >> /etc/docker/daemon.json
sudo systemctl restart docker
3.安装CRIU

CRIU的安装使用源码编译安装的方式。下载的CRIU版本为最新的3.14版。编译源代码时可能会要求安装其他的依赖软件,可以根据提示添加。最后如果criu check输出结果为Looks good.说明没有产生问题。

# criu install
curl -O -sSL http://download.openvz.org/criu/criu-3.14.tar.bz2
tar xjf criu-3.14.tar.bz2
cd criu-3.14
make
sudo cp ./criu/criu /usr/local/bin
# check
sudo criu check
4.容器热迁移

容器热迁移和进程热迁移类似,只需要加入docker的操作即可。基本的思路是在服务器上创建容器,然后暂停容器,查看运行的输出。在客户端恢复容器之后查看输出,如果运行的输出是紧接服务器输出即说明热迁移成功。整个过程都发生在服务器的/home/container目录下,客户端将服务器的/home/container目录挂载到本地的/home/container下。

  • 服务器端
    (1)首先使用docker创建容器looper2,该程序递增地输出i,每个一秒输出一次。
docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'

报错Unable to find image 'busybox:latest' locally不用管,等待一段时间,会自动下载依赖解决

root@yqq-HP-Pro-3348-MT:~/software/criu-3.14# docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
5f5dd3e95e9f: Pull complete 
Digest: sha256:9f1c79411e054199210b4d489ae600a061595967adb643cd923f8515ad8123d2
Status: Downloaded newer image for busybox:latest
0eb909831c3078fbd6545b90531c4a692cbce929325133484a07f7f8663c8fe3

(2)等待输出一段时间后中断程序,中断程序后会产生对应的目录,存储容器的运行状态,给恢复容器时使用。

sudo docker checkpoint create --checkpoint-dir=/home/container/ looper2 checkpoint2

(3)查看logs如下:

sudo docker logs looper2
root@yqq1-HP-Pro-3348-MT:~# docker logs looper2
0
1
2
3
4
5

PS:在服务器输入如下语句可恢复looper2运行。(这里先不恢复,若迁移未成功,再恢复重新迁移)

docker start looper2
  • 客户端
    (1)使用docker恢复容器,注意这里–checkpoint-dir只需要指定到checkpoints目录即可,不需要进一步制定checkpoint2(已经由–checkpoint指定)
docker create --name looper-clone --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'

docker start --checkpoint-dir=/home/container/0dc28109740d76c73c26de4c8a1eeb18e5228b63fbc5d14b3ab5961dad8c8448/checkpoints/ --checkpoint=checkpoint2 looper-clone

(2)恢复容器后可以使用同样的指令查看运行结果。如下:

root@yqq2-HP-Pro-3348-MT:~# docker logs looper-clone
6
7
8
9
...

PS: 可以为一个容器创建多个 checkpoint,每个起不同的名字就是了。列出已创建的checkpoint

docker checkpoint ls looper-clone
CHECKPOINT NAME


一些辅助命令:
  • (1)查看docker中所有的容器
    docker ps -a

  • (2)获取某个docker容器的详细信息
    docker inspect looper2

  • (3)启动
    docker start looper2 docker start 容器ID或容器名

  • (4)停止
    docker stop容器ID或容器名

  • (5)重启
    docker restart容器ID或容器名 可以不管容器是否启动,直接重启容器

  • (6)查看container
    docker container ls

-(7)查看镜像文件目录

ls /var/lib/docker/containers/0dc28109740d76c73c26de4c8a1eeb18e5228b63fbc5d14b3ab5961dad8c8448

0dc28109740d76c73c26de4c8a1eeb18e5228b63fbc5d14b3ab5961dad8c8448-json.log  config.v2.json
checkpoints                                                                hostconfig.json

ls /var/lib/docker/containers/0dc28109740d76c73c26de4c8a1eeb18e5228b63fbc5d14b3ab5961dad8c8448/checkpoints/

-(8)查看docker的所有镜像
docker images

图片.png


遇到的问题
  • (1)使用docker 18.06.1ce3-0版本,报Error response from daemon: custom checkpointdir is not supported的错误。如下:
root@yqq-HP-Pro-3348-MT:~/software# docker create --name looper-clone --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
5f5dd3e95e9f: Pull complete 
Digest: sha256:9f1c79411e054199210b4d489ae600a061595967adb643cd923f8515ad8123d2
Status: Downloaded newer image for busybox:latest
0dc28109740d76c73c26de4c8a1eeb18e5228b63fbc5d14b3ab5961dad8c8448
root@yqq-HP-Pro-3348-MT:~/software# docker start --checkpoint-dir=/home/container/1101bde4f985176cab26a3fae2957763c35be3c8d0c27f0fa9e469c1a4ff5928/checkpoints/ --checkpoint=checkpoint2 looper-clone
Error response from daemon: custom checkpointdir is not supported

据说是因为 docker 对 docker start 命令中的 —-checkpoint-dir 选项不支持,可以手动把 checkpoint 文件目录加入到对应容器的默认位置 /var/lib/docker/containers/<CONTAINER_ID>/checkpoints/。(我没试)


原理知识补充
  • 1.CRIU
    CRIU的功能的实现基本分为两个过程,checkpoint和restore。在checkpoint过程,criu主要通过ptrace机制把一段特殊代码动态注入到dumpee进程(待备份的程序进程)并运行,这段特殊代码就实现了收集dumpee进程的所有上下文信息,然后criu把这些上下文信息按功能分类存储为一个个镜像文件。在restore过程。criu解析checkpoint过程产生的镜像文件,以此来恢复程序备份前的状态没,让程序从备份前的状态继续运行。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容