跳到正文

备份与灾备说明

查看 Markdown

初稿(2026-11-05)。适用于私有化部署(单机 Docker Compose 与 Kubernetes)。部署形态见《产品架构与部署白皮书》;加密与访问控制见《安全白皮书》。

1. 数据在哪里

数据内容存放位置
PostgreSQL 集群平台业务库(租户、业务数据、草稿等)、审计库、身份(Zitadel)的库、工作流(Temporal)与各工具的库Postgres 数据卷
OpenBao敏感字段的数据密钥、租户凭据(自带存储、自带模型的密钥)、派生密钥的根OpenBao 数据卷(文件存储)
平台文件上传的文件、头像、录音、审计归档分段single:kwork 数据卷;onprem:自带 SeaweedFS;云 Pack:云厂商的桶
配置与密钥安装时生成的全部密钥(含备份加密密钥)、导出的网关根证书主机上的部署配置目录
许可证许可证文件与厂商公钥主机上的部署配置目录
租户自带存储租户自己配置的 S3 / OSS / COS / MinIO 桶里的文件租户自己的桶

2. 备份方式与频率

数据方式频率怎么打开
PostgreSQL 整个集群WAL-G:经复制协议持续接收 WAL,加密后上传到 S3 兼容存储;每天一次全量WAL 持续(每 60 秒强制切换一次 WAL 段);全量每天 02:30 UTC,默认保留最近 7 个安装时加 backup;默认不打开
OpenBao 数据卷、kwork 数据卷、配置与密钥状态包:一次打成一个加密归档,可直接上传到 S3 兼容存储每次执行一个;按每日执行配置定时任务(由你配置)随平台提供,需你安排定时执行
许可证不在任何备份里换文件时厂商给的原件另存
  • 数据库备份不改动、不重启 Postgres 服务,只通过网络读取。
  • 备份服务有健康检查:WAL 流在运行、上一次全量不超过 26 小时。不满足时显示为不健康。
  • 升级脚本在打开备份时,升级前先做一次全量备份和一次状态包。
  • 不打开数据库备份的安装,至少每天自行做一次数据库导出。
  • 以上备份服务与状态包只用于单机 Compose 形态。Kubernetes 形态的 PostgreSQL、对象存储与 OpenBao 由你提供,按所用服务的方式备份(例如托管数据库自带的时间点恢复)。

2.1 备份送到哪里

  • onprem 不另行配置时,数据库备份送到自带的 SeaweedFS。它还在同一台主机上:主机或磁盘整体损坏时备份也会丢失。生产环境请指向另一个机房或云上的存储。巡检(kwork doctor 的 backup_offsite)在备份送到同一台主机时给出提醒。
  • single 与云 Pack 必须先配置备份存储,否则安装拒绝打开备份。
  • 建议:备份存储的凭据只授权这一个桶;桶开启版本控制,可能时开启对象锁定,防止主机被入侵后备份被删除。

3. 加密与密钥保管

对象加密密钥谁保管
数据库全量与 WAL在主机上用 libsodium(secretbox)加密后才上传,存储方看不到内容备份加密密钥(32 字节,安装打开备份时生成)你:生成后立即离线另存,至少两份
状态包AES-256-CBC,PBKDF2 派生(200,000 轮)同一把备份加密密钥同上
OpenBao 数据OpenBao 自身封存5 份解封密钥,任意 3 份可解封你指定的不同保管人,各自离线保存
  • 丢了备份加密密钥,所有数据库备份和状态包都无法打开,没有任何恢复办法。不要只放在这台主机上。
  • 更换备份加密密钥只对之后的备份生效;旧备份仍需旧密钥,旧全量过了保留期之后才能丢弃旧密钥。
  • 解封密钥在初始化时写入主机上的一个文件。分发给保管人后要从主机删除该文件:否则它会进入状态包,解封份额、OpenBao 数据和加密密钥会出现在同一个包里,3/5 分持失去意义。OpenBao 的 root token 同样离线保存。巡检(kwork doctor 的 unseal_file)只看这个文件在不在、放了多久,不读内容:在就提醒,超过 7 天报异常。
  • OpenBao 每次重启后都处于封存状态,需要 5 位保管人中任意 3 位输入各自的份额解封;封存期间平台的就绪检查失败。目前没有自动解封。
  • 数据库备份角色可以读到整个集群的数据文件,其密码按超级用户密码的级别保管。

4. RPO 与 RTO

RPO 是可能丢失的数据时间窗口;RTO 是恢复所需时间。

项值类型
RPO≤ 5 分钟目标
RTO≤ 1 小时(SaaS 的目标;私有化部署的 RTO 取决于你的备份存储、数据量与演练结果)目标
丢数据窗口(设计上限)约 60 秒加上传时间(由 WAL 段切换间隔决定)配置值
丢数据窗口:源库被强制杀掉并删除数据卷后恢复33 秒实测
丢数据窗口:恢复后的第二条时间线55 秒实测
丢数据窗口:对运行中的完整平台数据库做备份并恢复42 秒实测
数据库恢复耗时:329 MB 集群,最新全量 + 全部 WAL,冷启动35.4 秒实测
数据库恢复耗时:时间点恢复17.4 秒实测
数据库恢复耗时:514 MB 的完整平台数据库13.0 秒实测

