Write the Code. Change the World.

11月 06

RustFS 平替 MinIO:S3 对象存储部署与选型对比

替换背景与结论

MinIO 社区版已从 Docker Hub、quay.io、dl.min.io 全面下架:dl.min.io 二进制地址返回 410,Docker Hub 上 minio/minio 任意 tag 均为 not found,quay.io/minio/minio 返回 401。逐个试 tag 只会浪费时间,应先确认上游已整体下架。

因此把对象存储换成 RustFS:同为标准 S3 API,端口布局与 MinIO 一致(9000 / 9001),鉴权走标准 SigV4,可以做到业务侧零改动迁移。

保留历史命名的原因很直接——容器名仍是 **milvus-minio,服务名仍是 minio**,它与 Milvus 已无关系;它现在是 OSS 的唯一文件实体存储,挂在 app 网络供两个后端访问。这样 Milvus 的 MINIO_ADDRESS=minio:9000、应用侧 MINIO_* 系列配置、密钥、端口全部不用改。

RustFS 是什么

名称与项目归属

不是 MinIO 改名,也不是 MinIO 的 Fork,而是一个独立的全新项目:

  • Rust:从零用 Rust 编写,底层存储引擎、元数据、内存模型、GC 全部自研,没有复用 MinIO 的 Go 源码。

  • FS:File System,做对象存储,对外提供 S3 文件语义。

  • 许可:Apache 2.0,修改与分发没有 AGPLv3 那样的强制开源义务。

  • 归属:独立开源项目,与 MinIO Inc 无隶属、赞助或商标关系;官方也明确澄清过这一点。

它为什么和 MinIO 长得这么像

因为它刻意对齐了 MinIO 的运维习惯,就是为了让存量系统平滑迁移:

  • 端口对齐:9000 为 S3,9001 为 Console。

  • 环境变量与凭据习惯对齐,RUSTFS_ACCESS_KEY / RUSTFS_SECRET_KEY 对应原来的 accessKey / secretKey。

  • 单盘、多盘、分布式纠删码三种模式的用法模仿 MinIO。

  • mc 工具可以直接拿来操作,绝大多数子命令正常。

它只兼容标准 S3 API,MinIO 的私有扩展(桶通知、ILM 私有接口、S3 Select、部分管理接口)并不存在,选型与测试时必须把这一点纳入验证范围。

Docker Compose 部署配置

下面这段直接替换原来 minio 那一段即可,服务名、容器名、端口、网络与历史配置保持一致。

services:
  minio:
    image: rustfs/rustfs:1.0.0
    container_name: milvus-minio
    hostname: minio
    restart: unless-stopped
    ports:
      - "9000:9000"
      - "9001:9001"
    environment:
      - RUSTFS_VOLUMES=/data
      - RUSTFS_ADDRESS=0.0.0.0:9000
      - RUSTFS_CONSOLE_ADDRESS=0.0.0.0:9001
      - RUSTFS_CONSOLE_ENABLE=true
      - RUSTFS_ACCESS_KEY=minioadmin
      - RUSTFS_SECRET_KEY=minioadmin
      - RUSTFS_OBS_LOGGER_LEVEL=warn
    volumes:
      - ./rustfs-data:/data
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://127.0.0.1:9000/health"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - app

networks:
  app:
    # 与现有 compose 的 app 网络配置保持一致

关键配置说明

  • 数据目录:RUSTFS_VOLUMES=/data 声明数据卷;早期写法用 command: /data,两者等价,二选一即可,不要重复声明。

  • 端口映射:集群内部通信走 minio:9000,若只在 compose 内部互通,ports 可以注释掉;但需要浏览器直连预签名地址时,必须把 9000 映射到宿主机。

  • 版本锁定:不要长期用 latest。锁定具体 tag,并避开发布早期存在漏洞的 beta 版本;实测 rustfs/rustfs:1.0.4 可正常启动、建桶、上传下载。

  • 探活:GET http://127.0.0.1:9000/health 返回 200 即就绪,可直接作为 healthcheck。

启动后的可用性验证

# 1. 探活
curl -fsS http://127.0.0.1:9000/health

# 2. 配置 mc 别名并建桶
mc alias set rustfs http://127.0.0.1:9000 minioadmin minioadmin
mc mb rustfs/oss            # RustFS 不会自动建桶,必须先建

# 3. 上传后从宿主机直接下载,确认 200 且内容一致
mc cp ./test.txt rustfs/oss/test.txt

RustFS / MinIO 社区版 / SeaweedFS 完整对比

