前文我們介紹了通過 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 的“類”概念。
卷快照能力為 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 來提供對卷快照的支持,詳見 CSI 驅動程序文檔(https://kubernetes-csi.github.io/docs/external-snapshotter.html)。
VolumeSnapshotContents 和 VolumeSnapshots 的生命周期包括資源供應、資源綁定、對使用 PVC 的保護機制和資源刪除等各個階段,這兩個對象會遵循這些生命周期。
資源供應:與 PV 的資源供應類似,VolumeSnapshotContent 也可以以靜態或動態兩種方式供應資源。
靜態供應:集群管理員會預先創建好一組 VolumeSnapshotContent 資源,類似于手動創建 PV動態供應:基于 VolumeSnapshotClass 資源,當用戶創建 VolumeSnapshot 申請時自動創建 VolumeSnapshotContent,類似于 StorageClass 動態創建 PV
資源綁定:快照控制器負責將 VolumeSnapshot 與一個合適的 VolumeSnapshotContent 進行綁定,包括靜態和動態供應兩種情況,VolumeSnapshot 和 VolumeSnapshotContent 之間也是一對一進行綁定的,不會存在一對多的情況。
對使用中的PVC的保護機制:當存儲快照 VolumeSnapshot 正在被創建且還未完成時,相關的 PVC 將會被標記為正被使用中,如果用戶對 PVC 進行刪除操作,系統不會立即刪除 PVC,以避免快照還未做完造成數據丟失,刪除操作會延遲到 VolumeSnapshot 創建完成(readyToUse 狀態)或被終止(aborted 狀態)的情況下完成。
資源刪除:對 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,我們可以從 https://github.com/kubernetes-csi/external-snapshotter 項目中來獲?。?span style="display:none">CK328資訊網——每日最新資訊28at.com
? git clone https://github.com/kubernetes-csi/external-snapshotter
? cd external-snapshotter && git checkout v5.0.1
? kubectl kustomize client/config/crd | kubectl create -f -
上面的命令會安裝上面提到的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-snapshot-demo
namespace: default
resourceVersion: "4967456"
uid: 1119649a-d4f2-447f-a21a-e527f202e43e
status:
creationTime: 1645597546000000000
readyToUse: true
restoreSize: 1073741824
snapshotHandle: bs://pvc-ec17a7e4-7bb4-4456-9380-353db3ed4307/backup-f5f28fd624a148ed
其中的 source.volumeHandle 字段的值是在后端存儲上創建并由 CSI 驅動在創建存儲卷期間返回的 Volume 的唯一標識符,在動態供應模式下需要該字段,指定的是快照的來源 Volume 信息,volumeSnapshotRef 下面就是和關聯的 VolumeSnapshot 對象的相關信息。當然這個時候我們在 Longhorn UI 界面上也可以看到上面我們創建的這個快照了,快照名稱為 snapshot-1119649a-d4f2-447f-a21a-e527f202e43e,后面的 ID 與上面的 VolumeSnapshotContent 名稱保持一致:
并且也會進行一次對應的 Backup 操作,備份的信息通過 snapshotHandle 進行指定的,格式為 bs://backup-/backup-:
這樣我們就完成了通過 CSI 實現卷的快照管理功能。
CSI 卷恢復
Kubernetes 對基于快照創建存儲卷在 1.17 版本更新到了 Beta 版本,要啟用該特性,就需要在 kube-apiserver、kube-controller-manager 和 kubelet 的 Feature Gate 中啟用 --feature-gates=...,VolumeSnapshotDataSource(我們這里是1.22版本默認已經啟用了),然后就可以基于某個快照創建一個新的 PVC 存儲卷了,比如現在我們來基于上面創建的 mysql-snapshot-demo 這個對象來創建一個新的 PVC:
# restore-mysql.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-restore-pvc
spec:
storageClassName: longhorn
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
dataSource:
apiGroup: snapshot.storage.k8s.io
kind: VolumeSnapshot
name: mysql-snapshot-demo
上面的 PVC 對象和我們平時聲明的方式基本一致,唯一不同的是通過一個 dataSource 字段配置了基于名為 mysql-snapshot-demo 的存儲快照進行創建,創建上面的資源對象后同樣會自動創建一個 PV 與之綁定:
? kubectl get pvc mysql-restore-pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mysql-restore-pvc Bound pvc-e4ddd985-31a8-4570-b393-dcedec3b0d95 1Gi RWO longhorn 17s
在 Longhorn UI 中去查看該卷,可以看到該卷的實際大小并不為0,這是因為我們是從快照中創建過來的,相當于從上面的快照中恢復的數據:
卷克隆
除了基于快照創建新的 PVC 對象之外,CSI 類型的存儲還支持存儲的克隆功能,可以基于已經存在的 PVC 克隆一個新的 PVC,實現方式也是通過在 dataSource 字段中來設置源 PVC 來實現。
克隆一個 PVC 其實就是對已存在的存儲卷創建一個副本,唯一的區別是,系統在為克隆 PVC 提供后端存儲資源時,不是新建一個空的 PV,而是復制一個與原 PVC 綁定 PV 完全一樣的 PV。
從 Kubernetes API 的角度看,克隆的實現只是在創建新的 PVC 時, 增加了指定一個現有 PVC 作為數據源的能力。源 PVC 必須是 bound 狀態且可用的(不在使用中)。
用戶在使用該功能時,需要注意以下事項:
克隆僅適用于 CSI 驅動克隆僅適用于動態供應克隆功能取決于具體的 CSI 驅動是否實現該功能要求目標 PVC 和源 PVC 必須處于同一個命名空間只支持在相同的 StorageClass 中(可以使用默認的)兩個存儲卷的存儲模式(VolumeMode)要一致
同樣我們來對前面的 mysql-pvc 這個存儲卷進行克隆操作,對應的 PVC 聲明如下所示:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-clone-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 1Gi # 必須大于或等于源的值
dataSource:
kind: PersistentVolumeClaim
name: mysql-pvc
該 PVC 和源 PVC 聲明一樣的配置,唯一不同的是通過 dataSource 指定了源 PVC 的名稱,直接創建這個資源對象,結果是 mysql-clone-pvc 這個新的 PVC 與源 mysql-pvc 擁有相同的數據。
? kubectl get pvc mysql-clone-pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mysql-clone-pvc Bound pvc-58eab5f0-a386-435c-91f4-0c26f7935695 1Gi RWO longhorn 31s
在 Longhorn UI 頁面中也可以看到對應的卷:
一旦新的 PVC 可用,被克隆的 PVC 就可以像其他 PVC 一樣被使用了,也可以對其進行克隆、快照、刪除等操作。
卷動態擴容
我們知道對于存儲來說擴容是一個非常重要的需求,對于 Kubernetes 中的卷動態擴容同樣也是需要的基本功能,PV 要做擴容操作是需要底層存儲支持該操作才能實現,Longhorn 底層是支持卷擴容操作的,但是要求擴展的卷必須處于 detached 狀態才能操作,有兩種方法可以擴容 Longhorn 卷:修改 PVC 和使用 Longhorn UI。
通過 Longhorn UI 操作比較簡單,直接在頁面中選擇要擴容的卷,在操作中選擇 Expand Volume 進行操作即可:
要通過 PVC 來進行擴容首先需要 PVC 由 Longhorn StorageClass 進行動態供應,并且在 StorageClass 中 allowVolumeExpansion 屬性設置為 true,建議使用這種方法,因為 PVC 和 PV 會自動更新,并且在擴容后都會保持一致。比如上面使用的 mysql-clone-pvc 這個卷(處于 detached 狀態)使用的 longhorn 這個 StorageClass 中就已經配置了 allowVolumeExpansion: true,然后直接修改 mysql-pvc 這個卷下面的 spec.resources.requests.storage 值即可:
? kubectl get pvc mysql-clone-pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mysql-clone-pvc Bound pvc-58eab5f0-a386-435c-91f4-0c26f7935695 1Gi RWO longhorn 40m
? kubectl patch pvc mysql-clone-pvc -p '{"spec":{"resources":{"requests":{"storage":"2Gi"}}}}}'
修改后可以查看該 PVC 的 events 信息:
? kubectl describe pvc mysql-clone-pvc
......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
......
Normal Resizing 14s external-resizer driver.longhorn.io External resizer is resizing volume pvc-58eab5f0-a386-435c-91f4-0c26f7935695
Warning ExternalExpanding 14s volume_expand Ignoring the PVC: didn't find a plugin capable of expanding the volume; waiting for an external controller to process this PVC.
Normal VolumeResizeSuccessful 2s external-resizer driver.longhorn.io Resize volume succeeded
可以看到通過 external-resizer 組件實現了 Resize 操作,查看 PVC 和 PV 的大小驗證:
? kubectl get pvc mysql-clone-pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mysql-clone-pvc Bound pvc-58eab5f0-a386-435c-91f4-0c26f7935695 2Gi RWO longhorn 43m
? kubectl get pv pvc-58eab5f0-a386-435c-91f4-0c26f7935695
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-58eab5f0-a386-435c-91f4-0c26f7935695 2Gi RWO Delete Bound default/mysql-clone-pvc longhorn 43m
可以看到 PVC 和 PV 中的容量都變成了 2Gi,證明擴容成功了,通過 Longhorn UI 也可以查看到卷擴容成功了:
本文鏈接:http://www.www897cc.com/showinfo-119-2181-0.html通過 Kubernetes CSI 實現 Longhorn 卷快照備份、恢復、克隆與擴容功能
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com