为备份配置 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 时,预检给出警告级结论(不是阻断),并附上该引擎对应的注解示例。
产品并不知道您的备份一定会失败,只知道有风险。代码注释对此的解释是:阻断会"伪装出一种确定性"——有些场景下崩溃一致的备份确实够用,把它一刀切掉反而是错的。
预检给出的是可复制的命令文本,不是可执行的蓝图。产品不会自动给您的 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-hook | post-hook |
|---|---|---|
| MySQL / MariaDB / Percona | FLUSH TABLES WITH READ LOCK | UNLOCK TABLES |
| PostgreSQL | CHECKPOINT | 不需要 |
| MongoDB | db.fsyncLock() | db.fsyncUnlock() |
| Redis | SAVE | 不需要 |
| ClickHouse | SYSTEM STOP MERGES | SYSTEM START MERGES |
| Apache Doris | 无单条 flush 命令,见下 | 不需要 |
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
再次保存策略时,备份就绪性检查中原先那条数据库警告应当消失。
最可靠的验证仍然是做一次真实还原:把备份还原到一个新建命名空间,确认数据库能正常启动且数据完整。