CRIU介绍

1、CRIU简介

  CRIU(Checkpoint/Restore In Userspace)运行在linux操作系统上的一个软件工具,其功能是在用户空间实现Checkpoint/Restore功能。使用这个工具,你可以冻结一个正在运行的程序,并且checkpoint它到一系列的文件,然后你就可以使用这些文件在任何主机重新恢复这个程序到被冻结的那个点(白话就是实现对已运行程序的备份和恢复)。所以criu通常被用在程序或者容器的热迁移、快照、远程调试等。CRIU 起初是Virtuozzo的一个项目,随着开源社区的帮助,现在也被整合到OpenVZ(它是 Virtuozzo 的开源版本), LXC/LXD, Docker, Podman等软件项目里。

Licence: GPLv2
官 网:http://criu.org
源码地址:https://github.com/checkpoint-restore/criu

贡献方式:Pull Request

2、一个简单的示例

  首先我编写了一个程序test,功能很简单,就是循环打印变量count++的值,count初始值为1。运行此程序:

[root@localhost gysun]# ./test &
25105
count=1
count=2
count=3

这时test程序已经运行,进程号是25105。然后我们在另一个shell里,先创建一个目录imgdir,用于存放备份进程时所生成的镜像文件。然后执行下面的命令:

[root@localhost gysun]# ./criu dump -D imgdir -j -t 25105
[1]+  已杀死               /home/gysun/test

这个命令就是暂停test进程的执行,备份相关数据到imgdir目录后杀死test进程。同时要注意的是criu需要root权限才可以运行。
我们可以看到imgdir目录中生成很多*.img文件。如下所示:

core-25105.img	fs-25105.img   mm-25105.img	  pstree.img   stats-restore
fdinfo-2.img	ids-25105.img  pagemap-25105.img  seccomp.img  timens-0.img
files.img	inventory.img  pages-1.img	  stats-dump   tty-info.img

这些文件保存了进程被criu杀死之前的所有信息。对这些信息的介绍可以参考我的另一篇文章:
Docker热迁移工具CRIU原理系列:images

riu将用这些文件在任何其他同体系架构的主机上对test程序做恢复。比如我就在本机恢复test程序的运行,命令如下:

[root@localhost gysun]# ./criu restore --restore-detached -D imgdir -j 
count=4
count=5	
count=6
count=7

可以看到,criu恢复test程序运行后,count值的打印是距被criu杀死之前的值3继续打印,所以是从4开始。这就实现了程序的热迁移。

  生产中的程序可并非如此简单。很多程序都是功能复杂,比如程序中可能有多个进程、有多个线程、有共享内存的使用、有tty设备的使用、有网络的使用、有ipc的使用等等。criu对此都可以成功的对相关状态进行备份和恢复。

3、CRIU高级特性

3.1 热迁移(Live migration)

  criu的主要功能就是可以实现程序的热迁移,但是需要手动编写很多命令。P.Haul项目提供了一个Go语言版本的库,封装了criu命令的复杂性,可以让我们更轻松的完成程序的热迁移工作。其源码地址是 https://github.com/checkpoint-restore/go-criu

3.2 代码动态注入(Parasite code injection)

  为了获取已运行进程的当前状态,CRIU需要让此进程执行一些代码去捕获当前进程相关信息。为了在不杀死此进程的情况下而实现这个功能,CRIU实现了代码动态注入(parasite code injection)技术。这个技术的详细介绍请参考我的另一篇文章:
同时这个功能被criu封装成一个独立的库libcompel。

3.3 TCP sockets checkpoint-restore

  CRIU另一个特性之一就是有能力在不破坏一个TCP链接的情况下,备份和恢复它的状态。这个功能不仅对CRIU本身有用,同时还可以通过它封装的库libsoccr单独使用。

