cgroup freezer 可原子冻结容器进程组实现冷迁移预处理,不终止进程、不丢失状态;需确认子系统就绪、归集全部关联进程至专用 cgroup、执行冻结并验证状态,迁移后解冻即可恢复执行。

Linux 中利用 Cgroup Freezer 实现容器组的暂停与恢复,是冷迁移预处理的关键一步。它不杀死进程、不丢状态,只让整个 cgroup 下所有任务“静止在时间里”,等迁移到目标节点后再原样唤醒——这是比信号级暂停更可靠、更原子的操作。
确认 Freezer 子系统已就绪
Freezer 在现代 Linux(内核 ≥ 2.6.28)中默认启用,但需确保其控制组挂载点可用:
- 检查是否已挂载:
mount -t cgroup | grep freezer;常见路径为/sys/fs/cgroup/freezer - 若未挂载(极少见),可手动创建并挂载:
sudo mkdir -p /sys/fs/cgroup/freezer && sudo mount -t cgroup -o freezer freezer /sys/fs/cgroup/freezer - Docker 默认使用 cgroups v2,而 freezer 在 v2 中已整合进 unified hierarchy,路径变为
/sys/fs/cgroup/xxx/,且通过cgroup.freeze文件控制(值为0表示 thawed,1表示 frozen)
定位并归集目标容器的进程到专用 cgroup
冷迁移需冻结整组关联进程(主进程 + 子进程 + 线程),不能只冻 PID 本身:
- 查容器 PID:用
docker inspect -f '{{.State.Pid}}' <container_name></container_name>获取初始 PID - 获取完整进程树:运行
sudo pstree -s -p <pid></pid>或sudo cat /proc/<pid>/cgroup</pid>确认当前归属的 cgroup 路径 - 新建隔离 cgroup(v1 示例):
sudo mkdir /sys/fs/cgroup/freezer/migration_prep - 将容器所有线程写入:
sudo sh -c "pgrep -P <pid> | xargs -r -I{} echo {} >> /sys/fs/cgroup/freezer/migration_prep/tasks"</pid>;再把主 PID 也加进去
执行原子冻结与状态验证
冻结不是瞬间完成的,内核需等待所有目标线程进入安全可停点(如 sleep、wait、用户态返回前):
- v1 冻结命令:
echo FROZEN | sudo tee /sys/fs/cgroup/freezer/migration_prep/freezer.state - v2 冻结命令:
echo 1 | sudo tee /sys/fs/cgroup/<docker_cgroup_path>/cgroup.freeze</docker_cgroup_path>(路径通常形如/sys/fs/cgroup/docker/xxx) - 验证是否真正冻结:
cat /sys/fs/cgroup/freezer/migration_prep/freezer.state(v1)或cat /sys/fs/cgroup/xxx/cgroup.freeze(v2)应返回FROZEN或1 - 观察进程状态:
ps -o pid,comm,state -p <pid></pid>中 state 应变为T(stopped),且 CPU 使用率归零、无新日志输出
配合冷迁移完成状态保存与恢复
冻结后即可安全执行镜像打包、内存快照导出、网络配置序列化等迁移前置动作:
- 内存状态保持在 RAM 中,无需 dump 到磁盘(区别于 hibernation);若需持久化,可搭配
criu做 checkpoint - 迁移完成后,在目标节点启动容器前,先将其加入对应 cgroup,再解冻:
echo THAWED | sudo tee .../freezer.state或echo 0 | sudo tee .../cgroup.freeze - 解冻后进程立即从上次系统调用断点继续,TCP 连接、文件偏移、锁持有状态均保持不变











