2. Docker容器状态模型:运行态、暂停态、停止态、删除态;容器文件系统层(UnionFS)与内存状态的区别
理解Docker容器的状态模型是进行异步迁移的前提。容器在生命周期中会经历四种核心状态:运行态、暂停态、停止态和删除态。每种状态对文件系统层和内存状态的处理方式截然不同,直接影响迁移策略的选择。
2.1 容器四态模型与状态转换
Docker容器并非简单的“运行/停止”二元状态。下图展示了完整的四态转换路径,以及各状态下的关键特征。
2.2 各状态下的资源保留情况
不同状态对容器文件系统层和内存状态的处理存在本质差异,这是迁移任务选型的核心依据。
| 容器状态 | 进程状态 | 文件系统层(UnionFS) | 内存状态 | 网络连接 | 迁移可行性 |
|---|---|---|---|---|---|
| 运行态 | 进程活跃 | 完整保留(含可写层) | 完整保留 | 保持连接 | 需 checkpoint/restore |
| 暂停态 | 进程冻结(SIGSTOP) | 完整保留(含可写层) | 完整保留(冻结) | 连接挂起 | 适合异步迁移 |
| 停止态 | 进程已退出 | 完整保留(含可写层) | 已释放 | 已断开 | 仅迁移文件系统 |
| 删除态 | 无 | 已释放 | 已释放 | 已断开 | 不可迁移 |
迁移选型要点:暂停态是异步迁移的“黄金状态”——它保留了完整的内存快照和文件系统层,同时进程被冻结,不会产生新的数据变更,确保迁移一致性。
2.3 容器文件系统层(UnionFS)详解
Docker镜像采用联合文件系统(UnionFS)实现分层存储。每个容器在镜像层之上叠加一个可写容器层,形成完整的容器文件系统视图。
2.4 内存状态与文件系统层的本质区别
在容器迁移场景中,必须清晰区分以下两个维度的数据:
| 对比维度 | 文件系统层(UnionFS) | 内存状态 |
|---|---|---|
| 存储介质 | 磁盘(持久化) | RAM(易失性) |
| 数据内容 | 程序文件、配置、日志、数据文件 | 进程堆栈、寄存器、打开的文件描述符、网络连接状态 |
| 持久性 | 容器停止后保留 | 容器停止后释放 |
| 迁移方式 | docker export / save / 卷拷贝 | CRIU checkpoint / restore |
| 数据量级 | 通常较大(MB ~ GB) | 通常较小(KB ~ MB) |
| 一致性要求 | 文件系统一致性(fsync) | 内存快照一致性(冻结进程) |
实践建议:在异步迁移设计中,文件系统层采用增量同步策略(先同步基础层,再同步变更层),而内存状态采用一次性 checkpoint策略。两者在时间窗口上解耦,这正是“异步”的核心含义。
2.5 状态模型对迁移策略的影响
不同容器状态决定了迁移任务的复杂度和选型方向:
- 运行态迁移:需要CRIU技术对运行中进程做checkpoint,捕获完整的内存状态和文件描述符。迁移后需在目标节点恢复进程执行。适用于零停机场景,但技术复杂度高。
- 暂停态迁移:先冻结进程(docker pause),此时内存状态不再变化,可安全做checkpoint。迁移完成后在目标节点unpause。适用于短时停机场景,是异步迁移的推荐起点。
- 停止态迁移:仅迁移文件系统层(容器可写层),无需处理内存状态。适用于无状态服务或可重新启动的应用。
- 删除态迁移:容器已不存在,无法迁移。需基于镜像重新创建容器。
注意:暂停态虽然保留了内存状态,但进程被冻结的时间不宜过长(建议不超过30秒),否则可能导致外部依赖超时或心跳检测失败。异步迁移设计应尽量缩短暂停窗口。
2.6 文件系统层迁移的增量策略
基于UnionFS的分层特性,文件系统迁移可以采用高效的增量策略:
- 基础镜像层复用:目标节点优先从本地镜像仓库拉取或缓存基础镜像层,避免重复传输。
- 容器可写层快照:使用
docker diff或overlay2驱动直接获取容器可写层的变更文件列表。 - 增量同步:首次同步全量可写层,后续仅同步变更的块或文件(基于rsync或自定义diff算法)。
- 最终一致性校验:在切换前做一次完整的checksum校验,确保文件系统层完整一致。
# 查看容器文件系统变更
docker diff <container_id>
# 导出容器文件系统(含可写层)
docker export -o container_fs.tar <container_id>
# 使用overlay2驱动查看可写层路径
docker inspect <container_id> --format '{{.GraphDriver.Data.UpperDir}}'