项目背景
在云计算和容器技术飞速发展的今天,Kubernetes 已经成为容器编排和管理的事实标准。然而,随着业务的不断扩展,如何在云原生环境下保护和迁移 Kubernetes 集群资源,成为了摆在运维人员面前的一大挑战。Velero,作为一款云原生的灾难恢复和迁移工具,以其强大的功能和灵活的使用方式,为 Kubernetes 集群的数据安全提供了坚实的保障。
环境介绍
本文将基于一个典型的云原生环境,介绍如何使用 Velero 进行 Kubernetes 集群的备份与迁移
- Kubernetes:v1.23.1
- Velero:1.11
开源地址:https://github.com/vmware-tanzu/velero
官方文档:https://velero.io/docs/v1.11/
支持的版本列表
组件介绍
Velero组件
Velero 组件一共分两部分,分别是服务端和客户端。
- 服务端:运行在你 Kubernetes 的集群中
- 客户端:是一些运行在本地的命令行的工具,需要已配置好 kubectl 及集群 kubeconfig 的机器上
velero备份流程
- Velero 客户端
发送 API 请求至 Kubernetes API Server,创建备份任务。 - Kubernetes API Server
接收并处理 Velero 客户端的请求,创建备份任务,同时通过 Watch 机制通知相关的控制器。 - Backup 控制器
通过 Watch 机制监听 API Server,获取备份任务后,向 API Server 请求需要备份的数据。 - 对象存储服务器
Backup 控制器将从 API Server 获取的数据备份至指定的对象存储服务器。
Velero 后端存储
Velero 支持两种用于配置后端存储的自定义资源定义 (CRD),分别是 BackupStorageLocation
和 VolumeSnapshotLocation
。
BackupStorageLocation
BackupStorageLocation
主要用于定义 Kubernetes 集群资源的备份存储位置,针对的是集群对象数据,而非持久化卷 (PVC) 的数据。该存储通常是 S3 兼容的对象存储,如 MinIO、阿里云 OSS 等。
VolumeSnapshotLocation
VolumeSnapshotLocation
主要用于对持久化卷 (PV) 进行快照备份,这要求云提供商提供相应的插件。阿里云已经提供了该插件,用户可以通过 CSI (容器存储接口) 等存储机制来进行 PV 的快照备份。此外,用户还可以使用专门的备份工具 Restic,将 PV 的数据备份到阿里云 OSS(安装 Velero 时可以选择自定义该选项)。
velero客户端
在 Github Release 页面下载指定的 velero 二进制客户端安装包,比如这里我们下载我们k8s集群对应的版本为 v1.11.1
版本列表:https://github.com/vmware-tanzu/velero/releases
安装velero客户端
$ wget https://github.com/vmware-tanzu/velero/releases/download/v1.11.1/velero-v1.11.1-linux-amd64.tar.gz
$ tar zxf velero-v1.11.1-linux-amd64.tar.gz
$ mv velero-v1.11.1-linux-amd64/velero /usr/bin/
$ velero -h
# 启用命令补全
$ source <(velero completion bash)
$ velero completion bash > /etc/bash_completion.d/velero
安装minio
Velero支持很多种存储插件,可查看:Velero Docs - Providers获取插件信息,我们这里使用minio作为S3兼容的对象存储提供程序。您也可以在任意地方部署Minio对象存储,只需要保证K8S集群可以访问到即可。
minio.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: storage
emptyDir: {}
- name: config
emptyDir: {}
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
volumeMounts:
- name: storage
mountPath: "/storage"
- name: config
mountPath: "/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: api
port: 9000
targetPort: 9000
nodePort: 32000
- name: console
port: 9001
targetPort: 9001
nodePort: 32001
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: 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应用
# 创建velero命名空间
$ kubectl create namespace velero
# 创建minio资源
$ kubectl apply -f minio.yaml
# 查看部署状态
[root@bt velero]# kubectl get sts,pod,svc -n velero
NAME READY STATUS RESTARTS AGE
pod/minio-78f994f86c-4t9lw 1/1 Running 0 27h
pod/minio-setup-d7vbl 0/1 Completed 4 27h
pod/node-agent-6z5mn 1/1 Running 0 27h
pod/node-agent-8kjcm 1/1 Running 0 27h
pod/node-agent-k8zbk 1/1 Running 0 27h
pod/velero-85dd87c457-mz5jm 1/1 Running 0 27h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/minio NodePort 172.21.25.69 <none> 9000:32000/TCP,9001:32001/TCP 27h
# 开放NodePort端口
$ kubectl patch svc minio -n velero -p '{"spec": {"type": "NodePort"}}'
$ kubectl patch svc minio -n velero --type='json' -p='[{"op": "replace", "path": "/spec/ports/0/nodePort", "value":9000},{"op": "replace", "path": "/spec/ports/1/nodePort", "value":9001}]'
[root@bt velero]# kubectl get svc -n velero
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
minio NodePort 172.21.25.69 <none> 9000:32000/TCP,9001:32001/TCP 27h
通过浏览器访问服务器IP:30282,并使用账号minio密码minio123登入验证。
velero 服务端
我们可以使用 velero 客户端来安装服务端,也可以使用 Helm Chart 来进行安装,比如这里我们用客户端来安装,velero 命令默认读取 kubectl 配置的集群上下文,所以前提是 velero 客户端所在的节点有可访问集群的 kubeconfig 配置。
创建密钥
首先准备密钥文件,在当前目录建立一个空白文本文件,内容如下所示:
$ cat > credentials-velero <<EOF
[default]
aws_access_key_id = minio
aws_secret_access_key = minio123
EOF
安装velero到k8s集群
替换为之前步骤中 minio 的对应 access key id 和 secret access key如果 minio 安装在 kubernetes 集群内时按照如下命令安装 velero 服务端:
$ velero install \
--provider aws \
--image velero/velero:v1.11.1 \
--plugins velero/velero-plugin-for-aws:v1.7.1 \
--bucket velero \
--secret-file ./credentials-velero \
--use-node-agent \
--use-volume-snapshots=false \
--namespace velero \
--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://minio:9000 \
--wait
# 执行install命令后会创建一系列清单,包括CustomResourceDefinition、Namespace、Deployment等。
# velero install .... --dry-run -o yaml > velero_deploy.yaml 如果为私仓,可以通过--dry-run 导出 YAML 文件调整在应用。
# 可使用如下命令查看运行日志
$ kubectl logs deployment/velero -n velero
# 查看velero创建的api对象
$ kubectl api-versions | grep velero
velero.io/v1
# 查看备份位置
$ velero backup-location get
NAME PROVIDER BUCKET/PREFIX PHASE LAST VALIDATED ACCESS MODE DEFAULT
default aws velero Available 2024-08-16 14:42:38 +0800 CST ReadWrite true
#卸载命令
# velero uninstall --namespace velero
You are about to uninstall Velero.
Are you sure you want to continue (Y/N)? y
Waiting for velero namespace "velero" to be deleted
............................................................................................................................................................................................
Velero namespace "velero" deleted
Velero uninstalled ⛵
选项说明:
--kubeconfig
(可选):指定kubeconfig
认证文件,默认使用.kube/config
;--provider
:定义插件提供方;--image
:定义运行velero的镜像,默认与velero客户端一致;--plugins
:指定使用aws s3兼容的插件镜像;--bucket
:指定对象存储Bucket桶名称;--secret-file
:指定对象存储认证文件;--use-node-agent
:创建Velero Node Agent守护进程,托管FSB模块;--use-volume-snapshots
:是否启使用快照;--namespace
:指定部署的namespace名称,默认为velero;--backup-location-config
:指定对象存储地址信息;
aws插件与velero版本对应关系:
卸载velero
如果您想从集群中完全卸载Velero,则以下命令将删除由velero install创建的所有资源:
kubectl delete namespace/velero clusterrolebinding/velero
kubectl delete crds -l component=velero
备份与恢复
备份命令:velero create backup NAME [flags]
backup选项:
--exclude-namespaces stringArray
: 要从备份中排除的名称空间--exclude-resources stringArray
: 要从备份中排除的资源,如storageclasses.storage.k8s.io
--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
: 指定快照的位置,也就是哪一个公有云驱动
使用官方案例创建测试应用
$ kubectl apply -f examples/nginx-app/base.yaml
namespace/nginx-example created
deployment.apps/nginx-deployment created
service/my-nginx created
# 查看资源清单
$ kubectl get all -n nginx-example
NAME READY STATUS RESTARTS AGE
pod/nginx-deployment-5c844b66c8-t5l9z 1/1 Running 0 27h
pod/nginx-deployment-5c844b66c8-vlkqj 1/1 Running 0 27h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/my-nginx LoadBalancer 172.21.18.168 192.168.102.51 80:31831/TCP 27h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-deployment 2/2 2 2 27h
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-deployment-5c844b66c8 2 2 2 27h
备份测试应用
$ velero backup create nginx-backup --include-namespaces nginx-example
Backup request "nginx-backup" submitted successfully.
Run `velero backup describe nginx-backup` or `velero backup logs nginx-backup` for more details.
选项:
--include-namespaces
:指定命名空间--selector
:标签选择器,如app=nginx
查看备份列表
$ velero backup get
NAME STATUS ERRORS WARNINGS CREATED EXPIRES STORAGE LOCATION SELECTOR
nginx-backup Completed 0 0 2024-08-15 11:17:18 +0800 CST 28d default <none>
# 查看备份详细信息
$ velero backup describe nginx-backup
# 查看备份日志
$ velero backup logs nginx-backup
登入minio控制台查看备份内容
定时备份指南
# 使用cron表达式备份
$ velero schedule create nginx-daily --schedule="0 1 * * *" --include-namespaces nginx-example
# 使用一些非标准的速记 cron 表达式
$ velero schedule create nginx-daily --schedule="@daily" --include-namespaces nginx-example
# 手动触发定时任务
$ velero backup create --from-schedule nginx-daily
更多cron示例请参考:cron package’s documentation
恢复
模拟灾难
# 删除nginx-example命名空间和资源
$ kubectl delete namespace nginx-example
# 检查是否删除
$ kubectl get all -n nginx-example
No resources found in nginx-example namespace.
恢复资源
$ velero backup get
NAME STATUS ERRORS WARNINGS CREATED EXPIRES STORAGE LOCATION SELECTOR
nginx-backup Completed 0 0 2024-04-06 21:47:16 +0800 CST 29d default <none>
$ velero restore create --from-backup nginx-backup
Restore request "nginx-backup-20240406215611" submitted successfully.
Run `velero restore describe nginx-backup-20240406215611` or `velero restore logs nginx-backup-20240406215611` for more details.
检查恢复的资源
$ velero restore get
NAME BACKUP STATUS STARTED COMPLETED ERRORS WARNINGS CREATED SELECTOR
nginx-backup-20240406215611 nginx-backup Completed 2024-04-06 21:56:11 +0800 CST 2024-04-06 21:56:12 +0800 CST 0 2 2024-04-06 21:56:11 +0800 CST <none>
# 查看详细信息
$ velero restore describe nginx-backup-20240406215611
# 检查资源状态
$ kubectl get all -n nginx-example
NAME READY STATUS RESTARTS AGE
pod/nginx-deployment-5c844b66c8-t5l9z 1/1 Running 0 27h
pod/nginx-deployment-5c844b66c8-vlkqj 1/1 Running 0 27h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/my-nginx LoadBalancer 172.21.18.168 192.168.102.51 80:31831/TCP 27h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-deployment 2/2 2 2 27h
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-deployment-5c844b66c8 2 2 2 27h
参考:
https://www.cnblogs.com/nf01/p/18118159
https://github.com/vmware-tanzu/velero
https://velero.io/docs/v1.11/