实测条件(2026-10-06):开发机上的 Docker 虚拟机(aarch64,4 核,与其他任务共用,磁盘 I/O 慢),存储为同网络的 SeaweedFS。恢复耗时只是数据库部分,不含新主机准备、状态包解开、OpenBao 解封和服务启动。按这次的速度粗算,取全量约 17 MB/s。

尚未实测的:

  • 几十 GB 到 TB 级数据的全量与回放耗时;
  • 跨机房、跨地域的备份存储,以及云厂商的对象存储(AWS S3、阿里云 OSS、腾讯云 COS);
  • 把恢复出的数据库换回正在运行的平台,以及整机重建的端到端耗时;
  • 7 天保留期的自然轮转;复制槽超过 8 GB 被放弃后的追赶。

5. 恢复演练

数据库恢复演练不碰正在运行的平台:

  1. 演练脚本在一个一次性的容器和数据卷里取出全量、从备份存储取 WAL 回放到末尾(或指定时间点),然后提升为主库。
  2. 恢复出的数据库只开本地 socket,不监听网络、不归档,网络上的任何服务都连不到它。
  3. 脚本检查业务库、审计库、身份库都在,报告租户数、迁移版本、审计事件数与最新事件时间,并与运行中的源库对比落后多少数据。
  4. 打印每一段的耗时:这就是你环境里数据库部分的 RTO。
  5. 结束后容器和数据卷全部删除。

状态包演练:用离线保存的那份备份加密密钥(不读主机上的配置)把最新状态包解到一个临时目录,确认 OpenBao 数据在其中。这同时证明离线保存的密钥是对的。

建议频率:上线前一次,之后每季度一次(单机 Beta 环境建议每月一次)。整机重建演练的顺序:新主机装好 Docker → 放上同一版本的部署文件与许可证 → 用离线密钥解开状态包并放回配置、密钥与 OpenBao 数据 → 恢复数据库到指定时间点 → 启动平台 → 保管人解封 OpenBao → 登录、打开一个已有文件、对每个租户校验审计链。网关的内置 CA 不在备份中,重建后会生成新的根证书,要重新分发给用户和运维人员。

6. 时间点恢复

  • 可以把数据库恢复到保留期内的任意时间点:默认保留最近 7 个每日全量及其之后的 WAL。
  • 实测:目标时间设在两批写入之间,恢复结果准确落在两批之间(第一批在、第二批不在)。
  • 真实恢复时先停止所有写入数据库的服务,把旧数据移到另一个数据卷(不删除),再恢复到空目录。恢复只往空目录写。
  • 恢复之后数据库进入新的时间线,要立刻做一次全量备份。
  • 时间点恢复会丢掉该时间之后的全部改动,要告知用户。
  • 数据库与 OpenBao 要恢复到同一时期,否则依赖派生密钥的退订链接与站点会话会失效。

7. 不在平台备份范围内的

数据说明
租户自带存储里的文件在租户自己的桶里,由租户开启版本控制或跨地域复制
云 Pack 的平台文件桶在你的云账号里,由你开启版本控制或跨区复制
onprem 自带 SeaweedFS 里的平台文件与审计归档不在状态包里,需另做复制
网关证书与内置 CA不备份;重建后重新签发
观测数据(指标、日志、链路、Langfuse)、模型网关的本地数据不备份;模型网关的供应商与密钥由平台重新同步
许可证文件与厂商公钥厂商给的原件另存
主机磁盘快照不由平台提供;云主机可使用云厂商的快照

8. 当前限制

  • 单机部署不是高可用:主机故障期间平台不可用,按本文 §5 的顺序在新主机上重建。
  • 多可用区与异地灾备没有提供。备份可以送到另一个地域的存储,但没有自动切换。
  • 数据库主备切换:只适用于 Kubernetes 形态,由你提供的 Postgres 负责切换,平台连跟随主库的地址。已在单节点测试集群上用 CloudNativePG(一主一备、异步复制)实测计划切换、删除主库、进程被杀、网络隔离、进程冻结五种场景,写入在约 2.5 秒到 126 秒内恢复,取决于场景。异步复制下非计划切换会丢失尚未复制到备库的已提交写入,实测中出现过“变更已生效、审计没写上”。同步复制、托管数据库(RDS、PolarDB 等)的切换、PgBouncer、多节点集群的真实节点故障都没有测。
  • OpenBao 需要人工解封:每次主机或 OpenBao 重启后,由保管人解封。
  • 审计归档的对象锁定:自带的 SeaweedFS 不支持对象锁定,此时归档是未锁定的独立副本;要锁定,换用支持对象锁定的 S3 兼容存储。

本页目录