用RustFS自建S3兼容对象存储,在Kubernetes上搞定数据库备份恢复
本文是一篇实操向技术教程。记录如何把 RustFS 作为自托管 S3 存储,配合 OpenEverest 在 Kubernetes 上完成 PostgreSQL 的备份与恢复。所有命令均经过原作者环境验证,可直接照抄。
为什么不直接用云厂商 S3?
跑数据库最怕两件事:误删/故障后没处恢复,以及备份全躺在云厂商桶里,想迁走又舍不得出网费。
如果你在做私有化部署、内网环境,或者单纯不想被云厂商锁定,一个 S3 兼容的自托管对象存储就是刚需。RustFS 是这两年比较活跃的一个选择——Apache 2.0 协议、S3 兼容、用 Rust 写的开源对象存储,单二进制轻量,standalone 模式一条 Helm 命令就能起来。
本文就用它替代云 S3,配合 OpenEverest(CNCF 下的 Kubernetes 数据库运维项目)走完一整套 PostgreSQL 备份 / 恢复流程。从部署到真实数据恢复验证,全程可复现。
环境与前置条件
开始前确认你已经具备:
一个可用的 Kubernetes 集群(k3s、kind 或任意发行版均可)
已安装并运行 OpenEverest,且至少启用一种数据库引擎(本文用 PostgreSQL)
已配置好 kubectl
已安装 helm
对 OpenEverest 控制台有基本了解
提示:本文默认 OpenEverest 已装好并运行。如果还没装,建议先看官方《Running Databases on Kubernetes Locally with OpenEverest》把底座搭起来。
一、部署 RustFS(standalone 模式)
RustFS 通过 Helm 安装。默认是 4 副本的分布式模式(追求高可用),但本教程只是测试/学习环境,用 standalone 单实例 就够了。
1.1 添加 Helm 仓库
helm repo add rustfs https://charts.rustfs.com helm repo update
1.2 先看一眼默认配置
改配置前,先了解 RustFS 默认用了哪些值:
helm show values rustfs/rustfs
用 override 文件时,Helm 只会覆盖你显式指定的字段,其余保持默认值不变。
1.3 写一份 override-values.yaml
cat < override-values.yaml replicaCount: 1 mode: standalone: enabled: true distributed: enabled: false secret: rustfs: access_key: secret_key: ingress: enabled: false EOF
把 和 换成你自己的值。自建存储一定要用独立凭证,别图省事用默认值。
1.4 安装
kubectl create namespace rustfs helm install rustfs rustfs/rustfs -n rustfs -f override-values.yaml
1.5 确认跑起来了
$ kubectl get pods -n rustfs NAME READY STATUS RESTARTS AGE rustfs-c8dd447c9-4wx2q 1/1 Running 0 47s
$ kubectl get svc -n rustfs NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE rustfs-svc ClusterIP 10.43.221.127 9000/TCP,9001/TCP 3m54s
你应该看到一个 Pod 在 Running,以及一个带两个端口的 Service:
9000:数据读写端口(OpenEverest 实际打交道的就是它)
9001:Web 控制台端口,用来浏览文件
1.6 打开控制台
把端口转发到本地,方便浏览器访问:
kubectl port-forward -n rustfs svc/ 9000:9000 9001:9001
然后浏览器打开 http://localhost:9001,用你刚设的 access key / secret key 登录。

二、在 RustFS 里建一个 Bucket
控制台能打开了,下一步建一个 bucket。bucket 就是存放备份的容器,类似一个文件夹。
左侧菜单进 Browser
右上角点 Create Bucket
起个名字,比如 postgresql-backups
点 Create
你的新 bucket 会出现在列表里。

继续之前,先把接下来要用到的信息记好:
Bucket 名:postgresql-backups
Access Key / Secret Key:就是 override-values.yaml 里设的那一对
Endpoint:下一步接入 OpenEverest 时要填,格式如下:
http://.rustfs.svc.cluster.local:9000
三、把 RustFS 接进 OpenEverest
RustFS 跑起来、bucket 也建好了,现在把它登记成 OpenEverest 的备份存储。
3.1 打开 Backup Storages 页面
在 OpenEverest 控制台里,进入 Settings → Backup Storages。

3.2 点 Add backup storage,按下面填
Name:rustfs-backup-storage
Namespace:everest
Type:S3 Compatible
Bucket Name:postgresql-backups
Region:us-east-1
Endpoint:http://.rustfs.svc.cluster.local:9000
Access Key:你的 RustFS access key
Secret Key:你的 RustFS secret key
Verify TLS certificate:不勾选
Force path-style URL access:勾选
3.3 点 Add
OpenEverest 会用这些信息去连 RustFS。填对了就能成功添加,列表里会出现这条备份存储。

几个容易踩的点:Region 字段 RustFS 本身不强制使用,但客户端表单要求必填,随便填一个 AWS 风格的串即可;Force path-style URL access 必须勾上,因为 RustFS 默认就是 path-style 寻址。本文没配 TLS 证书,所以走的是明文 HTTP,Verify TLS 不勾、endpoint 用 http://。如果你在部署里配了证书,那就反过来:勾上证书校验、endpoint 用 https://。
四、建数据库集群 + 配置定时备份
备份存储接好了,接着建一个数据库。本文用 PostgreSQL。
4.1 新建数据库
OpenEverest 首页点 Create database。
4.2 基础信息
引擎选 PostgreSQL,第一屏填:
Namespace:比如 everest
Display name:比如 postgresql-384
Database version:比如 18.3
点 Continue。

