云原生数据库备份:使用 Velero 实现 MySQL(StatefulSet 部署)的数据备份
全量 / 定时备份 MySQL 配置与 PV 数据;快速恢复故障环境,验证数据完整性;结合 hooks 保障备份数据一致性。后续可进一步扩展:集成 Prometheus 监控 Velero 备份状态,配置告警(如备份失败时通知运维),或实现跨集群备份(如从测试集群备份到生产集群恢复)。
原生数据库备份:使用 Velero 实现 MySQL(StatefulSet 部署)的数据备份
一、引言:为什么需要 Velero 备份 StatefulSet 部署的 MySQL?
在云原生架构中,MySQL 常通过 StatefulSet 部署以保证有状态特性(固定网络标识、持久化存储),但其数据备份面临两大核心挑战:
- 存储与配置同步备份:需同时备份 MySQL 的 StatefulSet 配置(如启动参数、环境变量)与 PV 中的数据,避免恢复时 “有配置无数据” 或 “有数据无配置”;
- 有状态应用一致性:StatefulSet 的 PV 与 Pod 强绑定(如 mysql-data-mysql-0 对应 mysql-0 Pod),普通备份工具难以识别这种关联关系。
Velero 作为云原生备份工具,支持K8s 资源 + PV 数据一体化备份,能自动关联 StatefulSet 与 PV 的依赖关系,且支持定时备份、跨集群恢复,是解决 StatefulSet 部署 MySQL 备份的最优方案之一。
二、前置条件:环境准备与工具安装
2.1 基础环境要求
- K8s 集群(1.20+,支持 StatefulSet 与 PV/PVC);
- MySQL 已通过 StatefulSet 部署(示例:Namespace 为 mysql-ns,StatefulSet 名称为 mysql,PV 挂载目录为 /var/lib/mysql);
- 备份存储后端(本文以 MinIO 为例,也可使用 AWS S3、阿里云 OSS 等);
- 工具:kubectl(集群管理)、velero(客户端)。
2.2 安装 Velero
步骤 1:下载 Velero 客户端
# 下载对应版本(本文用 v1.12.1)
wget https://github.com/vmware-tanzu/velero/releases/download/v1.12.1/velero-v1.12.1-linux-amd64.tar.gz
tar -zxvf velero-v1.12.1-linux-amd64.tar.gz
mv velero-v1.12.1-linux-amd64/velero /usr/local/bin/
# 验证安装
velero version
步骤 2:部署 Velero 到 K8s 集群(对接 MinIO)
- 准备 MinIO 密钥文件 credentials-velero:
[default]
aws_access_key_id = minioadmin # MinIO 访问密钥
aws_secret_access_key = minioadmin # MinIO 密钥
- 执行安装命令(指定 MinIO 地址与备份桶):
velero install \
--provider aws \
--plugins velero/velero-plugin-for-aws:v1.9.0 \
--bucket velero-mysql-backup # MinIO 中创建的备份桶名
--secret-file ./credentials-velero \
--use-volume-snapshots=false # 若用 restic 备份 PV,设为 false
--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://minio-service:9000 # MinIO 服务地址
--namespace velero \
--create-namespace
- 验证 Velero 部署状态:
kubectl get pods -n velero
# 预期输出:velero-xxxx-xxxx 状态为 Running
三、核心原理:Velero 备份 StatefulSet MySQL 的逻辑
Velero 备份 StatefulSet 部署的 MySQL 分为两大阶段,确保 “配置 + 数据” 完整:
- K8s 资源备份:自动抓取与 MySQL 相关的 StatefulSet、Service、ConfigMap、Secret、PVC 等资源,生成 YAML 配置文件;
- PV 数据备份:通过 restic 工具(需提前配置)备份 PVC 挂载的 /var/lib/mysql 目录数据,或通过 CSI 快照备份 PV(需集群支持 CSI)。
关键关联逻辑:Velero 通过 PVC 的 ownerReferences 字段识别其与 StatefulSet 的绑定关系,确保恢复时 PV 能重新关联到对应的 StatefulSet Pod。
四、实操步骤:实现 MySQL 数据备份与验证
4.1 准备工作:确认 MySQL 环境状态
- 查看 StatefulSet 与 Pod 状态:
kubectl get statefulset mysql -n mysql-ns
kubectl get pods -n mysql-ns -l app=mysql # 示例标签:app=mysql
# 预期输出:mysql-0(单节点)或 mysql-0、mysql-1(主从)状态为 Running
- 确认 PV/PVC 关联关系:
kubectl get pvc -n mysql-ns # 查看 MySQL 的 PVC(如 mysql-data-mysql-0)
kubectl get pv | grep mysql-data-mysql-0 # 确认 PVC 绑定的 PV
- (可选)添加 Restic 备份权限(若用 restic 备份 PV):
给 MySQL 的 ServiceAccount 授予 restic 备份权限:
# restic-permissions.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: velero-restic-role
namespace: mysql-ns
rules:
- apiGroups: [""]
resources: ["pods", "pods/exec"]
verbs: ["get", "list", "create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: velero-restic-rolebinding
namespace: mysql-ns
subjects:
- kind: ServiceAccount
name: default # MySQL 使用的 ServiceAccount(默认是 default)
namespace: mysql-ns
roleRef:
kind: Role
name: velero-restic-role
apiGroup: rbac.authorization.k8s.io
kubectl apply -f restic-permissions.yaml
4.2 执行全量备份:备份 MySQL 配置与数据
命令格式:
velero create backup <备份名> \
--namespace mysql-ns \
--include-resources statefulsets,services,configmaps,secrets,persistentvolumeclaims \
--include-namespaces mysql-ns \
--volume-snapshot-locations <快照位置> # 若用 CSI 快照,需指定;restic 可省略
--labels app=mysql-backup # 给备份打标签,便于筛选
实际执行示例:
velero create backup mysql-backup-20240520 \
--namespace mysql-ns \
--include-resources statefulsets,services,configmaps,secrets,persistentvolumeclaims \
--include-namespaces mysql-ns \
--labels app=mysql-backup
4.3 备份状态验证
- 查看备份进度:
velero get backups
# 预期输出:mysql-backup-20240520 状态为 Completed(约1-5分钟,取决于数据量)
- 查看备份详情(确认资源与数据已备份):
velero describe backup mysql-backup-20240520
# 关键检查点:
# - "Included Resources":包含 statefulsets/mysql、pvc/mysql-data-mysql-0 等
# - "Restic Backups":若用 restic,显示 "Completed"(数据备份成功)
- 验证 MinIO 中是否存在备份文件:
登录 MinIO 控制台,进入 velero-mysql-backup 桶,可看到 backups/mysql-backup-20240520 目录,包含备份的配置文件与数据文件。
五、关键补充:恢复测试与一致性保障
5.1 模拟故障:删除 MySQL 资源与数据
为验证备份有效性,模拟故障场景(删除 MySQL 的 StatefulSet 与 PVC):
# 删除 StatefulSet
kubectl delete statefulset mysql -n mysql-ns
# 删除 PVC(PV 会随 PVC 删除,若 PV 回收策略为 Delete)
kubectl delete pvc mysql-data-mysql-0 -n mysql-ns
5.2 从备份恢复 MySQL
velero create restore mysql-restore-20240520 \
--from-backup mysql-backup-20240520 \
--namespace mysql-ns
恢复验证:
- 查看恢复进度:
velero get restores
# 预期输出:mysql-restore-20240520 状态为 Completed
- 验证 MySQL 服务恢复:
# 查看 StatefulSet 与 Pod 恢复情况
kubectl get statefulset mysql -n mysql-ns # 状态为 Ready
kubectl get pods -n mysql-ns # mysql-0 状态为 Running
# 登录 MySQL 验证数据完整性
kubectl exec -it mysql-0 -n mysql-ns -- mysql -uroot -p
# 执行 SQL 查看数据(如查询测试表)
mysql> use testdb;
mysql> select * from test_table; # 预期输出:数据与备份前一致
5.3 数据一致性保障:避免备份时数据脏写
Velero 本身不处理应用层数据一致性,需结合 MySQL 特性优化:
- 备份前执行数据 flush:通过 Velero 的 pre-backup hook 在备份前锁定 MySQL 表,避免写入:
# mysql-pre-backup-hook.yaml
apiVersion: velero.io/v1
kind: Backup
metadata:
name: mysql-backup-with-hook
namespace: velero
spec:
includedNamespaces:
- mysql-ns
includedResources:
- statefulsets
- services
- configmaps
- secrets
- persistentvolumeclaims
hooks:
resources:
- name: mysql-pre-backup-hook
includedNamespaces:
- mysql-ns
labelSelector:
matchLabels:
app: mysql
pre:
exec:
command:
- /bin/sh
- -c
- "mysql -uroot -p$MYSQL_ROOT_PASSWORD -e 'FLUSH TABLES WITH READ LOCK;'" # 锁定表
onError: Fail # 若命令失败,备份终止
- 使用 MySQL 主从备份:若为 MySQL 主从集群(StatefulSet 多节点),可仅备份从库,避免影响主库业务。
六、优化与故障处理
6.1 定时备份:配置 Velero Schedule
避免手动备份遗漏,创建每日凌晨 2 点的定时备份:
velero create schedule mysql-daily-backup \
--schedule "0 2 * * *" \
--include-resources statefulsets,services,configmaps,secrets,persistentvolumeclaims \
--include-namespaces mysql-ns \
--retention 7 # 备份保留7天(自动删除过期备份)
查看定时任务:
velero get schedules
6.2 常见故障排查
- 备份失败:Restic 备份超时
-
- 原因:MySQL 数据量过大,restic 备份超时;
-
- 解决:调整 Velero 备份超时时间(修改 velero Deployment 的 --backup-timeout 参数,默认 1 小时),或分批次备份大文件。
- 恢复后 MySQL 启动失败
-
- 原因:PV 数据权限异常(如 /var/lib/mysql 目录属主不是 mysql 用户);
-
- 解决:恢复后执行命令修复权限:
kubectl exec -it mysql-0 -n mysql-ns -- chown -R mysql:mysql /var/lib/mysql
kubectl delete pod mysql-0 -n mysql-ns # 重启 Pod
- MinIO 连接失败
-
- 原因:Velero 配置的 MinIO 地址或密钥错误;
-
- 解决:重新创建 Velero 备份位置:
velero backup-location create minio-new \
--provider aws \
--config region=minio,s3ForcePathStyle="true",s3Url=http://minio-service:9000 \
--secret-file ./credentials-velero
七、总结
使用 Velero 备份 StatefulSet 部署的 MySQL,核心优势在于 **“配置 + 数据一体化备份” 与 “有状态关联自动识别”**,通过本文的实操步骤,可实现:
- 全量 / 定时备份 MySQL 配置与 PV 数据;
- 快速恢复故障环境,验证数据完整性;
- 结合 hooks 保障备份数据一致性。
后续可进一步扩展:集成 Prometheus 监控 Velero 备份状态,配置告警(如备份失败时通知运维),或实现跨集群备份(如从测试集群备份到生产集群恢复)。
更多推荐
所有评论(0)