使用 Velero 快速备份和迁移 Kubernetes 集群应用以及持久化数据

Posted by Mike on 2020-05-17

什么是 Velero?

Heptio Velero ( 以前的名字为 ARK) 是一款用于 Kubernetes 集群资源和持久存储卷(PV)的备份、迁移以及灾难恢复等的开源工具。

Velero 特性

Velero 目前包含以下特性:

  • 支持 Kubernetes 集群数据备份和恢复

  • 支持复制当前 Kubernetes 集群的资源到其它 Kubernetes 集群

  • 支持复制生产环境到开发以及测试环境

Velero 组件

Velero 组件一共分两部分,分别是服务端和客户端。服务端运行在你 Kubernetes 的集群中,客户端是一些运行在本地的命令行的工具。

Velero 支持的备份存储

  • AWS S3 以及兼容 S3 的存储,比如:Minio

  • Azure BloB 存储

  • Google Cloud 存储

项目地址:https://github.com/heptio/velero

与 Etcd 备份的区别

与 Etcd 备份相比,直接备份 Etcd 是将集群的全部资源备份起来。而 Velero 就是可以对 Kubernetes 集群内对象级别进行备份。除了对 Kubernetes 集群进行整体备份外,Velero 还可以通过对 TypeNamespaceLabel 等对象进行分类备份或者恢复。

注意: 备份过程中创建的对象是不会被备份的。

Velero 架构

Velero 备份过程

  1. 本地 Velero 客户端发送备份指令。

  2. Kubernetes 集群内就会创建一个 Backup 对象。

  3. BackupController 监测 Backup 对象并开始备份过程。

  4. BackupController 会向 API Server 查询相关数据。

  5. BackupController 将查询到的数据备份到远端的对象存储。

VeleroKubernetes 集群中创建了很多 CRD 以及相关的控制器,进行备份恢复等操作实质上是对相关 CRD 的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Velero 在 Kubernetes 集群中创建的 CRD
$ kubectl -n velero get crds -l component=velero
NAME CREATED AT
backups.velero.io 2019-08-28T03:19:56Z
backupstoragelocations.velero.io 2019-08-28T03:19:56Z
deletebackuprequests.velero.io 2019-08-28T03:19:56Z
downloadrequests.velero.io 2019-08-28T03:19:56Z
podvolumebackups.velero.io 2019-08-28T03:19:56Z
podvolumerestores.velero.io 2019-08-28T03:19:56Z
resticrepositories.velero.io 2019-08-28T03:19:56Z
restores.velero.io 2019-08-28T03:19:56Z
schedules.velero.io 2019-08-28T03:19:56Z
serverstatusrequests.velero.io 2019-08-28T03:19:56Z
volumesnapshotlocations.velero.io 2019-08-28T03:19:56Z

如何保证数据一致性

对象存储的数据是唯一的数据源,也就是说 Kubernetes 集群内的控制器会检查远程的 OSS 存储,发现有备份就会在集群内创建相关 CRD 。如果发现远端存储没有当前集群内的 CRD 所关联的存储数据,那么就会删除当前集群内的 CRD

Velero 支持的后端存储

Velero 支持两种关于后端存储的 CRD,分别是 BackupStorageLocationVolumeSnapshotLocation

  1. BackupStorageLocation

BackupStorageLocation 主要用来定义 Kubernetes 集群资源的数据存放位置,也就是集群对象数据,不是 PVC 的数据。主要支持的后端存储是 S3 兼容的存储,比如:Mino 和阿里云 OSS 等。

  • 使用 Minio
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
apiVersion: velero.io/v1
kind: BackupStorageLocation
metadata:
name: default
namespace: velero
spec:
# 只有 aws gcp azure
provider: aws
# 存储主要配置
objectStorage:
# bucket 的名称
bucket: myBucket
# bucket内的
prefix: backup
# 不同的 provider 不同的配置
config:
#bucket地区
region: us-west-2
# s3认证信息
profile: "default"
# 使用 Minio 的时候加上,默认为 false
# AWS 的 S3 可以支持两种 Url Bucket URL
# 1 Path style URL: http://s3endpoint/BUCKET
# 2 Virtual-hosted style URL: http://oss-cn-beijing.s3endpoint 将 Bucker Name 放到了 Host Header中
# 3 阿里云仅仅支持 Virtual hosted 如果下面写上 true, 阿里云 OSS 会报错 403
s3ForcePathStyle: "false"
# s3的地址,格式为 http://minio:9000
s3Url: http://minio:9000
  • 使用阿里云的 OSS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: velero.io/v1
kind: BackupStorageLocation
metadata:
labels:
component: velero
name: default
namespace: velero
spec:
config:
region: oss-cn-beijing
s3Url: http://oss-cn-beijing.aliyuncs.com
s3ForcePathStyle: "false"
objectStorage:
bucket: build-jenkins
prefix: ""
provider: aws
  1. VolumeSnapshotLocation