4.3 资源配置
节点数
单节点规格
PG Bouncer
测试环境 1 节点 Small 规格就够。点 Continue。

4.4 设置备份存储
向导往下走会到 Backups 步骤,在这里:
把备份位置选成 rustfs-backup-storage
打开定时备份(比如每天固定时间)
设保留策略(同时保留几份备份)

4.5 完成创建
走完剩余向导点 Create。OpenEverest 会拉起集群,可能要等几分钟。

4.6 确认组件都起来了
$ kubectl get pods -n everest NAME READY STATUS RESTARTS AGE percona-postgresql-operator-5c4dd655bd-9hmzm 1/1 Running 0 83m percona-server-mongodb-operator-7bb69bb49b-nq2xp 1/1 Running 0 83m percona-xtradb-cluster-operator-684cd7646c-286q6 1/1 Running 0 83m postgresql-384-backup-tssw-6chzs 0/1 Completed 0 102s postgresql-384-instance1-vvmn-0 4/4 Running 0 118s postgresql-384-pgbouncer-5fd7c9df7d-xflst 2/2 Running 0 115s postgresql-384-repo-host-0 2/2 Running 0 116s
你应该看到新的 Postgres 实例,连同它的 pgBouncer 和 repo-host Pod 都处于 Running。
五、手动备份,并确认真的存进了 RustFS
数据库跑起来、也连上了 RustFS,现在做一次备份,确认它真的落到了自托管的 S3 桶里。
5.1 打开 Backups 标签页
在 OpenEverest 里打开你的数据库集群,点 Backups 标签。

5.2 创建备份
点 Create backup,存储位置选 rustfs-backup-storage,启动。点 Create。

5.3 等它跑完
状态会从 Starting → Running → Succeeded,视库大小可能要一两分钟。

5.4 去 RustFS 控制台确认
打开 RustFS 控制台(http://localhost:9001),进你的 bucket,应该能看到这样的结构:
一个以 F 结尾的时间戳文件夹(全量备份)
一个 backup.history/ 文件夹
backup.info 和 backup.info.copy 文件
这些文件由 pgBackRest 生成——OpenEverest 在底层就是用它来做 Postgres 备份的。

六、恢复验证:用真实数据测一遍
光看状态 Succeeded 不算数,得真刀真枪验证恢复能回到备份时刻的状态。
6.1 先塞点数据
连进正在跑的 Postgres:
kubectl exec -it -n everest -- psql
建表插两行:
CREATE TABLE blog_demo (id SERIAL PRIMARY KEY, note TEXT, created_at TIMESTAMP DEFAULT now()); INSERT INTO blog_demo (note) VALUES ('before-backup-row-1'); INSERT INTO blog_demo (note) VALUES ('before-backup-row-2'); SELECT * FROM blog_demo;
预期看到 2 行。
6.2 做一次备份
按上一节的步骤来,等状态到 Succeeded。
6.3 再插一行(这行是"试金石")
INSERT INTO blog_demo (note) VALUES ('after-backup-should-disappear'); SELECT count(*) FROM blog_demo;
现在应该是 3 行。这行就是用来验证的——如果恢复有效,它该消失。
6.4 执行恢复
进集群的 Actions 菜单,点 Restore from a backup,选刚才那次备份,点 Restore。集群会短暂进入 restoring 状态,恢复完回到 Up。

6.5 校验数据
重新连进去查:
SELECT * FROM blog_demo; SELECT count(*) FROM blog_demo;
预期结果:count 回到 2,只剩 before-backup-row-1 和 before-backup-row-2,after-backup-should-disappear 没了。这说明恢复确实把数据带回了备份时刻的状态。
七、另一种恢复:从备份克隆出新集群
Actions 菜单里还有第二个选项 Create DB from a backup。它不往原集群恢复,而是用这份备份当初始数据,拉起一个全新的独立集群,原集群不受影响。
想搞一份数据副本做测试、预发、或者翻旧数据,又不想动线上库时,这个最方便:
Actions → Create DB from a backup → 选备份 → 填新集群名走完向导。
小结
这一套下来,我们用了 RustFS 这个自托管、开源的 S3 兼容存储,替代云厂商桶,给 OpenEverest 上的 PostgreSQL 做了备份,并真实验证了恢复。整套链路完全开源、不依赖任何云厂商,适合私有化、内网、降本和避免锁定。
几点个人体会,供参考:
RustFS 的 standalone 模式部署成本极低,本地 kind/k3s 里几分钟就能验证通,适合先跑通再上生产。
跟 OpenEverest 这类 K8s 数据库运维面板配合,备份/恢复基本是向导式操作,对不想手写 pgBackRest 脚本的同学很友好。
生产环境建议上分布式模式 + TLS,本文的 standalone + 明文 HTTP 仅用于学习和测试。
作为较年轻的项目,RustFS 在大规模生产场景的验证还在累积中,正式上生产前建议先在你们自己的 workload 上压一轮。
如果你们也试了这套组合,欢迎在评论区聊聊踩坑经验。
参考
OpenEverest 官方教程(英文原文):https://openeverest.io/blog/self-hosted-s3-rustfs/
RustFS 项目:https://www.rustfs.com
OpenEverest 项目:https://openeverest.io
本文配图来自 OpenEverest 官方教程(链接见上),仅作技术步骤示意,版权归原作者所有。
