4. Velero 实战部署:Helm 部署 + MinIO 存储 + 备份恢复验证

Velero 这个工具,说白了就是 Kubernetes 的「时光机」。它能帮你把整个命名空间、应用状态、PV 数据,一股脑儿备份到对象存储里。哪天集群炸了、误删了、升级回滚了,拉回来就能用。

我最早接触 Velero 是在一个金融客户的灾备项目里。当时他们要求 RPO 小于 15 分钟,RTO 小于 30 分钟。嗯,Velero 配合定时备份和快速恢复,确实扛住了压力。今天咱们就手把手把它部署起来。

4.1 整体架构速览

先看一张图,把 Velero 的组件和流程理清楚。你心里有个谱,后面操作才不会迷路。

Velero 备份恢复架构图 Velero Server Kubernetes API MinIO 对象存储 Velero 控制器 Velero CLI Restic / Kopia 备份文件 (tar.gz) 说明: Velero Server 通过控制器调用 K8s API 获取资源清单,同时通过 Restic/Kopia 读取 PV 数据。 所有数据打包后上传到 MinIO 桶中。恢复时反向操作。

Velero 由两部分组成:服务端(运行在集群里的控制器)和 客户端(命令行工具 velero)。服务端负责干活,客户端负责发号施令。

4.2 前置准备

动手之前,先把环境理清楚。我习惯列个清单,一项项打勾,省得到时候手忙脚乱。

项目 要求 说明
Kubernetes 集群 v1.20+ 建议用 1.24+,CRI 兼容性更好
Helm v3.8+ 我用的 v3.12,稳定
MinIO 最新稳定版 可以部署在集群内或外部
kubectl 与集群版本匹配 别差太多版本
对象存储桶 1 个 名字随意,比如 velero-backup
我的习惯:MinIO 我一般部署在集群外部,用独立的虚拟机或裸金属。这样集群挂了,备份数据还在。你想想看,如果 MinIO 和集群一起炸了,那备份还有什么意义?

4.3 部署 MinIO

MinIO 的部署方式很多。这里我用 Docker 快速起一个,方便演示。生产环境建议用 StatefulSet 部署到集群里,或者直接用硬件。

# 创建数据目录
mkdir -p /data/minio

# 启动 MinIO 容器
docker run -d \
  --name minio \
  -p 9000:9000 \
  -p 9001:9001 \
  -e MINIO_ROOT_USER=admin \
  -e MINIO_ROOT_PASSWORD=admin123456 \
  -v /data/minio:/data \
  quay.io/minio/minio server /data --console-address ":9001"

# 创建 bucket
# 访问 http://<你的IP>:9001,用 admin/admin123456 登录
# 手动创建一个名为 velero-backup 的桶

嗯,这里要注意。MinIO 的 Access Key 和 Secret Key 后面要用到,记下来。我一般把它们存到 Kubernetes Secret 里,而不是明文写在配置里。

4.4 使用 Helm 部署 Velero

Helm 部署 Velero 是最省事的方式。官方 Chart 已经把大部分配置都封装好了。你只需要提供 MinIO 的访问信息。

4.4.1 添加 Helm 仓库

helm repo add vmware-tanzu https://vmware-tanzu.github.io/helm-charts
helm repo update

4.4.2 创建 values 文件

我个人习惯把配置写到一个 values.yaml 里,方便版本管理和复用。下面是我常用的配置模板:

# velero-values.yaml
configuration:
  provider: aws
  backupStorageLocation:
    - name: default
      provider: aws
      bucket: velero-backup
      config:
        region: minio
        s3Url: http://192.168.1.100:9000
        publicUrl: http://192.168.1.100:9000
        s3ForcePathStyle: true
  volumeSnapshotLocation:
    - name: default
      provider: aws
      config:
        region: minio

credentials:
  useSecret: true
  secretContents:
    cloud: |
      [default]
      aws_access_key_id = admin
      aws_secret_access_key = admin123456

initContainers:
  - name: velero-plugin-for-aws
    image: velero/velero-plugin-for-aws:v1.7.0
    volumeMounts:
      - mountPath: /target
        name: plugins

deployRestic: true
restic:
  podVolumePath: /var/lib/kubelet/pods
我曾经踩过的坑:s3ForcePathStyle 这个参数一定要设为 true。MinIO 默认使用路径风格,不设的话 Velero 会一直报 403。还有,s3Url 要用 http 还是 https,取决于你的 MinIO 是否配了证书。测试环境用 http 没问题,生产环境一定要上 https。

4.4.3 执行部署

helm install velero vmware-tanzu/velero \
  --namespace velero \
  --create-namespace \
  -f velero-values.yaml

等个一两分钟,检查 Pod 状态:

kubectl get pods -n velero
# 输出示例:
# NAME                      READY   STATUS    RESTARTS   AGE
# velero-7d8f9c6b8c-abc12   1/1     Running   0          2m

看到 Running 就说明部署成功了。如果一直 Pending 或 CrashLoopBackOff,别慌。先看日志:

kubectl logs -n velero deployment/velero

大部分问题都是 MinIO 连不上、密钥不对、或者桶不存在。排查思路很直接。

4.5 安装 Velero CLI

