Skip to main content

为备份配置 Velero 原生 hook

对运行中的数据库直接做卷快照,拿到的是崩溃一致的数据——相当于给数据库拔电源后的磁盘状态。要得到应用一致的备份,必须在快照前让数据库把内存里的数据落盘并短暂静默。

SupKube 不会替您修改工作负载,这是产品的安全红线。它会识别出风险并给出对应引擎的命令,实际的注解由您自己施加。

前置条件​

  • 目标数据库以 StatefulSet 或 Deployment 形式运行在集群里。
  • 您有权限给目标工作负载添加注解。
  • 已了解备份策略的基本配置。

为什么需要这一步​

这不是理论风险。下面是一次真实的跨集群迁移故障:

跨集群迁移,还原到新集群后
│
┌──────────┴───────────┐
▼ ▼
无状态应用 运行中的数据库
全部正常起来 ┌────────────────────────────────┐
│ Doris BE 起不来 │
│ failed to get file size │
│ ...dat: No such file or │
│ directory │
│ │
│ mysql-n9e 崩溃退出 (exit=2) │
└────────────────────────────────┘

同一次备份、同一次还原,差别只在于备份时数据库是否处于可安全快照的状态。

崩溃一致(默认) 应用一致(配了 hook)
───────────────── ─────────────────────
直接对卷拍快照 pre-hook:落盘 + 上锁
│ │
▼ ▼
内存中未落盘的数据丢失 对卷拍快照
可能停在写了一半的事务中 │
│ ▼
▼ post-hook:解锁
还原后数据库可能拒绝启动 │
▼
还原后可正常启动

SupKube 帮您做到哪一步​

策略保存前的备份就绪性检查会自动识别运行中的数据库,并判断是否已经配了 hook。

识别靠两级启发式:

依据说明
容器镜像名9 个已知子串映射到 6 种引擎
容器端口3306、5432、27017、6379、8123、9030、8030、9060

命中且未配 hook 时,预检给出警告级结论(不是阻断),并附上该引擎对应的注解示例。

为什么是警告而不是阻断

产品并不知道您的备份一定会失败,只知道有风险。代码注释对此的解释是:阻断会"伪装出一种确定性"——有些场景下崩溃一致的备份确实够用,把它一刀切掉反而是错的。

SupKube 不会替您改工作负载

预检给出的是可复制的命令文本,不是可执行的蓝图。产品不会自动给您的 Pod 打注解。

这条红线在别处也一致:Azure 存储的 IAM 提权命令同样只给文本、绝不代跑。涉及修改您的工作负载或提升权限的操作,一律由您自己执行。

您需要自己做什么​

给数据库 Pod 打上 Velero hook 注解。可以直接 kubectl annotate,但推荐改工作负载模板——否则 Pod 重建后注解就没了。

注解加在 Pod 模板上(不是 StatefulSet 本身):

spec:
template:
metadata:
annotations:
pre.hook.backup.velero.io/container: mysql
pre.hook.backup.velero.io/command: '["/bin/bash","-c","mysql -uroot -p$MYSQL_ROOT_PASSWORD -e \"FLUSH TABLES WITH READ LOCK;\""]'
post.hook.backup.velero.io/container: mysql
post.hook.backup.velero.io/command: '["/bin/bash","-c","mysql -uroot -p$MYSQL_ROOT_PASSWORD -e \"UNLOCK TABLES;\""]'

各引擎对应的命令​

引擎pre-hookpost-hook
MySQL / MariaDB / PerconaFLUSH TABLES WITH READ LOCKUNLOCK TABLES
PostgreSQLCHECKPOINT不需要
MongoDBdb.fsyncLock()db.fsyncUnlock()
RedisSAVE不需要
ClickHouseSYSTEM STOP MERGESSYSTEM START MERGES
Apache Doris无单条 flush 命令,见下不需要
有 pre 就必须有 post

MySQL 与 MongoDB 的 pre-hook 会持有锁。如果 post-hook 缺失或执行失败,数据库会一直锁着,业务随即受影响。

配置后请务必做一次实际备份验证解锁生效,不要只在演练环境试一次就上生产。

PostgreSQL​

pre.hook.backup.velero.io/container: postgres
pre.hook.backup.velero.io/command: '["/bin/bash","-c","psql -U postgres -c \"CHECKPOINT;\""]'

CHECKPOINT 把脏页刷入磁盘,不持有长锁,因此不需要 post-hook。

MongoDB​

pre.hook.backup.velero.io/container: mongodb
pre.hook.backup.velero.io/command: '["/bin/bash","-c","mongosh --eval \"db.fsyncLock()\""]'
post.hook.backup.velero.io/container: mongodb
post.hook.backup.velero.io/command: '["/bin/bash","-c","mongosh --eval \"db.fsyncUnlock()\""]'

Apache Doris​

Doris 没有单条等价于 flush 的命令。可行的做法是在备份窗口前暂停导入任务,或接受崩溃一致备份并在还原后手工修复 BE 节点。这一条产品只给出占位提示,没有可直接复制的命令。

验证方法​

确认注解已经生效:

kubectl -n my-app get pod my-db-0 \
-o jsonpath='{.metadata.annotations}' | tr ',' '\n' | grep hook.backup

跑一次备份后,确认 hook 真的执行了:

kubectl -n supkube logs deploy/velero | grep -i hook

再次保存策略时,备份就绪性检查中原先那条数据库警告应当消失。

最可靠的验证仍然是做一次真实还原:把备份还原到一个新建命名空间,确认数据库能正常启动且数据完整。

相关文档​