Skip to content

跨可用区传输共享高性能存储数据

共享高性能存储卷只能挂载到同一可用区的 AICoder。如果需要把数据从一个可用区迁移到另一个可用区,请在两个可用区分别启动 AICoder,并让源端 AICoder 通过 SSH 和平台跳板机将数据直接同步到目标端 AICoder。

本地计算机只用于打开控制台、切换可用区和复制连接信息,不承载文件数据。实际数据路径如下:

图表预览

准备源端和目标端 AICoder

准备两个 AICoder 时,源存储卷和目标存储卷必须分别与挂载它们的 AICoder 位于同一可用区。不要先把数据复制到 AICoder 的 10 GiB 系统盘。

  1. 在源可用区启动 AICoder,挂载源共享高性能存储卷,并记录源目录,例如 /mnt/source-volume/dataset

  2. 在源端检查挂载点和待传输数据。df 输出中的文件系统应为源存储卷,而不是 AICoder 系统盘。

    language-bash
    findmnt -T <source-mount-path>
    df -h <source-mount-path>
    du -sh <source-directory>

    如果源目录包含大量文件,du 需要遍历目录,运行时间可能较长;已经从其他可信来源确认数据量时可跳过该命令。

  3. 关闭源端 AICoder Shell 窗口,切换到目标可用区并启动目标端 AICoder。关闭 Shell 窗口不会立即终止 AICoder 实例。

  4. 在目标端挂载目标共享高性能存储卷,确认可用空间足以容纳源数据,并记录目标目录,例如 /mnt/target-volume/dataset

    language-bash
    findmnt -T <target-mount-path>
    df -h <target-mount-path>

    只有 findmnt 显示目标共享存储文件系统而不是 / 或 OverlayFS 时,才能创建目标目录:

    language-bash
    mkdir -p <target-directory>
    test -w <target-directory> && echo target-ready

只有显示 target-ready 时,目标目录才通过当前用户的写入检查。AICoder 的可用区、存储卷挂载和实例存活限制详见存储空间配额和限制

在源端 AICoder 创建独立 SSH 密钥

SSH 私钥必须位于发起连接的客户端上。本任务的客户端是源端 AICoder,因此即使源端的 ~/.ssh/authorized_keys 中已有公钥,也不能用这些公钥发起到目标端的连接。

在源端 AICoder 中创建本次传输专用的密钥对:

language-bash
install -d -m 700 ~/.ssh
ssh-keygen -t ed25519 \
  -f ~/.ssh/id_ed25519_aicoder_cross_zone \
  -C "aicoder-cross-zone"
cat ~/.ssh/id_ed25519_aicoder_cross_zone.pub

按提示为私钥设置口令,并复制最后一条命令输出的完整公钥。私钥 ~/.ssh/id_ed25519_aicoder_cross_zone 应始终保留在源端 AICoder 中;不要把私钥粘贴到控制台或复制到目标端。

在目标端添加专用公钥

目标端需要加载源端生成的公钥,才能验证源端持有的私钥。对于本次一次性传输,建议直接把专用公钥添加到目标端;这种方式只影响目标 AICoder,并且无需重启即可生效。如果贵组织希望通过平台统一管理公钥,也可以使用平台 SSH 公钥管理功能。

方式一:直接添加到目标端(推荐)

在目标端 AICoder Shell 中,将 <source-public-key> 替换为源端 cat 命令输出的完整公钥:

language-bash
install -d -m 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
cross_zone_pubkey='<source-public-key>'
if grep -qxF -- "$cross_zone_pubkey" ~/.ssh/authorized_keys; then
  echo key-ready
else
  printf '%s\n' "$cross_zone_pubkey" >> ~/.ssh/authorized_keys
  echo key-added
fi
unset cross_zone_pubkey

显示 key-readykey-added 后,公钥即可用于连接,无需重启目标端。命令会把公钥追加到文件末尾,不要把手动添加的公钥放到 #### PLATFORM-MANAGED KEYS BEGIN ######## PLATFORM-MANAGED KEYS END #### 标记之间;平台会在实例重启时更新该区域。

方式二:通过平台添加

  1. 按照管理 SSH 公钥的步骤,将源端生成的专用公钥添加到平台。

  2. 在目标 AICoder Shell 窗口左上角点击一键重启图标。重启后,平台会把已登记的公钥写入目标端的 ~/.ssh/authorized_keys

    注意

    平台级 SSH 公钥按账号统一管理,不能只注入本次传输的目标 AICoder。上传后,该公钥会在账号下支持此功能的实例下次新建、重启或改配时注入。选择这种方式时,请把该账号级范围纳入现有的密钥管理流程。一键重启是 AICoder Shell 窗口中的界面操作,不是终端命令。

