当前位置: 首页 > news >正文

MinIO 停止维护怎么办?Docker 迁移 RustFS 实战:数据零丢失

前言

MinIO 说停就停,线上的文件服务还得接着跑。

2025 年 12 月,MinIO 官宣社区版进入维护模式。2026 年 2 月,仓库归档只读:不再有提交,CVE 不再修复,官方资源全面转向商业版 AIStor——订阅制,个人项目用不起。还在跑社区版的部署,等于抱着一个不再更新的黑盒。

youlai-boot(Spring Boot 权限管理后端)的文件存储一直跑在 MinIO 上,趁这次把迁移完整走了一遍:旧数据整目录复制、endpoint 和桶名不变,顺手把客户端换成 AWS SDK 标准实现。过程同样适用于任何 Docker 部署的 MinIO——包括 vue3-element-admin 配套环境在内。

本文看点:

  • 选型判断:RustFS / SeaweedFS / Garage 什么场景选谁
  • 标准客户端:顺手切 AWS SDK v2,跟协议不跟厂商
  • 数据零丢失:旧目录整目录复制,旧数据原样保留当备份

一、环境准备

1.1 MinIO 停更时间线

先看事实,再谈迁移:

时间事件
2025-12官宣社区版进入维护模式:不收新功能和 PR,安全修复"视情况评估"
2026-02GitHub 仓库归档只读,README 标注 “THIS REPOSITORY IS NO LONGER MAINTAINED”
之后官方资源全部转向商业版 AIStor,社区版已披露的 CVE 不再修复

1.2 替代品怎么选

主流开源替代有四个,先给结论表:

方案协议状态适合场景
SeaweedFSApache 2.0生产验证 10 年海量小文件,要久经考验
RustFSApache 2.0活跃迭代,较新单容器部署,MinIO 迁移成本最低
GarageAGPL v3生产可用地理分布式集群
Ceph RGWLGPL企业级PB 级规模,单机太重

四个候选都宣称 S3 兼容,所以这不是区分度。真正的分水岭是部署心智模型

  • SeaweedFS 最成熟,但它是 Master / Volume / Filer 多角色架构,从 MinIO 迁过来要重新理解一套部署模型
  • RustFS 单容器一条docker run,9000 API + 9001 控制台,和 MinIO 的使用习惯完全一致
  • RustFS 还直接兼容 MinIO 磁盘格式——旧数据整目录复制即可,数据不过网络(见 2.2 节),其他候选都得走网络搬运

我选 RustFS,理由是迁移路径最短:部署方式、端口约定、控制台操作全部延续,连磁盘数据格式都兼容,团队不需要学新东西,应用侧最小只换一对 AK/SK。

边界也要说清:RustFS 比 SeaweedFS 年轻,生产验证的厚度不如前者。PB 级核心存储选 SeaweedFS 或 Ceph 更稳;单机自用、中小规模,迁移成本这一票投给 RustFS。

1.3 迁移前检查

# Docker 环境docker-v# 磁盘空间:2.2 节整目录复制,需要约 2 倍旧数据的空间df-h/data# 记录旧 MinIO 数据目录路径(2.2 节复制数据用,本文示例为 /data/minio)dockerinspect minio--format'{{range .Mounts}}{{.Source}} -> {{.Destination}}{{"\n"}}{{end}}'

最后一项记下旧数据目录路径——它和新目录/data/rustfs平级对应,2.2 节从它复制数据。


二、迁移准备

整个迁移流程一张图:

停用 MinIO

复制旧数据

启动 RustFS

切换 AWS SDK

验证上传

流程只做一件事:数据先落位,服务后启动。不存在"先跑起来再迁数据"的折返——容器只启动一次,命令不重复执行。

2.1 停用 MinIO

# 容器删除,数据目录保留——迁移没验证完之前,随时可以回退dockerstop minio&&dockerrmminio

2.2 准备数据目录

旧数据在/data/minio(1.3 节查到的路径),整目录复制为/data/rustfs——两个目录平级独立,旧目录原样保留,天然就是回退备份。

