Kubernetes 1.32:卷組快照進入 Beta 階段

卷組快照在 Kubernetes 1.27 版本中作為 Alpha 特性被引入。最近釋出的 Kubernetes v1.32 將該支援提升到了 beta 階段。對卷組快照的支援依賴於一組用於組快照的擴充套件 API。這些 API 允許使用者為一組卷建立崩潰一致性快照。在後臺,Kubernetes 使用標籤選擇器將多個 PersistentVolumeClaim 分組以進行快照。一個關鍵目標是允許你將這組快照恢復到新的卷中,並基於一個崩潰一致的恢復點來恢復你的工作負載。

這項新功能僅支援 CSI 卷驅動。

卷組快照概述

一些儲存系統提供了建立多個卷的崩潰一致性快照的能力。組快照表示在同一時間點從多個卷建立的**副本**。組快照既可以用於重新生成新卷(預填充了快照資料),也可以用於將現有卷恢復到之前的狀態(由快照表示)。

為何向 Kubernetes 添加捲組快照?

Kubernetes 卷外掛系統已經提供了一個強大的抽象,可以自動執行塊儲存和檔案儲存的製備、掛接、掛載、調整大小和快照操作。

支撐所有這些特性的是 Kubernetes 的工作負載可移植性目標:Kubernetes 旨在在分散式應用程式和底層叢集之間建立一個抽象層,以便應用程式可以與它們執行的叢集的具體細節無關,並且應用程式部署不需要特定於叢集的知識。

已經有一個 VolumeSnapshot API,它提供了為持久卷建立快照以防止資料丟失或資料損壞的能力。然而,還有其他快照功能未被 VolumeSnapshot API 覆蓋。

一些儲存系統支援一致性組快照,允許在同一時間點從多個卷建立快照,以實現寫操作順序一致性。這對於包含多個卷的應用程式非常有用。例如,一個應用程式可能將資料儲存在一個卷中,將日誌儲存在另一個卷中。如果資料卷和日誌卷的快照在不同時間建立,當災難發生時,如果從這些快照恢復,應用程式將不一致,無法正常工作。

誠然,你可以先靜默應用程式,然後依次為作為應用程式一部分的每個卷建立單個快照,在所有單個快照都建立完畢後再取消靜默應用程式。這樣,你將獲得應用一致的快照。

然而,有時應用程式靜默可能非常耗時,以至於你希望減少靜默的頻率,或者可能根本無法靜默應用程式。例如,使用者可能希望每週執行一次帶有應用程式靜默的備份,而每晚執行一次不帶應用程式靜默但具有一致性組支援的備份,這種支援提供了組內所有卷的崩潰一致性。

用於卷組快照的 Kubernetes API

Kubernetes 對**卷組快照**的支援依賴於三種用於管理快照的 API Kind:

VolumeGroupSnapshot
由 Kubernetes 使用者(或者可能由你自己的自動化)建立,用於請求為多個持久卷宣告建立一個卷組快照。它包含有關卷組快照操作的資訊,例如卷組快照的建立時間戳以及是否準備就緒。此物件的建立和刪除表示希望建立或刪除叢集資源(一個組快照)。
VolumeGroupSnapshotContent
由快照控制器為動態建立的 VolumeGroupSnapshot 建立。它包含有關卷組快照的資訊,包括卷組快照 ID。此物件代表叢集上已製備的資源(一個組快照)。VolumeGroupSnapshotContent 物件與為其建立的 VolumeGroupSnapshot 存在一對一的繫結關係。
VolumeGroupSnapshotClass
由叢集管理員建立,用於描述應如何建立卷組快照,包括驅動資訊、刪除策略等。

這三個 API Kind 被定義為CustomResourceDefinitions (CRD)。為了讓 CSI 驅動支援卷組快照,這些 CRD 必須安裝在 Kubernetes 叢集中。

支援卷組快照需要哪些元件

卷組快照在 external-snapshotter 倉庫中實現。實現卷組快照意味著新增或更改了幾個元件:

  • 為 VolumeGroupSnapshot 和兩個支援性 API 添加了新的 CustomResourceDefinitions。
  • 卷組快照控制器邏輯被新增到通用快照控制器中。
  • 在 snapshotter sidecar 控制器中添加了呼叫 CSI 的邏輯。

卷快照控制器和 CRD 在每個叢集部署一次,而 sidecar 則與每個 CSI 驅動捆綁在一起。

因此,將卷快照控制器和 CRD 作為叢集外掛進行部署是合理的。

Kubernetes 專案建議 Kubernetes 發行版將卷快照控制器和 CRD 作為其 Kubernetes 叢集管理過程的一部分進行捆綁和部署(獨立於任何 CSI 驅動)。