完成其中一种公钥添加方式后,在目标端 AICoder Shell 的 SSH 连接弹窗中复制完整的 SSH 连接命令。记录以下值:

  • <target-jump-argument>:命令中 -J 后面的完整参数。如果其中包含用户名,也要保留。
  • <target-user>:目标 AICoder 的 SSH 用户名。
  • <target-aicoder-id>:目标 AICoder ID。

然后关闭目标端 Shell 窗口,重新打开源可用区的 AICoder Shell。

目标端连接信息必须来自目标可用区的 AICoder 弹窗,不要复用源端 AICoder ID。有关连接命令各字段的说明,参见SSH 远程连接

验证源端可以访问目标端

在源端启动 tmux

language-bash
tmux new -s cross-zone-transfer

进入新的 tmux 会话后,启动 ssh-agent 并加载专用私钥。后续测试和传输命令都在这个会话中运行。

language-bash
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519_aicoder_cross_zone
command -v rsync
rsync --version

输入私钥口令后,使用目标端弹窗中的连接信息测试 SSH,并再次检查目标挂载点:

注意

源端第一次通过 -J 连接时,OpenSSH 可能分别显示平台跳板机和目标 AICoder 的主机密钥指纹。核对提示中的主机名和 SHA256: 指纹,确认后输入 yes;SSH 客户端会把接受的记录保存到 known_hosts。如果提示内容与预期不同,先重新核对目标端弹窗中的连接信息。详见验证跳板机和目标 AICoder 的主机密钥

language-bash
ssh -J <target-jump-argument> \
  <target-user>@<target-aicoder-id> \
  'hostname && findmnt -T <target-mount-path> && df -h <target-mount-path> && test -w <target-directory> && command -v rsync && rsync --version && echo target-ready'

源端和目标端都应使用 rsync 3.1.0 或更高版本;3.1.0 是兼容性最低要求,应优先使用系统软件源提供的当前维护版本。--inc-recursive 只有在两端均为 rsync 3.0.0 或更高版本时才能使用增量递归算法,--info=progress2 要求发起传输的一端为 rsync 3.1.0 或更高版本。两端版本号不必完全相同。

以上检查和后续传输均在两个 Linux AICoder 之间执行,本地计算机不参与数据路径。命令还应显示目标端主机名、目标存储卷信息和 target-ready。如果认证失败,请先确认专用私钥已经通过 ssh-add 加载、公钥已经写入目标端(通过平台添加时还要确认目标端已重启),并且使用的是目标端弹窗中的完整连接信息。

使用 rsync 传输数据

rsync 支持增量同步和中断后续传,适合跨可用区传输大文件或目录。先只启动一个 rsync 进程:

language-bash
rsync -a \
  --inc-recursive \
  --one-file-system \
  --partial \
  --partial-dir=.rsync-partial \
  --info=progress2 \
  --human-readable \
  -e "ssh -T -o Compression=no -o ServerAliveInterval=30 -o ServerAliveCountMax=6 -J <target-jump-argument>" \
  <source-directory>/ \
  <target-user>@<target-aicoder-id>:<target-directory>/

将所有尖括号占位符替换为实际值。源目录末尾的 / 表示复制该目录中的内容,而不是再创建一层同名目录。

该命令使用以下设置控制资源占用并提高可恢复性:

  • --inc-recursive 逐步构建目录清单,降低超大目录树的文件清单内存压力。
  • --one-file-system 防止递归进入源目录下意外挂载的其他文件系统。
  • --partial-dir 在目标端已经接收到部分文件后保留未完成内容。连接中断后,重新运行同一条命令即可复用这些内容;如果连接在传输开始前中断,目标端可能还没有部分文件,重新运行会正常从头开始该文件。
  • Compression=no 避免为模型、压缩包、图片等通常已压缩的数据重复消耗 CPU。只有源数据以可压缩文本为主且带宽确实成为瓶颈时,才在小范围测试 rsync -z
  • SSH 保活选项可更快识别长时间无响应的连接;它们不会代替 rsync 的续传能力。

单个文件可以大于 AICoder 的 4 GiB 内存,因为 rsync 会分块读取和写入数据,不会把整个文件加载到内存。内存压力主要来自文件条目数量、同时运行的传输进程数,以及需要全局跟踪文件关系的选项。

