ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

单盘扛不住了?多节点部署 RustFS,把几台机器的磁盘并成一个纠删码存储池

单盘扛不住了?多节点部署 RustFS,把几台机器的磁盘并成一个纠删码存储池

单机 Docker 跑通之后,下一步往往是容量和容错双双见顶:一块盘坏了数据就悬,加盘也不是简单挂载。这时候上分布式,把几台机器的磁盘并成一个存储池,底层走纠删码(EC,Erasure Coding,一种把数据切片加校验、允许部分分片丢失仍能复原的编码方式),按设定的分片规则容忍若干块盘同时故障,还能往后横向扩。RustFS 的多节点部署用一条RUSTFS_VOLUMES把所有端点收拢,部署形态由这份驱动器列表直接决定。

多节点为什么不能用默认桥接网络

Docker 默认的 bridge 网络不支持跨节点通信。要让每个容器直接跟其他节点对话,得用 host 网络:

dockerrun-d\--namerustfs\--networkhost\-v/mnt/rustfs/data:/data\-eRUSTFS_ACCESS_KEY="<your-access-key>"\-eRUSTFS_SECRET_KEY="<your-secret-key>"\-eRUSTFS_ADDRESS=":9000"\-eRUSTFS_CONSOLE_ADDRESS=":9001"\-eRUSTFS_CONSOLE_ENABLE=true\-eRUSTFS_OBS_LOGGER_LEVEL=error\-eRUSTFS_OBS_LOG_DIRECTORY="/var/log/rustfs/"\-eRUSTFS_VOLUMES="http://node{1...4}:9000/data/rustfs{0...3}"\rustfs/rustfs:latest

这条命令要在每一台节点上各跑一遍,端口、密钥保持一致,RUSTFS_VOLUMES是四台节点共享的同一份。host 网络下容器直接占用宿主机端口,所以各节点的 9000/9001 不能和宿主机上别的进程冲突。

RUSTFS_VOLUMES 的写法:节点和盘各一层展开

http://node{1...4}:9000/data/rustfs{0...3}这种花括号是 RustFS 的展开语法:外层node{1...4}表示 node1 到 node4 四台机器,内层rustfs{0...3}表示每台机器上 4 个数据目录,合起来就是 4 × 4 = 16 块盘。要扩规模就调大这两个范围,比如node{1...8}配rustfs{0...3}就是 32 块盘——不过这是规划期就该定好的写法:已经有数据的集群不能再改这个范围,改已有池的表达式等于替换拓扑,扩容要按后面的追加流程走。

每台的/etc/hosts要把节点名解析到内网 IP:

192.168.1.1 node1 192.168.1.2 node2 192.168.1.3 node3 192.168.1.4 node4

节点间 9000 要互访,带宽不够 EC 写入会卡

host 网络下每个节点直接用宿主机 9000 通信,所以节点之间的 9000 必须放通,防火墙、安全组别只开 9000 对外、忘了节点间互访就会一半节点连不上。EC 在写入时会把分片发到所有节点,网络一抖写入延迟就上去,所以节点间走内网、走低延迟链路比走公网稳得多。部署前先用ping或iperf量一下节点间 RTT,把延迟压到可接受范围再上线。EC 大块写入很吃节点间带宽,用iperf3 -s/iperf3 -c量一下吞吐,带宽不够时写入会卡在等分片回包上。单节点内多条磁盘走本地总线、延迟可以忽略;一旦跨节点,网络就是 EC 写入的隐形瓶颈,规划容量时要把这部分余量留出来。

容量怎么算:EC 不是简单求和

分布式底层是纠删码,数据被切成数据分片和校验分片打散到所有盘上。16 块盘的总可用容量不是16 块盘容量直接相加,要按 EC 的分片规则折算出一部分给校验。分片比例看的是每个纠删集的驱动器数,不是集群总盘数:16 块 10TiB 盘组成 EC:4 的纠删集,可用容量约 160 × 12/16 = 120TiB(官方公式:原始容量 × (N−M)/N)。搭之前先过一遍官方的EC 配置页,把冗余留够。

把不同节点尽量分散到不同机架或宿主机,这样单个机架掉电不会一次丢两块以上的分片,EC 才兜得住。官方专门有一条警告:不要假定 EC:4 始终可以容忍四个完整节点故障,一个节点可能托管同一纠删集中的多个驱动器,节点级容错取决于纠删集的驱动器怎么分布在节点上。这一步比单纯加盘数更影响可靠性。

