← 返回资讯

RunPod 存储怎么选:容器盘、Volume 与 Network Volume 的取舍

2026-09-15

有一类事故几乎每个第一次租 GPU 的人都会遇到一遍:机器开起来,pip install 装了一堆依赖,从 Hugging Face 拉了十几 GB 权重,微调跑到一半先停机省点钱,第二天开机一看——环境没了,权重没了,只剩一个干净的容器。不是平台出故障,是这些东西当初落在了一个「停机就清空」的目录里。

RunPod 的存储这件事,坑不在复杂,在于它的三种存储长得很像,但持久化边界完全不同,而且一部分选择在「创建 Pod」那个表单里就一次性定死了,事后改要么重置要么重建。下面按官方文档的口径把这三层逐一拆开。涉及具体单价的部分本文一律只讲机制——那类数字以控制台当时显示的为准,抄进文章过两个月就是错误信息,计费本身另有一篇专门算:RunPod 计费机制拆解。如果你还没搞清 Pod 和 Serverless 这两种形态的差别,建议先看RunPod 是什么再回来。

一、三种存储的边界:先把这张表背下来

Pod 侧的三种存储,文档给的对照是这样的:

Container diskVolume diskNetwork volume
停机 / 重启后丢失保留保留
删除 Pod 后丢失丢失保留(独立存在)
挂载位置系统托管默认 /workspace/workspace(顶替 volume disk)
性能最快(本地)快(本地)可变(网络)
能否跨 Pod 共享可以
扩缩容可调只能增不能减可调
适合放操作系统、临时文件、缓存模型、数据集、checkpoint共享数据、需要带着走的存储

这张表里最值钱的是第一列和第二列的区别。很多人把「停机后还在」直接理解成「持久化」,于是把成果放在 volume disk 上就安心了——但 volume disk 的生命周期是跟着 Pod 的租期的,文档写得很直白:数据在停机和重启之间存活,Pod 一旦被终止(terminate)就删除。停机(stop)和终止(terminate)在控制台里是两个按钮,代价差着一个数据集。

二、Container Disk:停机即丢,这是头号坑

Container disk 是 Pod 启动时创建、停机时清空的临时空间。文档给它的定位是操作系统和会话数据,用途写的是临时文件、缓存、以及「不需要跨会话保留」的数据。它的挂载位置是系统托管的,也就是你的容器根目录——用 df -h 看的话,对应的是那个 overlay 文件系统。

问题就出在「容器根目录」这四个字上。你 SSH 进去之后默认落在 home 目录,pip install 装到系统 site-packages,Hugging Face 的缓存默认也在 home 下面——这些位置全都在 container disk 上,全都是停机就没。真正能活下来的只有 /workspace 这一棵子树。所以第一条纪律不是「记得备份」,而是把所有你不想重做的东西显式地挪到 /workspace 里去,包括缓存目录的环境变量。

Serverless 侧的行为是同一套逻辑的更极端版本。文档的说法是:container disk 只在 worker 运行期间存在,worker 停止或缩容时数据丢失;handler 函数里保存的所有数据,默认全都落在 container disk 上。Serverless 的 worker 是按需起、空闲关的,也就是说这个「停机」不是你手动点的,而是伸缩策略随时会替你点。想让数据活过一次缩容,就必须显式写到网络卷或者外部对象存储上。这一段和 worker 生命周期是连在一起看的:RunPod Serverless 部署推理服务

还有一句容易被忽略的成本口径:Serverless 的 container disk 费用是包含在 worker 运行成本里的,不单独计费。这意味着它便宜不是因为它慢,而是因为它随时会消失——你为它付的钱本质上是算力时间。

三、Network Volume 必须创建时挂载:这条约束比听起来严重

Network volume 是三层里唯一独立于 Pod 存在的那一层。可以挂给多个 Pod、在机器之间搬、删掉 Pod 数据还在,标准档和高性能档两个档位(高性能档的吞吐和 IOPS 按文档说法有成倍提升,具体倍数以官方页面为准)。听起来是「更好的那个选项」,但它带着三条硬约束。