为避免内存不足(OOM)并保持有效吞吐,请遵循以下做法:

  • 初次传输使用一个 rsync 进程;只有监控确认 CPU、内存和网络均有余量时,才逐步增加并发。
  • 包含数百万个文件时,按一级子目录分批串行传输。单纯增加并发通常会同时放大内存、元数据和 SSH 开销。
  • 不要在主传输中使用 --checksum。该选项会读取两端文件内容,适合最终校验,不适合提高首次传输速度。
  • 默认不要添加 -H-H 用于保留硬链接关系,但需要跟踪更多文件元数据,可能显著增加内存占用。如果业务依赖硬链接,请先用代表性目录测试峰值内存,再决定是否分批使用。
  • -a 不包含 ACL 和扩展属性。如果业务依赖这些元数据,并且两端存储均支持,可按需添加 -A-X 并先做小范围验证。
  • 不要把源文件或临时副本放到 AICoder 系统盘。源路径和目标路径都应位于各自挂载的共享高性能存储卷中。

需要暂时离开时,按 Ctrl+B,再按 D 分离 tmux 会话。返回源端后运行以下命令恢复查看:

language-bash
tmux attach-session -t cross-zone-transfer

tmux 只能防止浏览器或 SSH 断开导致前台命令退出,不能防止 AICoder 重启或实例终止。实例被终止后,请重新创建 tmux 会话、加载私钥并运行同一条 rsync 命令;已经写入目标存储卷的完整文件可以复用,传输开始后由 --partial-dir 保留的部分文件也可以复用。如果中断发生在目标端创建部分文件之前,重新运行会正常从头开始相应文件。

完成最终同步并校验数据

首次传输不应同时删除源数据。把跨可用区复制转换为迁移时,按以下顺序完成切换:

  1. 完成首次批量同步。

  2. 暂停所有会修改源目录的任务。rsync 不会为正在变化的目录创建一致性快照。

  3. 再次运行相同的 rsync 命令,传输首次同步后发生的变化。

  4. 如果需要逐文件内容校验,运行以下只读检查:

    language-bash
    rsync -a \
      --inc-recursive \
      --one-file-system \
      --checksum \
      --dry-run \
      --itemize-changes \
      -e "ssh -T -o Compression=no -o ServerAliveInterval=30 -o ServerAliveCountMax=6 -J <target-jump-argument>" \
      <source-directory>/ \
      <target-user>@<target-aicoder-id>:<target-directory>/

    如果没有列出文件差异,说明源端文件在目标端存在匹配的内容和受 -a 管理的元数据。该检查不会报告只存在于目标端的额外文件。--checksum 会完整读取两端文件,数据量很大时可能耗时较长,但不会再次传输匹配的文件内容。

  5. 让目标工作负载读取目标存储卷,确认数据可用。

  6. 根据业务回滚期和数据保留要求单独清理源数据。

警告

首次传输和最终校验中不要使用 --remove-source-files--delete 或边传边删除脚本。先验证目标数据和目标工作负载,再通过独立、可审计的操作清理源端。

清理传输专用凭证

确认迁移完成且不再需要源端访问目标端后,根据添加方式清理公钥。

直接添加到目标端时

先在源端重新显示并复制完整公钥:

language-bash
cat ~/.ssh/id_ed25519_aicoder_cross_zone.pub

然后在目标端 AICoder Shell 中删除与该公钥完全匹配的行:

language-bash
cross_zone_pubkey='<source-public-key>'
target_auth_keys=~/.ssh/authorized_keys
target_auth_keys_tmp="$(mktemp ~/.ssh/authorized_keys.XXXXXX)"
awk -v key="$cross_zone_pubkey" '$0 != key' "$target_auth_keys" > "$target_auth_keys_tmp" &&
  chmod 600 "$target_auth_keys_tmp" &&
  mv "$target_auth_keys_tmp" "$target_auth_keys"
if grep -qxF -- "$cross_zone_pubkey" "$target_auth_keys"; then
  echo key-still-present
else
  echo key-removed
fi
unset cross_zone_pubkey target_auth_keys target_auth_keys_tmp

显示 key-removed 后,目标端不再接受该专用公钥。

通过平台添加时

从平台 SSH 公钥管理页面删除本次登记的专用公钥,并重启目标端 AICoder,使其重新加载平台当前登记的公钥。如果其他实例也曾加载该公钥,平台会在这些实例各自下次重启时将其移除;可结合现有维护窗口安排重启。

最后,在源端卸载私钥:

language-bash
ssh-add -d ~/.ssh/id_ed25519_aicoder_cross_zone

如果后续也不再使用该密钥对,再删除源端的 id_ed25519_aicoder_cross_zoneid_ed25519_aicoder_cross_zone.pub 文件。不要删除其他用途的 SSH 密钥。