Kubernetes教程(五十二)---Velero快速入门:开源备份恢复工具实战

velero-quickstart.png

在之前的文章《Kubernetes PVC Clone & Snapshot 实战:基于 Csi-Driver-Nfs 的完整示例》中,我们探讨了如何使用 Kubernetes 内置的 PVC 克隆和快照功能进行数据保护。然而,当我们需要对整个 Kubernetes 集群进行全面的备份恢复时,就需要更专业的工具。

Velero(前身 Heptio Ark)正是这样一个专业的 Kubernetes 备份恢复工具,已成为 CNCF 毕业项目。它不仅能够备份持久卷数据,还能备份整个集群的应用配置、服务和资源状态,提供企业级的灾难恢复和集群迁移能力。

你将学到:

  • Velero 架构原理和核心特性
  • 单集群备份恢复完整操作流程
  • 跨集群应用迁移实战演示
  • 生产环境最佳实践和故障排查

1. Velero 简介

1.1 什么是 Velero

在前一篇文章中我们介绍了 PVC 级别的数据保护方案,但当我们需要对整个 Kubernetes 应用栈进行备份恢复时,就需要更全面的解决方案。

Velero(前身 Heptio Ark)正是一个用于备份与恢复 Kubernetes 集群资源和持久卷(PV/PVC)的专业开源工具,提供安全可靠的数据保护解决方案。

Velero 在 Kubernetes 生态中已被广泛视为开源领域事实标准 / 最主流备份恢复工具(CNCF 毕业项目,社区采用率最高)。

1.2 核心特性

  • 集群资源备份恢复:支持 Deployment、Service、ConfigMap、Secret 等 Kubernetes 资源的备份与恢复
  • 持久卷数据保护:通过云快照或文件系统备份工具(Kopia)保护 PVC 数据
  • 定时备份调度:支持自动化定时备份策略
  • 跨集群迁移:实现集群间应用和数据的安全迁移
  • 多存储后端:支持 S3、GCS、Azure Blob 等多种对象存储

1.3 适用场景

  • 灾难恢复:应对集群故障、误删除等意外情况

  • 集群升级迁移:安全地将应用迁移到新版本集群

  • 开发测试:为开发测试环境提供快速数据恢复能力

  • 合规要求:满足数据保护和审计合规需求

  • 开源地址https://github.com/vmware-tanzu/velero

  • 官方文档https://velero.io/docs/v1.17/

2. 架构和工作原理

2.1 组件构成

Velero 采用客户端-服务器架构:

  • 服务端:运行在 Kubernetes 集群中的控制器组件
  • 客户端:本地命令行工具,需要配置 kubectl 和集群 kubeconfig

2.2 备份流程

Velero 采用 Operator 模式,通过创建 CRD 对象触发备份操作:

velero-workflow.png

  1. 创建备份任务:Velero 客户端调用 Kubernetes API 创建 Backup CRD
  2. 监听任务:Backup Controller 通过 watch 机制获取备份任务
  3. 收集数据:Controller 通过 kube-apiserver 获取需要备份的资源数据
  4. 存储备份:将数据上传到指定的对象存储后端

2.3 存储后端配置

Velero 通过两种 CRD 管理存储后端:

BackupStorageLocation

定义 Kubernetes 集群资源的存储位置,主要用于存储 YAML 清单文件等元数据。支持 S3 兼容存储(如 MinIO、AWS S3、阿里云 OSS 等)。

VolumeSnapshotLocation

定义持久卷快照的存储位置,需要云提供商插件支持。对于不支持快照的环境,可以使用文件系统备份工具 Restic/Kopia。

Restic 是一款用 Go 语言开发的数据加密备份工具,支持多种存储后端:Local、SFTP、AWS S3、MinIO、Azure Blob Storage、Google Cloud Storage 等。
Kopia 是 Velero 从 v1.10 版本开始引入的新一代 文件级备份工具,用于替代传统的 Restic,相比 Restic 具有更好的性能和可靠性。

3. 安装部署

3.1 准备工作

存储插件选择

Velero 支持多种存储插件,可通过 官方文档 查看完整列表。本教程使用 MinIO 作为 S3 兼容的对象存储。

MinIO 部署

可以参考 MinIO 官方文档部署服务,或使用 Velero 提供的快速部署脚本:

1
kubectl apply -f https://raw.githubusercontent.com/vmware-tanzu/velero/main/examples/minio/00-minio-deployment.yaml

3.2 安装 CLI 工具

GitHub release 页面下载最新压缩包:

1
2
3
4
5
6
7
8
wget https://github.com/vmware-tanzu/velero/releases/download/v1.17.2/velero-v1.17.2-linux-amd64.tar.gz

tar -zxvf velero-v1.17.2-linux-amd64.tar.gz

mv velero-v1.17.2-linux-amd64/velero /usr/local/bin/