VolumeSnapshotLocation 主要用来给 PV 做快照,需要云提供商提供插件。阿里云已经提供了插件,这个需要使用 CSI 等存储机制。你也可以使用专门的备份工具 Restic,把 PV 数据备份到阿里云 OSS 中去(安装时需要自定义选项)。

1
2
3
4
5
# 安装时需要自定义选项
--use-restic

# 这里我们存储 PV 使用的是 OSS 也就是 BackupStorageLocation,因此不用创建 VolumeSnapshotLocation 对象
--use-volume-snapshots=false

Restic 是一款 GO 语言开发的数据加密备份工具,顾名思义,可以将本地数据加密后传输到指定的仓库。支持的仓库有 Local、SFTP、Aws S3、Minio、OpenStack Swift、Backblaze B2、Azure BS、Google Cloud storage、Rest Server。

项目地址:https://github.com/restic/restic

本文中,我们将使用 Restic 来对 PV 进行备份,不过现阶段通过 Restic 备份会有一些限制。

  • 不支持备份 hostPath
  • 备份数据标志只能通过 Pod 来识别
  • 单线程操作大量文件比较慢

安装 Velero

Velero 提供了一个命令行用来初始化服务端和进行常用的备份和恢复操作。该命令行和 Kubernetes 集群交互(和 Kubectl 的方式类似),也是通过寻找 kubeconfig 的相关配置来访问集群。kubeconfig 主要是通过 KUBECONFIG 环境变量和 ~/.kube/config 文件以及选项 –-kubeconfig 来指定。

本次安装将会使用阿里云的 OSS 和 Restic 来作为后端存储。

安装前的准备

  1. 开通阿里云的 OSS 并获取相关认证信息。

  2. Restic 需要 Docker 进程开通 Mount 传播,需要在 Docker 启动的 Systemd 文件内加入 MountFlags=shared

MountFlags:Docker 服务的 Mount Namespace 配置,会影响进程上下文中挂载点的信息。即服务是否会继承主机上已有挂载点,以及如果服务运行执行了挂载或卸载设备的操作,是否会真实地在主机上产生效果。可选值为 sharedslavedprivate

  • shared:服务与主机共用一个 Mount Namespace,继承主机挂载点,且服务挂载或卸载设备会真实地反映到主机上。

  • slave:服务使用独立的 Mount Namespace,它会继承主机挂载点,但服务对挂载点的操作只有在自己的 Namespace 内生效,不会反映到主机上。

  • private:服务使用独立的 Mount Namespace,它在启动时没有任何挂载点,服务对挂载点的操作也不会反映到主机上。

更多 Systemd 服务管理可参考:https://blog.mallux.me/2017/02/13/systemd/

安装 Velero

  1. 安装 Velero 客户端工具

下载最新版 Velero,并解压。这里以 Linux 平台为例:

1
2
3
$ wget https://github.com/heptio/velero/releases/download/v1.1.0/velero-v1.1.0-linux-amd64.tar.gz
$ tar xzvf velero-v1.1.0-linux-amd64.tar.gz
$ cp velero-v1.1.0-linux-amd64\velero \usr\local\bin

更多平台可以在官方 Releases 页面下载:https://github.com/heptio/velero/releases/

安装完成成后,可以加载下 Shell 自动完成功能,方便使用。

1
$ velero completion bash
  1. 启动 Velero 服务端

2.1 准备 credentials-velero 文件

credentials-velero 文件内容为阿里云 OSS 的认证信息,会用于在集群中创建密钥。

1
2
3
4
5
6
$ vim credentials-velero

# default 和 BackupStorageLocation 对象中 profile 字段的值要对应
[default]
aws_access_key_id = xxx
aws_secret_access_key = xxx

2.2 启动 Velero 服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ velero install \
--image gcr.azk8s.cn/heptio-images/velero:v1.1.0 \
--provider aws \
--bucket xxx \
--prefix xxx \
--namespace velero \
--secret-file ./credentials-velero \
--velero-pod-cpu-request 200m \
--velero-pod-mem-request 200Mi \
--velero-pod-cpu-limit 200m \
--velero-pod-mem-limit 200Mi \
--use-volume-snapshots=false \
--use-restic \
--restic-pod-cpu-request 200m \
--restic-pod-mem-request 200Mi \
--restic-pod-cpu-limit 200m \
--restic-pod-mem-limit 200Mi \
--backup-location-config region=oss-cn-beijing,s3ForcePathStyle="false",s3Url=http://oss-cn-beijing.aliyuncs.com

使用 Velero 进行数据备份和恢复

给 Pod 加注解

使用 Restic 给带有 PVCPod 进行备份,必须先给 Pod 加上注解。

先看一看基本语法:

1
$ kubectl -n YOUR_POD_NAMESPACE annotate pod/YOUR_POD_NAME backup.velero.io/backup-volumes=YOUR_VOLUME_NAME_1,YOUR_VOLUME_NAME_2,...

在来看一个实例,这里使用一个 ElasticsearchPod 为例:

