Velero VolumeSnapshotLocation(VSL)-使用快照备份&恢复集群

922 阅读7分钟

概念

VSL:VolumeSnapshotLocation,卷快照地址

Velero定义了一个VolumeSnapshotter的接口,这个接口需要被第三方存储厂商实现,来提供卷快照的功能,支持云厂商VSL需要实现Velero定义的一个VolumeSnapshotter的接口

Velero源码Git:github.com/vmware-tanz…

源码中VolumeSnapshotter接口的内容(v1.8.0)

位置:velero/pkg/plugin/velero/volume_snapshotter.go

image.png

接口中包含有7个功能函数,如要支持VSL,就需要针对这个接口功能的实现,该接口的定义能明白VSL的含义是:velero在备份期间,执行持久卷的快照;在恢复期间,还原快照中的持久卷

插件框架的主要代码在velero/pkg/plugin/framework,核心是Server接口。插件的注册、获取、删除,以及run插件服务都在此,而今天我们讲的VSL插件,就是通过Server注册进Velero服务中,并启动Server提供插件服务

image.png

Server中通过NewServer()方法来初始化一个新的Server对象以供调用

image.png

云厂商VSL

AWS

代码解析

源码Git:github.com/vmware-tanz…

  1. 从源码中可以看出引入了Velero中插件的框架并起名veleroplugin,main函数启动时,创建了一个NewServer()

image.png

  1. NewServer返回了一个Server,而这个Server其实是一个接口类型的对象,AWS插件实例化出一个Server接口后,实现了其中4个接口:BindFlags、RegisterObjectStore、RegisterVolumeSnapshotter、Serve,而AWS实现的插件注册即图中圈出的接口

image.png

 BindFlags: 定义插件服务器的命令行标志,此方法必须在调用.Serve()之前调用
 RegisterObjectStore: 注册一个对象存储,接受的格式:插件名称<DNS子域>/<非空名称>
 RegisterVolumeSnapshotter: 注册一个卷快照,接受的格式:插件名称<DNS子域>/<非空名称>
 Serve: 运行插件服务器
  1. 通过简单了解4个函数后,大体能知道AWS实现VSL的插件方式流程,即:
    1. 加载velero插件
    2. 初始化一个插件Server
    3. 注册插件、实现规定接口
    4. run服务
  2. 对于该插件实现的接口功能有2个,这次主要关注newAwsVolumeSnapshotter

image.png

  1. newAwsVolumeSnapshotter函数返回了一个interface类型,继续深入可以看到最终结果,

log暂且不用太关注,主要来看ec2这个对象,EC2是AWS的弹性计算云模块,我们则通过EC2提供的API来调用该对象的方法

image.png image.png

  1. EC2对象里初始化了一个客户端,该客户端实现基本客户端请求和响应处理

image.png image.png

  1. 初始化完毕后,就可以用VolumeSnapshotter对象调用指定的方法,例如调用创建快照的方法,该方法需要传递3个参数:snapshotID,volumeAZ(该参数并未调用),和tags,该方法运行成功后,会返回快照的ID字符串,否则返回空字符串

image.png 而当前方法中的volumeID参数也可以通过GetVolumeID方法获取 image.png

  1. 创建好快照后,可以调用CreateVolumeFromSnapshot方法根据快照创建Volume

image.png 该方法需要传递snapshotID, volumeType, volumeAZ(该参数并未调用), iops共4个参数,其中snapshotID通过步骤8执行后获得,volumeType可通过GetVolumeInfo方法获得,对于iops参数(磁盘吞吐量指标), 如果使用预配置的 IOPS则指定,否则就不指定 image.png

功能测试

测试前的准备工作:可用的K8S集群环境、云厂商对象存储功能

  1.  设置Velero的凭证配置文件,此处用的阿里云的AK/SK,大家可以自行定义
vim credentials-velero

[default]
aws_access_key_id=<输入合法的AK>
aws_secret_access_key=<输入合法的SK>
  1. 安装velero(指定AWS插件、BUCKET、VSL配置信息、NameSpace等)
