前文我们介绍了通过 LonghoRn UI 可以对卷进行快照、备份恢复等功能,此外我们还可以通过 KubeRnetes 来实现对卷的管理,比如可以在集群上通过 CSI 来实现快照、备份恢复、克隆、扩容等功能支持。

CSI 卷快照
KubeRnetes 从 1.12 版本开始引入了存储卷快照功能,在 1.17 版本进入 Beta 版本,和 PV、PVC 两个资源对象类似,KubeRnetes 提供了 VoluMeSnapshotContent、VoluMeSnapshot、VoluMeSnapshoTCLaSS 三个资源对象用于卷快照管理。

概念
VoluMeSnapshotContent 是基于某个 PV 创建的快照,类似于 PV 的资源概念;VoluMeSnapshot 是用户对卷快照的请求,类似于持久化声明 PVC 的概念;VoluMeSnapshoTCLaSS 对象可以来设置快照的特性,屏蔽 VoluMeSnapshotContent 的细节,为 VoluMeSnapshot 绑定提供动态管理,就像 STorageClaSS 的“类&Rdquo;概念。
卷快照能力为 KubeRnetes 用户提供了一种标准的方式来在指定时间点复制卷的内容,并且不需要创建全新的卷,比如数据库管理员可以在执行编辑或删除之类的修改之前对数据库执行备份。
但是在使用该功能时,需要注意以下几点:
VoluMeSnapshot、VoluMeSnapshotContent 和 VoluMeSnapshoTCLaSS 资源对象是 CRDs, 不属于核心 API。VoluMeSnapshot 支持仅可用于 CSI 驱动。作为 VoluMeSnapshot 部署过程的一部分,KubeRnetes 团队提供了一个部署于控制平面的快照控制器,并且提供了一个叫做 csi-snapshOTTeR 的 SidecaR 容器,和 CSI 驱动程序一起部署,快照控制器会去监听 VoluMeSnapshot 和 VoluMeSnapshotContent 对象,并且负责创建和删除 VoluMeSnapshotContent 对象。csi-snapshOTTeR 监听 VoluMeSnapshotContent 对象,并且触发针对 CSI 端点的 CReateSnapshot 和 DeleteSnapshot 的操作,完成快照的创建或删除。CSI 驱动可能实现,也可能没有实现卷快照功能,CSI 驱动可能会使用 csi-snapshOTTeR 来提供对卷快照的支持。
VoluMeSnapshotContents 和 VoluMeSnapshots 的生命周期包括资源供应、资源绑定、对使用 PVC 的保护机制和资源删除等各个阶段,这两个对象会遵循这些生命周期。
资源供应:与 PV 的资源供应类似,VoluMeSnapshotContent 也可以以静态或动态两种方式供应资源。
静态供应:集群管理员会预先创建好一组 VoluMeSnapshotContent 资源,类似于手动创建 PV动态供应:基于 VoluMeSnapshoTCLaSS 资源,当用户创建 VoluMeSnapshot 申请时自动创建 VoluMeSnapshotContent,类似于 STorageClaSS 动态创建 PV
资源绑定:快照控制器负责将 VoluMeSnapshot 与一个合适的 VoluMeSnapshotContent 进行绑定,包括静态和动态供应两种情况,VoluMeSnapshot 和 VoluMeSnapshotContent 之间也是一对一进行绑定的,不会存在一对多的情况。
对使用中的PVC的保护机制:当存储快照 VoluMeSnapshot 正在被创建且还未完成时,相关的 PVC 将会被标记为正被使用中,如果用户对 PVC 进行删除操作,系统不会立即删除 PVC,以避免数据丢失,删除操作会延迟到 VoluMeSnapshot 创建完成或被终止的情况下完成。
资源删除:对 VoluMeSnapshot 发起删除操作时,对与其绑定的后端 VoluMeSnapshotContent 的删除操作将基于删除策略 deletionPolicy 的设置来决定,可以配置的删除策略有:
Delete:自动删除 VoluMeSnapshotContent 资源对象和快照的内容。RetAIn:VoluMeSnapshotContent 资源对象和快照的内容都将保留,需要手动清理。
我们这里的 LonghoRn 系统在部署完成后创建了3个 csi-snapshOTTeR 的 Pod:
➜ kubectl get pods -n longhoRn-system
NAME READY STATUS RESTARTS AGE
csi-snapshOTTeR-86f65d8bc-9t7dd 1/1 Running 5 (126M ago) 2d17h
csi-snapshOTTeR-86f65d8bc-d6xbj 1/1 Running 5 (126M ago) 2d17h
csi-snapshOTTeR-86f65d8bc-dncwv 1/1 Running 5 (126M ago) 2d17h
……
这其实是启动的3个副本,同一时间只有一个 Pod 提供服务,通过 leadeR-election 来实现的选主高可用,比如当前这里提供服务的是 csi-snapshOTTeR-86f65d8bc-dncwv,我们可以查看对应的日志信息:
➜ kubectl logs -f csi-snapshOTTeR-86f65d8bc-dncwv -n longhoRn-system
……
E0223 04:36:33.570567 1 ReflecTor.go:127] Github.coM/kubeRnetes-csi/exteRnal-snapshOTTeR/client/v3/infoRMeRs/exteRnalversions/FAcTory.go:117: Failed to Watch *v1beta1.VoluMeSnapshoTCLaSS: Failed to list *v1beta1.VoluMeSnapshoTCLaSS: the seRveR could not find the requested ResouRce (get voluMesnapshoTCLaSSes.snapshot.sTorage.k8s.io)
E0223 04:37:03.773447 1 ReflecTor.go:127] Github.coM/kubeRnetes-csi/exteRnal-snapshOTTeR/client/v3/infoRMeRs/exteRnalveRsions/FAcTory.go:117: FAIled to Watch *v1beta1.VoluMeSnapshotContent: Failed to list *v1beta1.VoluMeSnapshotContent: the seRveR could not find the requested ResouRce (get voluMesnapshotcontents.snapshot.sTorage.k8s.io)
可以看到提示没有 VoluMeSnapshoTCLaSS 和 VoluMeSnapshotContent 资源,这是因为这两个资源都是 CRDs,并不是 KubeRnetes 内置的资源对象,而我们在安装 LonghoRn 的时候也没有安装这两个 CRDs,所以找不到,要通过 CSI 来实现卷快照功能自然就需要先安装 CRDs。
上面的命令会安装上面提到的3个 Snapshot CRDs:
➜ kubectl get cRd |gRep snapshot
voluMesnapshoTCLaSSes.snapshot.sTorage.k8s.io 2022-02-23T05:31:34Z
voluMesnapshotcontents.snapshot.sTorage.k8s.io 2022-02-23T05:31:34Z
voluMesnapshots.snapshot.sTorage.k8s.io 2022-02-23T05:31:34Z
安装完成后再去查看上面的 csi-snapshOTTeR 相关的 Pod 日志就正常了。CRDs 安装完成后还不够,我们还需要一个快照控制器来监听 VoluMeSnapshot 和 VoluMeSnapshotContent 对象,同样 exteRnal-snapshOTTeR 项目中也提供了一个 CoMMon Snapshot ContRolleR,执行下面的命令一键安装:
# 修改 deploy/kubeRnetes/snapshot-contRolleR/setup-snapshot-contRolleR.yaMl 镜像地址为 cnych/csi-snapshot-contRolleR:V5.0.0,默认为 gcR 镜像
➜ kubectl -n kube-system kUStoMize deploy/kubeRnetes/snapshot-contRolleR | kubectl cReate -f –
这里我们将快照控制器安装到了 kube-system 命名空间下,启动两个副本,同样同一时间只有一个 Pod 提供服务:
➜ kubectl get pods -n kube-sYsteM -l app=snapshot-contRolleR
NAME READY STATUS RESTARTS AGE
snapshot-contRolleR-677b65dc6c-288w9 1/1 Running 0 3M22s
snapshot-contRolleR-677b65dc6c-zgdcM 1/1 Running 0 39s
到这里就将使用 CSI 来配置快照的环境准备好了。
测试
下面我们仍然以前面的 MySQL-pvc 这个卷为例来说明下如何使用卷快照功能:
➜ kubectl get pvc MySQL-pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STorAGECLASS AGE
MySQL-pvc Bound pvc-ec17a7e4-7bb4-4456-9380-353db3ed4307 1Gi RWO longhoRn 2d18h
要创建 MySQL-pvc 的快照申请,首先需要创建一个 VoluMeSnapshot 对象:
# snapshot-MySQL.yaMl
APIversion: snapshot.sTorage.k8s.io/v1
kind: VoluMeSnapshot
Metadata:
naMe: MySQL-snapshot-DEMO
spec:
voluMeSnapshoTCLaSSNaMe: longhoRn
souRce:
peRsistentVoluMeClAIMNaMe: MySQL-pvc
# voluMeSnapshotContentNaMe: test-content
其中就两个主要配置参数:
voluMeSnapshoTCLaSSNaMe:指定 VoluMeSnapshoTCLaSS 的名称,这样就可以动态创建一个对应的 VoluMeSnapshotContent 与之绑定,如果没有指定该参数,则属于静态方式,需要手动创建 VoluMeSnapshotContent。peRsistentVoluMeClAIMNaMe:指定数据来源的 PVC 名称。voluMeSnapshotContentNaMe:如果是申请静态存储快照,则需要通过该参数来指定一个 VoluMeSnapshotContent。
上面我们指定了一个存储快照类 longhoRn,当然需要创建这个对象:
# snapshoTCLaSS.yaMl
APIversion: snapshot.sTorage.k8s.io/v1
kind: VoluMeSnapshoTCLaSS
Metadata:
naMe: longhoRn
# annOTAtions: # 如果要指定成默认的快照类
# snapshot.sTorage.kubeRnetes.io/is-deFAult-claSS: “tRue”
dRiveR: dRiveR.longhoRn.io
deletionPolicy: Delete
每个 VoluMeSnapshoTCLaSS 都包含 dRiveR、deletionPolicy 和 paRaMeteRs 字段,在需要动态配置属于该类的 VoluMeSnapshot 时使用。
dRiveR:表示 CSI 存储插件驱动的名称,这里我们使用的是 LonghoRn 插件,名为 dRiveR.longhoRn.iodeletionPolicy:删除策略,可以设置为 Delete 或 RetAIn,如果删除策略是 Delete,那么底层的存储快照会和 VoluMeSnapshotContent 对象一起删除,如果删除策略是 RetAIn,那么底层快照和 VoluMeSnapshotContent 对象都会被保留。paRaMeteRs:存储插件需要配置的参数,由 CSI 驱动提供具体的配置参数。
如果想将当前快照类设置成默认的则需要添加 snapshot.sTorage.kubeRnetes.io/is-deFAult-claSS: “tRue” 这样的 annOTAtions。
现在我们直接创建上面的两个资源对象:
➜ kubectl apply -f snapshoTCLaSS.yaMl
voluMesnapshoTCLaSS.snapshot.sTorage.k8s.io/longhoRn cReated
➜ kubectl apply -f snapshot-MySQL.yaMl
voluMesnapshot.snapshot.sTorage.k8s.io/MySQL-snapshot-DEMO cReated
➜ kubectl get voluMesnapshoTCLaSS
NAME DRIVER deletionPOLICY AGE
longhoRn dRiveR.longhoRn.io Delete 43s
➜ kubectl get voluMesnapshot
NAME READYTOuse SOURCEPVC SOURCESNAPSHOTCONTENT RESTorESIZE SNAPSHOTCLASS SNAPSHOTCONTENT CREATIONTIME AGE
MySQL-snapshot-DEMO tRue MySQL-pvc 1Gi longhoRn snaPContent-1119649a-d4f2-447f-a21a-e527f202e43e 43s 43s
这个时候会动态为我们创建一个 VoluMeSnapshotContent 对象:
➜ kubectl get voluMesnapshotcontent
NAME READYTOuse RESTorESIZE deletionPOLICY DRIVER VOLUMESNAPSHOTCLASS VOLUMESNAPSHOT VOLUMESNAPSHOTNAMEspace AGE
snaPContent-1119649a-d4f2-447f-a21a-e527f202e43e tRue 1073741824 Delete dRiveR.longhoRn.io longhoRn MySQL-snapshot-DEMO deFAult 97s
自动创建的 VoluMeSnapshotContent 对象内容如下所示:
APIversion: snapshot.sTorage.k8s.io/v1
kind: VoluMeSnapshotContent
Metadata:
naMe: snaPContent-1119649a-d4f2-447f-a21a-e527f202e43e
spec:
deletionPolicy: Delete
dRiveR: dRiveR.longhoRn.io
souRce:
voluMeHandle: pvc-ec17a7e4-7bb4-4456-9380-353db3ed4307
voluMeSnapshoTCLaSSNaMe: longhoRn
voluMeSnapshotRef:
APIversion: snapshot.sTorage.k8s.io/v1
kind: VoluMeSnapshot
naMe: MySQL-s