1. 为什么要在 AutoDL 上折腾 OSS:先搞清楚你到底在解决什么问题
用过 AutoDL 的朋友应该都有这种体验:GPU 实例的计费是按小时走的,关机状态下存储虽然便宜,但开机跑训练时,那几块数据盘说贵不贵,说便宜也不便宜。更麻烦的是,你在这个实例上辛辛苦苦下载的预训练模型、清洗好的数据集,一旦实例过期释放,就全没了。想换一台更高配置的机器,或者想从实验室的电脑同步一份数据过去,都得重新传。
OSS(Object Storage Service)在这里解决的就是"数据持久化 + 跨实例共享"的问题。你把它理解成一个不关机的网盘就行,但它专门给程序读写用,API 齐全、带宽充足、价格便宜。把数据集、模型权重、日志这类东西扔到 OSS 上,AutoDL 实例随开随用,每次开机拉取对应数据,关机也不产生额外存储费用——这套流程理顺了,整个训练迭代节奏会舒服很多。
我早期踩过的坑是:把数据直接放在 AutoDL 的数据盘里,实例过期后忘了备份,几天的标注数据和预处理脚本全没了。后来养成习惯,所有重要的东西先上 OSS,实例本地只留临时文件。这篇文章就是把这套流程完整梳理一遍,从注册 Bucket 到命令行工具配置,再到 Python SDK 接入,都是我自己实测过、可以直接照着抄的步骤。
不管你是刚接触 AutoDL 的深度学习初学者,还是已经在上面跑过几个项目、想优化数据管理流程的老手,这篇都适用。代码部分我会给出"复制即用"的版本,同时也会解释每个参数的含义,避免你改两行就报错。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 前置准备:没有这些东西,后面全是白搭
2.1 开通 OSS 服务并创建 Bucket
先去阿里云控制台开通 OSS,这个流程没什么好说的,实名认证之后按引导走就行。重点说一下创建 Bucket 时要选对配置,因为创建之后有些参数改起来很麻烦。
首先是地域,也就是 Region。这个选择直接决定了你后面访问 OSS 的 Endpoint 地址,也影响数据读写速度。如果你主要在 AutoDL 上跑训练,而 AutoDL 的上海地域节点用的人最多,那 Bucket 的地域就尽量选华东2(上海),这样内网互通有优势。如果你用 AutoDL 的其他地域节点,比如北京、广州,那就选对应的地域。
地域选好之后再选读写权限。这里有一个非常容易忽略的细节:如果你跑的是公开数据集下载后转存到 OSS,或者需要和别人的账号共享某个文件,可以考虑"公共读";但如果里面放的是自己的模型权重、未发布的数据集,老老实实选"私有"。选"私有"之后,访问时需要用 AccessKey 签名认证,后面命令行工具和 SDK 配置都是基于这个来的。
存储类型这块,训练数据和模型文件建议直接用"标准存储"。低频访问和省冷存储虽然单价低,但有最低存储时长和取回费用,实测下来省不了多少,反而引入额外的复杂性。我的原则是:数据流经 OSS 只是为了中转和备份,标准存储最省心。
2.2 拿到 AccessKey ID 和 AccessKey Secret
AccessKey 是访问 OSS 的钥匙,一定要保管好。在阿里云控制台右上角头像菜单里找到"AccessKey 管理",创建一个新的 AccessKey(或者使用子账号的 AccessKey),创建完成之后会一次性显示 AccessKey ID 和 AccessKey Secret,这个弹窗关掉之后就再也看不到完整的 Secret 了,所以第一时间复制保存到密码管理器里。
这里有一个我反复强调的安全习惯:不要在代码里硬编码 AccessKey。尤其是你可能会把代码推到 GitHub 或者分享给别人,一旦 Secret 泄露,别人就能用你的账号往 OSS 里传东西,账单直接飞到你的头上。建议用环境变量的方式传入,后面我会演示。
3. 工具选型:三种接入方式到底选哪个
3.1 ossutil 命令行工具:日常操作首选
ossutil 是阿里云官方提供的命令行工具,用起来和 Linux 下的 cp、ls 很像,支持批量上传、下载、删除、同步等操作。如果你只想把 AutoDL 上的数据传到 OSS,或者从 OSS 拉数据下来,这个工具是最直接的。
安装方式很简单,在 AutoDL 终端里执行官方提供的安装命令:
bash复制curl -L https://gosspublic.alicdn.com/ossutil/v2/ossutil-v2-linux-amd64.zip -o ossutil.zip
unzip ossutil.zip
sudo mv ossutil-v2-linux-amd64 /usr/local/bin/ossutil
装完之后配置凭证,ossutil 支持交互式配置,执行下面这条命令,然后按提示输入 AccessKey ID、AccessKey Secret、Endpoint:
bash复制ossutil config
Endpoint 的格式要注意,它是 oss-cn-shanghai.aliyuncs.com 这种形式,不带 https:// 前缀,也不用写 https。如果你在上海地域创建了 Bucket,那 Endpoint 就是 oss-cn-shanghai.aliyuncs.com。如果是北京,对应 oss-cn-beijing.aliyuncs.com,地域和 Endpoint 的对应关系在官方文档里有一张表,你可以按需查。
3.2 Python SDK:训练代码里无缝接入
如果你的需求是在训练脚本里实时读写 OSS,比如每个 epoch 保存一次 checkpoint 到 OSS,或者从 OSS 流式读取数据,那用 oss2 这个 Python SDK 会更顺手。安装就一条命令:
bash复制pip install oss2
SDK 的使用思路和命令行工具不一样,它不是"复制粘贴一条命令"就能搞定的,需要在你自己的代码里写几行初始化逻辑。很多人一开始搞混了命令行和 SDK 的关系,其实两者是互补的:手动传数据用命令行,代码周期性的数据操作用 SDK。
3.3 ossfs:把 OSS 挂载成本地硬盘
还有一个工具叫 ossfs,可以把 Bucket 挂载到 AutoDL 实例的某个目录下,之后你用 ls、cp、cat 操作这个目录,就相当于直接操作 OSS。听起来很方便,但实际体验并没有那么完美。OSS 毕竟是对象存储,不是文件系统,随机读写和小文件多的情况下性能很差,而且挂载不稳定的时候会出现文件句柄占用、读写出错的问题。
我的建议是:中小文件用 ossutil 手动同步,训练过程的数据读取不要走 ossfs,而是用 SDK 或先把数据拉到本地再读。ossfs 更适合你用 Jupyter Notebook 临时翻看 OSS 里的文件结构时用,省得一条条命令去 list。
4. 实操过程:从 AutoDL 命令行到 OSS 的完整流程
4.1 安装 ossutil 并完成配置
自己在 AutoDL 上实操的时候,强烈建议把安装命令写进一个 Shell 脚本里,这样以后在新的实例上初始化环境时,一条命令就能搞定所有配置。先手动执行一遍,确认每一步没问题之后再固化成脚本。
安装完成之后,验证一下是否装好:
bash复制ossutil --version
能正常输出版本号,说明安装这一步没问题。接着配置凭证,我推荐不要用交互式 ossutil config,而是直接用非交互方式写配置,这样方便脚本化:
bash复制ossutil config --endpoint oss-cn-shanghai.aliyuncs.com --access-key-id YOUR_ACCESS_KEY_ID --access-key-secret YOUR_ACCESS_KEY_SECRET
执行完之后,凭证默认保存在 ~/.ossutilconfig 文件里。你可以打开看看,里面就是明文存储的 AccessKey,所以这个文件本身也要注意保护,不要在公开的地方泄露。
配置完成之后,先用一条最简单的命令测试连通性,列出 Bucket 里的文件:
bash复制ossutil ls oss://your-bucket-name/
如果你的 Bucket 是新建的空的,这条命令不会报错,也不会输出内容。如果报错,重点检查 Endpoint 是否正确、AccessKey 是否有权限、Bucket 名称是否拼对。我遇到过朋友把 Bucket 名字大小写写错的情况,OSS 的 Bucket 名称要求全局唯一,而且必须小写,这个很容易忽略。
4.2 上传数据:从 AutoDL 实例到 OSS
数据上传是最常见的操作。先说最简单的单文件上传:
bash复制ossutil cp /root/autodl-tmp/data.zip oss://your-bucket-name/datasets/
这里 /root/autodl-tmp/data.zip 是你 AutoDL 实例上的文件路径,oss://your-bucket-name/datasets/ 是 OSS 上的目标路径。拷贝完成之后,建议用 ls 确认一下文件确实上传成功:
bash复制ossutil ls oss://your-bucket-name/datasets/
如果是一个目录,直接加 -r 递归参数:
bash复制ossutil cp -r /root/autodl-tmp/dataset_dir oss://your-bucket-name/datasets/
这个命令会把 dataset_dir 整个目录递归上传到 OSS。此时要注意一个细节:如果你 /root/autodl-tmp/dataset_dir 目录里有很多小文件,比如几万张图片,那么上传会比较慢,而且 OSS 控制台里看起来文件数很多。建议打包成单个压缩文件再传,效率会高很多。
我自己的习惯是传大目录前先压缩:
bash复制cd /root/autodl-tmp && tar -czf dataset.tar.gz dataset_dir
ossutil cp dataset.tar.gz oss://your-bucket-name/datasets/
压缩和解压都会消耗一些时间和磁盘空间,但综合来看比传几万个小文件要快。尤其是第一次搞大规模数据集的时候,这个经验能帮你省下很多时间。
4.3 下载数据:从 OSS 到 AutoDL 实例
下载和上传是对称的,只是源路径和目标路径换了一下:
bash复制ossutil cp oss://your-bucket-name/datasets/data.zip /root/autodl-tmp/
递归下载目录同样加 -r:
bash复制ossutil cp -r oss://your-bucket-name/datasets/ /root/autodl-tmp/
下载大文件或者其他耗时操作时,建议用 screen 或者 tmux 挂起任务。AutoDL 的终端连接有时候会断开,一旦断开,正在执行的 cp 任务可能中断,文件传了一半还得重来。把命令放到后台会话里跑,断线也不影响:
bash复制tmux new -s upload
ossutil cp -r /root/autodl-tmp/dataset_dir oss://your-bucket-name/datasets/
# Ctrl-b 然后按 d 脱离会话,任务继续跑
重新查看任务状态:
bash复制tmux attach -t upload
这里多提一句:ossutil 上传大文件是支持断点续传的,意外中断之后重新执行相同的上传命令,ossutil 会检测到本地已有片段的记录文件,继续上传未完成的部分,不需要从头再来。不过这种机制依赖本地临时文件,如果 AutoDL 实例被释放了,临时文件也会没,断点续传也就失效了,所以关键任务在实例释放前完成上传还是必要的。
4.4 同步操作:让本地和 OSS 保持一致
你更新了数据集、脚本、模型文件,希望 OSS 同步也更新,"全量重新传一次"显然不划算。ossutil 提供 sync 命令,只增量传输变化的部分:
bash复制ossutil sync /root/autodl-tmp/logs oss://your-bucket-name/logs/
sync 命令默认以上传方为准,如果本地文件比 OSS 上同名文件新(通过修改时间判断),就会覆盖上传。这个命令在做实验日志定期备份时特别好用,训练完了把最新的日志目录同步上去,不用管哪些文件是旧的。
需要注意,sync 命令的源目录末尾不要加斜杠,目标目录末尾要不要加斜杠,语义略有差异。我的经验是统一都不加斜杠,路径写完整,避免歧义。
5. Python SDK 接入:训练脚本里的 OSS 读写
5.1 初始化 Bucket 对象
如果你要在训练脚本里直接操作 OSS,需要用到 oss2 SDK。基础用法是初始化一个 Bucket 对象,所有文件操作都通过这个对象完成:
python复制import oss2
# 你的 AccessKey 信息
auth = oss2.Auth('YOUR_ACCESS_KEY_ID', 'YOUR_ACCESS_KEY_SECRET')
# Endpoint 不带 https:// 前缀
endpoint = 'oss-cn-shanghai.aliyuncs.com'
# 你的 Bucket 名称
bucket_name = 'your-bucket-name'
bucket = oss2.Bucket(auth, endpoint, bucket_name)
这一步初始化不需要网络请求,真正发请求是在你调用具体方法的时候。所以即使 Endpoint 配错了,第一句代码也不会报错,直到上传/下载时才报错。
更安全的做法是用环境变量传入 AccessKey,不要在代码里硬编码:
python复制import os
import oss2
auth = oss2.Auth(os.environ['ALIYUN_OSS_ACCESS_KEY_ID'], os.environ['ALIYUN_OSS_ACCESS_KEY_SECRET'])
bucket = oss2.Bucket(auth, 'oss-cn-shanghai.aliyuncs.com', 'your-bucket-name')
在 AutoDL 实例里设置环境变量:
bash复制export ALIYUN_OSS_ACCESS_KEY_ID="your_access_key_id"
export ALIYUN_OSS_ACCESS_KEY_SECRET="your_access_key_secret"
或者写入 ~/.bashrc,每次登录自动加载。
5.2 常用操作:上传、下载、删除、列举
上传一个文件:
python复制# put_object_from_file:从本地文件上传到 OSS
result = bucket.put_object_from_file('models/epoch_10.pth', '/root/autodl-tmp/epoch_10.pth')
# 检查返回的状态码,200 表示成功
if result.status == 200:
print("上传成功")
下载一个文件到本地:
python复制result = bucket.get_object_to_file('models/epoch_10.pth', '/root/autodl-tmp/epoch_10.pth')
if result.status == 200:
print("下载成功")
删除文件:
python复制bucket.delete_object('models/epoch_10.pth')
列举 Bucket 里的文件:
python复制for obj in oss2.ObjectIterator(bucket, prefix='models/'):
print(obj.key)
这里的 prefix 参数很有用,相当于目录前缀过滤。OSS 没有真正的目录概念,models/epoch_10.pth 就是一个完整的 key,但通过前缀过滤可以模拟目录浏览的效果。很多人在 OSS 控制台里看到了"文件夹",以为 OSS 支持目录,其实那只是控制台对 key 的展示方式,底层仍然是扁平结构。
5.3 训练过程自动保存 checkpoint 到 OSS
实际训练中,我会在每次保存 checkpoint 的代码里加一个同步步骤,把本地模型文件上传到 OSS。核心逻辑很简单,但有几个细节需要考虑:
- 上传是否要阻塞训练?分片上传大文件上传需要几秒到几十秒,如果每轮都同步上传,训练节奏会受影响。我一般会开一个后台线程,上传完成之后再通知主线程继续。
- 是否只保留最新 N 个 checkpoint?防止 OSS 上的文件无限增长,定期清理旧版本。
下面是一个简化版本,用线程池来做异步上传:
python复制import threading
import oss2
auth = oss2.Auth(os.environ['ALIYUN_OSS_ACCESS_KEY_ID'], os.environ['ALIYUN_OSS_ACCESS_KEY_SECRET'])
bucket = oss2.Bucket(auth, 'oss-cn-shanghai.aliyuncs.com', 'your-bucket-name')
def upload_to_oss(local_path, remote_key):
try:
bucket.put_object_from_file(remote_key, local_path)
print(f"上传成功: {remote_key}")
except Exception as e:
print(f"上传失败: {remote_key}, 错误: {e}")
# 保存 checkpoint 后调用
upload_thread = threading.Thread(target=upload_to_oss, args=(
'/root/autodl-tmp/checkpoints/epoch_50.pth',
'checkpoints/epoch_50.pth'
))
upload_thread.start()
这里要注意:上传线程是非阻塞的,如果你的训练脚本在主线程结束后马上退出,上传可能还没完成。所以在程序结束前最好 join 一下所有上传线程:
python复制upload_thread.join()
5.4 SDK 初始化失败、超时怎么排查
大部分初学者遇到的问题是 oss2.exceptions.ServerError。最常见的错误码是 AccessDenied,说明身份认证没通过或者权限不足。逐项排查:
- AccessKey ID 和 Secret 是否对应同一个账号?注意前 16 位和后 32 位的完整性,不能有多余空格。
- Bucket 的权限是否允许当前账号写入?如果是私有权限,需要在初始化时携带认证信息,默认就带上了。
- Endpoint 是否正确?华东2上海对应的 Endpoint 是
oss-cn-shanghai.aliyuncs.com,如果你 Bucket 创建在北京,却用上海的 Endpoint,会提示 Bucket 不存在或者NoSuchBucket。
还有一个容易踩坑的点:OSS 的 Bucket 名称在阿里云范围内是全局唯一的,你在上海创建了一个叫 my-bucket 的 Bucket,在北京地域就不能再创建同名 Bucket。如果创建 Bucket 时提示名称已被占用,换一个更独特的名字即可。
6. 常见问题速查与避坑技巧
6.1 上传速度慢,如何提速
上传 OSS 的速度受限于 AutoDL 实例的公网带宽,这在很多实例上都不是很高。如果你上传的是几个 GB 的大文件,建议用 ossutil 开启分片并发上传,默认就自动开启了。你也可以通过 --parallel 和 --part-size 参数控制并发数和分片大小。
实际经验是:上传大文件时,单个分片设置为 16MB 或者 32MB,并发数 4 到 8,速度通常能跑到接近带宽上限。但设置太高也可能触发限流,如果观察到上传失败重试增多,适当降低并发数。
另外,一个思路是把 AutoDL 实例切换到和 OSS 相同地域的节点,通过内网地址访问。比如你 Bucket 在上海,AutoDL 实例也选上海地域,那么 Endpoint 可以用 oss-cn-shanghai-internal.aliyuncs.com,走内网,既快又免流量费。这个内网地址只在同一个地域的机器上才能访问,用公网地址访问内网 Endpoint 会连不上。
6.2 清理 OSS 文件,注意版本管理和生命周期
有时候你删除了 OSS 里的文件,但发现计费还在增长,很可能是开启版本控制导致的,文件的历史版本还占着空间。如果你不需要版本控制,直接在 Bucket 的"基础设置"里关掉,并配置生命周期规则,自动清理过期文件。
AutoDL 实例上的数据集,如果只是临时用一下,也不用着急传 OSS 永久保存,先想清楚一下:是不是可以在 OSS 上建一个生命周期规则,设置 30 天后自动清理 tmp/ 前缀下的文件?这样临时文件不会堆积,又不用手动清理。
配置生命周期规则时,前缀要写准确,比如 tmp/,避免误删正式数据。
6.3 AccessKey 泄露了怎么办
发现 AccessKey 泄露,第一步是立刻到阿里云控制台禁用或删除这个 AccessKey,然后创建一个新的。禁用之后,旧 Key 立刻失效,不需要等。
如果泄露的 Key 已经被恶意使用,产生了费用,可以在费用中心核实账单,并提交工单申请处理。但说实话,防患于未然远比事后处理省心。我的习惯是:AccessKey 只在 AutoDL 的环境变量里配置,不写进代码,不传到公开仓库,不截图发到群里。
6.4 AutoDL 实例释放后,数据盘怎么办
AutoDL 实例释放,数据盘内的文件会一起销毁。如果你的训练数据、模型文件都在数据盘里,释放前必须同步到 OSS 或者其他持久化存储。
有一个更彻底的办法:把整个项目目录做成一个压缩包,连同依赖清单一起上传 OSS。新实例启动后,下载、解压、安装依赖,几分钟就能恢复到之前的工作环境。我每次跑完一个大型实验,都会把代码、conda 环境导出文件、checkpoint 这三样东西打包上 OSS,这样即使实例过期了,也不会觉得心疼。
7. 从"能跑通"到"用得顺手":我的几条经验
最后分享几点我自己的使用习惯,不一定适合所有人,但确实帮我省了很多事。
第一,Bucket 命名和目录规划要提前想清楚。我见过有人把所有文件都堆在 Bucket 根目录下,几个月后文件一多,列表拉半天。最好是按项目分目录:project_name/datasets/、project_name/checkpoints/、project_name/logs/。这样排查问题、清理过期数据都方便很多。
第二,给不同用途的数据配置不同的权限。公开的预训练模型下载地址可以设成公共读,方便其他实例直接拉取;私有数据集和模型权重保持私有,不要图省事全设成公共读。你永远不知道哪个文件会被搜索引擎收录或被人猜到,公共读就代表任何人知道 URL 就能下载。
第三,自动化脚本里要做好错误处理。像上传 checkpoint 这种操作,如果网络抖动导致上传失败,训练脚本可能照样继续,你以为同步成功了,实际上 OSS 上没有文件。我写了简单的日志记录和重试机制,每次训练结束检查一遍上传日志,确保没有失败的记录。
第四,费用控制。OSS 的存储费用很便宜,但流量费用不低。如果你频繁从 OSS 下载大文件到不同地域的实例,流量费可能比存储费还高。尽量让 AutoDL 实例和 OSS 在同一个地域,走内网访问,能省下一大笔钱。另外,临时没用的数据及时删除,堆在 OSS 里几个月不看,也是一种浪费。
OSS 配置这件事本身不复杂,真正麻烦的是把整套流程嵌入到你自己的实验流程里,并且形成习惯。配置好一次,后面每次开新实例,装好 ossutil、配好环境变量,你的所有数据都在手边,那种感觉还是很踏实的。
