一、简介
Velero是一个Go语言编写的开源工具。有了它,可以更方便地对kubernetes资源,存储卷进行备份,恢复,迁移。
- GitHub:GitHub - vmware-tanzu/velero: Backup and migrate Kubernetes applications and their persistent volumes
- 官方文档:Velero Docs - Overview
1.1、支持的版本列表
Velero版本 | Expected Kubernetes version compatibility | Tested on Kubernetes version |
---|---|---|
1.14 | 1.18-latest | 1.27.9, 1.28.9, and 1.29.4 |
1.13 | 1.18-latest | 1.26.5, 1.27.3, 1.27.8, and 1.28.3 |
1.12 | 1.18-latest | 1.25.7, 1.26.5, 1.26.7, and 1.27.3 |
1.11 | 1.18-latest | 1.23.10, 1.24.9, 1.25.5, and 1.26.1 |
1.10 | 1.18-latest | 1.22.5, 1.23.8, 1.24.6 and 1.25.1 |
1.2、Velero组件
Velero工具包含两部分:服务端(部署在集群里面),客户端(命令行工具)。
- 服务端:部署在你的kubernetes集群里面
- 客户端:命令行工具
二、工作机制
每一个Verelo操作,都是一个CRD资源,如下:
# kubectl get crd | grep velero
backups.velero.io 2023-08-07T10:00:27Z
backupstoragelocations.velero.io 2023-08-07T10:00:27Z
deletebackuprequests.velero.io 2023-08-07T10:00:27Z
downloadrequests.velero.io 2023-08-07T10:00:27Z
podvolumebackups.velero.io 2023-08-07T10:00:27Z
podvolumerestores.velero.io 2023-08-07T10:00:27Z
resticrepositories.velero.io 2023-08-07T10:00:27Z
restores.velero.io 2023-08-07T10:00:27Z
schedules.velero.io 2023-08-07T10:00:27Z
serverstatusrequests.velero.io 2023-08-07T10:00:27Z
volumesnapshotlocations.velero.io 2023-08-07T10:00:27Z
Velero支持按需备份,定时备份,备份还原。
- 按需备份:通过资源类型,命名空间,标签来过滤,仅对需要备份的资源备份,然后将备份后的tar包上传到对象存储里面。需要注意,集群备份不是严格的原子备份,如果在备份期间创建或者删除资源,可能不会包含在备份里面。
- 定时备份:定时备份数据,通过cron指定备份周期。每个备份文件通过时间戳区分
- 备份还原:将备份的资源对象和存储卷恢复到集群里面
备份流程
执行命令 velero backup create test-backup
的时候,会执行下面的操作:
- Velero 客户端调用 Kubernetes APIServer 创建 Backup 这个 CRD 对象
- Backup 控制器 watch 到新的 Backup 对象被创建并执行验证
- Backup 控制器开始执行备份,通过查询 APIServer 来获取资源收集数据进行备份
- Backup 控制器调用对象存储服务,比如 S3 上传备份文件
默认情况下 velero backup create
支持任何持久卷的磁盘快照,可以通过指定其他参数来调整快照,可以使用 --snapshot-volumes=false
选项禁用快照。

