参考来源:
- velero 官网: https://velero.io/
- velero 手册: https://velero.io/docs/v1.6/
velero 供应商: https://velero.io/docs/v1.6/supported-providers/
引言
在运维安全管理中容灾备份是非常重要的一环, 那在Kubernetes集群中如何进行备份和迁移 Kubernetes 资源和持久卷数据。
常常采用手动进行容灾备份, 如备份资源清单、或者helm模板,但是针对Kubernetes 资源和持久卷(PV/PVC)中得数据无法进行备份迁移,所以在这样得场景下我们就需要 Velero 是一个开源工具。
并且,kubernetes集群备份也是一个难点。虽然可以通过备份ETCD的方式来实现K8S集群备份,并且可以恢复集群到某一个时刻的状态,但是这种备份方式很难实现恢复单个资源对象,因为ETCD一般使用快照的形式进行备份和恢复
再有的时候可能有些新同事不熟悉环境导致误操作将某个namespace点击删除,然后导致下面的资源全部丢失,这时候也只能一步一步通过之前的资源清单重新创建,严重的可能会重新部署集群velero基础概述
Velero是一个开源工具,用于安全备份和恢复、执行灾难恢复以及迁移kubernetes集群资源和持久卷
Velero 可以让您备份您的集群并在丢失时恢复、将集群资源迁移到其他集群、将您的生产集群复制到开发和测试集群, 详细解析说明:
1.灾难恢复 : 在基础设施丢失、数据损坏和/或服务中断的情况下减少恢复时间。支持 Kubernetes 集群数据备份和恢复
2.数据迁移 : 通过轻松地将 Kubernetes 资源从一个集群迁移到另一个集群,实现集群可移植性。支持复制当前 Kubernetes 集群的资源到其它 Kubernetes 集群
3.数据保护 : 提供关键数据保护功能,例如计划备份、保留计划以及用于自定义操作的备份前或备份后挂钩。
Velero 特点: 您可以备份或恢复集群中的所有对象,也可以按类型、命名空间和/或标签过滤对象。
1.备份集群 : 使用命名空间或标签选择器为整个集群或集群的一部分备份 Kubernetes 资源和卷。
2.计划备份 : 设置计划以定期自动启动备份。
3.备份挂钩 : 配置备份前和备份后挂钩,以在 Velero 备份之前和之后执行自定义操作。
你可以通过云提供商或本地运行 Velero, 其组件包括在集群上运行的服务器和本地运行的命令行客户端。
使用Minio服务进行管理存储备份在ETCD的数据、使用velero客户端进行备份和还原操作
与 Etcd 备份相比,直接备份 Etcd 是将集群的全部资源备份起来。而 Velero 就是可以对 Kubernetes 集群内对象级别进行备份。除了对 Kubernetes 集群进行整体备份外,Velero 还可以通过对 Type、Namespace、Label 等对象进行分类备份或者恢复。
Velero支持 AWS S3以及兼容S3的存储,比如Minio,ZureBlob存储,Google Cloud存储,同时也给出了插件功能用来拓展其他平台的存储,阿里云也提供了 Velero 的插件,用于将备份存储到 OSS 中Velero工作原理
一般情况下使用Velero主要是从下面几个方面入手
1.按需备份: 将复制的 Kubernetes 对象的 tarball 上传到云对象存储中,调用云提供商 API 以制作持久卷的磁盘快照(如果指定)。
- 2.计划备份: 由 Cron 表达式指定在循环间隔备份您的数据,计划备份以名称保存
- ,其中 格式为YYYYMMDDhhmmss。 - 3.容灾恢复: 该恢复操作可以恢复所有对象和持久卷从先前创建的备份,还原的默认名称为
- , 恢复的对象还包括一个带有 key velero.io/restore-name 和 value的标签 - 4.备份过期: 可以通过添加标志来指定—ttl
参数来设置备份得生存时间(默认30天)。到期后则会删除备份资源、来自云对象存储的备份文件、所有 PersistentVolume 快照、所有关联的恢复。 - 5.对象存储同步: 它会不断检查以确保始终存在正确的备份资源。如果存储桶中有格式正确的备份文件,但 Kubernetes API 中没有相应的备份资源,Velero 会将信息从对象存储同步到 Kubernetes。
工作流程:
当你运行velero backup create test-backup命令。
1.Velero 客户端调用 Kubernetes API 服务器来创建一个Backup对象。
2.该 BackupController 注意到新的 Backup 对象并进行验证。
3.在 BackupController 开始备份过程。它通过向 API 服务器查询资源来收集要备份的数据。
4.将 BackupController 使得对象存储服务的调用-例如,AWS S3 -上传备份文件。
默认情况下 velero backup create 为任何持久卷制作磁盘快照, 可以通过指定附加标志来调整快照—snapshot-volumes=false(使用选项禁用快照)。
实际上 Velero 在 Kubernetes 集群中创建了很多 CRD 以及相关的控制器,进行备份恢复等操作实质上是对相关 CRD 的操作。
Velero 使用 Kubernetes API 服务器的首选版本为每个组/资源备份资源。恢复资源时,目标集群中必须存在相同的 API 组/版本才能成功恢复。
环境部署
先决条件
- Kubernetes 集群 API Version >= 1.7
- Kubernetes 集群已部署 DNS 服务器 (例如: CoreDNS)。
- 在 Minio 中存储备份可用磁盘空间少于 1GB,Minio 将无法运行。(你可以可以使用阿里云或其他云厂商的OSS)
- velero组件分为两部分,分别是服务端和客户端。服务端运行在你的kubernetes集群中,客户端是一些运行在本地的命令行工具
下载部署velero客户端
下载 最新的官方版本的tarball,每个版本的 tarball 都包含velero命令行客户端,,并将elero二进制文件从 Velero 目录移动到 PATH 中的某个位置。
验证velero clientcurl -fSL https://github.com/vmware-tanzu/velero/releases/download/v1.6.2/velero-v1.6.2-linux-amd64.tar.gztar -zxvf velero-v1.6.2-linux-amd64.tar.gz -C /usr/local/ln -s /usr/local/velero-v1.6.2-linux-amd64/velero /usr/bin/velero
[root@kube-master-01 velero]# velero versionClient:Version: v1.6.2Git commit: 8c9cdb9603446760452979dc77f93b17054ea1cc[root@kube-master-01 velero]#
配置Minio服务
因为我们使用的是本地存储的方式,所以需要自己搭建一个支持S3协议的对象存储服务
在本地目录中创建 Velero 特定的凭据文件。
修改启动服务器和本地存储服务。[root@kube-master-01 velero]# cat /tmp/credentials-velero[default]aws_access_key_id = minioaws_secret_access_key = minio123[root@kube-master-01 velero]#
在Velero解压的目中/velero/examples/minio中修改00-minio-deployment.yaml内容如下
请注意:对于minio服务的暴露方式我使用的是nodeport```yaml
apiVersion: v1 kind: Namespace metadata: name: velero
apiVersion: apps/v1 kind: Deployment metadata: namespace: velero name: minio labels: component: minio spec: strategy: type: Recreate selector: matchLabels: component: minio template: metadata: labels: component: minio spec: volumes:
- name: storageemptyDir: {}- name: configemptyDir: {}containers:- name: minioimage: minio/minio:latestimagePullPolicy: IfNotPresent# 设置静态得Console监控端口(推荐)args:- server- /storage- --config-dir=/config- --console-address- ":31234"# 注意事项: 主要修改点是以下环境变量名称`MINIO_ROOT_USER|MINIO_ROOT_PASSWORD`否则。# WARNING: MINIO_ACCESS_KEY and MINIO_SECRET_KEY are deprecated.# Please use MINIO_ROOT_USER and MINIO_ROOT_PASSWORDenv:- name: MINIO_ROOT_USERvalue: "minio"- name: MINIO_ROOT_PASSWORDvalue: "minio123"# Pod 暴露 minio 服务和 console web 服务端口以供SVC使用ports:- name: webcontainerPort: 9000- name: consolecontainerPort: 31234volumeMounts:- name: storagemountPath: "/storage"- name: configmountPath: "/config"
apiVersion: v1 kind: Service metadata: namespace: velero name: minio labels: component: minio spec:
ClusterIP is recommended for production environments.
Change to NodePort if needed per documentation,
but only if you run Minio in a test/trial environment, for example with Minikube.
type: NodePort ports:
- name: web port: 9000 targetPort: 9000 nodePort: 30090 protocol: TCP
- name: console port: 31234 targetPort: 31234 nodePort: 31234 protocol: TCP selector: component: minio
apiVersion: batch/v1 kind: Job metadata: namespace: velero name: minio-setup labels: component: minio spec: template: metadata: name: minio-setup spec: restartPolicy: OnFailure volumes:
- name: configemptyDir: {}containers:- name: mcimage: minio/mc:latestimagePullPolicy: IfNotPresent# Minio状态检测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: configmountPath: "/config"
注意 Velero 1.6.2 版本中minio得yaml配置文件我们需要相应进行改变。<br />注意 提供的 Minio yaml 示例使用"空目录",您的节点需要有足够的可用空间来存储要备份的数据以及 1GB 的可用空间。如果节点没有足够的空间,您可以修改示例 yaml 以使用 Persistent Volume 而不是empty dir。<br />注意 使用 Service 在集群外公开 Minio 时需要Pod暴露两个应用端口即Service 9000和Console 默认随机,此时你可以将将 Minio 服务类型从更改ClusterIP为NodePort,具体配置查看上述资源清单。部署minio资源清单以及服务查看```bash# 使用本地集群minio作为备份存储kubectl apply -f examples/minio/00-minio-deployment.yaml[root@kube-master-01 minio]# kubectl get svc -n veleroNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEminio NodePort 10.1.200.33 <none> 9000:30090/TCP,31234:31234/TCP 65m[root@kube-master-01 minio]#[root@kube-master-01 minio]# kubectl get pods -n velero -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESminio-85dfcfdb9-d9x59 1/1 Running 0 65m 10.244.236.67 kube-node-02 <none> <none>minio-setup-rh8g2 0/1 Completed 0 65m 10.244.10.68 kube-node-01 <none> <none>[root@kube-master-01 minio]#
打开浏览器访问Minio服务端,此时他会访问跳转到31234端口
用户名:minio
密码:minion123
安装velero客户端
之前有说过,velero是C/S架构的工具
# 获取指定 minio 服务地址和服务端口minio_service_ip="172.18.14.102"minio_service_port=$(kubectl -n velero get svc/minio -o jsonpath='{.spec.ports[0].nodePort}')# kubernetes Master 节点上安装 velero 或者在其他集群上安装执行velero install \--image velero/velero:v1.6.2 \--provider aws \ #使用的是S3协议--bucket velero \ #存储桶的名称--namespace velero \--plugins velero/velero-plugin-for-aws:v1.2.0 \--secret-file /tmp/credentials-velero \--velero-pod-cpu-request 200m \--velero-pod-mem-request 200Mi \--velero-pod-cpu-limit 1000m \--velero-pod-mem-limit 1000Mi \--use-volume-snapshots=false \--use-restic \--restic-pod-cpu-request 200m \--restic-pod-mem-request 200Mi \--restic-pod-cpu-limit 1000m \--restic-pod-mem-limit 1000Mi \--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://${minio_service_ip}:${minio_service_port}# 出现下述表示安装成功, 并且此时可以看到相关服务已经正常运行,Job 任务正常完成退出,大量 CRD 被创建。# Velero is installed! ⛵ Use 'kubectl logs deployment/velero -n velero' to view the status.
在kubernetes主节点中验证查看velero部署得所有服务
[root@kube-master-01 minio]# kubectl get all -n veleroNAME READY STATUS RESTARTS AGEpod/minio-85dfcfdb9-d9x59 1/1 Running 0 76mpod/minio-setup-rh8g2 0/1 Completed 0 76mpod/restic-4sn85 1/1 Running 0 68mpod/restic-7lnpr 1/1 Running 0 68mpod/restic-9kvtf 1/1 Running 0 68mpod/restic-dnm5z 1/1 Running 0 68mpod/restic-kkbfd 1/1 Running 0 68mpod/restic-lp82j 1/1 Running 0 68mpod/restic-p84bq 1/1 Running 0 68mpod/velero-7b8b8fc8f-5fwtc 1/1 Running 0 68mNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/minio NodePort 10.1.200.33 <none> 9000:30090/TCP,31234:31234/TCP 76mNAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGEdaemonset.apps/restic 7 7 7 7 7 <none> 68mNAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/minio 1/1 1 1 76mdeployment.apps/velero 1/1 1 1 68mNAME DESIRED CURRENT READY AGEreplicaset.apps/minio-85dfcfdb9 1 1 1 76mreplicaset.apps/velero-7b8b8fc8f 1 1 1 68mNAME COMPLETIONS DURATION AGEjob.batch/minio-setup 1/1 2m2s 76m[root@kube-master-01 minio]#[root@kube-master-01 minio]# kubectl logs -n velero pod/minio-85dfcfdb9-d9x59API: http://10.244.236.67:9000 http://127.0.0.1:9000Console: http://10.244.236.67:31234 http://127.0.0.1:31234Documentation: https://docs.min.io[root@kube-master-01 minio]#
验证velero服务是否安装成功
[root@kube-master-01 velero]# velero versionClient:Version: v1.6.2Git commit: 8c9cdb9603446760452979dc77f93b17054ea1ccServer:Version: v1.6.2[root@kube-master-01 velero]#
备份实践
备份单个资源对象
在velero的解压目录中提供了一个nginx的部署清单,可以使用这个demo进行备份的测试,我这里直接使用的是别的pod进行备份测试
[root@kube-master-01 velero]# velero backup create dingtalk-backup-20211229 --selector app=dingtalk-webhookBackup request "dingtalk-backup-20211229" submitted successfully.Run `velero backup describe dingtalk-backup-20211229` or `velero backup logs dingtalk-backup-20211229` for more details.[root@kube-master-01 velero]#[root@kube-master-01 velero]# velero backup describe dingtalk-backup-20211229Name: dingtalk-backup-20211229Namespace: veleroLabels: velero.io/storage-location=defaultAnnotations: velero.io/source-cluster-k8s-gitversion=v1.19.3velero.io/source-cluster-k8s-major-version=1velero.io/source-cluster-k8s-minor-version=19Phase: CompletedErrors: 0Warnings: 0Namespaces:Included: *Excluded: <none>Resources:Included: *Excluded: <none>Cluster-scoped: autoLabel selector: app=dingtalk-webhookStorage Location: defaultVelero-Native Snapshot PVs: autoTTL: 720h0m0sHooks: <none>Backup Format Version: 1.1.0Started: 2021-12-29 16:28:41 +0800 CSTCompleted: 2021-12-29 16:28:54 +0800 CSTExpiration: 2022-01-28 16:28:41 +0800 CSTTotal items to be backed up: 5Items backed up: 5Velero-Native Snapshots: <none included>[root@kube-master-01 velero]#
备份除匹配标签之外的所有对象
[root@kube-master-01 velero]# velero backup create all-backup --selector 'backup notin (ignore)'Backup request "all-backup" submitted successfully.Run `velero backup describe all-backup` or `velero backup logs all-backup` for more details.[root@kube-master-01 velero]# velero backup describe all-backupName: all-backupNamespace: veleroLabels: velero.io/storage-location=defaultAnnotations: velero.io/source-cluster-k8s-gitversion=v1.19.3velero.io/source-cluster-k8s-major-version=1velero.io/source-cluster-k8s-minor-version=19Phase: CompletedErrors: 0Warnings: 0Namespaces:Included: *Excluded: <none>Resources:Included: *Excluded: <none>Cluster-scoped: autoLabel selector: backup notin (ignore)Storage Location: defaultVelero-Native Snapshot PVs: autoTTL: 720h0m0sHooks: <none>Backup Format Version: 1.1.0Started: 2021-12-29 16:33:39 +0800 CSTCompleted: 2021-12-29 16:34:02 +0800 CSTExpiration: 2022-01-28 16:33:39 +0800 CSTTotal items to be backed up: 1190Items backed up: 1190Velero-Native Snapshots: <none included>[root@kube-master-01 velero]#
定期备份
$ velero schedule create nginx-daily --schedule="0 1 * * *" --selector app=nginx# 或者,您可以使用一些非标准速记 cron 表达式:$ velero schedule create nginx-daily --schedule="@daily" --selector app=nginx
查看备份
[root@kube-master-01 dingtalk]# velero backup getNAME STATUS ERRORS WARNINGS CREATED EXPIRES STORAGE LOCATION SELECTORall-backup Completed 0 0 2021-12-29 16:33:39 +0800 CST 29d default backup notin (ignore)dingtalk-backup Completed 0 0 2021-12-29 15:30:29 +0800 CST 29d default app=dingtalk-webhookdingtalk-backup-20211229 Completed 0 0 2021-12-29 16:28:41 +0800 CST 29d default app=dingtalk-webhook[root@kube-master-01 dingtalk]#
恢复实践
模拟删除Pod
模拟删除掉dingtalk这个Pod,因为是deployment,所以直接使用资源配置清单模拟删除
[root@kube-master-01 dingtalk]# kubectl delete -f dingtalk-deployment.yamldeployment.apps "dingtalk-webhook" deletedservice "dingtalk-webhook" deleted[root@kube-master-01 dingtalk]#
检查Pod是否已经删除
[root@kube-master-01 dingtalk]# kubectl get pods -n kubesphere-monitoring-system -l app=dingtalk-webhookNo resources found in kubesphere-monitoring-system namespace.[root@kube-master-01 dingtalk]#
模拟恢复Pod资源
利用velero中的备份进行恢复刚才删除的Pod资源
[root@kube-master-01 dingtalk]# velero restore create --from-backup dingtalk-backup-20211229Restore request "dingtalk-backup-20211229-20211229164228" submitted successfully.Run `velero restore describe dingtalk-backup-20211229-20211229164228` or `velero restore logs dingtalk-backup-20211229-20211229164228` for more details.[root@kube-master-01 dingtalk]#
查看恢复状态
#成功恢复后该STATUS列Completed[root@kube-master-01 dingtalk]# velero restore getNAME BACKUP STATUS STARTED COMPLETED ERRORS WARNINGS CREATED SELECTORdingtalk-backup-20211229-20211229164228 dingtalk-backup-20211229 Completed 2021-12-29 16:42:28 +0800 CST 2021-12-29 16:42:29 +0800 CST 0 0 2021-12-29 16:42:28 +0800 CST <none>[root@kube-master-01 dingtalk]##如果有错误信息可以使用如下命令详细查看$ velero restore describe dingtalk-backup-20211229-20211229164228[root@kube-master-01 dingtalk]# kubectl get pods -n kubesphere-monitoring-system -l app=dingtalk-webhookNAME READY STATUS RESTARTS AGEdingtalk-webhook-8bc897cd6-hqzzr 1/1 Running 0 2m49s[root@kube-master-01 dingtalk]#
其他操作
删除创建的备份
[root@kube-master-01 dingtalk]# velero backup delete all-backupAre you sure you want to continue (Y/N)? yRequest to delete backup "all-backup" submitted successfully.The backup will be fully deleted after all associated data (disk snapshots, backup files, restores) are removed.[root@kube-master-01 dingtalk]#[root@kube-master-01 dingtalk]# velero backup getNAME STATUS ERRORS WARNINGS CREATED EXPIRES STORAGE LOCATION SELECTORdingtalk-backup Completed 0 0 2021-12-29 15:30:29 +0800 CST 29d default app=dingtalk-webhookdingtalk-backup-20211229 Completed 0 0 2021-12-29 16:28:41 +0800 CST 29d default app=dingtalk-webhook[root@kube-master-01 dingtalk]#
删除所有备份
[root@kube-master-01 dingtalk]# velero backup delete --allAre you sure you want to continue (Y/N)? yRequest to delete backup "dingtalk-backup" submitted successfully.The backup will be fully deleted after all associated data (disk snapshots, backup files, restores) are removed.Request to delete backup "dingtalk-backup-20211229" submitted successfully.The backup will be fully deleted after all associated data (disk snapshots, backup files, restores) are removed.[root@kube-master-01 dingtalk]#[root@kube-master-01 dingtalk]# velero backup get[root@kube-master-01 dingtalk]#
卸载velero、minio
[root@kube-master-01 dingtalk]# kubectl delete namespace/velero clusterrolebinding/veleronamespace "velero" deletedclusterrolebinding.rbac.authorization.k8s.io "velero" deleted[root@kube-master-01 dingtalk]# kubectl delete crds -l component=velerocustomresourcedefinition.apiextensions.k8s.io "backups.velero.io" deletedcustomresourcedefinition.apiextensions.k8s.io "backupstoragelocations.velero.io" deletedcustomresourcedefinition.apiextensions.k8s.io "deletebackuprequests.velero.io" deletedcustomresourcedefinition.apiextensions.k8s.io "downloadrequests.velero.io" deletedcustomresourcedefinition.apiextensions.k8s.io "podvolumebackups.velero.io" deletedcustomresourcedefinition.apiextensions.k8s.io "podvolumerestores.velero.io" deletedcustomresourcedefinition.apiextensions.k8s.io "resticrepositories.velero.io" deletedcustomresourcedefinition.apiextensions.k8s.io "restores.velero.io" deletedcustomresourcedefinition.apiextensions.k8s.io "schedules.velero.io" deletedcustomresourcedefinition.apiextensions.k8s.io "serverstatusrequests.velero.io" deletedcustomresourcedefinition.apiextensions.k8s.io "volumesnapshotlocations.velero.io" deleted[root@kube-master-01 dingtalk]#
在 Docker (KinD) 中使用 Kubernetes 在集群外公开 Minio
# 1.您可以使用端口转发来访问 Minio 存储桶。MINIO_POD=$(kubectl get pods -n velero -l component=minio -o jsonpath='{.items[0].metadata.name}')kubectl port-forward $MINIO_POD -n velero 9000:9000# 2.然后在另一个终端中执行如下命令, 并且将`publicUrl: http://localhost:9000`在该spec.config部分下添加。kubectl edit backupstoragelocation default -n velero
