etcd 快照救的是 API server 里的数据PV 里的数据不在其中业务对象加 PV 数据的应用级备份K8s 生态里的标准工具是 Velero把集群资源对象和 PV 数据备份进对象存储桶恢复时再从桶里拉回来。它通过 AWS 插件兼容任意 S3 后端不过官方对 S3 兼容存储的定位要说准兼容列表的措辞是用户报告可用users have reportedVelero 团队不做常规测试。MinIO、Tencent Cloud、Ceph 都在这个列表里社区用量大、文档齐全但选型时要知道这层背书的分量。这篇把 Velero 的备份后端接到自建的 RustFS 上从装到恢复演练走一遍。当前最新版是 v1.18官方安装文档为准AWS 插件版本要按官方兼容表跟 Velero 版本对齐。PV 数据走哪条路先想清楚Velero 备份分两层集群资源对象yaml 世界直接序列化进桶PV 数据要另选路径。云上有卷快照插件EBS、Azure Disk 这类自建存储通常没有对等的快照能力所以走File System BackupFSB在每个节点上跑 node-agent把 PV 数据当作文件直接复制进桶不需要卷快照插件。装服务端时加--use-node-agent就启用它。FSB 的官方定性是beta 质量FSB 文档原话 “considered beta quality”前提也先对齐Kubernetes v1.16.0 以上且集群要启用 MountPropagation 特性老集群先自查这两条。实现上实际走的是 kopia 的模块文档开头还并列提了 restic但正文通篇 backed by kopia官方 NOTE 明确 restic 路径在弃用流程里v1.17 起不能再做 restic 备份v1.19 起连恢复老 restic 备份也会关掉。当默认路径用没问题但几条限制要先知道hostPath 卷不支持local PV 支持只能备被 Pod 挂载着的卷不能直接从 PVC 备没有运行中 Pod 的孤儿 PVC 备不了社区的做法是先起一个挂着 sleep 容器的 staging podscale 到 0 的 StatefulSet 撞的就是这个增量链只对 PVC 保持emptyDir 这类非 PVC 卷在 Pod 重建后下一次是全量单个大文件数据库文件的去重扫描很慢即使实际差异很小。还有一条安全边界值得单独记FSB 的备份仓库用一把静态公共加密密钥官方原话是任何能访问你备份存储的人都能解密你的备份数据。桶的访问控制要按看到桶看到全部数据来收紧这也是给 Velero 桶单发凭证之外更要在意桶策略的原因。顺带一提 node-agent 的运行环境它靠读宿主机文件系统来拿 Pod 卷数据官方 Pros/Cons 里写明需要 root、部分环境还要 privileged 模式OpenShift/SELinux 这类受限环境用--privileged-node-agent安装或自建 SCC 放开。标准 K8s 集群一般不用管安全基线紧的集群要先跟平台方对齐。另一个要提前想好的点Velero 的备份对象自带 TTL 管理创建备份时可以给--ttl指定保留期不设默认 30 天到期由垃圾回收流程清理桶里的备份文件。所以桶上不该再叠 lifecycle expiration更不能配 immutability / object lock 这类防改写保留策略官方文档明确说 v1.11 起 Velero 备份完成时要改写桶内对象元数据桶一旦配了不可变保留备份删除会出问题。顺带一提桶版本控制的账官方在 AWS S3 一节写明 object lock 只作用于版本化桶这时删备份只是打 delete marker对象的旧版本不会被删空间不会真的释放。默认建议是备份桶不开版本控制若出于防误删仍想开就得自己补一条非当前版本的过期规则来回收旧版本空间做法在之前 RustFS lifecycle 那篇里核过的--noncurrent-expiry-days。这个和 JuiceFS 那篇别叠 lifecycle的道理同源在备份桶上代价更直接。第一步起 RustFS建桶dockerrun-d\--namerustfs\--restartunless-stopped\-p9000:9000\-p9001:9001\-vrustfs-data:/data\-eRUSTFS_ACCESS_KEYyour-access-key\-eRUSTFS_SECRET_KEYyour-secret-key\-eRUSTFS_ADDRESS:9000\-eRUSTFS_CONSOLE_ADDRESS:9001\-eRUSTFS_CONSOLE_ENABLEtrue\rustfs/rustfs:latest\/data建一个 Velero 专用的桶凭证单发给备份系统单独一把 key权限面小exportAWS_ACCESS_KEY_IDyour-access-keyexportAWS_SECRET_ACCESS_KEYyour-secret-keyaws --endpoint-url http://localhost:9000 s3 mb s3://velero第二步凭证文件与 velero installVelero 用 AWS 风格的凭证文件建一个credentials-velero[default] aws_access_key_id your-access-key aws_secret_access_key your-secret-key然后装服务端这是全文最关键的一条命令veleroinstall\--provideraws\--pluginsvelero/velero-plugin-for-aws:plugin-version\--bucketvelero\--secret-file ./credentials-velero\--use-volume-snapshotsfalse\--use-node-agent\--backup-location-configregionminio,s3ForcePathStyletrue,s3Urlhttp://rustfs-host:9000\--wait几个参数的来历--provider aws配 AWS 插件这是接所有 S3 兼容后端的官方姿势RustFS 不需要专门的插件。插件版本按官方兼容表对齐主版本对应关系简单插件 v1.14.x ↔ Velero v1.18.x往下 v1.13.x ↔ 1.17.x、v1.12.x ↔ 1.16.x混着装会有兼容问题。--use-volume-snapshotsfalse自建侧没有卷快照提供方明确关掉避免创建用不上的 VolumeSnapshotLocation。regionminio是官方 MinIO 示例的填法。自建服务没有真的 region 概念照抄这个惯例值就行。s3ForcePathStyletrue是自建后端的生死开关。官方文档的原话值得整段读不设或设为 false 时 AWS SDK 走 virtual-host 寻址桶名进域名而 MinIO 这类自建服务默认只支持 path-style 寻址桶名进路径不匹配的后果是 Velero能把备份传上去但从桶里下载不了也就是备份看起来在跑恢复时才炸。官方给了一个真实 issue 作例子解法有两条设s3ForcePathStyletrue官方推荐或者让服务端支持 virtual-host 寻址MinIO 配MINIO_DOMAIN环境变量。多数自建场景选第一条更省事。BSL 的全部 config 键含校验和、签名版本、证书这些后文会用到的在 AWS 插件的 BackupStorageLocation 文档里有逐键说明。s3Url指向 RustFS 的内网地址K8s 节点要能直达。第三步第一个备份验证装好了然后拿一个带 PV 的应用开刀velero backup-location get velero backup create demo-backup--selectorappdemo --default-volumes-to-fs-backup velero backup describe demo-backup--details--default-volumes-to-fs-backup让这次备份的 PV 数据全走 FSB 路径这个参数也可以在velero install时直接带上对所有备份生效。describe 的输出里看两个东西Phase 是不是 CompletedFSB 的条目有没有挂错误。桶里此刻应该已经出现了备份 tarball 和 FSB 数据对应的对象node-agent 的日志是 FSB 排障的第一入口。第四步恢复演练——备份的检验标准只有这一条备完了不算完删掉重来才算kubectl delete namespacedemo-nsvelero restore create --from-backup demo-backup velero restore getSTATUS 从 InProgress 走到 Completed、WARNINGS 和 ERRORS 都是 0才叫这套备份真的能用。有错就velero restore describe name --details报错条目会指到具体资源。还有一类静默失败值得提防官方文档main 分支新增的 File Ownership and Permission Preservation 一节写明在属主和权限由挂载配置强制决定的卷上Azure Files 的 SMB/CIFS、blobfuse、GCP FUSE 这类 mount-constant identity 文件系统FSB 恢复时以 root 执行 chown/chmod 会返回成功但什么都没改restore 照样 Completed 零告警日志里也没有痕迹。自建块存储的 ext4/xfs PVC 不在此列但演练时多抽查一两个文件的属主和权限成本很低。定期备份一个 cron 搞定velero schedule create demo-daily--schedule0 1 * * *--selectorappdemo --default-volumes-to-fs-backup自建后端常见的四个坑describe 打不开日志或下载链接失效。velero backup describe --details和velero logs会生成预签名 URL 供客户端下载URL 默认指向 s3Url 的集群内地址从你的笔记本当然打不开。修法是给 BackupStorageLocation 加publicUrl值是集群外可达的地址NodePort 或 Ingress 都行必须带http://或https://前缀。自签名证书。RustFS 前面挂了 HTTPS 用自签证书时官方给的两条路是 BSL config 里设insecureSkipTLSVerify: true或提交 CA 证书。官方文档自己标注了 insecureSkipTLSVerify 有中间人风险、不推荐生产生产环境老老实实配 CA。上传报校验类错误。AWS 插件给上传对象默认附 CRC32 校验和BSL config 键checksumAlgorithm默认值 CRC32个别自建端点不支持时可以把它设为空字符串关掉。注意这个开关和 JuiceFS 的disable-checksum不是一层东西Velero 的checksumAlgorithm控制 AWS SDK 上传请求头里的校验和JuiceFS 那个控制的是它自身写进对象元数据的 CRC遇到报错先分清是哪一层的校验在喊疼。签名版本。预签名 URL 走 SigV4默认极少数 S3 兼容实现只认 V1BSL config 里signatureVersion: 1是官方留的开关Quobyte 这类属于此列。这套组合里对象存储的位置Velero 把备份的调度、资源序列化、PV 数据搬运全做了对后端只有一个要求S3 兼容、path-style、稳定可达。RustFS 单二进制起服务S3 全兼容接进来就是建一个桶加三条 config 的成本。备份系统里最不该薄的其实是演练上面的第四步每周跑一次比任何配置优化都值钱。