云原生数据库自动备份策略|K8s 定时备份 + 异地存储 + 过期清理
摘要
数据库上 K8s 后,别再把备份脚本挂 cron 里裸奔了。本文交付一套生产级云原生数据库自动备份方案,覆盖达梦 DM8、人大金仓 KingbaseES V9,使用 K8s CronJob 实现定时全量/增量备份,推送到 S3/MinIO 异地存储,并自动清理过期备份集。文中提供可直接复制的 YAML 配置、备份脚本、过期策略对照表及避坑清单,让你的信创数据库备份也享受云原生红利。
📌政务选金仓,金融选达梦;MySQL 迁移选金仓,Oracle 迁移选达梦。
1. 备份需求与总体设计
生产级数据库备份必须满足3-2-1 原则:至少 3 份副本,2 种不同介质,1 份异地。 容器化环境下的难点在于:
备份工具需在容器内可用,且不能依赖宿主机 cron。
数据目录通过 PVC 挂载,备份时要做到一致性。
备份文件要自动推到异地存储,不能留下单点。
总体设计:
K8s CronJob驱动备份任务,与数据库 Pod 共享数据卷(或通过远程备份)。
备份类型:每日全量 + 每小时归档日志备份。
存储目标:本地 NAS/NFS 先落一份,再通过
mc或s3cmd同步到 MinIO/S3 异地桶。过期清理:基于备份标签和保留天数自动删除。
✅ 适用场景:达梦单机/主备集群、人大金仓单机/高可用集群。
2. 环境与存储准备
| 组件 | 版本/说明 |
|---|---|
| Kubernetes | v1.28 |
| 达梦数据库 | DM8.1.2.192 |
| 人大金仓 | KingbaseES V9 |
| 本地备份存储 | NFS PV,挂载到/backup/local |
| 异地对象存储 | MinIO(或 AWS S3),bucket:db-backup-offsite |
| 备份工具 | dmrman(达梦)、sys_dump / sys_basebackup(金仓)、mc 客户端 |
存储类与 PVC 定义:
yaml # 本地备份 PVC apiVersion: v1 kind: PersistentVolumeClaim metadata: name: backup-local-pvc namespace: dm spec: accessModes: - ReadWriteMany resources: requests: storage: 500Gi storageClassName: nfs-clientMinIO 认证 Secret:
bash kubectl create secret generic s3-credentials \ --from-literal=accesskey=minioadmin \ --from-literal=secretkey=minioadmin \ -n dm3. CronJob 定时备份实战
3.1 达梦数据库全量备份 CronJob
达梦使用dmrman进行全量备份,需指定数据库 INI 文件路径。我们通过共享 PVC 的方式直接访问数据目录,并在容器中执行备份。
yaml apiVersion: batch/v1 kind: CronJob metadata: name: dm-full-backup namespace: dm spec: schedule: "0 2 * * *" # 每天凌晨2点 successfulJobsHistoryLimit: 2 failedJobsHistoryLimit: 2 jobTemplate: spec: template: spec: containers: - name: backup image: harbor.dm.local/dm8:tools # 包含 dmrman 的镜像 env: - name: BACKUP_DIR value: "/backup/local/dm/$(date +%Y%m%d)" - name: S3_BUCKET value: "db-backup-offsite" - name: S3_ACCESS_KEY valueFrom: secretKeyRef: name: s3-credentials key: accesskey - name: S3_SECRET_KEY valueFrom: secretKeyRef: name: s3-credentials key: secretkey command: ["/bin/bash", "-c"] args: - | set -e mkdir -p $BACKUP_DIR echo "开始达梦全量备份..." dmrman CTLSTMT="BACKUP DATABASE '/dm/data/DAMENG/dm.ini' FULL BACKUPSET '$BACKUP_DIR' COMPRESSED LEVEL 1" echo "备份完成,文件列表:" ls -lh $BACKUP_DIR # 同步到 S3/MinIO mc alias set myminio http://minio.minio:9000 $S3_ACCESS_KEY $S3_SECRET_KEY mc mirror $BACKUP_DIR myminio/$S3_BUCKET/dm/$(date +%Y%m%d)/ echo "异地同步完成" volumeMounts: - name: data mountPath: /dm/data readOnly: true # 只读挂载,保证一致性 - name: local-backup mountPath: /backup/local volumes: - name: data persistentVolumeClaim: claimName:>yaml apiVersion: batch/v1 kind: CronJob metadata: name: kingbase-full-backup namespace: kingbase spec: schedule: "0 2 * * *" jobTemplate: spec: template: spec: containers: - name: backup image: kingbase_v9:latest env: - name: PGDATA value: "/var/lib/kingbase/data" - name: BACKUP_DIR value: "/backup/local/kingbase/$(date +%Y%m%d)" command: ["/bin/bash", "-c"] args: - | set -e mkdir -p $BACKUP_DIR # 开始物理备份 sys_basebackup -h localhost -p 54321 -U system -D $BACKUP_DIR/base -Ft -z -P echo "金仓全量备份完成" # 推送到异地,工具类同 mc alias set myminio http://minio.minio:9000 $S3_ACCESS_KEY $S3_SECRET_KEY mc mirror $BACKUP_DIR myminio/$S3_BUCKET/kingbase/$(date +%Y%m%d)/ volumeMounts: - name: local-backup mountPath: /backup/local - name: data persistentVolumeClaim: claimName:>bash mc mb myminio/db-backup-offsite mc admin policy create myminio db-backup-write <<EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject", "s3:ListBucket"], "Resource": ["arn:aws:s3:::db-backup-offsite/*", "arn:aws:s3:::db-backup-offsite"] } ] } EOF mc admin user add myminio dbbackupuser <password> mc admin policy attach myminio db-backup-write --user dbbackupuser同步命令核心参数:
bash mc mirror --overwrite --remove --watch /backup/local myminio/db-backup-offsite/ 但在 CronJob 中我们通常执行单次同步,不需要 --watch,改为: bash mc mirror $BACKUP_DIR myminio/$S3_BUCKET/dm/$(date +%Y%m%d)/ mirror 命令会自动对比并只上传差异部分,节省带宽。5. 过期备份自动清理策略
保留策略建议:
| 备份类型 | 保留数量/天数 | 清理方式 |
|---|---|---|
| 每日全量 | 保留最近 7 天 | CronJob 每日检查,删除 7 天前目录 |
| 每小时归档 | 保留最近 24 小时 | 与全量同步清理 |
| 异地存储 | 保留 30 天 | MinIO 生命周期规则自动过期 |
本地清理脚本(附加在全量备份 CronJob 末尾):
bash # 清理 7 天前的本地备份 find /backup/local/dm/ -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \;MinIO 生命周期规则(通过 mc 设置):
bash mc ilm rule add --expire-days 30 myminio/db-backup-offsite这条规则会让 bucket 中超过 30 天的对象自动删除,无需手动干预。
✅ 为防误删,可在清理前加入文件列表审计:
bash find /backup/local/dm/ -maxdepth 1 -type d -mtime +7 > /tmp/cleanup.log6. 监控与告警闭环
备份任务不能悄无声息地失败,必须建立监控。
实现方式:
CronJob 成功/失败状态通过
kube-state-metrics暴露指标。配置 Prometheus 告警规则:最近一次 CronJob 执行失败或超过 24 小时未成功。
备份大小异常告警(与昨天比较波动 > 50%)。
Prometheus 告警规则示例:
yaml groups: - name: db-backup rules: - alert: DatabaseBackupJobFailed expr: kube_job_status_failed{job_name=~"dm-full-backup|kingbase-full-backup"} > 0 for: 5m labels: severity: critical annotations: summary: "数据库备份 Job 失败" description: "{{ $labels.job_name }} 执行失败,请立即检查。" - alert: DatabaseBackupMissing expr: time() - kube_job_status_last_successful_time{job_name=~"dm-full-backup-.*"} > 86400 for: 5m labels: severity: critical annotations: summary: "数据库备份超过 24 小时未成功"备份验证:定期(例如每周)从异地存储拉取备份进行恢复演练,确保备份可用。
7. 避坑清单(血泪史)
| 坑点 | 现象 | 根因与解决 |
|---|---|---|
| 备份时数据不一致 | 恢复后发现数据缺失 | 未用只读挂载或未开启归档;达梦务必用dmrman且数据库为 ARCHIVELOG 模式,金仓物理备份需连接数据库获取一致性位点 |
| CronJob 并发导致磁盘爆满 | 节点磁盘 100%,所有 Pod 异常 | 设置concurrencyPolicy: Forbid,并发时跳过新任务;并加上容量监控 |
| mc 推送失败但不中断脚本 | 后续删除过期备份,导致仅剩残缺副本 | 在脚本中加set -e且mc mirror返回非 0 时退出;或推送失败发送告警 |
| 权限不足导致备份文件无法读取 | 备份文件属主是 root,恢复容器内 dmdba 无法访问 | 在备份容器中设置securityContext.fsGroup: 1000,或在备份后执行chown 1000:1000 |
| PVC 容量不足,备份写到一半失败 | 备份任务连续失败 | 监控 PVC 使用率,设置persistentVolumeClaimRetentionPolicy配合清理脚本,或直接备份到对象存储(绕过本地) |
特别警示:绝对不要将数据库数据卷以读写方式挂载给多个 Pod,极易造成数据文件损坏。备份任务务必只读挂载数据卷。
📢 总结
这篇云原生备份方案,从 CronJob 定时调度、全量备份脚本、异地 MinIO 同步,到过期清理和监控告警,完整覆盖了达梦和人大金仓两大信创数据库的自动备份需求。所有 YAML 配置都可以直接复制进项目,稍作环境变量调整就能跑。
数据库上 K8s,备份策略不是脚本的堆砌,而是一套包含一致性保障、异地多副本、自动生命周期管理的闭环系统。把这套方案落地,你的数据库即使遭遇 PVC 损坏、机房级灾难,也能在分钟级恢复业务。