2. Docker容器状态模型:运行态、暂停态、停止态、删除态;容器文件系统层(UnionFS)与内存状态的区别

理解Docker容器的状态模型是进行异步迁移的前提。容器在生命周期中会经历四种核心状态:运行态、暂停态、停止态和删除态。每种状态对文件系统层和内存状态的处理方式截然不同,直接影响迁移策略的选择。

2.1 容器四态模型与状态转换

Docker容器并非简单的“运行/停止”二元状态。下图展示了完整的四态转换路径,以及各状态下的关键特征。

Docker容器四态转换模型 运行态 进程运行中 暂停态 进程冻结 停止态 进程已退出 删除态 元数据清除 docker pause docker unpause docker stop / kill docker start docker rm docker rm -f 关键说明: 暂停态保留内存状态(冻结),停止态释放内存但保留文件系统层,删除态释放所有资源。

2.2 各状态下的资源保留情况

不同状态对容器文件系统层和内存状态的处理存在本质差异,这是迁移任务选型的核心依据。

容器状态 进程状态 文件系统层(UnionFS) 内存状态 网络连接 迁移可行性
运行态 进程活跃 完整保留(含可写层) 完整保留 保持连接 需 checkpoint/restore
暂停态 进程冻结(SIGSTOP) 完整保留(含可写层) 完整保留(冻结) 连接挂起 适合异步迁移
停止态 进程已退出 完整保留(含可写层) 已释放 已断开 仅迁移文件系统
删除态 无 已释放 已释放 已断开 不可迁移

迁移选型要点:暂停态是异步迁移的“黄金状态”——它保留了完整的内存快照和文件系统层,同时进程被冻结,不会产生新的数据变更,确保迁移一致性。

2.3 容器文件系统层(UnionFS)详解

Docker镜像采用联合文件系统(UnionFS)实现分层存储。每个容器在镜像层之上叠加一个可写容器层,形成完整的容器文件系统视图。

容器文件系统层(UnionFS)结构 容器可写层(读写) 容器运行时产生的文件变更 镜像层 n(只读) 镜像层 n-1(只读) 镜像层 2(只读) 镜像层 1(只读)— 基础层 容器层 镜像层 UnionFS 特点: • 写时复制(CoW) • 层叠挂载 • 镜像层共享 • 容器层隔离 迁移影响: 仅需传输容器可写层 + 内存状态(暂停态) 镜像层可在目标节点 本地缓存或复用

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的分层特性,文件系统迁移可以采用高效的增量策略:

  1. 基础镜像层复用:目标节点优先从本地镜像仓库拉取或缓存基础镜像层,避免重复传输。
  2. 容器可写层快照:使用 docker diff 或 overlay2 驱动直接获取容器可写层的变更文件列表。
  3. 增量同步:首次同步全量可写层,后续仅同步变更的块或文件(基于rsync或自定义diff算法)。
  4. 最终一致性校验:在切换前做一次完整的checksum校验,确保文件系统层完整一致。
# 查看容器文件系统变更
docker diff <container_id>

# 导出容器文件系统(含可写层)
docker export -o container_fs.tar <container_id>

# 使用overlay2驱动查看可写层路径
docker inspect <container_id> --format '{{.GraphDriver.Data.UpperDir}}'