技术博客

Velero 实战:Kubernetes 集群备份、跨集群迁移与灾难恢复完整指南

Velero 是 Kubernetes 备份和灾难恢复的事实标准工具,由 VMware 维护并已贡献给 CNCF。v1.14 起 CSI 插件直接集成到主包(无需单独安装),内置 Kopia 数据移动器支持 PV 数据备份。本文讲解 Velero 的完整落地方案:安装配置(对象存储 + CSI 快照)、定时备份策略、Kubernetes 跨集群应用迁移、DR 演练流程,以及与 Velero 配合的备份黄金法则。

VeleroKubernetes备份灾难恢复DRCSI高可用运维

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(恢复点目标),形成文档。备份没有演练过等于没有备份。