velero install \
--provider aws \
--plugins velero/velero-plugin-for-aws:v1.3.1,velero/velero-plugin-for-csi:v0.2.0 \
--bucket <bucket> \
--prefix <prefix> \
--secret-file ./credentials-velero \
--backup-location-config region=<region>,s3ForcePathStyle="false",s3Url=https://oss-<region>.aliyuncs.com \
--snapshot-location-config region=region> \
--namespace velero-yx \
--wait

成功安装完成后会有提示,这时候velero就安装到k8s中,命名空间是velero-yx,这里需要注意的是,BSL的状态应该为:Available image.png image.png image.png image.png

  1. 创建VolumeSnapshotClass对象,因为使用的是腾讯云集群,所以CSI驱动要选择腾讯版本
# 新建snapshotclass.yaml文件
vim snapshotclass.yaml

# 创建VolumeSnapshotClass对象
apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshotClass
metadata:
  name: cbs-snapclass
  labels:
    velero.io/csi-volumesnapshot-class: "true"
driver: com.tencent.cloud.csi.cbs
deletionPolicy: Retain

# 应用到集群
kubectl apply -f snapshotclass.yaml 

执行以下命令,查看对象是否创建成功, image.png

  1. 创建 VolumeSnapshotLocation 对象以供 Velero 在拍摄卷快照时使用
velero snapshot-location create yx-vsl1 \
--provider aws \
-n velero-yx \
--config region=cn-beijing

image.png 查看VSL详细信息

[root@i-encdmzhz ~]# velero snapshot-location get yx-vsl1 -n velero-yx -o json
{
  "kind": "VolumeSnapshotLocation",
  "apiVersion": "velero.io/v1",
  "metadata": {
    "name": "yx-vsl1",
    "namespace": "velero-yx",
    "selfLink": "/apis/velero.io/v1/namespaces/velero-yx/volumesnapshotlocations/yx-vsl1",
    "uid": "34484778-e449-4e47-a32d-0cd4cdd2b5d7",
    "resourceVersion": "323710390",
    "generation": 1,
    "creationTimestamp": "2022-03-15T02:22:51Z",
    "managedFields": [
      {
        "manager": "velero",
        "operation": "Update",
        "apiVersion": "velero.io/v1",
        "time": "2022-03-15T02:22:51Z",
        "fieldsType": "FieldsV1",
        "fieldsV1": {"f:spec":{".":{},"f:config":{".":{},"f:region":{}},"f:provider":{}},"f:status":{}}
      }
    ]
  },
  "spec": {
    "provider": "aws",
    "config": {
      "region": "cn-beijing"
    }
  },
  "status": {
    
  }
}

  1. 备份apps命名空间资源并创建卷快照。这里注意,需要确定当前apps命名空间Pod绑定的PV资源删除回收策略是Retain,如果是Delete则会导致快照失败 image.png image.png 创建velero备份任务,并指定备份apps命名空间
velero backup create yx-bk1 \
--include-namespaces=apps \
--snapshot-volumes=true \
--default-volumes-to-restic=false \
-n velero-yx \
--storage-location default \
--volume-snapshot-locations yx-vsl1
  1. 查看备份任务信息,这里PhaseCompleted表示备份完成(其余状态都代表失败,需要去日志查看详情)
[root@i-encdmzhz ~]# velero backup describe yx-bk1 -n velero-yx
Name:         yx-bk1
Namespace:    velero-yx
Labels:       velero.io/storage-location=default
Annotations:  velero.io/source-cluster-k8s-gitversion=v1.20.6-tke.12
              velero.io/source-cluster-k8s-major-version=1
              velero.io/source-cluster-k8s-minor-version=20+

Phase:  Completed

Errors:    0
Warnings:  1

Namespaces:
  Included:  apps
  Excluded:  <none>

Resources:
  Included:        *
  Excluded:        <none>
  Cluster-scoped:  auto

Label selector:  <none>

Storage Location:  default

Velero-Native Snapshot PVs:  true

TTL:  720h0m0s

Hooks:  <none>

Backup Format Version:  1.1.0

Started:    2022-03-15 10:40:35 +0800 CST
Completed:  2022-03-15 10:40:42 +0800 CST

Expiration:  2022-04-14 10:40:35 +0800 CST

Total items to be backed up:  20
Items backed up:              20

Velero-Native Snapshots: <none included>

