跳到主要内容

Checkpoint 与恢复

概述

Checkpoint 功能可以将正在运行的作业状态保存到磁盘,之后可以恢复继续执行。该操作会捕获进程内存、打开的文件和执行状态,实现比较复杂。

重要提示:Checkpoint 功能不保证适用于所有应用程序。能否成功取决于应用程序特性、系统配置和运行时条件。该功能目前为实验性质,生产环境使用前必须充分测试。

支持版本

fsched 在 (TBD) 版本之后开始支持该功能。

潜在使用场景

如果 Checkpoint 功能对您的应用程序可靠有效,可以在以下场景使用:

  • 节点故障恢复:节点故障后,fsched 可自动从 Checkpoint 恢复作业,避免从头重启(需应用程序兼容且恢复成功)
  • 长时间运行的作业:为兼容的应用程序提供一定的中断保护
  • 计划维护:系统维护前暂停作业,但不保证一定能恢复成功
  • 资源管理:如果应用程序支持,可以将作业从繁忙节点腾出

重要考虑事项

这些使用场景的可行性完全取决于您的具体应用程序:

  • 应用程序兼容性:大多数复杂应用程序存在限制,甚至可能完全不可用
  • 可靠性:Checkpoint 或恢复操作可能因各种原因失败
  • 测试要求:每个应用程序和工作负载都必须进行广泛测试
  • 无保证:即使经过测试,生产环境中 Checkpoint/恢复仍可能失败

未经广泛验证前,不要将 Checkpoint 作为主要的容错或作业管理手段。

工作原理

该功能基于 CRIU(Checkpoint/Restore In Userspace)技术。CRIU 是一个 Linux 工具,可以冻结正在运行的应用程序并保存其状态到磁盘。我们使用了专为 HPC 工作负载优化的定制版本。

Checkpoint 过程包括两步:

  1. 冻结:暂停作业(时长取决于作业大小和系统负载)
  2. 转储:将作业状态写入磁盘

恢复时,fsched 会尝试重建作业状态,包括:

  • 内存内容
  • 打开的文件描述符
  • 网络连接
  • 进程树结构
  • 环境变量

注意:能否成功恢复取决于多种因素。具有外部依赖、网络状态或硬件访问的复杂应用程序可能无法正确恢复。

关键限制

注意

Checkpoint 功能复杂且容易失败

许多应用程序无法正确使用 Checkpoint 功能。即使基本测试成功,生产环境中仍可能出现故障。

已知不兼容情况

  • GPU 和专用硬件访问(通常不支持)
  • 大多数 MPI 应用程序(不可靠)
  • 具有复杂网络状态的应用程序
  • 实时或时序敏感的应用程序
  • 依赖外部服务的应用程序
  • 复杂的进程间通信模式

即使简单应用程序也可能失败

  • Checkpoint 期间正在进行的文件 I/O 操作
  • 超时或无法重新建立的网络连接
  • Checkpoint 和恢复之间发生变化的临时文件或系统资源
  • 内核或库版本差异

性能影响

  • Checkpoint 操作会中断作业(根据内存大小,可能持续几秒到几分钟)
  • Checkpoint 创建期间产生大量 I/O 负载
  • 存储空间需求等于或大于作业内存大小
  • 失败的 Checkpoint 会浪费时间和资源

系统要求

  • 强烈建议使用 Linux kernel 4.x 或更高版本
  • 需要高 I/O 性能的共享文件系统
  • 充足的可用磁盘空间(建议为作业内存大小的数倍)

强制性测试:切勿假设 Checkpoint 功能能正常工作。必须在真实条件下进行广泛测试,即便如此,生产环境中仍可能出现故障。

入门指南

集群管理员

要在集群上启用 Checkpoint 功能,请配置以下内容:

# 启用 Checkpoint 插件
CheckpointType = checkpoint/criu

这是最基本的配置。fsched 独有的高级设置请参考下面的配置选项部分。

注意

系统要求:Checkpoint 功能需要 Linux kernel 3.11 或更高版本。为了获得完整功能和可靠性,强烈建议使用 kernel 4.x 或更高版本。CentOS/RHEL 7 可能不支持所有功能。

用户

提交启用 Checkpoint 的作业

提交作业时使用 --checkpoint 选项即可启用自动 Checkpoint:

sbatch --checkpoint=30:00 my_job_script.sh

