
Kubernetes 上的有状态应用,数据大多躺在 Longhorn 的副本盘里。副本解决了单盘损坏,但解决不了误删卷、集群整体出问题、或者你想把备份挪到另一个机房这些事。Longhorn 自带一套备份机制,把卷快照成内容寻址的块丢进一个 S3 目标。把这个目标指向 RustFS,备份就不再是某几块本地盘的私产,而是能跨节点、跨集群读回的对象。副本保证的是高可用,备份保证的是可恢复,这是两件事,不能互相替代。
把备份放进对象存储还有一个附带好处:它不绑定任何一台机器。哪天你想把这套 Longhorn 迁到另一个机房,或者源集群彻底报废,只要新集群能访问同一个 RustFS 桶,备份就能在新环境里恢复,数据迁移的成本从搬盘变成改一个端点。这也是为什么很多团队把备份目标单独放一个和主集群物理隔离的存储里。
Longhorn 的备份到底存在哪
Longhorn(开源项目)做备份的逻辑和常见的块存储整卷复制不同。它不把整卷拷一份,而是把卷切成内容寻址的块,再配一个很小的卷配置文件,一起写进备份目标的 backupstore/volumes/ 前缀下。所谓内容寻址,就是同样的数据块只存一份,靠哈希去重,所以第二次备份同一个卷时增量很小,只有变化的块会被新写入。这份块和配置文件与源集群解耦:你删了原来的卷,只要桶还在,就能在另一套 Longhorn 里用备份 URL 拉出一个新卷。
对象存储在这里扮演的是备份的持久层,本地副本盘扮演的是运行时的高可用层。两者职责不同,备份不替代副本,副本也不替代备份。官方已经给出 Longhorn 接 RustFS 的指南,本篇重点放在怎么把你已经跑着的 Longhorn 指向你已经有的 RustFS,以及哪些地方最容易踩空。

先把桶建好,这步不能省
RustFS 这边要用 rc 客户端建一个专用桶。Longhorn 自己不会建桶,这是它的设计取舍:备份目标只负责读写对象,桶的生命周期由你来控制。第一次备份之前桶必须存在,否则备份会直接报缺少输入参数。
bash
rc alias set rustfs http://<your-rustfs-endpoint>:9000 <your-access-key> <your-secret-key>
rc mb rustfs/longhorn-backups
官方指南用 Longhorn 1.9.0(k3s、Kubernetes 1.30)配合 rustfs/rustfs-x86-musl:v2.3.1 验证通过。桶名随你定,下面统一用 longhorn-backups。建议给这个桶单独建一套 IAM 子凭证,只对这个桶有读写权,不要拿管理员密钥去填 Longhorn 的 Secret。备份数据长期留存,凭证范围收得越小,出事时的波及面越小。
把 RustFS 凭证交给 Longhorn
凭证以 Secret 的形式放进 longhorn-system 命名空间,三个字段一个不能少:AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY,以及最关键的 AWS_ENDPOINTS。
bash
kubectl -n longhorn-system create secret generic rustfs-s3-secret \
--from-literal=AWS_ACCESS_KEY_ID=<your-access-key> \
--from-literal=AWS_SECRET_ACCESS_KEY=<your-secret-key> \
--from-literal=AWS_ENDPOINTS=http://<your-rustfs-endpoint>:9000
AWS_ENDPOINTS 必须是每个节点都能访问到的地址,用节点 IP 或者内部负载均衡地址,不要填你工作站上端口转发的地址。Longhorn 的备份管理器跑在每个节点上,节点访问不到端点,目标就永远不可用。这个错误很隐蔽,因为在工作站上 kubectl 能连通不代表节点上的管理器也能连通,排查时要到节点网络视角去看。
一句话改掉默认备份目标
Longhorn 1.9 用 BackupTarget 资源管备份目标。把默认的那个目标 patch 成 RustFS 的桶就行:
bash
kubectl -n longhorn-system patch backupTarget default --type merge -p '
spec:
backupTargetURL: s3://longhorn-backups@us-east-1/
credentialSecret: rustfs-s3-secret
pollInterval: 5m'
s3://longhorn-backups@us-east-1/ 里的 @us-east-1 只是 S3 URL 格式里的区域标注,不要求和你真实的部署区域一致,RustFS 不校验这块,填一个非空值即可。pollInterval: 5m 是 Longhorn 周期性检查目标可用性的间隔,目标变成 AVAILABLE=true 之后才会真正开始接受备份。等状态确认可用,说明 Longhorn 已经拿着 Secret 连上了桶:
bash
kubectl -n longhorn-system get backupTarget default
输出里 AVAILABLE 一列会变成 true,并带一个最近同步时间。这之前发起的备份会失败,所以一定先确认可用再建备份,别一上来就急着打快照。

真删了卷也能从桶里拉回来
备份做不做对,得靠一次真实往返来验证。先在 Longhorn UI 里给某个卷打快照再点备份,或者声明式地建 Snapshot 再建 Backup 资源,等状态变成 Completed,拿到 backupURL。然后删掉原卷,用这个 backupURL 建一个 fromBackup 的新卷,挂到验证 Pod 上读原来的文件。能读到,就证明数据确实经由 RustFS 完成了闭环。
在 RustFS 这一侧,用 rc ls 能看到桶里出现了卷配置文件和内容寻址块:
bash
rc ls rustfs/longhorn-backups/ -r
那个 .cfg 是卷的配置,.blk 是真正的数据块。恢复时 Longhorn 读回这些块,按配置拼回卷。生产里恢复通常是周期性的计划任务,而不是手动删卷验证,但这次手动往返是确认链路有效的唯一硬证据。建议把周期性备份和计划快照也配起来,官方 Longhorn 备份文档里有对应的配置方式。
RustFS 当前稳定版是 1.0.4(2026-10-25),从单节点到多节点集群都覆盖 Longhorn 需要的这些 S3 操作。官方 GA 基准里 4KiB 小对象 PUT 大约能到 MinIO 的 2.3 倍,备份这种大量小块的写入场景,小对象吞吐高一点,备份完成得就快一点。控制台在 /rustfs/console/ 路径下,进去能直接翻 backupstore/ 前缀确认块到位。
几个容易踩的点
- 端点从节点可达 :
AWS_ENDPOINTS填端口转发地址,备份管理器在节点上连不通,目标一直不可用; - Secret 先于目标:Secret 不存在就去 patch 目标,同步会失败,顺序不能反;
- 区域标注不是真区域 :
@us-east-1填啥都行,但这一栏不能为空; - 官方指南是集成测试用途:文档本身声明不适用于生产环境,生产里要补上专用凭证、TLS、限流和资源规划;
- 备份不替代副本:对象存储备份负责可恢复,运行时的高可用仍靠 Longhorn 副本,两者都要有。
接好之后,Longhorn 的卷删了、集群换了,备份都还在 RustFS 桶里,恢复只是换个地方读回那些块。
官方把 Longhorn 接进 RustFS 的完整步骤在 Longhorn 集成指南 里,包含快照、备份与恢复的示例清单。生产凭证的创建方式看 访问密钥管理,S3 兼容性细节看 S3 协议说明。