第一,必须在创建 Pod 的时候挂上,事后既不能挂也不能卸。 文档这句话是加在 Note 里的,读的时候很容易滑过去,实际后果是:你开机跑了三天,突然发现需要把结果共享给另一台机器,这时候没有「加挂一个网络卷」这个动作可选,只能重建 Pod 或者走数据搬运。团队里只要有一个人开机时忘了勾,这台机器在整个生命周期里都是孤岛。

第二,挂上之后它会在 /workspace 顶替掉 volume disk。 不是并存,是替换。所以你的脚本里那些写死 /workspace/... 的路径,在挂网络卷和不挂网络卷的两台机器上指向的是完全不同的两块盘。这个坑的隐蔽之处在于它不报错——路径存在、能写入、就是东西不在你以为的地方。

第三,网络卷会把部署锁在它所在的数据中心。 这条写在 Serverless 存储文档的 Behavior notes 里:网络卷会把部署约束到该卷所在的数据中心,可能影响 GPU 可用性。翻译一下就是,你为了持久化挂了个网络卷,代价是从此只能在那一个机房里抢卡。赶上那个机房的目标机型紧张,你要么等,要么换机型,要么把数据搬到另一个区去——而搬数据本身又要走一遍第一条约束。选机房这件事因此不只是延迟问题,GPU 云租用那篇里讲的可用性判据在这里会被存储位置反向绑定。

顺带记一个路径差异:Pod 侧网络卷挂在 /workspace,Serverless 侧文档里给的挂载点是 /runpod-volume。同一个东西两个名字,写 handler 的时候别照抄 Pod 的脚本。

还有一个和网络卷容易混的东西:Serverless 的模型缓存功能用的挂载路径也是 /runpod-volume/,但文档专门澄清了——缓存模型的加载速度明显快于从网络卷加载同一个模型,两者不是一回事。而且文档提到模型下载期间不计 worker 时间费用。也就是说「为了加快冷启动而挂网络卷存权重」这个直觉,在 Hugging Face 托管的模型上可能不是最优解。

四、加密只覆盖一层:跨 Pod 共享和加密凑不到一起

这是全文我认为最该在方案阶段就定下来的一条。文档的口径是:

  • Volume disk 可以加密。创建 Pod 时勾选 Encrypt volume,卷在宿主机上静态加密,只有你的 Pod 能访问数据。
  • 密钥不可取回,也不支持自带密钥(BYOK)。RunPod 替你保管,并在运行时传给你的容器镜像。
  • Container disk 和 network volume 都不能加密

三条叠起来的结论很硬:「静态加密 + 独立于 Pod 持久 + 跨 Pod 共享」这个组合,在官方文档给出的能力里凑不出来。 你要加密就只能用 volume disk,而 volume disk 不能共享、也活不过 Pod 被删;你要共享就只能用 network volume,而它不能加密。如果你的合规要求是「所有落盘数据必须加密」,那网络卷这条路在立项时就该被划掉,连带着上面那些共享数据集、多 Pod 协作的方案也一起划掉。这个约束不是配置问题,绕不过去。

密钥不可取回这一条也值得单独想一下:它意味着加密的作用范围是「防宿主机侧的静态读取」,不是「你自己掌握密钥的那种加密」。做合规答辩的时候,这两者在很多审计口径下不等价。

五、Edit Pod 会重置什么:一个「只是想加点盘」的动作

改容量的操作路径文档写的是:Pods 页面 → Pod 旁边的三个点 → Edit Pod → 调整 container 或 volume disk 大小 → Save。其中 volume disk 的容量只能增不能减