怎么确认池子真的并成了

逐台curl /health都绿,只是说明每个节点自己活着。确认 16 块盘进了同一个池,用rc admin info cluster看后端布局、纠删码校验数和存储池成员关系(控制台的 Status 页是同一份信息),或者用 aws-cli 在一个节点写对象、到另一个节点读,能跨节点读到说明池子通了。EC 的校验分片打散在所有盘上,单个节点挂掉时,只要该节点承载的驱动器数仍在纠删集的容忍范围内,读写都不受影响。

curl--failhttp://localhost:9000/health

单机数据搬不过来,集群扩容要按追加走

有一点必须提前讲清:单节点是零校验的单驱动器布局,和分布式的纠删集不是同一种布局,已经在单机写进去的数据,实践上按新集群迁移处理,别指望重启就能转换布局。

分布式集群自身的扩容,官方流程的第一步就是改RUSTFS_VOLUMES:在每台节点的RUSTFS_VOLUMES里追加新的存储池表达式,原有表达式不动、顺序保持一致,全集群重启后新写入就能用上新增容量,再跑rc admin rebalance start rustfs把旧数据搬到新池摊匀。官方扩容页还有两条硬要求:动手前备份关键数据、在维护窗口执行;遗漏现有存储池、或在某个节点上用了不同的表达式,会造成拓扑不一致。池子只能追加不能替换,退役则是另一套流程:用rc admin decommission start rustfs 0 --by-id启动、rc admin decommission status rustfs看进度(控制台的 Pool Decommission 页是同一操作),前提是其余池的可用空间装得下待排空的数据再留 30% 余量;状态到complete后,把该表达式从每台的RUSTFS_VOLUMES里删掉再重启。

如果是从旧的单机或独立部署把数据迁到新集群,别只想到mc mirror,它只搬对象。RustFS 的站点复制(rc admin replicate add site1 site2)在两个独立部署之间同步桶、对象版本、删除标记,连 IAM 用户、组、策略和服务账户一起同步,前提是两边都启用桶版本控制、9000 端口双向连通,生产环境用 TLS。迁完验证无误再切流量。

生产前补三样:TLS、日志轮转、定期备份

官方建议生产前走预安装检查清单:启用 TLS 加密节点间通信、配置日志轮转、设定期备份策略。TLS 靠挂证书目录实现,证书文件必须命名为rustfs_cert.pem和rustfs_key.pem放进该目录:

-v/path/to/certs:/certs\-eRUSTFS_TLS_PATH=/certs\

多节点本身已经提供了盘级容错,但备份和 TLS 是另一层,别因为有了 EC 就省掉。EC 保的是盘故障,备份保的是误删、勒索和站点级灾难,两者不是一回事。

什么时候该上分布式

单块盘容量见顶、或者一块盘坏就丢数据,这两件事任意一个发生就是信号。四台机器各挂几块盘、用 EC 并成一个池,是中小规模里性价比很高的起点;再大就进多池 + rebalance 继续扩。

自动档位封顶 EC:4:盘越多,容量效率反而越高

不必纠结具体 k(数据分片)和 m(校验分片)怎么手算,自动档位下校验分片数按纠删集宽度定档、封顶 4:宽度 2~3 是 EC:1,4~5 是 EC:2,6~7 是 EC:3,8~16 块都是 EC:4。所以盘数越多,容量效率反而越高(8 块盘 50%,16 块盘 75%),可容忍的同时故障分片数在自动档位下随宽度升到 4 之后封顶;想提高容错要显式设RUSTFS_STORAGE_CLASS_STANDARD=EC:<m>,且受M ≤ N/2约束,无效值会导致启动失败而不是静默降级。盘数建议取能均匀铺开的布局,让数据分片和校验分片能打散到每块盘,避免某一块成为热点拖慢整体。EC 每次写都要把分片发到所有节点,节点太多、延迟累积,小对象写的尾延迟会涨,所以经验上中小规模 4 到 8 个节点通常是个稳的起点(官方文档只约束纠删集宽度 2~16,节点数按布局和延迟自行定),更大规模再走多池继续扩。

下一步

先把四台机器的/etc/hosts和RUSTFS_VOLUMES对齐,逐台起服务、逐台/health探活,确认 16 块盘都进池再用 aws-cli 建桶写入。多节点部署细节以官方文档为准:RustFS 容器部署 ,镜像与协调说明在 rustfs/rustfs 。容量规划拿不准时,先小集群跑通再翻倍。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进