摘要

 数据库上 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. 环境与存储准备

组件版本/说明
Kubernetesv1.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-client

MinIO 认证 Secret:

bash

kubectl create secret generic s3-credentials \
  --from-literal=accesskey=minioadmin \
  --from-literal=secretkey=minioadmin \
  -n dm

3. 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: data-dm-primary-0   # 与数据库 Pod 相同 PVC
          - name: local-backup
            persistentVolumeClaim:
              claimName: backup-local-pvc
          restartPolicy: OnFailure

💡 只读挂载数据卷,避免备份任务意外修改数据文件。达梦的 dmrman 在读环境下可正常备份,但一定要确保数据库处于归档模式。

3.2 人大金仓全量备份 CronJob

金仓可使用 sys_dump 进行逻辑备份,或 sys_basebackup 做物理备份。物理备份效率高,适合大型库。

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: data-kingbase-0
            readOnly: true
          ...

🛑 注意: 物理备份需要连接到数据库实例,如果数据库 Pod 没有 Service,可以通过 sidecar 或者直接 kubectl exec 方式;这里推荐使用独立 CronJob 连接数据库 Service 执行备份,更解耦。


4. 异地存储推送:S3/MinIO 接入

我们选择 MinIO 作为异地存储,兼容 S3 协议。备份完成后使用 mc 客户端镜像同步。

最小权限策略: 创建专用 bucket 并限制访问。

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.log

6. 监控与告警闭环

备份任务不能悄无声息地失败,必须建立监控。

实现方式:

  • 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 损坏、机房级灾难,也能在分钟级恢复业务。

更多推荐