Velero 实战:Kubernetes 集群备份、跨集群迁移与灾难恢复完整指南
Velero 是 Kubernetes 备份和灾难恢复的事实标准工具,由 VMware 维护并已贡献给 CNCF。v1.14 起 CSI 插件直接集成到主包(无需单独安装),内置 Kopia 数据移动器支持 PV 数据备份。本文讲解 Velero 的完整落地方案:安装配置(对象存储 + CSI 快照)、定时备份策略、Kubernetes 跨集群应用迁移、DR 演练流程,以及与 Velero 配合的备份黄金法则。
Kubernetes 集群上跑的生产业务,备份是绕不开的话题。但“备份 Kubernetes”到底备的是什么?有哪些层次?
Kubernetes 备份的三个层次:
1. etcd 快照备份(管控平面)
备的是:所有 K8s 对象(Deployment、Service、ConfigMap、Secret 等)
不包括:PV 里的实际数据
适合:集群灾难恢复(整个控制平面挂了)
2. Velero 应用级备份
备的是:指定命名空间的 K8s 对象 + PV 数据(通过 CSI 快照或 Kopia)
不需要:访问 etcd
适合:应用迁移、命名空间级灾难恢复、跨集群复制
3. 数据库独立备份
备的是:业务数据本身
工具:mysqldump、pg_dump、mongodump 等
适合:配合前两种,确保数据一致性
Velero 是第二层的核心工具,本文讲清楚怎么用好它。
Velero 核心架构
Velero 组件:
velero server(Deployment):控制器,处理 Backup/Restore 请求
node-agent(DaemonSet):在每个节点上运行,负责 PV 文件级备份
BackupStorageLocation(BSL):定义备份存储位置(S3/OSS/GCS/Azure Blob)
VolumeSnapshotLocation(VSL):定义 PV 快照提供者(CSI/云厂商快照)
备份流程(含 PV 数据):
1. Velero Server 收到 Backup 请求
2. 序列化并上传 K8s 对象(YAML)到 S3/OSS
3. 通过 CSI VolumeSnapshot API 触发 PV 快照
4. 启动 Kopia 数据移动器:读取快照数据,上传到 S3/OSS
5. 记录 Backup 完成状态
v1.14 关键变化:CSI 插件直接内置,无需单独安装 velero-plugin-for-csi
安装 Velero
准备对象存储(以阿里云 OSS 为例)
# 创建 OSS Bucket(用于存储备份)
# 建议开启版本控制和跨区域复制(增加 DR 可靠性)
# 创建 RAM 用户并授予 OSS 访问权限
# 最小权限策略:oss:PutObject、oss:GetObject、oss:DeleteObject、oss:ListObjects
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": [
"oss:PutObject",
"oss:GetObject",
"oss:DeleteObject",
"oss:ListObjects",
"oss:ListBuckets",
"oss:GetBucketLocation"
],
"Resource": [
"acs:oss:*:*:my-velero-backup",
"acs:oss:*:*:my-velero-backup/*"
]
}
]
}
安装 Velero CLI
# 下载 Velero CLI
VELERO_VERSION=v1.15.0
curl -L https://github.com/vmware-tanzu/velero/releases/download/${VELERO_VERSION}/velero-${VELERO_VERSION}-linux-amd64.tar.gz \
| tar -xz --strip-components=1 velero-${VELERO_VERSION}-linux-amd64/velero
chmod +x velero
mv velero /usr/local/bin/
velero version
安装 Velero Server(AWS S3 示例)
# 创建存储凭据文件
cat > credentials-velero << EOF
[default]
aws_access_key_id=<ACCESS_KEY>
aws_secret_access_key=<SECRET_KEY>
EOF
# 安装 Velero(AWS/阿里云 OSS 兼容 S3 协议)
velero install \
--provider aws \
--plugins velero/velero-plugin-for-aws:v1.10.0 \
--bucket my-velero-backup \
--secret-file ./credentials-velero \
--backup-location-config \
region=cn-hangzhou,\
s3ForcePathStyle=true,\
s3Url=https://oss-cn-hangzhou.aliyuncs.com \
--snapshot-location-config region=cn-hangzhou \
--use-node-agent \ # 启用 DaemonSet(用于文件级备份)
--default-volumes-to-fs-backup # 默认对所有 PV 做文件级备份
# 验证安装
kubectl get pods -n velero
velero backup-location get
# 输出应该显示 PHASE: Available
安装 Velero Server(使用 Helm)
helm repo add vmware-tanzu https://vmware-tanzu.github.io/helm-charts
helm repo update
cat > velero-values.yaml << 'EOF'
configuration:
backupStorageLocation:
- name: default
provider: aws
bucket: my-velero-backup
config:
region: cn-hangzhou
s3ForcePathStyle: "true"
s3Url: https://oss-cn-hangzhou.aliyuncs.com
volumeSnapshotLocation:
- name: default
provider: aws
config:
region: cn-hangzhou
credentials:
secretContents:
cloud: |
[default]
aws_access_key_id=<ACCESS_KEY>
aws_secret_access_key=<SECRET_KEY>
initContainers:
- name: velero-plugin-for-aws
image: velero/velero-plugin-for-aws:v1.10.0
volumeMounts:
- mountPath: /target
name: plugins
nodeAgent:
enabled: true # 启用 Kopia 文件级备份
deployNodeAgent: true
EOF
helm install velero vmware-tanzu/velero \
--namespace velero \
--create-namespace \
--values velero-values.yaml
手动备份与恢复
# 备份单个命名空间(包含 PV 数据)
velero backup create production-backup-$(date +%Y%m%d) \
--include-namespaces production \
--default-volumes-to-fs-backup # 使用 Kopia 文件级备份 PV
# 备份多个命名空间
velero backup create multi-ns-backup \
--include-namespaces production,staging,monitoring
# 备份整个集群(排除某些命名空间)
velero backup create full-cluster-backup \
--exclude-namespaces kube-system,velero
# 查看备份状态
velero backup get
velero backup describe production-backup-20261109 --details
# 查看备份日志(排查问题)
velero backup logs production-backup-20261109
# 从备份恢复(恢复到同一集群)
velero restore create \
--from-backup production-backup-20261109 \
--include-namespaces production
# 查看恢复状态
velero restore get
velero restore describe <restore-name> --details
定时备份策略(Schedule)
# 每天凌晨 2 点备份 production 命名空间,保留 30 天
velero schedule create daily-production \
--schedule="0 2 * * *" \
--include-namespaces production \
--default-volumes-to-fs-backup \
--ttl 720h # 30 天 = 720 小时
# 每周日凌晨 3 点全量备份,保留 90 天
velero schedule create weekly-full \
--schedule="0 3 * * 0" \
--ttl 2160h # 90 天
# 每 6 小时备份关键命名空间,保留 48 小时(短期快照)
velero schedule create frequent-critical \
--schedule="0 */6 * * *" \
--include-namespaces payments,orders \
--ttl 48h
# 查看已配置的定时任务
velero schedule get
# 手动触发定时备份(临时需要)
velero backup create --from-schedule daily-production
CSI 快照备份(适合云厂商托管存储)
对于使用云厂商 PVC(如阿里云 ESSD、AWS EBS)的场景,CSI 快照比文件级备份更快且一致性更好。
# 确认集群有 CSI 快照控制器
kubectl get crd | grep volumesnapshot
# volumesnapshotclasses.snapshot.storage.k8s.io
# volumesnapshots.snapshot.storage.k8s.io
# volumesnapshotcontents.snapshot.storage.k8s.io
# 创建 VolumeSnapshotClass(以阿里云 ESSD 为例)
cat << 'EOF' | kubectl apply -f -
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
name: alicloud-disk-snapshot
labels:
velero.io/csi-volumesnapshot-class: "true" # 必须加这个 label
driver: diskplugin.csi.alibabacloud.com
deletionPolicy: Delete
EOF
# 使用 CSI 快照做备份(不需要 node-agent)
velero backup create csi-backup \
--include-namespaces production \
--snapshot-move-data=false # 只做 CSI 快照,不做数据移动
跨集群应用迁移
Velero 最实用的场景之一:把应用从一个集群完整迁移到另一个集群。
# 场景:把 production 命名空间从集群 A 迁移到集群 B
# ==== 在集群 A 上操作 ====
# 1. 创建迁移前备份
velero backup create migration-$(date +%Y%m%d) \
--include-namespaces production \
--default-volumes-to-fs-backup
# 2. 等待备份完成
velero backup wait migration-$(date +%Y%m%d)
# 3. 确认备份成功
velero backup describe migration-$(date +%Y%m%d) | grep Phase
# Phase: Completed
# ==== 在集群 B 上操作 ====
# 1. 安装 Velero(指向同一个 OSS Bucket)
# 使用与集群 A 相同的 bucket 配置安装 Velero
# 2. 等待 Velero 同步备份信息
velero backup get
# 此时可以看到集群 A 创建的备份
# 3. 执行恢复
velero restore create \
--from-backup migration-$(date +%Y%m%d) \
--include-namespaces production
# 4. 验证恢复结果
kubectl get pods -n production
kubectl get pvc -n production
velero restore describe <restore-name> --details
备份前钩子和备份后钩子
对于有状态应用(数据库),备份前需要先做数据静默(quiesce),保证数据一致性。
# 通过 Pod annotation 配置备份钩子
apiVersion: v1
kind: Pod
metadata:
name: mysql-pod
annotations:
# 备份前:执行 FLUSH TABLES WITH READ LOCK(锁表保证一致性)
pre.hook.backup.velero.io/container: mysql
pre.hook.backup.velero.io/command: >-
["/bin/bash", "-c", "mysql -u root -p$MYSQL_ROOT_PASSWORD -e 'FLUSH TABLES WITH READ LOCK'"]
pre.hook.backup.velero.io/timeout: 30s
# 备份后:释放锁
post.hook.backup.velero.io/container: mysql
post.hook.backup.velero.io/command: >-
["/bin/bash", "-c", "mysql -u root -p$MYSQL_ROOT_PASSWORD -e 'UNLOCK TABLES'"]
post.hook.backup.velero.io/on-error: Fail
DR 演练:灾难恢复测试流程
备份配好了不代表 DR 可靠,必须定期演练恢复。
# DR 演练建议:每季度在非生产环境执行一次完整恢复测试
# 1. 从最新备份恢复到测试命名空间
velero restore create dr-test-$(date +%Y%m%d) \
--from-backup daily-production-$(date +%Y%m%d) \
--namespace-mappings production:dr-test # 恢复到不同的命名空间
# 2. 等待恢复完成
velero restore wait dr-test-$(date +%Y%m%d)
# 3. 验证恢复结果
kubectl get pods -n dr-test
kubectl get pvc -n dr-test
kubectl get secrets -n dr-test
# 4. 功能验证(运行业务层面的健康检查)
# 例如:访问恢复后的 API,检查数据完整性
# 5. 记录恢复时间(RTO 指标)
# 从开始恢复到服务可用的时间
# 6. 清理测试命名空间
kubectl delete namespace dr-test
常见问题排查
# 备份卡在 InProgress
# 查看 node-agent 日志(Kopia 传输进度)
kubectl logs -n velero -l name=node-agent -f
# PV 备份失败(没有 node-agent)
# 确认 --use-node-agent 参数
kubectl get daemonset -n velero
# 备份存储不可访问
velero backup-location get
# 如果 PHASE 是 Unavailable,检查凭据和网络
# 查看 Velero 详细日志
kubectl logs -n velero deployment/velero --tail=100
# 验证 CSI 快照能力
kubectl get volumesnapshotclasses
kubectl get volumesnapshots -A
小结
Velero 的核心价值在于命名空间级的应用备份和恢复,而不是替代 etcd 快照。两者应该配合使用:etcd 快照保护控制平面,Velero 保护应用数据,数据库工具(mysqldump 等)保护业务数据,三层备份构成完整的 K8s DR 体系。
落地建议:先配好定时备份(每天一次),再做一次完整的 DR 演练验证恢复流程,记录 RTO(恢复时间目标)和 RPO(恢复点目标),形成文档。备份没有演练过等于没有备份。