但紧跟着有一条加粗警告:编辑一个运行中的 Pod 会把它完全重置,抹掉所有不在 /workspace 里的数据。 也就是说「我只是想把盘加大一点」这个看起来无害的动作,会顺手清掉你装在系统目录里的全部环境。第二节讲的那些默认落在 container disk 上的东西,会在这一步一起消失。

这条我建议直接写进团队操作规范:改盘之前先确认 /workspace 外面没有你还要的东西。 顺序上更省事的做法是,第一次开机就把容量按预期用量的上限开够——反正 volume disk 后面也只能加不能减,一开始开小了并不省事。

和容量有关的还有个实用排查手法,文档在 storage full 那页给了几条命令:df -h 看整体用量(看 overlay 那行就是容器盘)、du -sh . 看当前目录、以及揪出最大文件的组合式:

find /workspace -type f -exec du -h {} + | sort -rh | head -n 10

另外有个反直觉的坑:在 JupyterLab 界面里删掉的文件可能只是进了隐藏回收站,盘并没有空出来。文档给的排查方向是去看 $HOME/.local/share/Trash//workspace/.Trash* 这两个位置。碰到「明明删了但还是满」的时候先查这里,比对着 df 干瞪眼有用。

六、数据进出的四种方式

文档列的四种方法,各自的适用面不同:

方式适合前置条件
runpodctl零星的小到中等文件Pod 上已预装,本地要装
SCP常规文件操作,不限大小配好 SSH
rsync大数据集、增量同步SSH + 装 rsync,本地需 Linux 或 WSL
Cloud Sync备份、多环境共享目标云厂商侧配好凭据

runpodctl 的机制是一次性口令码:源端 runpodctl send 文件名,它回一串形如 8338-galileo-collect-fidel 的码,目标端 runpodctl receive 那串码。不用配 SSH,适合「就传一个文件」的场合。

rsync 是大数据集的首选,理由是增量——文档里那两段示例输出很能说明问题:第一次传是完整拷贝,第二次同一个文件只发了很少的字节,因为已存在的文件不会重传。常用标记是 -a 保留权限时间戳、-v 详细输出、-z 传输时压缩(省带宽费 CPU)、-p 显示进度、-d 删除目标端源端已不存在的文件。有个细节值得记:目录路径带不带尾斜杠含义不同,带斜杠是传目录内容,不带是传目录本身。

Cloud Sync 走的是 Pod 页面上的 Cloud Sync 按钮,文档支持的目标是 Amazon S3、Google Cloud Storage、Microsoft Azure Blob、Backblaze B2、Dropbox。认证方式各不相同(S3 是 Access Key + Secret,GCS 是服务账号 JSON,Azure 是账户名 + 密钥,B2 是应用密钥,Dropbox 是 OAuth 令牌)。有一个容易搞错的点文档专门标了:Cloud Sync 对接的是 Google Cloud Storage,不是 Google Drive,Drive 得走另外的路子。

Serverless 侧还多一个选项:S3 兼容存储。用你自己的凭据连外部对象存储,适合超出 API 载荷限制的大文件,存储在 RunPod 基础设施之外、账单归你自己的服务商。请求体里传的是 s3Config,字段是 accessIdaccessSecretbucketNameendpointUrl。注意文档的提醒:平台只负责把这些信息传给你的 worker,真正的读写逻辑要你自己在代码里写,它不是一个自动挂载。

最后是官方自己的一句免责,值得原样记住:RunPod 不是为长期云存储设计的,文档建议把关键数据备份到本地或专门的云存储服务商。

七、存储计费的机制:停机不等于不花钱