Beta 版本有哪些新功能?

  • CSI 規範中的 VolumeGroupSnapshot 特性在 v1.11.0 版本中進入了 GA 階段。

  • 快照驗證 webhook 在 external-snapshotter v8.0.0 中被棄用,現已被移除。大部分驗證 webhook 邏輯已作為驗證規則新增到 CRD 中。這些驗證規則要求的最低 Kubernetes 版本是 1.25。驗證 webhook 中有一項功能未移至 CRD,即防止為同一 CSI 驅動建立多個預設的卷快照類和多個預設的卷組快照類。隨著驗證 webhook 的移除,當為同一 CSI 驅動存在多個預設卷快照類或多個預設卷組快照類時,動態製備 VolumeSnapshot 或 VolumeGroupSnapshot 時仍會引發錯誤。

  • snapshot-controller 和 CSI snapshotter sidecar 中的 enable-volumegroup-snapshot 標誌已被特性門控取代。由於 VolumeGroupSnapshot 是一個新 API,該特性進入 Beta 階段,但特性門控預設是停用的。要使用此特性,請在啟動 snapshot-controller 和 CSI snapshotter sidecar 時新增標誌 --feature-gates=CSIVolumeGroupSnapshot=true 來啟用該特性門控。

  • 動態建立 VolumeGroupSnapshot 及其對應的單個 VolumeSnapshot 和 VolumeSnapshotContent 物件的邏輯已從 CSI snapshotter 移至通用 snapshot-controller。新的 RBAC 規則已新增到通用 snapshot-controller 中,並且相應地從 CSI snapshotter sidecar 中刪除了一些 RBAC 規則。

我如何使用 Kubernetes 卷組快照

使用 Kubernetes 建立一個新的組快照

一旦定義了 VolumeGroupSnapshotClass 物件,並且你有一些想要一起快照的卷,你可以透過建立一個 VolumeGroupSnapshot 物件來請求一個新的組快照。

組快照的源(source)指定了底層的組快照是應該動態建立,還是應該使用一個預先存在的 VolumeGroupSnapshotContent。

預先存在的 VolumeGroupSnapshotContent 由叢集管理員建立。它包含了儲存系統上真實卷組快照的詳細資訊,可供叢集使用者使用。

必須設定組快照的源中的以下成員之一。

  • selector - 一個針對要組合在一起進行快照的 PersistentVolumeClaim 的標籤查詢。此選擇器將用於匹配新增到 PVC 的標籤。
  • volumeGroupSnapshotContentName - 指定一個代表現有卷組快照的預先存在的 VolumeGroupSnapshotContent 物件的名稱。

動態製備組快照

在以下示例中,有兩個 PVC。

NAME    STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      VOLUMEATTRIBUTESCLASS   AGE
pvc-0   Bound    pvc-6e1f7d34-a5c5-4548-b104-01e72c72b9f2   100Mi      RWO            csi-hostpath-sc   <unset>                 2m15s
pvc-1   Bound    pvc-abc640b3-2cc1-4c56-ad0c-4f0f0e636efa   100Mi      RWO            csi-hostpath-sc   <unset>                 2m7s

為 PVC 新增標籤。

% kubectl label pvc pvc-0 group=myGroup
persistentvolumeclaim/pvc-0 labeled

% kubectl label pvc pvc-1 group=myGroup
persistentvolumeclaim/pvc-1 labeled

對於動態製備,必須設定一個選擇器,以便快照控制器可以找到帶有匹配標籤的 PVC,將它們一起進行快照。

apiVersion: groupsnapshot.storage.k8s.io/v1beta1
kind: VolumeGroupSnapshot
metadata:
  name: snapshot-daily-20241217
  namespace: demo-namespace
spec:
  volumeGroupSnapshotClassName: csi-groupSnapclass
  source:
    selector:
      matchLabels:
        group: myGroup

在 VolumeGroupSnapshot 規約中,使用者可以指定 VolumeGroupSnapshotClass,其中包含有關應使用哪個 CSI 驅動來建立組快照的資訊。動態製備需要一個 VolumGroupSnapshotClass。

apiVersion: groupsnapshot.storage.k8s.io/v1beta1
kind: VolumeGroupSnapshotClass
metadata:
  name: csi-groupSnapclass
  annotations:
    kubernetes.io/description: "Example group snapshot class"
driver: example.csi.k8s.io
deletionPolicy: Delete

卷組快照建立的結果是,將建立一個相應的 VolumeGroupSnapshotContent 物件,其 volumeGroupSnapshotHandle 指向儲存系統上的一個資源。

作為卷組快照建立的一部分,將建立兩個單獨的卷快照。

NAME                                                                        READYTOUSE   SOURCEPVC   RESTORESIZE   SNAPSHOTCONTENT                                                                AGE
snapshot-0962a745b2bf930bb385b7b50c9b08af471f1a16780726de19429dd9c94eaca0   true         pvc-0       100Mi         snapcontent-0962a745b2bf930bb385b7b50c9b08af471f1a16780726de19429dd9c94eaca0   16m
snapshot-da577d76bd2106c410616b346b2e72440f6ec7b12a75156263b989192b78caff   true         pvc-1       100Mi         snapcontent-da577d76bd2106c410616b346b2e72440f6ec7b12a75156263b989192b78caff   16m