1
2
3
$ kubectl -n elasticsearch annotate pod elasticsearch-master-0 backup.velero.io/backup-volumes=elasticsearch-master
$ kubectl get pod -n elasticsearch elasticsearch-master-0 -o jsonpath='{.metadata.annotations}'
map[backup.velero.io/backup-volumes:elasticsearch-master]

创建备份数据

  1. 基本命令语法
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
$ velero create backup NAME [flags]

# 剔除 namespace
--exclude-namespaces stringArray namespaces to exclude from the backup

# 剔除资源类型
--exclude-resources stringArray resources to exclude from the backup, formatted as resource.group, such as storageclasses.storage.k8s.io

# 包含集群资源类型
--include-cluster-resources optionalBool[=true] include cluster-scoped resources in the backup

# 包含 namespace
--include-namespaces stringArray namespaces to include in the backup (use '*' for all namespaces) (default *)

# 包含 namespace 资源类型
--include-resources stringArray resources to include in the backup, formatted as resource.group, such as storageclasses.storage.k8s.io (use '*' for all resources)

# 给这个备份加上标签
--labels mapStringString labels to apply to the backup
-o, --output string Output display format. For create commands, display the object but do not send it to the server. Valid formats are 'table', 'json', and 'yaml'. 'table' is not valid for the install command.

# 对指定标签的资源进行备份
-l, --selector labelSelector only back up resources matching this label selector (default <none>)

# 对 PV 创建快照
--snapshot-volumes optionalBool[=true] take snapshots of PersistentVolumes as part of the backup

# 指定备份的位置
--storage-location string location in which to store the backup

# 备份数据多久删掉

--ttl duration how long before the backup can be garbage collected (default 720h0m0s)

# 指定快照的位置,也就是哪一个公有云驱动
--volume-snapshot-locations strings list of locations (at most one per provider) where volume snapshots should be stored
  1. 创建一个备份

这里同样以上面提到的 elasticsearch 为例。

1
$ velero create backup es --include-namespaces=elasticsearch

注 Restic 会使用 Path Style,而阿里云禁止 Path style 需要使用 Virtual-Hosted,所以暂时备份没有办法备份 PV 到 OSS。

备份创建成功后会创建一个名为 backups.velero.io 的 CRD 对象。

恢复一个备份数据

  1. 基本命令语法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ velero restore create [RESTORE_NAME] [--from-backup BACKUP_NAME | --from-schedule SCHEDULE_NAME] [flags]

--exclude-namespaces stringArray namespaces to exclude from the restore
--exclude-resources stringArray resources to exclude from the restore, formatted as resource.group, such as storageclasses.storage.k8s.io
--from-backup string backup to restore from
--from-schedule string schedule to restore from
-h, --help help for create
--include-cluster-resources optionalBool[=true] include cluster-scoped resources in the restore
--include-namespaces stringArray namespaces to include in the restore (use '*' for all namespaces) (default *)
--include-resources stringArray resources to include in the restore, formatted as resource.group, such as storageclasses.storage.k8s.io (use '*' for all resources)
--label-columns stringArray a comma-separated list of labels to be displayed as columns
--labels mapStringString labels to apply to the restore
--namespace-mappings mapStringString namespace mappings from name in the backup to desired restored name in the form src1:dst1,src2:dst2,...
-o, --output string Output display format. For create commands, display the object but do not send it to the server. Valid formats are 'table', 'json', and 'yaml'. 'table' is not valid for the install command.
--restore-volumes optionalBool[=true] whether to restore volumes from snapshots
-l, --selector labelSelector only restore resources matching this label selector (default <none>)
--show-labels show labels in the last column
-w, --wait
  1. 恢复一个备份数据
1
$ velero restore create back --from-backup es

恢复成功后,同样也会创建一个 restores.velero.io CRD 对象。

使用 Velero 进行集群数据迁移

首先,在集群 1 中创建备份(默认 TTL 是 30 天,你可以使用 --ttl 来修改):

1
$ velero backup create <BACKUP-NAME>

然后,为集群 2 配置 BackupStorageLocations 和 VolumeSnapshotLocations,指向与集群 1 相同的备份和快照路径,并确保 BackupStorageLocations 是只读的(使用 --access-mode=ReadOnly)。接下来,稍微等一会(默认的同步时间为 1 分钟),等待 Backup 对象创建成功。

1
2
3
# The default sync interval is 1 minute, so make sure to wait before checking.
# You can configure this interval with the --backup-sync-period flag to the Velero server.
$ velero backup describe <BACKUP-NAME>

最后,执行数据恢复:

1
2
3
$ velero restore create --from-backup <BACKUP-NAME>
$ velero restore get
$ velero restore describe <RESTORE-NAME-FROM-GET-COMMAND>

本文在 「集群备份工具 Velero 使用 」一文基础上修改而成。

参考文档

  1. http://www.google.com

  2. http://t.cn/AiRQWtIe

  3. https://velero.io/docs/master/restic/

  4. https://www.cnblogs.com/rongfengliang/p/11095330.html

  5. https://feisky.gitbooks.io/kubernetes/practice/backup.html