# 查看版本
velero version

3.3 安装服务端组件

创建认证文件

先创建 S3 配置文件,提供 MinIO 的访问凭证:

1
2
3
4
5
cat > credentials-s3 <<EOF
[default]
aws_access_key_id = your-access-key-id
aws_secret_access_key = your-secret-access-key
EOF

部署 Velero 服务端

开始部署 Velero 服务端组件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
REGISTRY=docker.io
S3URL=http://your-minio-endpoint:port
BUCKET=velero

velero install    \
     --namespace velero  \
     --provider aws   \
     --image $REGISTRY/velero/velero:v1.17.2  \
     --plugins $REGISTRY/velero/velero-plugin-for-aws:v1.13.2  \
     --secret-file ./credentials-s3  \
     --bucket $BUCKET \
     --use-node-agent \
     --use-volume-snapshots=false \
     --backup-location-config region=minio,s3ForcePathStyle="true",s3Url=$S3URL

参数说明

  • --namespace:指定部署的 namespace 名称,默认为 velero
  • --provider:定义插件提供方,aws 表示 AWS S3 兼容
  • --image:定义运行 velero 的镜像
  • --plugins:指定使用 aws s3 兼容的插件镜像
  • --secret-file:指定对象存储认证文件
  • --bucket:指定对象存储 Bucket 桶名称
  • --use-node-agent:创建 Velero Node Agent 守护进程,用于通过 Kopia 备份 PVC 数据
  • --use-volume-snapshots:是否启用快照功能