三、部署对象存储minio
velero支持多种对象存储,不同的对象存储使用对应厂商提供的插件即可。比如:
-
阿里云:AliyunContainerService/velero-plugin (github.com)
-
#安装velero服务端的时候指定阿里云插件和指定bucket信息 velero install \ --provider alibabacloud \ --image registry.$REGION.aliyuncs.com/acs/velero:1.4.2-2b9dce65-aliyun \ --bucket $BUCKET \ --secret-file ./credentials-velero \ --use-volume-snapshots=false \ --backup-location-config region=$REGION \ --use-restic \ --plugins registry.$REGION.aliyuncs.com/acs/velero-plugin-alibabacloud:v1.0.0-2d33b89 \ --wait
-
-
腾讯云:Velero Docs - Use Tencent Cloud Object Storage as Velero's storage destination.
-
velero install --provider aws --plugins velero/velero-plugin-for-aws:v1.1.0 --bucket <BucketName> \ --secret-file ./credentials-velero \ --use-node-agent \ --default-volumes-to-fs-backup \ --backup-location-config \ region=ap-guangzhou,s3ForcePathStyle="true",s3Url=https://cos.ap-guangzhou.myqcloud.com
-
当然,也可以自建对象存储,比如minio。minio可以使用docker一键部署,如果只是临时迁移数据用的话够用了:
#9001是web控制台端口,账户名minio,密码minio123
docker run -d \
-p 9000:9000 \
-p 9001:9001 \
--name minio \
-v /data/minio/data:/data \
-e "MINIO_ROOT_USER=minio" \
-e "MINIO_ROOT_PASSWORD=minio123" \
quay.io/minio/minio server /data \
--console-address ":9001"
也可以部署在k8s集群里面(下面的例子也是单节点的,非集群部署):
#9001是web控制台端口,账户名minio,密码minio123,下面使用pvc持久化数据,测试的话也可以改emptyDir,最后创建了一个job资源,用于在minio里面创建bucket
apiVersion: v1
kind: Namespace
metadata:
name: minio
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: minio-pv-claim
namespace: minio
spec:
storageClassName: default
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: minio
name: minio
labels:
app: minio
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: minio
template:
metadata:
labels:
app: minio
spec:
volumes:
- name: storage
persistentVolumeClaim:
claimName: minio-pv-claim
containers:
- name: minio
image: minio/minio:latest
imagePullPolicy: IfNotPresent
args:
- server
- /storage
- --config-dir=/config
- --console-address=:9001
env:
- name: MINIO_ACCESS_KEY
value: "minio"
- name: MINIO_SECRET_KEY
value: "minio123"
ports:
- containerPort: 9000
- containerPort: 9001
volumeMounts:
- name: storage
mountPath: "/storage"
---
apiVersion: v1
kind: Service
metadata:
namespace: minio
name: minio
labels:
app: minio
spec:
type: NodePort
ports:
- name: api
port: 9000
targetPort: 9000
- name: console
port: 9001
targetPort: 9001
selector:
component: minio
---
apiVersion: batch/v1
kind: Job
metadata:
namespace: minio
name: minio-setup
labels:
app: minio
spec:
template:
metadata:
name: minio-setup
spec:
restartPolicy: OnFailure
volumes:
- name: config
emptyDir: {}
containers:
- name: mc
image: minio/mc:latest
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- "mc --config-dir=/config config host add velero http://minio:9000 minio minio123 && mc --config-dir=/config mb -p velero/velero"
volumeMounts:
- name: config
mountPath: "/config"
当然也可以使用minio官方的operator部署minio存储集群, Helm Operator Charts 和 Helm Tenant Charts
四、部署velero服务端
velero部署在k8s集群里面,可以使用helm方式部署,也可以使用velero客户端工具部署。
- helm:Helm chart
- 命令行:velero install
命令行部署:
4.1、准备velero配置文件
root@ubuntu:~/velero# cat velero-auth.txt
[default]
aws_access_key_id = minio
aws_secret_access_key = minio123
4.2、部署velero服务端
#下载velero命令行工具
root@ubuntu:~/velero# wget https://www.ghproxy.cn/https://github.com/vmware-tanzu/velero/releases/download/v1.14.1/velero-v1.14.1-linux-amd64.tar.gz
root@ubuntu:~/velero# mv velero-v1.14.1-linux-amd64/velero /usr/local/bin/
#设置bash补全
root@ubuntu:~/velero# apt install bash-completion
root@ubuntu:~/velero# source <(velero completion bash)
root@ubuntu:~/velero# echo 'source <(velero completion bash)' >>~/.bashrc
#这里使用velero命令行来部署
root@ubuntu:~/velero# velero install \
--provider aws \
--plugins xxxxxx.azurecr.cn/velero/velero-plugin-for-aws:v1.10.0 \
--bucket velero \
--secret-file ./velero-auth.txt \
--image xxxxxx.azurecr.cn/velero/velero:v1.14.1 \
--use-node-agent \
--use-volume-snapshots=false \
--namespace velero\
--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://minio.minio.svc:9000
...
velero is installed! ⛵ Use 'kubectl logs deployment/velero -n velero-system' to view the status.
--provider aws
:声明使用的 Velero 插件类型为AWS。minio是兼容S3协议的。--plugins xxxxxx.azurecr.cn/velero/velero-plugin-for-aws:v1.10.0
:指定存储插件镜像。内网环境可以指定镜像,避免镜像拉取不到--bucket velero
:指定bucket,velero将使用这个bucket存放备份数据--secret-file
:指定包含访问 S3 存储桶所需凭证的文件路径--image
:指定 Velero 服务器的镜像。内网环境可以指定镜像,避免镜像拉取不到--use-node-agent
:启用 Node Agent 功能。Node Agent 是一个在每个节点上运行的组件。使用--default-volumes-to-fs-backup
备份文件系统时候需要--use-volume-snapshots=false
:禁用卷快照功能。这意味着 Velero 不会使用云提供商的卷快照功能来备份持久卷--namespace velero
:指定 Velero 安装所在的命名空间--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://minio.minio.svc:9000
:指定备份位置的配置参数:region=minio
: 设置区域为minio
。这通常用于 AWS 区域标识,但在这里只是一个自定义标识。s3ForcePathStyle="true"
: 强制使用路径样式访问 S3 API,而不是虚拟托管样式。这对于 MinIO 是必需的,因为它不支持虚拟托管样式。s3Url=http://minio.minio.svc:9000
: 指定 MinIO 服务的 URL。这里的 URL 是http://minio.minio.svc:9000
,假设 MinIO 服务在minio
命名空间中运行,并且通过 Service 名称minio
可以访问到它。
五、备份集群
更多备份相关的疑问,移步这里
备份指定namespace资源
~# velero backup create mysql-backup \
--include-namespaces mysql \
--exclude-resources statefulsets \
--default-volumes-to-fs-backup
Backup request "mysql-backup" submitted successfully.
mysql-backup
:备份的名称--include-namespaces mysql
:指定要包含在备份中的命名空间。也可以指定过个namespace。同时也可以使用--exclude-namespaces
来排除哪些namespace--exclude-resources statefulsets
:指定要排除的资源类型。在这个例子中,statefulsets 资源将不会被包含在备份中。--default-volumes-to-fs-backup
:指定默认情况下如何处理持久卷(Persistent Volumes, PVs)。这个参数告诉 Velero 将所有未显式指定为快照的持久卷通过文件系统备份(而不是使用云提供商的卷快照功能)。使用文件系统备份时,Velero 会将持久卷的内容复制到 S3 存储桶中,而不是创建一个单独的卷快照。
查看备份
#velero backup get是从minio中查询的数据
root@ubuntu:~/minio# velero backup get
NAME STATUS ERRORS WARNINGS CREATED EXPIRES STORAGE LOCATION SELECTOR
mysql-backup Completed 0 0 2024-09-24 06:15:00 +0000 UTC 27d default <none>
#kubectl可以查询到备份记录,但是不存储数据
root@ubuntu:~/minio# kubectl -n velero get backup
NAME AGE
mysql-backup 2d1h
#查看备份详情
root@ubuntu:~/minio# velero backup describe mysql-backup
Name: mysql-backup
Namespace: velero
Labels: velero.io/storage-location=default
Annotations: velero.io/resource-timeout=10m0s
velero.io/source-cluster-k8s-gitversion=v1.27.7+k3s2
velero.io/source-cluster-k8s-major-version=1
velero.io/source-cluster-k8s-minor-version=27
Phase: Completed
Namespaces:
Included: mysql
Excluded: <none>
Resources:
Included: *
Excluded: <none>
Cluster-scoped: auto
Label selector: <none>
Or label selector: <none>
Storage Location: default
Velero-Native Snapshot PVs: auto
Snapshot Move Data: false
Data Mover: velero
TTL: 720h0m0s
CSISnapshotTimeout: 10m0s
ItemOperationTimeout: 4h0m0s
Hooks: <none>
Backup Format Version: 1.1.0
Started: 2024-09-24 06:15:00 +0000 UTC
Completed: 2024-09-24 06:15:03 +0000 UTC
Expiration: 2024-10-24 06:15:00 +0000 UTC
Total items to be backed up: 11
Items backed up: 11
Backup Volumes:
Velero-Native Snapshots: <none included>
CSI Snapshots: <none included>
Pod Volume Backups - kopia (specify --details for more information):
Completed: 1
HooksAttempted: 0
HooksFailed: 0
六、恢复数据
更多恢复相关的疑问,移步这里
如果是跨集群恢复数据,新的集群里面也需要部署velero
root@ubuntu:~/velero# cat velero-auth.txt
[default]
aws_access_key_id = minio
aws_secret_access_key = minio123
#恢复数据卷的时候会使用velero-restore-helper镜像在每个pod里面启动一个init容器,如果是内网环境可能拉不到这个镜像,这里通过ConfigMap指定velero-restore-helper镜像地址
root@ubuntu:~/velero# cat cm_velero.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: fs-restore-action-config
namespace: velero
labels:
velero.io/plugin-config: ""
velero.io/pod-volume-restore: RestoreItemAction
data:
image: "xxxxxx.azurecr.cn/velero/velero-restore-helper:v1.14.1"
secCtxRunAsUser: "0"
secCtxRunAsGroup: "0"
secCtxAllowPrivilegeEscalation: "false"
root@ubuntu:~/velero# velero install \
--provider aws \
--plugins xxxxxx.azurecr.cn/velero/velero-plugin-for-aws:v1.10.0 \
--bucket velero \
--secret-file ./velero-auth.txt \
--image xxxxxx.azurecr.cn/velero/velero:v1.14.1 \
--use-node-agent \
--use-volume-snapshots=false \
--namespace velero\
--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://minio.minio.svc:9000
...
velero is installed! ⛵ Use 'kubectl logs deployment/velero -n velero-system' to view the status.
恢复数据
root@ubuntu:~/minio# velero restore create mysql-restore \
--from-backup mysql-backup \
--namespace-mappings mysql:mysql-demo \
--preserve-nodeports=false \
--existing-resource-policy=none
mysql-restore
:这是恢复操作的名称--from-backup mysql-backup
:指定要从中恢复数据的备份名称。在这个例子中,恢复操作将从名为 mysql-backup 的备份中恢复数据。--namespace-mappings mysql:mysql-demo
:指定命名空间映射。这个参数允许您将备份中的命名空间映射到目标集群中的不同命名空间。也可以跟多个--preserve-nodeports=false
:定是否保留 NodePort 服务的端口。如果设置为false
,则 Velero 不会尝试保留 NodePort 服务的端口。可以避免端口冲突的情况。另外不建议生产环境使用NodePort暴露服务--existing-resource-policy=none
:指定处理现有资源的策略。这个参数控制当恢复过程中遇到已经存在的资源时,Velero 应该如何处理。默认是none,表示不做处理,如果设置为update,velero将会尝试更新资源。
#查看恢复详细信息
root@ubuntu:~# velero restore get
NAME BACKUP STATUS STARTED COMPLETED ERRORS WARNINGS CREATED SELECTOR
mysql-restore mysql-backup Completed 2024-09-26 07:46:53 +0000 UTC 2024-09-26 07:46:58 +0000 UTC 0 1 2024-09-26 07:46:53 +0000 UTC <none>
root@ubuntu:~# velero restore describe mysql-restore --details
Name: mysql-restore
Namespace: velero
Labels: <none>
Annotations: <none>
Phase: Completed
Total items to be restored: 11
Items restored: 11
Started: 2024-09-26 07:46:53 +0000 UTC
Completed: 2024-09-26 07:46:58 +0000 UTC
Warnings:
Velero: <none>
Cluster: <none>
Namespaces:
mysql-demo: could not restore, ConfigMap "kube-root-ca.crt" already exists. Warning: the in-cluster version is different than the backed-up version
Backup: mysql-backup
Namespaces:
Included: all namespaces found in the backup
Excluded: <none>
Resources:
Included: *
Excluded: nodes, events, events.events.k8s.io, backups.velero.io, restores.velero.io, resticrepositories.velero.io, csinodes.storage.k8s.io, volumeattachments.storage.k8s.io, backuprepositories.velero.io
Cluster-scoped: auto
Namespace mappings: mysql=mysql-demo
Label selector: <none>
Or label selector: <none>
Restore PVs: auto
kopia Restores:
Completed:
mysql-demo/mysql-7c5b44974d-ghsz4: mysql-data
CSI Snapshot Restores: <none included>
Existing Resource Policy: none
ItemOperationTimeout: 4h0m0s
Preserve Service NodePorts: false
Uploader config:
HooksAttempted: 0
HooksFailed: 0
Resource List:
apps/v1/Deployment:
- mysql-demo/mysql(created)
apps/v1/ReplicaSet:
- mysql-demo/mysql-7c5b44974d(created)
discovery.k8s.io/v1/EndpointSlice:
- mysql-demo/mysql-r96dl(created)
v1/ConfigMap:
- mysql-demo/kube-root-ca.crt(failed)
v1/Endpoints:
- mysql-demo/mysql(created)
v1/Namespace:
- mysql-demo(created)
v1/PersistentVolume:
- pvc-a427785d-f5f5-49af-802a-067c205b4544(skipped)
v1/PersistentVolumeClaim:
- mysql-demo/pvc-mysql(created)
v1/Pod:
- mysql-demo/mysql-7c5b44974d-ghsz4(created)
v1/Service:
- mysql-demo/mysql(created)
v1/ServiceAccount:
- mysql-demo/default(skipped)
#如果恢复显示失败,可以使用logs查看恢复日志
root@ubuntu:~# velero restore logs mysql-restore
恢复原理
参考官方文档
- 1. Velero 客户端调用 Kubernetes API 服务器创建一个 Restore 对象
- 2. RestoreController 注意到新的 Restore 对象并进行验证
- 3. 获取备份的基本信息
- RestoreController 获取要恢复的备份的基本信息,如 BackupStorageLocation (BSL)
- 它还获取备份中的集群资源 tarball、将使用文件系统备份恢复的任何卷以及要恢复的任何卷快照
- 4. 提取和预处理资源
- RestoreController 将备份的集群资源 tarball 提取到
/tmp
文件夹,并对资源进行一些预处理,包括:- 排序资源:帮助 Velero 决定使用的恢复顺序。
- 发现资源:尝试通过 Kubernetes Group Version Resource (GVR) 发现资源。如果某个资源不可发现,Velero 将排除它。更多关于 Velero 如何备份 API 版本的信息请参阅相关文档。
- 应用配置的资源过滤器。
- 验证目标命名空间:如果您配置了
--namespace-mappings
恢复选项,则会验证目标命名空间。
- RestoreController 将备份的集群资源 tarball 提取到
- 5. 开始恢复符合条件的资源
- RestoreController 开始逐个恢复符合条件的资源。Velero 将当前资源提取为 Kubernetes 资源对象。根据资源类型和您指定的恢复选项,Velero 将对资源或目标集群进行以下修改或准备,然后尝试创建资源:
- 确保目标命名空间存在:如果目标命名空间不存在,RestoreController 将在集群上创建一个新的命名空间。
- 如果资源是 Persistent Volume (PV):RestoreController 将重命名 PV 并重新映射其命名空间。
- 如果资源是 Persistent Volume Claim (PVC):RestoreController 将修改 PVC 的元数据。
- 执行自定义插件:如果配置了自定义插件,则执行资源的 RestoreItemAction 自定义插件。
- 更新资源对象的命名空间:如果您配置了命名空间映射,则更新资源对象的命名空间。
- 添加标签:RestoreController 向资源添加
velero.io/backup-name
标签(包含备份名称)和velero.io/restore-name
标签(包含恢复名称)。这有助于您轻松识别已恢复的资源及其来源备份。
- RestoreController 开始逐个恢复符合条件的资源。Velero 将当前资源提取为 Kubernetes 资源对象。根据资源类型和您指定的恢复选项,Velero 将对资源或目标集群进行以下修改或准备,然后尝试创建资源:
- 6. 在目标集群上创建资源对象
- RestoreController 在目标集群上创建资源对象。如果资源是 PV,则 RestoreController 将从持久快照、文件系统备份或 CSI 快照中恢复 PV 数据,具体取决于 PV 的备份方式。
- 7. 处理现有资源:
- 如果资源已经存在于目标集群中(由 Kubernetes API 在资源创建期间确定),则 RestoreController 将跳过该资源。唯一的例外是 Service Accounts,Velero 将尝试合并备份的 ServiceAccount 和目标集群上的 ServiceAccount 之间的差异。您可以使用
--existing-resource-policy
选项更改默认的现有资源恢复策略,以更新资源而不是跳过它们。
- 如果资源已经存在于目标集群中(由 Kubernetes API 在资源创建期间确定),则 RestoreController 将跳过该资源。唯一的例外是 Service Accounts,Velero 将尝试合并备份的 ServiceAccount 和目标集群上的 ServiceAccount 之间的差异。您可以使用
- 8. 额外步骤和等待
- 一旦资源在目标集群上创建,Velero 可能需要采取一些额外的步骤或等待其他进程完成,然后再继续恢复下一个资源。
- 如果资源是 Pod:RestoreController 将执行任何 Restore Hooks 并等待钩子完成。
- 如果资源是通过文件系统备份恢复的 PV:RestoreController 将等待文件系统备份的恢复完成。RestoreController 为在恢复过程中使用文件系统备份恢复的任何资源设置超时时间。默认超时时间为 4 小时,但您可以使用
--fs-backup-timeout
恢复选项来配置它。 - 如果资源是 Custom Resource Definition:RestoreController 将等待其在集群中的可用性。超时时间为 1 分钟。
- 如果在完成这些步骤时发生任何故障:RestoreController 将在恢复结果中记录错误并继续恢复。
- 一旦资源在目标集群上创建,Velero 可能需要采取一些额外的步骤或等待其他进程完成,然后再继续恢复下一个资源。
恢复顺序
默认情况下,Velero 将按以下顺序恢复资源:
1. **Custom Resource Definitions**
2. **Namespaces**
3. **StorageClasses**
4. **VolumeSnapshotClass**
5. **VolumeSnapshotContents**
6. **VolumeSnapshots**
7. **PersistentVolumes**
8. **PersistentVolumeClaims**
9. **Secrets**
10. **ConfigMaps**
11. **ServiceAccounts**
12. **LimitRanges**
13. **Pods**
14. **ReplicaSets**
15. **Clusters**
16. **ClusterResourceSets**
pv和pvc如何恢复
Velero 在恢复 Persistent Volume (PV) 时有三种方法,具体取决于备份是如何进行的。
- 从快照恢复
- 当从快照恢复时,Velero 静态创建 PV,然后将其绑定到已恢复的 PVC。
- Velero 的 PV 重命名和重新映射过程仅在这种情况下使用,因为这是唯一 Velero 直接创建 PV 资源的情况。
- 使用文件系统备份恢复
- 当使用文件系统备份恢复时,Velero 在创建 PVC 后使用 Kubernetes 的动态供应过程来供应 PV。
- 使用 CSI 插件恢复
- 当使用 CSI 插件恢复时,PV 是由 CSI 驱动程序从 CSI 快照创建的。
- Velero 不直接创建 PV。相反,Velero 创建一个 PVC,并将其 DataSource 引用到 CSI VolumeSnapshot 对象。
七、其他
velero功能还是挺强大的。本文只是介绍了velero的冰山一脚,实际使用过程中还是要看文档和帮助。velero还支持以下功能:
- 定时备份
- 设置备份过期时间
- backup hooks
- restore hooks
- 配置存储类映射关系(如果新集群和旧集群的storageclass不一样的话可以配置映射关系)
更多备份相关的疑问,移步这里
更多恢复相关的疑问,移步这里