使用 Kubernetes 匯入現有組快照

要將一個預先存在的卷組快照匯入 Kubernetes,你還必須匯入相應的單個卷快照。

識別單個卷快照控制代碼,首先手動構造一個 VolumeSnapshotContent 物件,然後建立一個指向該 VolumeSnapshotContent 物件的 VolumeSnapshot 物件。對每個單個卷快照重複此操作。

然後手動建立一個 VolumeGroupSnapshotContent 物件,指定儲存系統上已存在的 volumeGroupSnapshotHandle 和單個 volumeSnapshotHandles。

apiVersion: groupsnapshot.storage.k8s.io/v1beta1
kind: VolumeGroupSnapshotContent
metadata:
  name: static-group-content
spec:
  deletionPolicy: Delete
  driver: hostpath.csi.k8s.io
  source:
    groupSnapshotHandles:
      volumeGroupSnapshotHandle: e8779136-a93e-11ef-9549-66940726f2fd
      volumeSnapshotHandles:
      - e8779147-a93e-11ef-9549-66940726f2fd
      - e8783cd0-a93e-11ef-9549-66940726f2fd
  volumeGroupSnapshotRef:
    name: static-group-snapshot
    namespace: demo-namespace

之後,建立一個指向該 VolumeGroupSnapshotContent 物件的 VolumeGroupSnapshot 物件。

apiVersion: groupsnapshot.storage.k8s.io/v1beta1
kind: VolumeGroupSnapshot
metadata:
  name: static-group-snapshot
  namespace: demo-namespace
spec:
  source:
    volumeGroupSnapshotContentName: static-group-content

如何在 Kubernetes 中使用組快照進行恢復

在恢復時,使用者可以請求從作為 VolumeGroupSnapshot 一部分的 VolumeSnapshot 物件建立一個新的 PersistentVolumeClaim。這將觸發製備一個新卷,該卷預先填充了來自指定快照的資料。使用者應重複此操作,直到從屬於組快照的所有快照中創建出所有卷。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: examplepvc-restored-2024-12-17
  namespace: demo-namespace
spec:
  storageClassName: example-foo-nearline
  dataSource:
    name: snapshot-0962a745b2bf930bb385b7b50c9b08af471f1a16780726de19429dd9c94eaca0
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
  accessModes:
    - ReadWriteOncePod
  resources:
    requests:
      storage: 100Mi # must be enough storage to fit the existing snapshot

作為儲存供應商,我如何為我的 CSI 驅動新增對組快照的支援?

要實現卷組快照功能,CSI 驅動**必須**:

  • 實現一個新的組控制器服務。
  • 實現組控制器 RPC:`CreateVolumeGroupSnapshot`、`DeleteVolumeGroupSnapshot` 和 `GetVolumeGroupSnapshot`。
  • 新增組控制器能力 `CREATE_DELETE_GET_VOLUME_GROUP_SNAPSHOT`。

更多詳細資訊,請參閱 CSI 規範Kubernetes-CSI 驅動開發者指南

如前所述,強烈建議 Kubernetes 發行版將卷快照控制器和 CRD 作為其 Kubernetes 叢集管理過程的一部分進行捆綁和部署(獨立於任何 CSI 驅動)。

作為此推薦部署過程的一部分,Kubernetes 團隊提供了許多 sidecar(輔助)容器,包括已更新以支援卷組快照的 external-snapshotter sidecar 容器

external-snapshotter 監視 Kubernetes API 伺服器上的 VolumeGroupSnapshotContent 物件,並觸發針對 CSI 端點的 `CreateVolumeGroupSnapshot` 和 `DeleteVolumeGroupSnapshot` 操作。

有哪些限制?

Kubernetes 卷組快照的 Beta 實現有以下限制:

  • 不支援將現有 PVC 恢復到由快照表示的早期狀態(僅支援從快照製備新卷)。
  • 除了儲存系統提供的任何保證(例如崩潰一致性)之外,不提供應用程式一致性保證。有關應用程式一致性的更多討論,請參閱此文件

下一步是什麼?

根據反饋和採用情況,Kubernetes 專案計劃在未來版本中將卷組快照實現推向正式釋出(GA)。

我如何瞭解更多資訊?

我如何參與?

這個專案,和所有 Kubernetes 專案一樣,是許多來自不同背景的貢獻者共同努力的成果。我謹代表 SIG Storage,向在過去幾個季度中挺身而出,幫助專案達到 Beta 階段的貢獻者們表示衷心的感謝:

對於有興趣參與 CSI 或 Kubernetes 儲存系統任何部分的設計和開發的人,歡迎加入 Kubernetes 儲存特別興趣小組 (SIG)。我們隨時歡迎新的貢獻者。

我們還定期舉行資料保護工作組會議。歡迎新成員加入我們的討論。