单价一律不写,但这几条机制会决定你账单的形状:

  • 存储是独立计费项,不包含在算力里(Serverless 的 container disk 例外,它算在 worker 运行成本里)。
  • 计费粒度不同:文档的口径是 container disk 与 volume disk 按秒计费,network volume 按小时计费。
  • 停机后 volume disk 还在计费,而且停机状态的单价档位高于运行状态(这是反直觉的一条,方向就是这样,具体数额看官方页面)。Container disk 停机后不计费——因为它已经被清空了。
  • 想真正停止计费,得把 Pod 删掉,而删掉 volume disk 上的数据就一起没了。这就是为什么第一节那张持久化表必须先看懂再决定怎么省钱:「停机省钱」这个动作只省掉算力,盘照旧。
  • savings plan 这类长期承诺只覆盖 GPU 算力,不覆盖存储,存储按标准价走,并且在 Pod 停机期间继续累积。
  • 余额耗尽时的行为按有没有网络卷分岔:文档写的是余额见底时 Pod 会被自动停止,有网络卷的数据被保留,没有网络卷的会被终止且数据不可恢复。这条是把「存储选型」和「账户风控」绑在一起的——挂不挂网络卷在这一刻的差别是数据还在还是永久没了。
  • 另有一条对你有利的:宿主机不可用时不计费

八、五条操作纪律

把上面的东西压成五条能贴在墙上的:

  1. 凡是不想重做的东西,一律显式放进 /workspace 包括改 Hugging Face 缓存目录的环境变量。默认位置全在 container disk 上,停机即清空。
  2. 开机表单里三件事一次定死:用不用网络卷、要不要加密、容量开多大。 网络卷事后不能挂也不能卸、加密只能创建时勾、volume disk 只能增不能减——这三个都没有「以后再说」这个选项。
  3. 停机(stop)和终止(terminate)当成两个风险等级不同的动作对待。 停机留着 volume disk 也留着账单,终止连数据一起清。别在控制台里凭肌肉记忆点。
  4. 改盘之前先确认 /workspace 外面没有你还要的东西。 Edit Pod 会把运行中的 Pod 完全重置。要装环境就装进工作区,或者干脆固化到镜像里——镜像里放什么不放什么的取舍见RunPod 模板与自定义镜像
  5. 关键数据在平台之外再存一份。 这是官方自己的建议,不是我加的。用 rsync 往本地拉,或者用 Cloud Sync 往对象存储推,选一个做成定时任务。

九、这些判断哪里可能不作数

先说本文的边界:以上全部来自 RunPod 官方文档的文字,我没有账号逐项验证控制台的实际行为。有几处文档本身说得不够细,我不替它补:网络卷从「删掉最后一个挂载它的 Pod」到「真正停止计费」之间的结算细节、跨数据中心搬网络卷的具体操作代价、加密卷在宿主机维护或迁移时的行为——这些官方文档没有明确说明,以控制台和账单实际显示为准。网络卷本身另有一页独立文档,本文引用的是存储总览、Serverless 存储总览与计费页里给出的口径。

再说什么情况下这套取舍根本不重要。如果你的任务是「开机、跑完、结果拉走、删机」的一次性形态,三种存储的区别对你几乎为零——全放 container disk 都行,反正你也不打算让它活过今晚。这类负载纠结存储布局是浪费时间,把精力放在抢到卡和跑完上更实在。

真正需要把这一篇读两遍的是两种人:一是要长期维护一个数据集或者模型库、多人多机共用的团队,你们会同时撞上「网络卷不能事后挂」和「网络卷不能加密」这两面墙,而且撞的时候通常已经开机了;二是有合规要求的团队,加密只覆盖 volume disk 这一条会直接改变你的架构选择,越晚发现返工越大。

最后一句不太好听的:存储这件事上最贵的从来不是盘费,是「以为存下来了但其实没有」的那次返工。第一次开机时花十分钟做件小事就能挡掉大半——开个最小配置的 Pod,把依赖装在你打算用的位置,停机再开机,看看还在不在。这个验证比读任何文档都快,包括这一篇。

算完账发现自建推理不划算?

先用托管端点把业务跑起来,量上来了再回头算自建的平衡点。

去试用

这个页面有问题?

提交时会附带当前页面地址和浏览器信息,帮助我们定位问题。不填联系方式即为匿名。