ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

升级 RustFS 二进制不停机:一条一条换,留一条退路

升级 RustFS 二进制不停机:一条一条换,留一条退路 一个四节点集群跑了半年没重启过版本落后两个小版本。升级这件事真正的难点是出了事怎么退回去把新二进制放上去那一步反而不难。RustFS 官方的二进制升级页给的流程很短但里面那两条备份命令才是整个流程的核心备份配置以及把当前正在跑的那个可执行文件另存一份。少了第二条的升级等于把回滚路径删掉了。升级前的两件事确认健康留好退路官方给的第一步是对每个节点检查就绪状态curl-fsShttp://node:9000/health/ready这个检查要在每台机器上各跑一次全部返回成功再动第一个节点。文档在开头写明了前提先读目标版本的发行说明再确认每个节点都健康。这两句话听起来像套话实际是因为滚动升级的前提就是「一次只下线一个节点」任何一个节点带着既有问题参与进去故障排查时就没法确定问题是不是升级引入的。第二条是备份sudocp/etc/default/rustfs /etc/default/rustfs.baksudocp/usr/local/bin/rustfs /usr/local/bin/rustfs.previous第一行备份的是环境变量配置。升级本身不会改这个文件但如果你在发布说明里看到新增的环境变量改配置这一步就是人工的忘了就得手动补。第二行是回滚的关键把当前可执行文件和路径上那个同名文件做一次拷贝。RustFS 的升级流程要求保留正在运行的可执行文件官方原话就是让它可用于回滚。这两行命令本身没有难度但落地的两个位置值得单独看一眼。/etc/default/rustfs里放着访问密钥和秘密密钥官方安装脚本写完这个文件之后会立刻执行chmod 600也就是只允许属主读写。备份出来的rustfs.bak是它的副本内容一样敏感而/etc/default/这个目录并不设防同主机上的其他账号照样读得到。升级前顺手补一句sudo chmod 600 /etc/default/rustfs.bak比事后发现密钥躺在一份可读文件里要省事。rustfs.previous是另一回事。它只是个可执行文件不含任何密钥但和rustfs一样大。真正需要注意的是替换那一刻磁盘上同时躺着三份二进制旧的、备份的、新拷进来的。替换之前还要看一眼剩余空间。这一轮里磁盘上同时存在三个占用正在跑的旧二进制、备份出来的rustfs.previous、拷进来的新版本。拷到一半盘满了写出来的rustfs是个截断文件启动时报的是权限或格式错误比压根没升级更难收拾。先df -h /usr/local/bin确认余量按新版本体积再留一倍比较稳。换二进制的顺序每一步都要等就绪单节点的替换动作只有四步但顺序不能颠倒sudosystemctl stop rustfssudocprustfs-new /usr/local/bin/rustfssudochmodx /usr/local/bin/rustfssudosystemctl start rustfscurl-fsShttp://node:9000/health/ready官方文档对节奏的要求写得比较硬一次只升级一个节点在重启的节点报告就绪之前不要继续。这条约束的原因是节点间 RPC 复用 9000 端口节点之间要能互相访问同时停掉两个就意味着某个瞬间没有节点能对上话。systemctl stop rustfs那一下的后果比命令看上去重。这个节点上的分片在这一刻全部离线集群进入降级模式读写靠纠删码的冗余撑着继续服务。冗余够不够取决于这个节点之前还剩多少余量一块盘已经坏了但还没换的集群某个纠删集本来就已经少一片此时再停掉一台机器剩下的分片可能连最小的读 quorum 都凑不齐。所以动第一个节点之前值得先确认集群没有正在跑的修复任务rc admin heal status rustfs--json|jq{queue: .healQueueLength, active: .healActiveTasks}队列不为零就再等一会儿。修复本身在读旧盘写新盘正吃着 IO 和冗余这时候再停一台机器是往已经紧绷的地方又加了一道。官方也提醒过队列长度为零只能说明积压清了不能代表离线盘已经换回、更不能代表每个对象都修好了。它表示的只是现在可以开始不构成已经安全的确认。chmod x这一步也别省。用cp覆盖一个已经存在的可执行文件新文件的权限会沿用源文件也就是rustfs-new的权限如果那个文件是从别处拷贝来的、没有可执行位启动时就会以权限错误退出。混版本窗口里有几扇门必须先确认没开新旧版本在同一个集群里共存的那段时间真正要盯的不是版本号是几项会改变磁盘格式的特性。官方运维文档开头就写明了前提替换可执行文件或容器镜像不会改动磁盘上的数据格式换完重启也不会自动跑迁移步骤。但有几个特性一旦激活旧版本二进制就读不懂新版本写出去的内容官方给这类特性起的名字是版本下限version floor要求是在混版本滚动升级的全过程里保持未激活。一共四项其中三项是双开关特性门激活条件激活后的后果Local SSE wrapped-DEK JSON 信封替换旧格式base64(nonce):base64(ciphertext)的那个发布版本旧节点读不了以 JSON 信封写入的对象。必须先把所有对象变更来源客户端写入、生命周期、复制冻结升级完全部节点再恢复流量。写入新加密对象之后不支持回退Data-movement 分片校验和 sidecarRUSTFS_DATA_MOVEMENT_PART_CHECKSUMS_WRITE与RUSTFS_DATA_MOVEMENT_PART_CHECKSUMS_FLEET_CONFIRMED两者同时为真只有全体读写对象元数据的节点都支持这个 sidecar、且整个集群已把该版本当作回滚下限之后才可启用。一旦 rebalance 或 decommission 在两者都开着的状态下迁移了带校验和的旧式分片上传对象回退就不被支持旧客户端会忽略 sidecarPool 元数据版本 2RUSTFS_POOL_META_V2_WRITE与RUSTFS_POOL_META_V2_FLEET_CONFIRMED两者同时为真任何一个节点观察到或写入了版本 2pool.bin 就不再降级旧二进制和回滚版本都读不了。未处理的 decommission 条目以失败关闭的方式处理不再写成版本 1 格式Pool 元数据版本 3RUSTFS_POOL_META_V3_WRITE与RUSTFS_POOL_META_V3_FLEET_CONFIRMED已有集群上两者同时为真才激活引入持久代和可恢复的跨池提交协议。一旦提交只支持 V1/V2 的二进制无法重新加入双开关那层设计值得单独说一句。带WRITE后缀的那个表示本节点要写入新格式带FLEET_CONFIRMED后缀的表示运维确认整个集群所有读写方都支持。两个都为真才生效单个节点误开不会当场造成格式分叉。它们默认都是关着的但一旦调过就留下来了所以升级前的检查清单里值得列一行。混版本只能是过渡状态不能当作稳态。全部节点升级完成这次升级才算结束窗口拖得越久某一台旧节点撞上新格式的机会越大。中途停下来的集群比一开始就等的集群更危险。回滚走的是同一套动作方向相反新版本验证不通过时回滚流程与升级几乎同构只是源文件不同sudosystemctl stop rustfssudocp/usr/local/bin/rustfs.previous /usr/local/bin/rustfssudosystemctl start rustfscurl-fsShttp://node:9000/health/ready同样是一次一个节点同样要等就绪再继续。这里有个容易忽略的点rustfs.previous是升级之前那份可执行文件的副本所以它对应的配置组合是当前集群大部分节点的组合。如果你在升级过程中还顺手改了环境变量回滚二进制而不回滚配置就落在了一个从未被验证过的组合上。要改就等升级和回滚都结束之后。换部署形态之后流程要跟着换官方把升级分成三条路径各自的回滚方式不同。二进制部署是上面这套。容器部署的做法是在每个节点上跑同一套 Docker、Podman 或 Compose 流程保留该节点原有的挂载和配置回滚时停掉失败的替换容器再用之前记录的镜像标签重跑一次对应的 run 命令Compose 场景下改回docker-compose.yml里上一个镜像值再重建服务。多节点部署同样是一次一个节点、等就绪再继续。容器这条路的回滚依赖的是「那个镜像标签还在」。官方发布的标签在远端仓库上本地被清理掉也能拉回来。真正会卡住的是另一类自己构建过、或者做过重新打标签的镜像本地镜像被docker image prune或节点重启清掉之后那个标签在仓库里已经不存在了。回滚命令停在一个没有任何提示的位置容器没起来日志也是空的因为压根没启动过。多节点集群上尤其要当心因为回滚要逐个节点重复同样的失败。生产环境里让回滚镜像始终留在远端仓库别把本地缓存当退路。Helm 和 Operator 那套又是另一回事升级由工具自己完成滚动回滚用helm rollback回到上一个修订版本。官方对这条路的描述是让 Helm 恢复 chart、values 和镜像配置这句话里有两层容易漏掉的边界。第一层是 CRD。自定义资源定义不属于 Helm 的发布历史helm rollback不会还原它官方文档直接写了这一句。Operator 的 CRD 是集群级的、所有 Tenant 命名空间共用升级流程里要先单独kubectl apply上新 CRD 再升控制器。所以回滚之前要确认目标版本对 CRD 的要求文档里那句判断是如果这个版本明确支持降级就还原上一个 Helm 修订、不要套用旧的 CRD 文件如果它标注了一次性的单向迁移就别回滚往前修到下一个可用版本。第二层是配置本身。升级前的事前准备里有一条是「把现有的部署值和清单纳入版本控制包括镜像标签、存储拓扑、调度规则和 Secret 引用」。Secret 和 ConfigMap 是集群里的独立对象helm rollback管不到它们。如果升级窗口里有人改过这些回滚之后会剩下一份新版本写入、旧版本运行的不匹配配置。Kubernetes 那条路径上另外还有两条硬约束值得单独记升级和回滚过程中都不要删除 PVCOperator 部署场景下不要在一个维护窗口里同时升级 Operator 和多个 Tenant先升控制面、确认 CRD 和组件正常再逐个动 Tenant。发布说明里最先该看的两类改动滚动升级的文档把「读发行说明」写在开头但具体该读什么往往没人说清。有两类改动值得优先看。第一类是配置语义的变化。RustFS 的很多环境变量有默认值默认值变了不会在启动时报错只会在行为上体现出来。一轮升级跨了两个小版本时环境参考页里默认值那一列的变化就是重点。凡是涉及存储布局、存储级别、缓冲配置的默认值变动都要按「新默认值会不会影响存量数据」来判断影响面。第二类是接口层面的废弃。RustFS 保留了MINIO_*到RUSTFS_*的映射表和几个旧变量名弃用的写法仍能跑但会打警告。升级之后如果日志里出现这类警告说明有配置走了旧路径虽然不影响当前运行但下一个大版本里未必还留着。升级之后该验证什么curl -fsS http://node:9000/health/ready只能证明这个节点起来了。要看清楚集群层面的状态用rc admin info cluster rustfs它会报告集群状态、RustFS 版本、服务器和磁盘数量、后端类型与纠删奇偶节点列表里给出运行时长、网络连通性、磁盘可用性和池成员归属。版本这栏尤其值得盯一眼。滚动升级过程中某个节点忘了处理的话集群会停在新旧版本混跑的状态接口表现往往正常只有在这一栏里能看到不同版本的节点并列。这一项也正好收束前面那节混版本是过渡态全部节点版本一致才算这次升级结束。发现了就按回滚流程逐个处理不要指望它会自己追上。一个通用的排错入口RustFS 二进制还带了一个诊断子命令rustfs diagnose用于分析日志文件并报出可能的原因。版本升级之后日志格式可能变化排查新版本报出的异常时rustfs diagnose --path指向日志目录比在几万行日志里自己找要快。同族的还有rustfs tls inspect --path可以检查证书目录的布局与解析状态升级顺手轮换证书时用它验证一遍。把这套流程固化成文档里的检查单之后升级这件事就不再需要每次现场判断。四节点集群一轮滚动升级大约十几分钟其中绝大部分时间花在等节点就绪上真正的操作只有四条命令。还有一条经验升级窗口里不要同时做别的变更。换证书、扩池、改环境变量这几件事和滚动升级叠在一起出问题时无法判断是哪个引入的。真要一起做顺序上先升版本再动其他中间留一个观察期。观察期里值得盯的三个指标是集群状态是否所有节点都在线、各节点报告的 RustFS 版本是否已全部一致、存储可用容量是否在正常波动范围内。前两项决定这次升级算不算成功第三项用来排除升级过程中误操作带来的容量变化。还有一个容易漏的收尾动作。四台机器都升级完、版本栏核对无误之后把/etc/default/rustfs.bak和/usr/local/bin/rustfs.previous的处理想清楚它们留着是有价值的下一次升级就会覆盖rustfs.previous配置文件备份则容易被下一轮升级里冒出来的改动需求带偏。比较稳妥的做法是在确认新版本稳定运行一段时间后把这一轮的备份归档保存而不是让它一直躺在原地。归档的时候连权限一起带过去别把一份 600 权限的配置文件挪进共享目录之后又变回 644。还有一条和版本相关的经验值得记跨大版本升级前先确认目标版本对纠删集宽度和布局的要求有没有变化。这类变化不会在升级日志里出现提示只在新布局落地的集群上才看得出来。核对方式是升级前在各节点上记下当前的后端类型和纠删奇偶升级完成后再用rc admin info cluster rustfs读一遍两次结果不一致就停下来查发行说明。把这一轮的顺序再压缩一下每台机器四条命令其中两条是复制、一条是重启、一条是验证。真正消耗时间的是重启之后等就绪所以集群规模越大总耗时越长但单节点的操作窗口始终只有一次systemctl stop的时长。
返回列表