备份完成后,可以登录阿里云OSS桶中查看备份文件 image.png 可以查看快照及详细信息 image.png

[root@i-encdmzhz ~]# kubectl get volumesnapshot -n apps velero-mysql-stcxj -o json
{
    "apiVersion": "snapshot.storage.k8s.io/v1beta1",
    "kind": "VolumeSnapshot",
    "metadata": {
        "creationTimestamp": "2022-03-15T09:08:40Z",
        "finalizers": [
            "snapshot.storage.kubernetes.io/volumesnapshot-as-source-protection"
        ],
        "generateName": "velero-mysql-",
        "generation": 1,
        "labels": {
            "velero.io/backup-name": "yx-bk1"
        },
        "managedFields": [
            {
                "apiVersion": "snapshot.storage.k8s.io/v1beta1",
                "fieldsType": "FieldsV1",
                "fieldsV1": {
                    "f:metadata": {
                        "f:generateName": {},
                        "f:labels": {
                            ".": {},
                            "f:velero.io/backup-name": {}
                        }
                    },
                    "f:spec": {
                        ".": {},
                        "f:source": {
                            ".": {},
                            "f:persistentVolumeClaimName": {}
                        },
                        "f:volumeSnapshotClassName": {}
                    }
                },
                "manager": "velero-plugin-for-csi",
                "operation": "Update",
                "time": "2022-03-15T09:08:40Z"
            },
            {
                "apiVersion": "snapshot.storage.k8s.io/v1beta1",
                "fieldsType": "FieldsV1",
                "fieldsV1": {
                    "f:metadata": {
                        "f:finalizers": {
                            ".": {},
                            "v:\"snapshot.storage.kubernetes.io/volumesnapshot-as-source-protection\"": {}
                        }
                    },
                    "f:status": {
                        ".": {},
                        "f:boundVolumeSnapshotContentName": {},
                        "f:creationTime": {},
                        "f:readyToUse": {},
                        "f:restoreSize": {}
                    }
                },
                "manager": "snapshot-controller",
                "operation": "Update",
                "time": "2022-03-15T09:08:45Z"
            }
        ],
        "name": "velero-mysql-stcxj",
        "namespace": "apps",
        "resourceVersion": "327684042",
        "selfLink": "/apis/snapshot.storage.k8s.io/v1beta1/namespaces/apps/volumesnapshots/velero-mysql-stcxj",
        "uid": "f1b089ef-38c6-4723-b947-bc294b496254"
    },
    "spec": {
        "source": {
            "persistentVolumeClaimName": "mysql"
        },
        "volumeSnapshotClassName": "cbs-snapclass"
    },
    "status": {
        "boundVolumeSnapshotContentName": "snapcontent-f1b089ef-38c6-4723-b947-bc294b496254",
        "creationTime": "2022-03-15T09:08:43Z",
        "readyToUse": true,
        "restoreSize": "10Gi"
    }
}
  1. 模拟灾难场景,我们将备份好的apps命名空间删除,可以看到namespace中已经没有apps了 image.png

  2. 从备份恢复时,将从快照创建一个克隆卷并绑定到恢复的 PVC

velero restore create yx-re1 \
--from-backup yx-bk1 \
-n velero-yx

通过查看任务详情,可以看到任务的状态是Completed

[root@i-encdmzhz ~]# velero restore describe yx-re1 -n velero-yx
Name:         yx-re1
Namespace:    velero-yx
Labels:       <none>
Annotations:  <none>

Phase:  Completed

Started:    2022-03-15 11:02:34 +0800 CST
Completed:  2022-03-15 11:02:39 +0800 CST

Backup:  yx-bk1

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
  Cluster-scoped:  auto

Namespace mappings:  <none>

Label selector:  <none>

Restore PVs:  auto
  1. 那我们再去查看命名空间列表,可以看到apps已经恢复了,并且POD的状态也是Running image.png image.png

  2. 查看通过快照创建的PVC以及PV的信息 image.png

至此,通过VSL快照的方式恢复集群资源到这里就结束了

参考资料

github.com/vmware-tanz…

github.com/vmware-tanz…

tanzucommunityedition.io/docs/latest…

www.digitalocean.com/community/t…

cloud.tencent.com/document/pr…

blog.csdn.net/u013189824/…