# 清掉可能存在的空目录:复制要求目标目录不存在rm-rf/data/rustfs# 旧目录整体复制为新目录:-a 保留权限与时间戳cp-a/data/minio /data/rustfs# 副本属主还是 root(旧 MinIO 以 root 跑),对齐 RustFS 的运行身份chown-R10001:10001 /data/rustfs

为什么直接复制磁盘目录就行:先纠正一个直觉——MinIO 磁盘上不是"一个对象一个文件",ls /data/minio/public看到的不是图片,而是一堆和对象同名的目录(里面是xl.meta元数据和分片),所以挑出"图片文件"复制行不通。但整目录复制可以:RustFS 自 1.0.0-alpha.89 起兼容 MinIO 磁盘格式(官方称 drop-in replacement,issue #2212),桶、对象、桶策略一并识别,数据不过网络。TB 级数据走网络搬运要数小时,目录复制只受磁盘速度限制(参考:2.3 TB 生产迁移实录)。

复制过来的数据,有三件事心里要有数:

  • Access Key 不随数据迁移(社区实测反馈):旧密钥别指望能用,统一用启动时环境变量里的新 AK/SK——所以第四章的应用配置还是要改
  • 兼容边界:桶元数据、对象(含标签/版本/对象锁)、生命周期、IAM 在迁移范围;站点复制、事件通知、LDAP/OIDC 不在
  • 旧目录先别删:确认 3.2 验证通过后再清理,在那之前它就是现成的回退备份

三、启动 RustFS

3.1 启动容器

数据已就位,这一步只管把服务跑起来:

dockerrun-d\--namerustfs\--restartunless-stopped\-p9000:9000\-p9001:9001\-v/data/rustfs:/data\-eRUSTFS_ACCESS_KEY=rustfs-admin\-eRUSTFS_SECRET_KEY='换成你的强密码'\rustfs/rustfs:latest

端口含义和 MinIO 完全一致:9000 是 S3 API(应用连这个),9001 是 Web 控制台。云服务器安全组原来为 MinIO 放行过的话,一个端口都不用改。

数据目录属主必须是 10001。MinIO 官方镜像以 root 运行,挂哪都能写;RustFS 镜像在 Dockerfile 里声明了USER 10001,容器进程以这个非 root 身份运行。而 bind mount 不转换权限——容器内的 UID 10001 写/data时,内核按宿主机目录的属主检查。属主没对齐时,容器一启动就崩:

# 启动即崩:[FATAL] Server runtime failed: Io error: Permission denied (os error 13)

2.2 已经对副本执行过chown 10001,这里可以正常启动。

两个常见疑问。为什么不用chmod 755?755 只给属主写权限,UID 10001 落在"其他人"位,照样不能写;用chmod 777能绕过但等于向服务器所有用户开放写权限。10001 哪来的?docker inspect rustfs/rustfs:latest --format '{{.Config.User}}'可查——镜像作者声明的普通用户区间(10000-60000)身份。官方 issue #2396 确认了这是非 root 容器的标准要求。

3.2 验证服务

dockerps|greprustfs# 状态 Up 即成功dockerlogs-frustfs# 日志无报错

浏览器打开http://服务器IP:9001,用启动时设置的 AK/SK 登录——控制台里应该直接看到旧 MinIO 的桶和文件。

3.3 开启匿名读

旧桶策略随数据带过来;如果是新建的桶(或旧桶没开过),博客图床、前端直链场景要开匿名下载。操作路径两步:

  1. 左侧菜单第一项对象浏览→ 存储桶列表 → 找到目标桶,点行末的设置按钮
  2. 进入桶详情后,在访问与共享 → 访问策略处点击编辑,改为公开,保存后出现“修改成功”提示即生效

不开的话,外链图片一律 403。注意“公开”是只读匿名访问——外链能拉取图片,但上传仍然要走 AK/SK 认证,安全性可控。


四、应用切换

4.1 切换 AWS SDK

io.minio:minio是个 S3 协议客户端库,现在还能用,但命脉系于一家已全面转向商业版的公司。AWS SDK for Java v2 是 S3 生态的事实标准,官方支持连接任意 S3 兼容存储——既然都动手迁移了,一起换掉,以后不再挑 SDK:

<dependency><groupId>software.amazon.awssdk</groupId><artifactId>s3</artifactId><!-- 写作时最新版,实际以 Maven Central 为准 --><version>2.54.2</version></dependency>

完整实现源码:RustFSFileServiceImpl.java

file-storage:type:s3# 枚举改为 s3:跟协议走,不跟厂商走s3:endpoint:http://服务器IP:9000access-key:rustfs-admin# RustFS 的新 AKsecret-key:换成你的强密码# RustFS 的新 SKbucket:public# 数据已复制过来,桶还是原来那个
importsoftware.amazon.awssdk.auth.credentials.*;importsoftware.amazon.awssdk.regions.Region;importsoftware.amazon.awssdk.services.s3.S3Client;@BeanpublicS3Clients3Client(FileStoragePropertiesprops){vars3=props.getS3();returnS3Client.builder()// 连自己的服务器,而非 AWS.endpointOverride(URI.create(s3.getEndpoint()))// 非 AWS 服务必填,值任意.region(Region.US_EAST_1)// IP 端点必须:桶名走路径不走子域名(见踩坑清单).forcePathStyle(true).credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(s3.getAccessKey(),s3.getSecretKey()))).build();}

上传调用从MinioClient换成S3Client.putObject,参数语义一一对应,改动集中在一个 Service 实现类(RustFSFileServiceImpl.java)里。

判断标准一句话:协议客户端跟协议走,不跟厂商走。S3 协议是 AWS 定的开放标准,比任何一家对象存储公司都活得久。

4.2 验证上传

# 重启应用mvn spring-boot:run

方式一:打开http://localhost:8000/doc.html,调文件上传接口,接口返回文件 URL 即成功。

方式二:打开vue3-element-admin前端「组件封装 → 图片上传」,选择图片上传;也可以直接访问有来在线环境:https://vue.youlai.tech/#/component/upload

上传成功后,复制返回的文件 URL 在浏览器打开——图片正常显示,说明后端到 RustFS 的链路通了。

最后回 RustFS 控制台,public桶里能看到刚上传的图片文件,迁移端到端验证完成。


五、踩坑清单

现象解法
目录属主不对启动即崩,Permission denied (os error 13)RustFS 以 UID 10001 非 root 运行,chown -R 10001:10001数据目录(官方 issue #2396)
旧密钥失效沿用旧 AK/SK 上传报 403 AccessDenied旧 MinIO 的 Service Account 不会迁移,统一换 RustFS 启动时的新 AK/SK
SDK 没开 path-style请求域名解析成桶名.服务器IP,连接失败AWS SDK 设S3Configuration.pathStyleAccessEnabled(true)(旧版方法名forcePathStyle),IP 端点必须走路径式
桶不存在应用上传报 NoSuchBucket旧桶随数据复制带过来;只在全新空目录部署时才需手动重建
直接挑文件复制复制完对象不显示:MinIO 磁盘上每个对象是目录(xl.meta+分片),不是文件整目录cp -a复制,RustFS 兼容该格式(≥ 1.0.0-alpha.89)
新版 SDK 签名报错XAmzContentSHA256Mismatch旧 MinIO 不支持流式签名,永不修复——该迁移了
外链图片 403匿名拉取被拒桶的访问策略设为「公开」(只读匿名访问),见 3.3 节

属主问题的根源是镜像安全模型的差异:MinIO 官方镜像以 root 运行,挂哪都能写;RustFS 以 UID 10001 的非 root 用户运行,宿主机目录必须先chown 10001再启动(官方 issue #2396 确认)。照着 MinIO 习惯迁移的人,几乎 100% 在这里崩一次。

403 的迷惑性最强:签名校验是过的,死在策略层。排查的人总以为是密钥打错了,其实是旧 Service Account 连同它绑定的桶策略,一起留在了旧系统里。

path-style 是 IP 直连的隐藏要求:AWS SDK 默认虚拟主机式寻址,把桶名拼进域名,public.服务器IP这种地址 DNS 直接解析失败。旧 MinIO Java SDK 默认路径式所以无感,切 AWS SDK 后pathStyleAccessEnabled(true)就是必写项——4.1 装配代码里已带上。

最后一条是本文的引子:用新版 AWS SDK 向旧版 MinIO 上传,报XAmzContentSHA256Mismatch。这不是配置错了——新版 SDK 默认走流式分块签名,旧版 MinIO 解析不了,而且永远不会修。遇到它别再排查配置,这是 MinIO 停更砸到你身上的第一块石头。

补一句新校验和的坑:AWS SDK 2025 年起默认开启新校验和,个别 S3 兼容服务也会报同族错误,兜底开关是环境变量AWS_REQUEST_CHECKSUM_CALCULATION=when_required


六、总结

对象存储的选型不是一锤子买卖,再主流的方案也可能停更。这次迁移真正值钱的不是 RustFS,而是S3 协议这层抽象——服务端换成谁都是配置级改动;客户端统一到 AWS SDK 这个事实标准,以后连 SDK 都不用再挑。

后续可扩展:

  • RustFS 分布式部署:多节点纠删码,数据可靠性再上一档
  • 接入监控告警:桶容量、请求量的观测

相关开源项目:

项目简介源码
youlai-bootSpring Boot 4 权限管理后端,本文文件存储所在项目Gitee · GitHub · AtomGit
vue3-element-admin配套 Vue3 前端Gitee · GitHub · AtomGit

在线体验:vue.youlai.tech(PC) · app.youlai.tech(移动端)

如果你的 MinIO 还在带病运行,别等下一个 CVE——S3 兼容的替代方案,切换成本比你想的低得多。

http://www.cnnetsun.cn/news/4225817.html

相关文章:

  • LX Music 桌面版:免费音乐聚合播放器完整指南
  • Outfit 字体完整指南:9 种字重免费商用,3 分钟装进系统
  • Shallows序列化能力清单:JSON、Plist与String存储映射全覆盖指南
  • 数字化转型全景解析:标准化、信息化、数字化与智能化的演进路径与实践指南
  • 为什么Intel放弃Hyperscan:Vectorscan项目背后的开源反击战
  • Java面试前,我建议你重点复习这几个核心知识点
  • 谷歌数据分析 V 笔记(二)
  • 2026年口碑出众的表型平台生产厂家盘点,值得你深入了解
  • 3步完成微信聊天记录导出全指南:免费永久保存为HTML和Word
  • 如何用 Cosmic Ray 的 cr-rate 诊断测试薄弱点:变异存活率分析完全教程
  • Paperless-ngx 完整上手指南:五步把纸质文件变成可搜索档案
  • 如何使用 DALL-E 2?
  • 2026年,揭秘宜昌市伍家岗区那些超好的差旅型酒店门店!
  • 朱雀三号首次陆地回收
  • 金融工程Financial Engineering Competition-2回归MSE优化
  • 银行模拟器,装x神器 吊打市面上所有模拟器,泡妹神器
  • 构建机器学习模型识别图像AI生成内容的检测
  • 中小团队的后端技术栈搭配:稳定、高效、易维护
  • TorchOpt API参考速查:从优化器到Transform的完整函数地图
  • 单靠死工资不够?这本《AI创富手册》教你用AI开启第二收入曲线
  • JobRadar:基于本地大模型的职位匹配评分与智能筛选指南
  • 推理增强工程实践:DeepSeek-Reasonix与esengine组合落地指南
  • 贪心算法的思路和典型例题
  • AI找矿实战:如何用机器学习圈定高纯石英靶区
  • Vue3数字输入框(InputNumber)
  • 基于MCP Server构建AI可查询的错误知识库:从协议到实践
  • MCP Server实践:AI错误诊断工具,让报错不再难懂
  • 来看界面控件DevExtreme如何实现数据表单的高效动态更新
  • AI网站构建器背后:结构化页面表示与生成链路解析
  • 基于高德API与异步Python构建智能选址AI Skill实战