4. CRIU 技术详解:Checkpoint/Restore In Userspace 的架构、内核依赖、支持与限制

CRIU(Checkpoint/Restore In Userspace)是实现容器热迁移与异步迁移的核心底层技术。它能够在用户空间捕获一个运行中进程树的状态(Checkpoint),并将其完整保存到磁盘;随后在相同或兼容的宿主机上恢复执行(Restore),且进程本身几乎感知不到中断。本章深入剖析 CRIU 的架构设计、内核依赖、关键能力与已知限制。

4.1 CRIU 整体架构与核心组件

CRIU 采用用户空间守护进程 + 内核辅助模块的混合架构。其核心组件包括:

  • CRIU 主进程(criu):用户空间命令行工具,负责协调 Checkpoint/Restore 全流程。
  • ptrace 引擎:通过 ptrace() 系统调用冻结目标进程、读取寄存器与内存映射。
  • /proc 文件系统解析器:从 /proc/[pid]/ 读取进程状态、文件描述符、命名空间、cgroup 等信息。
  • 内核模块(criu.ko):可选加载,用于加速某些内核对象的转储与恢复(如 TCP 连接、Unix socket)。
  • 镜像文件生成器:将捕获的状态序列化为 .img 文件,采用 Google Protocol Buffers 格式。
  • 恢复引擎:逆向解析镜像文件,重建进程树、内存映射、文件描述符与网络连接。
CRIU 架构组件与数据流 CRIU 架构组件与数据流 用户空间 内核空间 持久化存储 criu 主进程 ptrace 引擎 /proc 解析器 镜像生成器 criu.ko 内核模块 内核系统调用接口 TCP/UDP 栈 .img 镜像文件(Protocol Buffers) 说明:CRIU 通过 ptrace 冻结进程,结合 /proc 与内核模块收集状态,最终序列化为 .img 文件;恢复时逆向执行。

4.2 内核依赖与系统调用要求

CRIU 对 Linux 内核版本和编译选项有严格依赖。缺少关键内核特性将导致 Checkpoint 或 Restore 失败。

内核特性 最低内核版本 内核配置选项 用途
命名空间(Namespace) 3.8 CONFIG_NAMESPACES 隔离进程树、网络、挂载点
ptrace 冻结 3.3 CONFIG_CHECKPOINT_RESTORE 冻结/解冻目标进程
/proc//map_files 3.5 CONFIG_PROC_PID_MAP_FILES 精确获取内存映射文件路径
TCP 连接转储 4.11 CONFIG_TCP_REPAIR 保存/恢复 TCP 连接状态
Unix socket 转储 4.15 CONFIG_UNIX_DIAG 保存/恢复 Unix socket 队列
用户空间事件轮询(epoll) 4.5 CONFIG_EPOLL 保存 epoll 实例与监听事件
cgroup v2 支持 5.2 CONFIG_CGROUP_BPF 恢复 cgroup 层级与资源限制
⚠ 内核依赖检查命令: 在目标宿主机上执行 criu check --all 可验证所有必需内核特性是否启用。若输出包含 WARN 或 FAIL,则需升级内核或重新编译内核模块。

4.3 Checkpoint 与 Restore 核心流程

CRIU 的 Checkpoint 和 Restore 分别遵循严格的阶段化流程,确保状态一致性与可恢复性。

4.3.1 Checkpoint 阶段

  1. 冻结(Freeze):通过 ptrace(PTRACE_SEIZE) 附加到目标进程树,发送 SIGSTOP 信号,暂停所有线程。
  2. 收集(Collect):遍历 /proc/[pid]/ 收集进程状态、内存映射、文件描述符、信号处理、命名空间等。
  3. 转储(Dump):将收集到的状态序列化为 .img 文件,包括内存页(通过 process_vm_readv 读取)。
  4. 解冻(Thaw):发送 SIGCONT 恢复进程执行(若为热迁移,则进程继续运行)。
  5. 验证(Verify):检查镜像文件完整性,生成校验和。

4.3.2 Restore 阶段

  1. 解析(Parse):读取 .img 文件,重建进程树拓扑结构。
  2. 创建(Create):通过 fork() / clone() 创建进程,恢复命名空间、cgroup、挂载点。
  3. 恢复内存(Restore Memory):使用 mmap() 映射内存区域,通过 process_vm_writev 写入内存页内容。
  4. 恢复文件描述符(Restore FDs):重建文件、socket、pipe、eventfd 等描述符。
  5. 恢复网络(Restore Network):重建 TCP 连接(通过 TCP_REPAIR 模式)、Unix socket 队列。
  6. 恢复信号与定时器(Restore Signals & Timers):恢复信号掩码、pending 信号、POSIX 定时器。
  7. 恢复执行(Resume):通过 ptrace(PTRACE_DETACH) 释放进程,进程从暂停点继续执行。
