
兼容要落到哪一层才算数
一套跑了三年的 S3 工具链,多半长这样:aws-cli 脚本每晚把数据库 dump 推到桶里,mc 负责日常的桶和生命周期管理,rclone 在两个机房之间同步构建产物,应用侧用 AWS SDK 直连。要换掉底层存储的时候,团队问的第一个问题几乎都一样:这些脚本要不要改。
答案取决于"兼容"落到了哪一层。只喊一句"兼容 S3"意义不大。有人迁移之后才发现,分片上传中断后的 abort 清理、对象锁的合规模式,还有预签名 URL 在边界条件下的行为,和原来那套对不上,备份脚本静默失败好几天没人察觉。所以务实的做法,是找一份跑过测试的兼容性矩阵,逐项对一遍。
455 项通过,17 项规划中
RustFS 把"S3 兼容"做成了可执行的测试门禁,结果公开在 docs.rustfs.com/en/reference/s3-compatibility。基准用 Ceph 项目维护的开源测试套件 s3tests,它测的是 S3 API 的通用兼容行为,任何实现 S3 类 API 的服务都能拿来跑,不是只对 Ceph 自己的实现。
- 455 项标准用例在默认兼容门禁下通过
- 5 项生命周期行为在专用生命周期门禁下通过
- 17 项标准行为仍标记为规划中(planned)
- 270 项被显式排除(excluded)

455 是测试用例数,跟 API 总数是两回事。一个接口会按正常、异常、边界输入拆成多条用例,别拿它去对 AWS 的接口总数。
要留意最后一项。被排除的 270 项分三类:厂商特定行为(只有某个云平台才有的扩展接口)、有意不支持的产品行为(比如前文说的 ACL 授权)、不在默认门禁覆盖范围内的边角用例(比如分片上传列举的部分边界场景)。所以"100% 兼容"指的是核心 S3 数据平面上的可执行测试集合全部通过;它没有宣称 AWS 每一个私有行为都支持。这个区分对迁移方案很重要:建桶、上传、列举,连同版本控制、对象锁定和预签名 URL,这一批常用操作靠的是跑过的测试,不只是一句兼容承诺。

只改 endpoint-url,aws-cli 和 rclone 就能接上
被测试覆盖到的能力,落到操作上就是改端点不改代码。RustFS 在主监听器上启用 S3 API,用 AWS Signature Version 4 签名,默认路径式寻址,现有客户端把 endpoint-url 指过来即可。
bash
aws --endpoint-url http://localhost:9000 \
--region us-east-1 \
s3 mb s3://my-bucket
aws --endpoint-url http://localhost:9000 \
--region us-east-1 \
s3 cp ./model.pt s3://my-bucket/model.pt
mc alias set rustfs http://localhost:9000 "$RUSTFS_ACCESS_KEY" "$RUSTFS_SECRET_KEY"
mc mb rustfs/my-bucket
mc cp ./data.parquet rustfs/my-bucket/
rclone 是同一套逻辑,在 rclone.conf 里加一段:
ini
[rustfs]
type = s3
provider = Other
endpoint = http://localhost:9000
access_key_id = YOUR_ACCESS_KEY
secret_access_key = YOUR_SECRET_KEY
force_path_style = true
原来的 rclone sync 命令原样跑,远端写成 rustfs:bucket 就行。请求从客户端到落盘的完整链路是这样:

RustFS 默认用路径式(http://endpoint/bucket/key)寻址,不需要任何 DNS 配置;虚拟主机式(bucket.endpoint)也支持,但要设 RUSTFS_SERVER_DOMAINS、配泛解析和覆盖桶域名的证书,内网自签环境往往凑不齐这些条件。迁移时优先确认客户端开着路径式选项(AWS SDK 里的 force_path_style=true),能省掉一类配置问题。
两条要写进迁移方案的边界
兼容不是无条件的。翻迁移方案的时候,把这两条补进去。
ACL 授权被显式排除。 矩阵里 ACL authorization 标的是 Excluded,RustFS 有意不支持桶级和对象级的 ACL。原来依赖 x-amz-acl 或者对象级 ACL 的权限模型,要改成 IAM 策略或桶策略。官方把它当作设计选择而不是缺口:授权收口到 IAM 和桶策略之后,审计面比散落在每个对象头上的 ACL 小得多。迁移前先 grep 一遍现有脚本里的 set-acl 和 PutObjectAcl,统一往策略改。检索范围别只圈 shell 脚本,业务代码和 SDK 调用里传的 ACL 参数(比如 ACL: "public-read")同样要清。
加密对象的格式跨实现不互通。 SSE-C 和部分 SSE-KMS 用例在矩阵里标的"已测",前提是 RustFS 自己加密的对象能在 RustFS 之间往返,它不保证能直接读取由别的实现写出的加密对象。所以迁移加密桶的时候,稳妥路径是源端解密、落到新存储、再按新存储的密钥重新加密,而不是期待加密格式透明平移。未加密数据是另一回事,直接搬过去就行。
planned 列表上还有两项要留意:桶访问日志(bucket access logging)和桶所有权控制(bucket ownership controls)。前者意味着存储侧暂时不会按桶自动输出访问日志,审计要靠服务端日志(RUSTFS_AUDIT_ENABLE)或业务层埋点补位;后者影响对象所有权回收的自动化。依赖这两项的流程,先在应用层或者 sidecar 里补上,别等它落地再动。
迁移前的验证顺序
迁移前按这个顺序过一遍。
- 用你真实的客户端跑核心路径:建桶、分片上传一个大文件、开关版本控制、对象锁合规模式、预签名 GET 与 PUT。逐条跑,不要只看文档。
- grep 现有脚本和业务代码里的 set-acl、PutObjectAcl 调用,改成 IAM 或桶策略。
- 加密桶走重加密路径,源端解密、落新存储、新密钥重加密。
- 对接时写死版本标签 1.0.0,别让 latest 漂移带来行为变化。
- 确认客户端用路径式寻址(RustFS 默认),虚拟主机式需要额外的 DNS 配置。
验证时还有一个高频坑:分片上传对象的 ETag 生成逻辑各 S3 实现并不统一,不能拿它当内容校验和用。迁移后跑 mc diff 这类对比工具会因 ETag 不同产生误报,完整性校验交给客户端自己的哈希或清单文件。
上传、列举这些日常操作,连同版本、锁定、预签名和分片上传,都在测试覆盖里,可以直接搬。ACL 和加密互通这两条,提前在迁移方案里留好位置就行。
真要动手,从备份、构建产物或者 staging 桶这类写多读少的工作负载里挑一个先搬过去,跑稳了再扩。RustFS 1.0.0 已于 2026-09-16 正式 GA,Apache 2.0 协议,兼容性矩阵的实时结果在 https://docs.rustfs.com/en/reference/s3-compatibility ,仓库在 https://github.com/rustfs/rustfs 。动手前拿业务实际用到的 API 对照矩阵逐项验证,别只参考测评。