注意:从 Velero 1.7 开始,Kopia 成为默认的文件系统备份工具,取代了之前的 Restic。Kopia 提供了更好的性能和可靠性。

  • --backup-location-config:指定对象存储地址信息
    • region:MinIO 本身没有区域概念,但 AWS S3 插件需要 region 参数,因此使用 minio 作为占位符
    • s3ForcePathStyle:路径风格访问,强制使用路径风格的 URL(http://endpoint/bucket/key),这是 MinIO 的推荐访问方式
    • s3Url:MinIO 服务地址

验证安装状态

1
2
3
4
5
6
7
8
9
# 检查 Pod 状态
kubectl -n velero get pod

# 查看 BackupStorageLocation
kubectl -n velero get BackupStorageLocation

# 示例输出:
# NAME      PHASE       LAST VALIDATED   AGE     DEFAULT
# default   Available   43s              5m      true

3.4 卸载 Velero

如果需要从集群中完全卸载 Velero:

1
2
3
4
5
6
# 使用 velero 命令卸载
velero uninstall

# 或者手动删除相关资源
kubectl delete namespace/velero clusterrolebinding/velero
kubectl delete crds -l component=velero

4. 基础操作

4.1 备份命令详解

备份命令:velero create backup NAME [flags]

4.2 定时备份配置

除了手动备份外,Velero 还支持定时备份,可以通过 Schedule CRD 实现自动化备份:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 创建每天凌晨2点的定时备份
velero create schedule daily-backup \
    --schedule="0 2 * * *" \
    --include-namespaces nginx-example \
    --default-volumes-to-fs-backup \
    --ttl 72h

# 查看定时备份列表
velero get schedules

# 查看定时备份的执行历史
velero get backups --selector velero.io/schedule-name=daily-backup

定时表达式说明

  • 0 2 * * *:每天凌晨2点执行
  • 0 */6 * * *:每6小时执行一次
  • 0 0 * * 0:每周日午夜执行

常用选项

  • --exclude-namespaces stringArray:从备份中排除的命名空间
  • --exclude-resources stringArray:从备份中排除的资源类型
  • --include-cluster-resources optionalBool[=true]:是否包含集群级资源
  • --include-namespaces stringArray:要包含的命名空间(默认 ‘*’)
  • --include-resources stringArray:要备份的资源类型
  • --labels mapStringString:为备份添加标签
  • -o, --output string:输出格式(table/json/yaml)
  • -l, --selector labelSelector:按标签筛选资源
  • --snapshot-volumes optionalBool[=true]:是否为 PV 创建快照
  • --storage-location string:指定备份位置
  • --ttl duration:备份数据的过期时间
  • --volume-snapshot-locations strings:指定快照位置

5. 实战演示:单集群备份恢复

5.1 创建测试应用

创建一个 Nginx 应用并挂载 PVC,用于验证备份恢复功能:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
cat > nginx-demo.yaml <<EOF
apiVersion: v1
kind: Namespace
metadata:
  name: nginx-example
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-html-pvc
  namespace: nginx-example
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs  # 请修改为你的集群中可用的StorageClass
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: nginx-example
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: registry.cn-shanghai.aliyuncs.com/99cloud-sh/nginx:1.20
        ports:
        - containerPort: 80
        volumeMounts:
        - name: html-volume
          mountPath: /usr/share/nginx/html  # Nginx默认的网页根目录
      volumes:
      - name: html-volume
        persistentVolumeClaim:
          claimName: nginx-html-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: nginx-example
spec:
  type: NodePort  # 为了方便从集群外部访问,使用NodePort类型
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
EOF
1
kubectl apply -f nginx-demo.yaml

5.2 写入测试数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 获取 Nginx Pod 名称
NGINX_POD=$(kubectl get pods -n nginx-example -l app=nginx -o jsonpath='{.items[0].metadata.name}')
echo $NGINX_POD

# 创建测试文件并复制到 Pod
echo '<h1>Hello from Velero Backup Demo!</h1><p>This file was created on '"$(date)"'.</p>' > test-index.html
kubectl cp test-index.html nginx-example/$NGINX_POD:/usr/share/nginx/html/index.html

# 验证数据写入
kubectl get svc nginx-service -n nginx-example
curl http://<cluster-ip>:80

5.3 执行备份

1
velero backup create nginx-backup-pvc --include-namespaces nginx-example --default-volumes-to-fs-backup

参数说明

  • --include-namespaces:指定要备份的命名空间
  • --default-volumes-to-fs-backup:使用文件系统备份工具备份 PVC 数据

5.4 监控备份状态

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 查看备份列表
velero backup get

# 示例输出:
# NAME               STATUS      ERRORS   WARNINGS   CREATED                         EXPIRES   STORAGE LOCATION   SELECTOR
# nginx-backup-pvc   Completed   0        0          2026-01-27 08:36:54 +0000 UTC   29d       default            <none>

# 查看详细备份信息
velero backup describe nginx-backup-pvc

# 查看备份日志
velero backup logs nginx-backup-pvc

5.5 验证备份结果

备份完成后,可以在 MinIO 存储中查看备份内容:

Kubernetes 资源配置备份velero-save-in-minio-yaml.png

PVC 数据文件备份velero-save-in-minio-pvc.png

5.5 模拟灾难恢复

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 删除应用模拟灾难
kubectl delete namespace nginx-example

# 执行恢复
velero restore create --from-backup nginx-backup-pvc

# 监控恢复进度
velero restore get

# 示例输出:
# NAME                              BACKUP             STATUS      STARTED                         COMPLETED                       ERRORS   WARNINGS   CREATED                         SELECTOR
# nginx-backup-pvc-20260127084915   nginx-backup-pvc   Completed   2026-01-27 08:49:15 +0000 UTC   2026-01-27 08:49:23 +0000 UTC   0        1          2026-01-27 08:49:15 +0000 UTC   <none>

# 验证恢复结果
kubectl -n nginx-example get pod,svc,pvc
curl <nginx-service-cluster-ip>

6. 高级功能:跨集群迁移

只要我们将每个 velero 实例指向相同的对象存储,velero 就能将资源从一个群集迁移到另一个群集。

velero-demo-cross-cluster.png

6.1 环境要求

  • 集群版本一致:建议两个 Kubernetes 集群版本保持一致
  • 存储类匹配:确保目标集群有相同名称的 StorageClass
  • 共享存储后端:两个集群的 Velero 需连接同一对象存储

以下是集群信息:

角色集群IP集群版本部署软件
K8S 集群A172.16.131.134v1.34.2velero、demo-app
K8S 集群B172.16.131.171v1.34.2velero、minio

6.2 源集群操作

在集群 A 部署上应用。

部署测试应用

创建一个 nginx app,并挂载 pvc 用于验证备份恢复功能。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
cat > nginx-demo.yaml <<EOF
apiVersion: v1
kind: Namespace
metadata:
  name: nginx-example
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-html-pvc
  namespace: nginx-example
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs  # 请修改为你的集群中可用的StorageClass
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: nginx-example
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: registry.cn-shanghai.aliyuncs.com/99cloud-sh/nginx:1.20
        ports:
        - containerPort: 80
        volumeMounts:
        - name: html-volume
          mountPath: /usr/share/nginx/html  # Nginx默认的网页根目录
      volumes:
      - name: html-volume
        persistentVolumeClaim:
          claimName: nginx-html-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: nginx-example
spec:
  type: NodePort  # 为了方便从集群外部访问,使用NodePort类型
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
EOF
1
kubectl apply -f nginx-demo.yaml

写入测试

1
2
NGINX_POD=$(kubectl get pods -n nginx-example -l app=nginx -o jsonpath='{.items[0].metadata.name}')
echo $NGINX_POD

将一个简单的 html 复制到 nginx 数据目录中

1
2
3
4
# 首先在本机创建一个测试文件
echo '<h1>Hello from Velero Backup Demo!</h1><p>This file was created on '"$(date)"'.</p>' > test-index.html
# 将文件拷贝到Pod内的PVC目录
kubectl cp test-index.html nginx-example/$NGINX_POD:/usr/share/nginx/html/index.html

访问 nginx 进行验证

1
2
3
4
5
6
kubectl get svc nginx-service -n nginx-example
# 使用输出的NodePort端口访问,例如节点IP为192.168.1.100,端口为32000
curl http://<cluster-ip>:80

root@lixd-dev-2:~# curl 10.111.66.141
<h1>Hello from Velero Backup Demo!</h1><p>This file was created on Tue Jan 27 07:49:17 UTC 2026.</p>

Velero 备份

1
2
3
root@lixd-dev-1:~/velero# velero backup create nginx-backup-pvc --include-namespaces nginx-example --default-volumes-to-fs-backup
Backup request "nginx-backup-pvc" submitted successfully.
Run `velero backup describe nginx-backup-pvc` or `velero backup logs nginx-backup-pvc` for more details.

参数:

  • --include-namespaces:指定命名空间,这里测试仅备份 nginx-example 下的内容。
  • --default-volumes-to-fs-backup:使用文件系统备份工具(Kopia)来备份数据。这种方式更通用。

查看状态

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
root@lixd-dev-1:~/velero# velero backup get
NAME               STATUS       ERRORS   WARNINGS   CREATED                         EXPIRES   STORAGE LOCATION   SELECTOR
nginx-backup-pvc   InProgress   0        0          2026-01-28 07:41:25 +0000 UTC   29d       default            <none>
root@lixd-dev-1:~/velero# velero backup get
NAME               STATUS      ERRORS   WARNINGS   CREATED                         EXPIRES   STORAGE LOCATION   SELECTOR
nginx-backup-pvc   Completed   0        0          2026-01-28 07:41:25 +0000 UTC   29d       default            <none>

# 查看备份详细信息
$ velero backup describe nginx-backup
 
# 查看备份日志
$ velero backup logs nginx-backup

这样就备份好了。

6.4 集群 B 恢复

恢复

在目标集群查看备份对象(如果连接到同一个 S3 存储,Velero 会自动同步):

1
2
3
root@lixd-dev-2:~# velero get backup
NAME               STATUS      ERRORS   WARNINGS   CREATED                         EXPIRES   STORAGE LOCATION   SELECTOR
nginx-backup-pvc   Completed   0        0          2026-01-28 07:41:25 +0000 UTC   29d       default            <none>

恢复数据

1
2
3
root@lixd-dev-2:~# velero restore create --from-backup nginx-backup-pvc
Restore request "nginx-backup-20260127075810" submitted successfully.
Run `velero restore describe nginx-backup-20260127075810` or `velero restore logs nginx-backup-20260127075810` for more details.

查看恢复进度

1
2
3
4
5
6
root@lixd-dev-2:~# velero restore get
NAME                              BACKUP             STATUS       STARTED                         COMPLETED   ERRORS   WARNINGS   CREATED                         SELECTOR
nginx-backup-pvc-20260128080008   nginx-backup-pvc   InProgress   2026-01-28 08:00:08 +0000 UTC   <nil>       0        0          2026-01-28 08:00:08 +0000 UTC   <none>
root@lixd-dev-2:~# velero restore get
NAME                              BACKUP             STATUS      STARTED                         COMPLETED                       ERRORS   WARNINGS   CREATED                         SELECTOR
nginx-backup-pvc-20260128080008   nginx-backup-pvc   Completed   2026-01-28 08:00:08 +0000 UTC   2026-01-28 08:00:17 +0000 UTC   0        1          2026-01-28 08:00:08 +0000 UTC   <none>

验证

验证 Nginx 是否完全恢复

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
root@lixd-dev-2:~/velero# kubectl -n nginx-example get po
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-7cf7667b79-cmjfm   1/1     Running   0          41s
root@lixd-dev-2:~/velero# kubectl -n nginx-example get svc
NAME            TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
nginx-service   NodePort   10.103.125.238   <none>        80:32285/TCP   42s
root@lixd-dev-2:~/velero# kubectl -n nginx-example get pvc
NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
nginx-html-pvc   Bound    pvc-99f0060d-fd8b-4887-a5e5-cdc6858d3590   1Gi        RWO            nfs            <unset>                 45s
root@lixd-dev-2:~# curl 10.111.49.149
<h1>Hello from Velero Backup Demo!</h1><p>This file was created on Wed Jan 28 07:48:15 UTC 2026.</p>

一切正常。

跨集群迁移完成。

小结

Velero 作为一个成熟的 Kubernetes 备份恢复工具,提供了完整的灾难恢复和集群迁移解决方案。通过本文的实战演示,您可以掌握:

  1. Velero 的基本安装和配置
  2. 单集群内应用的备份恢复操作
  3. 跨集群的应用和数据迁移流程
  4. 生产环境的最佳实践建议
0%