该命令会每 30 分钟创建一次 Checkpoint。支持的时间格式:

  • minutes(例如 30
  • minutes:seconds(例如 30:00
  • hours:minutes:seconds(例如 2:30:00
  • days-hours(例如 1-0 表示 1 天)
  • days-hours:minutes(例如 1-0:30
  • days-hours:minutes:seconds(例如 1-2:30:00

建议的起始间隔(需根据测试调整):

  • 测试阶段:--checkpoint=5:00(每 5 分钟)
  • 应用程序验证兼容后:--checkpoint=30:00--checkpoint=2:00:00
  • 需权衡 Checkpoint 开销与可能丢失的工作量

手动 Checkpoint 操作

也可以使用 scontrol 手动控制 Checkpoint:

手动创建 Checkpoint

scontrol checkpoint create <job_id>

为正在运行的作业创建 Checkpoint,可能会因应用程序状态而失败。

暂停作业并保存状态(释放资源):

scontrol checkpoint vacate <job_id>

对作业进行 Checkpoint 后终止它。如果 Checkpoint 失败,作业不会被终止。

恢复已 Checkpoint 的作业

scontrol checkpoint restart <job_id>

从最后的 Checkpoint 恢复作业,可能因各种原因失败。

基本工作流示例

# 1. 提交启用 Checkpoint 的测试作业
$ sbatch --checkpoint=1:00:00 test_job.sh
Submitted batch job 12345

# 2. 检查作业状态
$ squeue -j 12345
JOBID PARTITION NAME USER ST TIME NODES
12345 compute test alice R 2:15 1

# 3. 尝试腾空(可能失败)
$ scontrol checkpoint vacate 12345

# 4. 如果成功,作业已被 Checkpoint,可以重启
$ scontrol checkpoint restart 12345

# 注意:验证作业输出以确保恢复正常工作

配置选项

可通过以下选项自定义 Checkpoint 行为。所有选项都是可选的,有合理的默认值。

fsched 独有功能

fsched 提供了标准 Slurm 中没有的几项高级 Checkpoint 功能:

节点故障自动恢复 - 节点故障导致作业重新排队时,fsched 会自动尝试从最后的 Checkpoint 恢复,而非从头重启。可为兼容应用提供容错能力,但不保证一定成功。需要额外的超时配置(见下文)。

负载感知 Checkpoint - 系统负载过高时跳过 Checkpoint,减少对其他工作负载的影响。负载持续较高时,可能长时间无法创建 Checkpoint。

增量 Checkpoint - 仅保存自上次 Checkpoint 以来的内存变化。对内存访问模式稳定的应用可以节省时间和存储空间,但会在 Checkpoint 之间产生依赖,可能使恢复过程复杂化。

预转储技术 - 最终冻结前预先复制内存,减少暂停时间。效果取决于应用程序的内存访问模式。

节点故障恢复配置

要启用节点故障时的自动 Checkpoint 恢复,需要以下额外配置:

BatchStartTimeout = 10
SlurmdTimeout = 15
AuthInfo = cred_expire=180,ttl=180,requeue_timeout=30
注意

高负载环境请勿使用这些设置。

这些超时设置比较激进,主要用于快速检测故障和重新排队。但在节点高负载时,可能导致误判和不必要的作业失败:

  • 节点临时变慢时,作业可能被错误标记为失败
  • 正常作业可能被不必要地终止和重新排队
  • 高利用率时系统可能不稳定

仅在以下情况使用这些设置:

  • 集群通常有充足的空闲容量
  • 节点故障频繁且需要快速恢复
  • 可以容忍偶尔的误判

对于高利用率集群,不要启用自动节点故障恢复,应使用手动 Checkpoint/释放资源/重启方式。

基本选项

CRIU_MaxEpochs(默认值:1

  • 要保留的 Checkpoint 快照数量
  • 旧的 Checkpoint 会自动删除
  • 更高的值提供更多恢复选项但使用更多磁盘空间
  • 示例:CRIU_MaxEpochs = 3 保留最后 3 个 Checkpoint

性能优化

CRIU_Incremental(默认值:NO

  • 启用后仅保存自上次 Checkpoint 以来的更改
  • 对某些应用可减少 Checkpoint 时间和存储占用
  • 缺点:恢复时需要完整的增量链,任何一个文件损坏都会导致恢复失败
  • 会增加系统复杂度和潜在故障点

CRIU_FullEvery(默认值:10

  • 使用增量 Checkpoint 时,每 N 个 Checkpoint 执行一次完整 Checkpoint
  • 防止过长的增量链导致恢复变慢
  • 仅在 CRIU_Incremental = YES 时适用
  • 示例:设置 CRIU_FullEvery = 10 时,Checkpoint 1-9 是增量的,10 是完整的,然后重复

CRIU_PreDump(默认值:NO

  • 在最后冻结之前预先复制内存以尝试减少冻结时间
  • 效果取决于应用程序内存访问模式
  • 对于内存变动频繁的应用程序可能无法显著减少冻结时间

CRIU_PreDumpDelay(默认值:5 秒)

  • 预转储和最终转储之间等待的时间
  • 允许应用程序在预转储后稳定下来
  • 仅在 CRIU_PreDump = YES 时适用

负载感知 Checkpoint

CRIU_LoadAware(默认值:NO

  • 如果系统负载过高则跳过计划的 Checkpoint
  • 如果系统持续繁忙,可能导致长时间没有 Checkpoint
  • 检查 CPU、I/O 和内存负载是否超过阈值

CRIU_LoadThresholdCPU(默认值:0.95

  • 如果 CPU 利用率超过此比例(0.0 到 1.0),则跳过 Checkpoint
  • 示例:0.95 表示如果 CPU 超过 95% 利用率则跳过

CRIU_LoadThresholdIO(默认值:0.50

  • 如果 I/O 等待超过此比例(0.0 到 1.0),则跳过 Checkpoint
  • 示例:0.50 表示如果 I/O 等待超过 50% 则跳过

CRIU_LoadThresholdMemory(默认值:0.85

  • 如果内存使用超过此比例(0.0 到 1.0),则跳过 Checkpoint
  • 示例:0.85 表示如果内存超过 85% 利用率则跳过

配置示例

最小配置(从这里开始)

CheckpointType = checkpoint/criu

使用增量(使用前充分测试)

CheckpointType = checkpoint/criu
CRIU_Incremental = YES
CRIU_FullEvery = 5
CRIU_MaxEpochs = 2

使用负载感知(Checkpoint 可能被跳过)

CheckpointType = checkpoint/criu
CRIU_LoadAware = YES
CRIU_LoadThresholdCPU = 0.90
CRIU_LoadThresholdIO = 0.60
CRIU_LoadThresholdMemory = 0.80

注意:从最小配置开始。仅在验证特定应用程序可用后再添加功能。

命令参考

用户命令

命令描述何时使用
sbatch --checkpoint=<interval> script.sh提交启用自动 Checkpoint 的作业启动需要定期 Checkpoint 的新作业
scontrol checkpoint create <job_id>立即创建 Checkpoint风险操作之前或手动备份
scontrol checkpoint vacate <job_id>Checkpoint 并暂停作业,释放资源计划维护、资源重新平衡
scontrol checkpoint restart <job_id>恢复并继续已腾空的作业维护后或资源可用时
scontrol show job <job_id>查看作业详细信息包括 Checkpoint 状态检查 Checkpoint 配置和状态

示例命令

检查作业是否启用了 Checkpoint

scontrol show job 12345 | grep Checkpoint

尝试创建 Checkpoint

scontrol checkpoint create 12345
# 检查日志以验证成功

尝试腾空多个作业

for job in 12345 12346 12347; do
scontrol checkpoint vacate $job
# 在依赖它之前验证每个 Checkpoint 是否成功
done

注意:假设作业可恢复前,务必通过检查日志和测试恢复来验证 Checkpoint 是否成功。

最佳实践

选择 Checkpoint 间隔

Checkpoint 间隔的选择取决于多种因素,需要反复测试:

考虑因素

  • Checkpoint 开销随作业内存增大而增加
  • 存储 I/O 性能会影响 Checkpoint 时长
  • Checkpoint 越频繁,开销越大,但失败时损失越小
  • 应用程序对 Checkpoint 中断的敏感程度不同

测试方法

  1. 测试时从较长间隔开始(1-2 小时)
  2. 实际测量 Checkpoint 耗时和对应用的影响
  3. 根据观察到的开销和可接受的风险调整
  4. 监控 Checkpoint 失败情况并相应调整

没有通用的"最佳"间隔,需要针对具体应用和工作负载反复测试确定。

存储管理

  • 监控 Checkpoint 存储使用:du -sh /path/to/checkpoint/dir/<job_id>
  • 作业完成后 Checkpoint 不会自动清理
  • 对于长时间运行的作业,考虑使用 CRIU_MaxEpochs 来限制存储
  • 确保有足够的可用空间(建议为作业内存大小的 2 倍)

应用程序兼容性

注意

生产环境使用前必须测试。

Checkpoint 工作在进程级别,并非所有应用都兼容。使用复杂 I/O、网络连接、硬件设备或对时序敏感的应用可能无法可靠运行。

必需测试

  1. 使用实际应用程序和工作负载测试
  2. 恢复后验证输出正确性
  3. 在生产环境的实际硬件和配置上测试
  4. 记录应用程序的特定限制或变通方案

未经充分测试,切勿假设 Checkpoint 能正常工作。

测试清单

Checkpoint 用于重要工作前,必须完成全面测试:

  1. 基本功能测试

    sbatch --checkpoint=5:00 test_job.sh
    # 等待第一个 Checkpoint 完成
    scontrol checkpoint vacate <job_id>
    scontrol checkpoint restart <job_id>
    # 检查作业是否真正重启(可能失败)
  2. 输出验证

    • 将输出文件与正常运行结果逐字节对比
    • 检查是否有损坏、重复或缺失的数据
    • 验证恢复后应用状态是否一致
  3. 测量开销

    • 测量 Checkpoint 操作耗时(可能远超预期)
    • 测量对作业总运行时间的影响
    • 检查存储空间占用
  4. 测试多种场景

    • 在作业执行的不同阶段进行 Checkpoint
    • 在不同节点上测试恢复(可能失败)
    • 使用真实工作负载,而非简单示例
    • 测试 Checkpoint 失败的情况
  5. 长期可靠性

    • 运行多轮 Checkpoint/恢复循环
    • 监控是否有性能退化或数据损坏
    • 在系统负载下测试

重要:基本测试通过不代表生产环境一定可靠,投入生产后需持续监控。

常见问题

问:GPU 作业可以使用 Checkpoint 吗? 答:GPU Checkpoint 有严重限制,不建议使用。CRIU 对 GPU 状态支持不完整,大多数 CUDA/GPU 应用无法正常 Checkpoint 或恢复。如果必须使用,需进行充分测试,但预期会有问题。

问:作业完成后 Checkpoint 文件怎么办? 答:作业完成后 Checkpoint 文件会保留在磁盘上,需要手动清理以释放空间。请监控 Checkpoint 存储使用情况,及时删除不再需要的旧 Checkpoint 目录。

问:MPI 作业可以使用 Checkpoint 吗? 答:MPI Checkpoint 实现复杂且通常不可靠,高度依赖 MPI 实现、网络架构和进程通信方式。许多 MPI 作业无法成功 Checkpoint,即使经过充分测试,可靠性也可能有限。

问:Checkpoint 需要多少磁盘空间? 答:每个 Checkpoint 约等于作业的内存使用量。CRIU_MaxEpochs = 3 时至少需要 3 倍内存大小的空间。增量 Checkpoint 可以节省一些空间,但仍需要较大存储。建议使用高速存储并确保有足够空间。

问:可以将 Checkpoint 移到其他集群吗? 答:不可以。Checkpoint 与特定系统配置紧密耦合(包括内核版本、库、文件路径和硬件),只能在创建它的同一集群上恢复。

问:Checkpoint 会影响作业性能吗? 答:会。Checkpoint 创建时作业会被暂停(冻结时间),根据内存大小可能持续几毫秒到几秒。写入 Checkpoint 数据还会产生 I/O 开销。启用预转储可以减轻但无法消除影响。两次 Checkpoint 之间不影响性能。

问:Checkpoint 失败会怎样? 答:作业会继续正常运行。失败的 Checkpoint 会被记录但不会终止作业。但是会失去这个恢复点,如果作业在下次成功 Checkpoint 前失败,就需要从更早的 Checkpoint 或从头重启。

问:可以在作业脚本内触发 Checkpoint 吗? 答:不可以,Checkpoint 必须通过 fsched 命令(scontrol)控制。作业脚本无法直接请求 Checkpoint。如有需要,可以在应用层面单独实现 Checkpoint 机制。

问:如何确认 Checkpoint 是否成功? 答:查看 fsched 日志中的 Checkpoint 成功/失败消息,日志位置取决于配置。注意:没有错误消息不代表 Checkpoint 一定有效,只有成功恢复测试才能确认。

问:提交后可以修改 Checkpoint 间隔吗? 答:不可以。Checkpoint 间隔在作业提交时确定,运行期间无法修改。

问:Checkpoint 和 fsched 的作业重启功能一样吗? 答:不一样。作业重启(--requeue)会终止作业并从头开始。Checkpoint 则是保存进程状态后从中断点继续执行。两者用途不同。