4、CRIU实现原理

  CRIU的功能的实现基本分为两个过程,checkpoint和restore。在checkpoint过程,criu主要通过ptrace机制把一段特殊代码动态注入到dumpee进程(待备份的程序进程)并运行,这段特殊代码就实现了收集dumpee进程的所有上下文信息,然后criu把这些上下文信息按功能分类存储为一个个镜像文件。在restore过程。criu解析checkpoint过程产生的镜像文件,以此来恢复程序备份前的状态没,让程序从备份前的状态继续运行。
  下面详细介绍checkpoint和restore这两个过程。

4.1 Checkpoint

  checkpoint的过程基本依赖ptrace功能实现。程序严重依赖**/proc**文件系统,它从/proc收集的信息包括:

  • 文件描述信息(通过**/proc/ p i d / f d ∗ ∗ 和 ∗ ∗ / p r o c / pid/fd** 和 **/proc/ pid/fd/proc/pid/fdinfo**)
  • 管道参数信息
  • 内存表(通过**/proc/ p i d / m a p s ∗ ∗ 和 ∗ ∗ / p r o c / pid/maps** 和 **/proc/ pid/maps/proc/pid/map_files/**)

  checkpoint过程中,criu做的工作由如下步骤组成:
说明:在描述checkpoint中,我们把criu进程称为dumper进程,简称dumper。把要备份的进程称为dumpee进程,简称dumpee。

步骤1:收集并且冻结dumpee的进程树

  dumper通过dumpee的pid遍历**/proc/%pid/task/路径收集线程tid,并且递归遍历/proc/ p i d / t a s k / pid/task/ pid/task/tid/children**,然后通过ptrace函数的PTRACE_ATTACHPTRACE_SEIZE命令冻结dumpee程序。

步骤2:收集dumpee的资源并保存

  在这个阶段,dumper获取dumpee的所有可获取的资源信息并写到文件里。这些资源的获取通过如下步骤:

  1. 通过 /proc/ p i d / s m a p s ∗ ∗ 解 析 所 有 V M A s 区 域 , 并 且 通 过 ∗ ∗ / p r o c / pid/smaps** 解析所有VMAs区域,并且通过**/proc/ pid/smapsVMAs/proc/pid/map_files 连接读取所有maps文件。
  2. 通过 /proc/$pid/fd获取文件描述号。
  3. 通过ptrace接口和解析**/proc/$pid/stat**块完成一个进程的核心参数(寄存器和friends)的获取。
  4. 通过ptrace接口向dumpee注入parasite code。这个过程由两步完成:首先注入mmap系统调用到任务被冻结那一刻的CS:IP位置,然后ptrace允许我们运行这个被注入的系统调用,这样我们就在被监控进程里申请到了足够的内存用于parasite code块。接下来把parasite code拷贝到这个新申请到的内存地址,并把CS:IP指向到parasite code的位置。
    从注入上下文,CRIU可以获取更多的信息,比如认证、内存容量等。
    parasite code 代码注入的过程可以参考我的另一篇文章:代码动态注入
步骤3:清理dumpee

  dumper获取到dumpee所有信息(比如内存页,它只能从被监控程序内部地址空间写出)后,我们使用ptrace的系列参数去掉步骤2中对dumpee进程的修改。主要是对被注入代码的清理并并恢复dumpee的地址空间。基本通过PTRACE_DETACHPTACE_CONT。然后criu可以选择杀死dumpee或者让dumpee继续运行。上面的test实例中选择的就是在备份dumpee后杀死进程,实际工作中,如果要对程序做差分备份(或者叫增量备份)时可以选择继续运行dumpee。

4.2 Restore

  恢复程序的过程完全依赖checkpoint过程后产生的镜像文件,主要过程分如下4步:

步骤1:处理共享资源

  在这个步骤里,criu读取*.img镜像文件并找出哪些(子)进程共享了哪些资源,比如共享内存。如果有共享资源存在,稍后共享资源由这个程序的某个(子)进程还原,其他进程要么在第2阶段继承一个(如会话),要么以其他方式获取。例如,后者是通过unix套接字与SCM-CREDS消息一起发送的共享文件,或者是通过memfd文件描述符还原的共享内存区域。

步骤2:生成进程树

  在这一步,CRIU会调用fork()函数一次或多次来重新创建所需进程。

步骤3:恢复基本的资源信息

  在此阶段CRIU打开文件、准备namespaces、重新映射所有私有内存区域、创建sockets、调用chdir() 和 chroot()等等。

步骤4:切换到dumpee的上下文

  通过将restorer.built-in.bin的代码注入到dumpee进程,来完成余下的内存区域、timers、credentials、threads的恢复。

5、CRIU的使用和接口

  CRIU不仅提供了命令行工具CLI供使用,还提供远程调用方式的RPC接口。同时还封装了一个本地接口库API供开发使用。这3种方式的介绍和使用请参阅我的另一篇文章:Docker热迁移工具CRIU原理系列: CLI, RPC and C API

6、常见的热迁移工具(CRIU、BLCR、DMTCP、OPENVZ)

  openvz是在内核态实现的c/r工具,BLCR、DMTCP和CRIU都是在用户态实现的c/r工具。从功能完善性、api支持、发展趋势上,criu都更具优势。他们之间的对比可以参考我的另一篇文章Docker热迁移工具CRIU原理系列:竞品分析CRIU、DMTCP、BLCR、OPENVZ

7、CRIU需要内核开启的配置选项

  CRIU虽是用户态工具,但是它的成功运行离不开kernel的配合。当我们使用命令“criu check”验证当前系统是否正常使用criu时,如果显示"Look good",那么恭喜你,当前系统可以正常使用criu工具,否则出现类似如下错误:

    $ criu check
    Warn (criu/kerndat.c:792): Can't load /run/criu.kdat
    Error (criu/sockets.c:136): Diag module missing (-2)
    Error (criu/util.c:803): exited, status=1
    Error (criu/util.c:803): exited, status=1
    Warn (criu/net.c:2770): Unable to get socket network namespace
    Error (criu/tun.c:82): Unable to create tun: No such file or directory

那么就需要你修改内核配置来支持criu。CRIU需要内核开启的配置项请参看
https://criu.org/Linux_kernel

8、CRIU备份/恢复docker示例

  验证criu对docker容器的热迁移功能,可以参看官网demo

  • 11
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
CRIUCheckpoint/Restore in Userspace的缩写,它是一个用于在用户空间进行容器检查点和恢复操作的工具。通过使用CRIU,可以实现对运行中的容器进行迁移。以下是使用CRIU进行容器迁移的步骤: 1. 首先,您需要删除当前运行的容器以便观察。可以使用以下命令删除所有运行中的容器: [1 ``` docker kill $(docker ps -q) docker rm $(docker ps -a) ``` 2. 然后,您可以使用docker run命令创建一个容器。例如,可以使用以下命令创建一个名为test的容器: [1 ``` docker run -id --security-opt=seccomp:unconfined --name test -h test test:1222 /etc/rc.local ``` 3. 接下来,使用相同的docker run命令创建一个名为looper2-clone的容器,并立即暂停该容器,以避免写入过多日志: [2] ``` docker run -d --name looper2-clone --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done' docker stop looper2-clone ``` 4. 在进行容器迁移之前,您还需要在宿主机上进行一些配置。您可以编辑```/etc/docker/daemon.json```文件,将以下内容添加到文件中: [3] ``` { "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"], "experimental": true } ``` 请确保您的操作系统是CentOS 7.6,并且已经安装了Docker。 5. 接下来,您可以使用CRIU工具来进行容器检查点和恢复操作,实现容器的迁移。具体的CRIU命令将根据您的需求和环境进行设置。 以上是使用CRIU进行容器迁移的基本步骤。请注意,这只是一个简单的示例,实际的操作可能会因为您的需求和环境而有所不同。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Docker容器迁移技术(基于CRIU实现)](https://blog.csdn.net/qq_37076942/article/details/111571322)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海棠花败

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值