对比项 RustFS MinIO(社区版) SeaweedFS
开发语言 Rust Go Go
许可证 Apache 2.0,商业友好,无强制开源义务 AGPLv3,网络分发与托管服务的衍生代码需开源 Apache 2.0,商业友好
项目归属 独立新项目,不是 MinIO Fork MinIO Inc 官方项目,社区版已冻结,重心转向商业版 AIStor 独立开源项目,长期活跃
核心架构 对等节点 + Set 纠删码,无中心元数据节点,S3 与控制台单进程一体化 同上,最成熟稳定,池化扩容 三层:Master + Volume Server + Filer,存在中心元数据角色
S3 兼容范围 标准 S3 SigV4、桶与对象、分片上传、版本、生命周期;无 MinIO 私有扩展 标准 S3 + 大量私有扩展:桶通知、站点复制、ILM、S3 Select、内部运维接口 S3 网关模式,支持 IAM、STS、对象锁、服务端加密;底层是 Filer 网关包装
默认端口 9000(S3)/ 9001(Console),与 MinIO 完全一致 9000 / 9001 无固定 9000 / 9001 约定,控制台独立
mc 工具兼容 可直接使用,大部分命令正常 原生支持 可用,部分 MinIO 专属子命令不支持
纠删码 EC 原生内置,按 Set 划分,启动时固定 Set 布局 原生内置,成熟,按 Pool 扩展 社区版固定比例 EC,企业版可自定义;读放大为 O(1)
单节点部署 支持单盘 / 多盘单机,适合 Milvus 附属存储 非常成熟 一键启动,但 Master 仍是单点
K8s 生态 官方 Helm Chart,支持 StatefulSet 官方 Operator,生态最强 Helm,社区维护
控制台 UI 自研,简洁;桶管理、密钥、日志等基础功能为主 功能极强,运维、监控、策略、复制、告警齐备 基础 WebUI,重心在 S3 与 FUSE
小文件场景 一般,对象存储思路,与 MinIO 接近 一般 强项,原始设计即解决海量小文件,亿级规模优势明显
大文件 / AI 数据集 Rust 无 GC 抖动,尾延迟稳定,NVMe 下吞吐表现好 成熟稳定,高并发下 Go GC 有延迟抖动 可用,但不是为大对象流式场景设计
元数据瓶颈 分散在各 Set,无中心瓶颈 分散在各 Pool,无中心瓶颈 瓶颈在 Filer / Master,海量文件时是上限
扩容逻辑 新增 Set;Set 创建后磁盘数量不可改 新增 Pool;Pool 内规模固定,不能在线扩盘 可直接新增 Volume 节点,扩容更灵活
站点跨集群复制 支持,逐步完善 成熟稳定,企业级核心能力 支持,机制不同
S3 Select 暂不支持 原生支持 不支持
桶通知 / Webhook 标准 S3 事件部分支持,无 MinIO 专属通知 完善,Kafka / Redis / Webhook 等 支持标准 S3 事件
POSIX / FUSE 不支持,纯对象存储 FUSE 为额外扩展 原生 FUSE,同一份数据同时支持 POSIX、S3、HDFS
Iceberg 内置 Iceberg REST Catalog(特色) 需外部组件 支持 S3 Tables
成熟度 已 GA,新项目迭代快,社区规模中等,踩坑文档偏少 社区版停止维护,镜像下架,存量可用、新部署不建议 多年稳定项目,生产案例多
是否适配 Milvus 场景 最合适:零改配置、端口对齐、mc 直接可用、Apache 2.0 不适合新部署:镜像拿不到、许可风险、停更 能用,但要改 endpoint 与端口、部署更重,没有必要

选型建议

  • 只要能平替 MinIO、不改代码与配置:选 RustFS。代价是放弃 MinIO 私有扩展(桶通知、S3 Select 等),只依赖标准 S3;项目较新,运维案例不如老牌方案多。

  • 海量图片 / 小附件、需要 FUSE 挂载、要 POSIX 文件访问:选 SeaweedFS,但它的 Master 是单点,生产必须做 Master 集群。

  • MinIO 社区版:只适合存量老集群继续运行。许可(AGPLv3)+ 停更 + 镜像下架三重问题,新项目不要再上;如果产品是对外托管的 SaaS,AGPLv3 风险尤其高。

迁移踩坑清单

部署与运维

  • 不自动建桶:RustFS 与老 MinIO 一样不会自动创建 bucket,Milvus 启动前必须预建,否则 Milvus 侧报桶不存在。最好用 init 容器一次性建好。

  • Set 规模一次性定死:和 MinIO 相同,Set 创建后不能增减磁盘,规划集群时就要定好每个 Set 的盘数。

  • 控制台不一样:UI 是 RustFS 自研,基础上传与桶管理够用,但和 MinIO Console 的操作路径不同,交接文档要重写一遍。

  • 混合配置里别留 MinIO 残留:加密、站点复制、ILM 的私有配置项搬到 RustFS 会直接失效,迁移时清理掉。

SigV4 与预签名地址(手写签名时的高频故障)

  • 建桶请求的规范 URI 不带尾斜杠:真实请求是 PUT /bucket,按 /bucket/ 计算签名会返回 SignatureDoesNotMatch 403,而上传对象却正常,很容易误判成凭据错误。

  • 附加 query 参数必须参与签名:如 response-content-disposition 要放进 canonical query 一起算,签完再拼会表现为「地址能生成但下载 401 / 403」。

  • 对外端点与内部端点分开配置:签名只与 host 有关。服务端调用走 minio:9000,预签名地址必须用宿主机可访问的对外端点,否则签出来的链接浏览器打不开。

  • 验证方式:上传后从宿主机 curl 下载,确认 HTTP 200 且内容与上传一致;只看上传返回 200 不足以证明签名正确。

(注:部分内容由豆包工作 AI 生成)