服务端跑起来了,还得装个客户端工具。CLI 用来下发备份、恢复、查看状态等操作。

# 下载最新版 CLI
wget https://github.com/vmware-tanzu/velero/releases/download/v1.12.0/velero-v1.12.0-linux-amd64.tar.gz
tar -xzf velero-v1.12.0-linux-amd64.tar.gz
sudo mv velero-v1.12.0-linux-amd64/velero /usr/local/bin/

# 验证
velero version

CLI 会自动读取 kubeconfig 和 velero 命名空间。你不需要额外配置,直接就能用。

4.6 验证备份功能

部署完了,得真刀真枪试一下。我一般先备份一个测试命名空间,看看能不能正常跑通。

4.6.1 创建测试应用

kubectl create namespace test-backup
kubectl create deployment nginx -n test-backup --image=nginx
kubectl expose deployment nginx -n test-backup --port=80

4.6.2 执行手动备份

velero backup create test-backup-001 \
  --include-namespaces test-backup \
  --ttl 72h

备份命令执行后,Velero 会做以下几件事:

  • 调用 K8s API 获取 test-backup 命名空间下的所有资源清单
  • 通过 Restic 读取挂载的 PV 数据
  • 将所有数据打包成 tar.gz,上传到 MinIO 桶

查看备份状态:

velero backup get
# 输出示例:
# NAME              STATUS      CREATED                         EXPIRES
# test-backup-001   Completed   2024-01-15 10:30:00 +0800 CST   3d

STATUS 为 Completed 就说明备份成功了。如果显示 Failed,用 velero backup describe test-backup-001 看详细错误。

验证数据完整性:我建议你登录 MinIO 控制台,看看 velero-backup 桶里有没有生成备份文件。目录结构一般是 backups/test-backup-001/,里面包含资源清单的 JSON 和 PV 数据的 tar 包。

4.7 验证恢复功能

备份是为了恢复。咱们模拟一个灾难场景:把 test-backup 命名空间删了,然后用 Velero 恢复。

4.7.1 模拟灾难

kubectl delete namespace test-backup
# 确认命名空间已删除
kubectl get ns test-backup
# 输出:Error from server (NotFound): namespaces "test-backup" not found

4.7.2 执行恢复

velero restore create --from-backup test-backup-001

恢复过程是备份的逆操作:

  • 从 MinIO 下载备份包
  • 解析资源清单,调用 K8s API 重建资源
  • 如果有 PV 数据,通过 Restic 恢复到对应 PVC

查看恢复状态:

velero restore get
# 输出示例:
# NAME                          BACKUP            STATUS      CREATED
# test-backup-001-202401151045  test-backup-001   Completed   2024-01-15 10:45:00 +0800 CST

验证恢复结果:

kubectl get all -n test-backup
# 应该能看到 nginx deployment 和 service 都回来了
我的经验:恢复时要注意命名空间冲突。如果目标命名空间已经存在,Velero 默认会跳过已存在的资源。你可以用 --namespace-mappings 参数把备份恢复到不同的命名空间,比如 --namespace-mappings test-backup:test-backup-restored。这在做跨集群迁移时特别有用。

4.8 定时备份配置

手动备份只是验证功能。生产环境肯定要配定时备份。Velero 用 Schedule 资源来实现。

# 创建每天凌晨 2 点执行的定时备份
velero schedule create daily-backup \
  --schedule="0 2 * * *" \
  --include-namespaces test-backup \
  --ttl 168h

查看定时任务:

velero schedule get
# 输出示例:
# NAME           STATUS    CREATED                         SCHEDULE
# daily-backup   Enabled   2024-01-15 11:00:00 +0800 CST   0 2 * * *

定时备份会自动创建备份对象,你只需要定期检查备份状态就行。我一般会在监控里加一条告警:如果最近一次备份失败,就发钉钉或邮件通知。

4.9 常见问题与避坑

最后,分享几个我实际项目中遇到过的问题,你遇到了可以少走弯路。

问题 原因 解决方案
备份一直 Pending Velero 无法连接 MinIO 检查 s3Url 是否正确,网络是否可达
备份 Failed,报 403 Access Key / Secret Key 错误,或 s3ForcePathStyle 未设置 检查密钥,添加 s3ForcePathStyle: true
恢复后 Pod 起不来 PV 数据恢复失败,或 StorageClass 不匹配 检查 Restic 日志,确认 PVC 的 StorageClass 存在
Restic 备份很慢 PV 数据量大,或网络带宽不足 考虑使用 Kopia 替代 Restic,或限速备份
我曾经踩过的坑:有一次备份一直 Failed,查了半天发现是 MinIO 的桶名写错了。Velero 不会自动创建桶,你得提前建好。还有一次,Restic 备份 PV 时,因为 kubelet 的 podVolumePath 不是默认路径,导致 Restic 找不到挂载点。所以部署时一定要确认 restic.podVolumePath 和你的集群配置一致。

好了,到这一步,Velero 的部署、备份、恢复、定时任务就全跑通了。你可以在测试环境多试几次,熟悉一下各种参数。后面咱们会讲更高级的用法,比如跨集群迁移、加密备份、增量备份等等。