Checkpoint 与 Restore 流程对比 Checkpoint 与 Restore 流程对比 Checkpoint(转储) Restore(恢复) ① 冻结(ptrace + SIGSTOP) ② 收集(/proc + 内核接口) ③ 转储(序列化为 .img) ④ 解冻(SIGCONT) ⑤ 验证(校验和检查) ① 解析(读取 .img 文件) ② 创建(fork + 命名空间) ③ 恢复内存(mmap + 写页) ④ 恢复文件描述符 ⑤ 恢复网络(TCP_REPAIR) ⑥ 恢复信号/定时器 ⑦ 恢复执行(ptrace 分离) 说明:Checkpoint 与 Restore 流程并非完全对称;Restore 需要额外处理网络重建与信号恢复,步骤更多。

4.4 支持的能力与功能矩阵

CRIU 支持丰富的进程状态保存与恢复能力,但并非所有 Linux 资源都可被完整转储。下表列出主要支持项与当前状态。

资源类型 支持状态 备注
进程树(多进程/多线程) ✅ 完整支持 支持 clone() 创建的线程组
内存映射(匿名/文件映射) ✅ 完整支持 包括 huge page、mremap
文件描述符(普通文件) ✅ 完整支持 需文件系统支持 fdinfo
TCP 连接 ✅ 支持(≥4.11) 通过 TCP_REPAIR 模式,需内核模块
Unix socket ✅ 支持(≥4.15) 支持 DGRAM 与 STREAM 类型
信号与信号处理 ✅ 支持 包括 pending 信号与 sigaction
POSIX 定时器 ✅ 支持 包括 timer_create
epoll 实例 ✅ 支持(≥4.5) 保存监听事件与就绪列表
eventfd / signalfd / timerfd ✅ 支持 需内核 ≥3.10
cgroup v1 / v2 ✅ 支持 v2 需内核 ≥5.2
命名空间(所有类型) ✅ 支持 包括 PID、网络、挂载、用户、UTS
设备映射(Device Mapper) ⚠️ 部分支持 仅支持 snapshot 设备,不支持 thin provisioning
GPU 状态(NVIDIA/CUDA) ❌ 不支持 GPU 显存、上下文、驱动状态无法转储
DMA / RDMA 设备 ❌ 不支持 硬件状态无法用户空间捕获
FUSE 文件系统 ⚠️ 部分支持 需 FUSE 守护进程配合,可能丢失状态

4.5 关键限制与避坑指南

在生产环境中使用 CRIU 进行容器迁移时,以下限制需要特别关注:

🔴 GPU 与加速器限制: CRIU 无法捕获 GPU 显存内容、CUDA 上下文、OpenCL 状态或任何硬件加速器内部状态。如果容器使用了 NVIDIA GPU 或 AMD ROCm,Checkpoint 操作将失败。解决方案:在 Checkpoint 前将 GPU 任务排空,或使用 GPU 热迁移专用方案(如 NVIDIA MIG 配合 vGPU)。
⚠ 设备映射(Device Mapper)限制: CRIU 对 Device Mapper 的支持仅限于 snapshot 设备。如果容器使用了 dm-thin 或 dm-crypt,转储时可能丢失设备元数据。建议在 Checkpoint 前将设备映射转换为普通文件映射,或使用 --ext-unix-sk 选项绕过。
  • 时间敏感应用: Checkpoint 过程会导致进程冻结数十毫秒到数秒(取决于内存大小)。对于需要严格低延迟的应用(如高频交易),冻结时间可能触发超时或连接断开。
  • 网络连接中断: 虽然 CRIU 支持 TCP 连接恢复,但恢复后对端可能已经超时关闭连接。建议在迁移前设置较长的 TCP keepalive 间隔。
  • 文件系统一致性: CRIU 不会对磁盘文件系统做快照。如果进程在 Checkpoint 时正在写入文件,恢复后文件可能处于不一致状态。建议配合文件系统快照(如 fsfreeze)使用。
  • 内核版本兼容性: Checkpoint 和 Restore 必须在相同或兼容的内核版本上进行。跨大版本迁移(如 4.x → 5.x)可能导致恢复失败。建议源和目标宿主机内核版本差异不超过一个 minor 版本。
  • 内存开销: Checkpoint 时 CRIU 会将所有内存页读取到用户空间并写入磁盘。对于内存密集型容器(如 64GB+),转储过程可能消耗大量临时磁盘空间和 I/O 带宽。

4.6 CRIU 与 Docker 集成实践

Docker 从 1.11 版本开始内置 CRIU 支持,通过 docker checkpoint 和 docker restore 命令实现容器级 Checkpoint/Restore。底层调用链如下:

# 创建容器时启用 checkpoint 支持
docker run -d --name myapp --security-opt seccomp=unconfined \
  --cap-add=SYS_PTRACE myapp:latest

# 执行 Checkpoint(生成镜像文件)
docker checkpoint create myapp checkpoint1 \
  --leave-running=false \
  --checkpoint-dir=/var/lib/docker/checkpoints/

# 在目标节点执行 Restore
docker start --checkpoint checkpoint1 \
  --checkpoint-dir=/var/lib/docker/checkpoints/ myapp
💡 生产建议: 使用 --leave-running=false 确保 Checkpoint 后容器停止,避免状态冲突。迁移前执行 criu check --all 验证目标节点内核兼容性。对于跨节点迁移,需手动同步 --checkpoint-dir 目录到目标节点。