本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

為 Kubernetes 引入卷快照 Alpha

Kubernetes v1.12 引入了對卷快照的 alpha 支援。此功能允許建立/刪除卷快照,以及使用 Kubernetes API 從快照本地建立新卷。

什麼是快照?

許多儲存系統(如 Google Cloud Persistent Disks、Amazon Elastic Block Storage 和許多本地儲存系統)都提供建立持久卷“快照”的功能。快照代表卷的時間點副本。快照可用於置備新卷(預填充快照資料)或將現有卷恢復到以前的狀態(由快照表示)。

為什麼將快照新增到 Kubernetes?

Kubernetes 卷外掛系統已經提供了強大的抽象,可以自動化塊儲存和檔案儲存的供應、附加和掛載。

所有這些功能的基礎是 Kubernetes 的工作負載可移植性目標:Kubernetes 旨在在分散式系統應用程式和底層叢集之間建立一個抽象層,以便應用程式可以不依賴於它們執行的叢集的特定細節,並且應用程式部署不需要“叢集特定”的知識。

Kubernetes 儲存 SIG 將快照操作識別為許多有狀態工作負載的關鍵功能。例如,資料庫管理員可能希望在開始資料庫操作之前對資料庫捲進行快照。

透過提供一種在 Kubernetes API 中觸發快照操作的標準方式,Kubernetes 使用者現在可以處理此類用例,而無需繞過 Kubernetes API(並手動執行儲存系統特定的操作)。

相反,Kubernetes 使用者現在可以以叢集無關的方式將快照操作整合到他們的工具和策略中,並且可以安心地知道它將適用於任意 Kubernetes 叢集,而無論底層儲存如何。

此外,這些 Kubernetes 快照原語充當了基本構建塊,可以開發用於 Kubernetes 的高階企業級儲存管理功能:例如資料保護、資料複製和資料遷移。

哪些卷外掛支援 Kubernetes 快照?

Kubernetes 支援三種類型的卷外掛:in-tree、Flex 和 CSI。有關詳細資訊,請參閱Kubernetes 卷外掛常見問題解答

快照僅支援 CSI 驅動程式(不支援 in-tree 或 Flex)。要使用 Kubernetes 快照功能,請確保已在您的叢集上部署實現了快照的 CSI 驅動程式。

截至本部落格釋出時,以下 CSI 驅動程式支援快照:

對其他驅動程式的快照支援正在進行中,應該很快就會推出。閱讀“Kubernetes 容器儲存介面 (CSI) 進入 Beta 版”部落格文章,瞭解有關 CSI 以及如何部署 CSI 驅動程式的更多資訊。

Kubernetes 快照 API

與用於管理 Kubernetes 持久卷的 API 類似,Kubernetes 卷快照引入了三個新的 API 物件來管理快照:

  • VolumeSnapshot
    • 由 Kubernetes 使用者建立,用於請求為指定卷建立快照。它包含有關快照操作的資訊,例如快照拍攝的時間戳以及快照是否已準備好使用。
    • 類似於 PersistentVolumeClaim 物件,此物件的建立和刪除表示使用者希望建立或刪除叢集資源(快照)。
  • VolumeSnapshotContent
    • 快照成功建立後由 CSI 卷驅動程式建立。它包含有關快照的資訊,包括快照 ID。
    • 類似於 PersistentVolume 物件,此物件表示叢集上已置備的資源(快照)。
    • PersistentVolumeClaimPersistentVolume 物件一樣,快照建立後,VolumeSnapshotContent 物件會繫結到它所建立的 VolumeSnapshot(一對一對映)。
  • VolumeSnapshotClass
    • 由叢集管理員建立,用於描述應如何建立快照,包括驅動程式資訊、訪問快照的秘密等。

重要的是要注意,與核心 Kubernetes 持久卷物件不同,這些快照物件被定義為自定義資源定義 (CRD)。Kubernetes 專案正在從 API 伺服器中預定義資源型別的模式轉向 API 伺服器獨立於 API 物件的模型。這允許 API 伺服器被其他 Kubernetes 專案重用,並且使用者(如 Kubernetes)可以簡單地安裝他們所需的資源型別作為 CRD。

支援快照的CSI 驅動程式將自動安裝所需的 CRD。Kubernetes 終端使用者只需要驗證支援快照的 CSI 驅動程式已部署在其 Kubernetes 叢集上。

除了這些新物件之外,PersistentVolumeClaim 物件還添加了一個新的 DataSource 欄位:

type PersistentVolumeClaimSpec struct {
	AccessModes []PersistentVolumeAccessMode
	Selector *metav1.LabelSelector
	Resources ResourceRequirements
	VolumeName string
	StorageClassName *string
	VolumeMode *PersistentVolumeMode
	DataSource *TypedLocalObjectReference
}

這個新的 alpha 欄位允許建立新卷並自動使用現有快照中的資料進行預填充。

Kubernetes 快照要求

在使用 Kubernetes 卷快照之前,您必須:

  • 確保已在您的 Kubernetes 叢集上部署並執行實現了快照的 CSI 驅動程式。
  • 透過新的 Kubernetes 功能門啟用 Kubernetes 卷快照功能(alpha 版預設停用)
    • 在 API 伺服器二進位制檔案上設定以下標誌:--feature-gates=VolumeSnapshotDataSource=true

在建立快照之前,您還需要透過建立 VolumeSnapshotClass 物件並將 snapshotter 欄位設定為指向您的 CSI 驅動程式來指定快照的 CSI 驅動程式資訊。在下面的 VolumeSnapshotClass 示例中,CSI 驅動程式是 com.example.csi-driver。每個快照置備程式至少需要一個 VolumeSnapshotClass 物件。您還可以透過在類定義中添加註解 snapshot.storage.kubernetes.io/is-default-class: "true" 來為每個 CSI 驅動程式設定預設的 VolumeSnapshotClass

apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshotClass
metadata:
  name: default-snapclass
  annotations:
    snapshot.storage.kubernetes.io/is-default-class: "true"
snapshotter: com.example.csi-driver


apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshotClass
metadata:
  name: csi-snapclass
snapshotter: com.example.csi-driver
parameters:
  fakeSnapshotOption: foo
  csiSnapshotterSecretName: csi-secret
  csiSnapshotterSecretNamespace: csi-namespace

您必須根據 CSI 驅動程式的文件設定任何所需的透明引數。如上例所示,引數 fakeSnapshotOption: foo 和任何引用的秘密將在快照建立和刪除期間傳遞給 CSI 驅動程式。預設的 CSI 外部快照器保留引數鍵 csiSnapshotterSecretNamecsiSnapshotterSecretNamespace。如果指定,它會獲取秘密並在建立和刪除快照時將其傳遞給 CSI 驅動程式。

最後,在建立快照之前,您必須使用 CSI 驅動程式置備卷,並使用您要快照的一些資料填充它(有關如何建立和使用 CSI 卷,請參閱 CSI 部落格文章)。

使用 Kubernetes 建立新快照

定義 VolumeSnapshotClass 物件並擁有要快照的卷後,您可以透過建立 VolumeSnapshot 物件來建立新快照。

快照的源指定要從中建立快照的卷。它有兩個引數:

  • kind - 必須是 PersistentVolumeClaim
  • name - PVC API 物件的名稱

要快照的卷的名稱空間假定與 VolumeSnapshot 物件的名稱空間相同。

apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshot
metadata:
  name: new-snapshot-demo
  namespace: demo-namespace
spec:
  snapshotClassName: csi-snapclass
  source:
    name: mypvc
    kind: PersistentVolumeClaim

VolumeSnapshot 規範中,使用者可以指定 VolumeSnapshotClass,其中包含有關應使用哪個 CSI 驅動程式建立快照的資訊。當建立 VolumeSnapshot 物件時,引數 fakeSnapshotOption: fooVolumeSnapshotClass 中引用的任何秘密將透過 CreateSnapshot 呼叫傳遞給 CSI 外掛 com.example.csi-driver

作為響應,CSI 驅動程式會觸發卷快照,然後自動建立一個 VolumeSnapshotContent 物件來表示新快照,並將新的 VolumeSnapshotContent 物件繫結到 VolumeSnapshot,使其可供使用。如果 CSI 驅動程式未能建立快照並返回錯誤,快照控制器會在 VolumeSnapshot 物件的status中報告錯誤,並且不會重試(這與 Kubernetes 中的其他控制器不同,旨在防止快照在意外時間被拍攝)。

如果未指定快照類,則外部快照器將嘗試查詢併為快照設定預設快照類。預設快照類中由 snapshotter 指定的 CSI 驅動程式必須與 PVC 儲存類中由 provisioner 指定的 CSI 驅動程式匹配。

請注意,Kubernetes 快照的 alpha 版本不提供任何一致性保證。您必須在拍攝快照以確保資料一致性之前準備好應用程式(暫停應用程式、凍結檔案系統等)。

您可以透過執行 kubectl describe volumesnapshot 來驗證 VolumeSnapshot 物件是否已建立並與 VolumeSnapshotContent 繫結。

  • Ready 應該在 Status 下設定為 true,表示此卷快照已準備好使用。
  • Creation Time 欄位表示快照實際建立(剪下)的時間。
  • Restore Size 欄位表示從快照恢復卷時的最小卷大小。
  • spec 中的 Snapshot Content Name 欄位指向為此快照建立的 VolumeSnapshotContent 物件。

使用 Kubernetes 匯入現有快照

您始終可以透過手動建立 VolumeSnapshotContent 物件來表示現有快照,從而將現有快照匯入 Kubernetes。由於 VolumeSnapshotContent 是一個非名稱空間 API 物件,因此只有系統管理員才擁有建立它的許可權。建立 VolumeSnapshotContent 物件後,使用者可以建立指向 VolumeSnapshotContent 物件的 VolumeSnapshot 物件。外部快照器控制器將在驗證快照是否存在以及 VolumeSnapshotVolumeSnapshotContent 物件之間的繫結正確後將快照標記為就緒。繫結後,快照即可在 Kubernetes 中使用。

應使用以下欄位建立 VolumeSnapshotContent 物件以表示預置快照:

  • csiVolumeSnapshotSource - 快照識別資訊。
    • snapshotHandle - 快照的名稱/識別符號。此欄位是必需的。
    • driver - 用於處理此卷的 CSI 驅動程式。此欄位是必需的。它必須與快照控制器中的快照器名稱匹配。
    • creationTimerestoreSize - 這些欄位對於預置卷不是必需的。外部快照器控制器將在建立後自動更新它們。
  • volumeSnapshotRef - 指向此物件應繫結到的 VolumeSnapshot 物件的指標。
    • namenamespace - 它指定內容繫結到的 VolumeSnapshot 物件的名稱和名稱空間。
    • UID - 這些欄位對於預置卷不是必需的。外部快照器控制器將在繫結後自動更新該欄位。如果使用者指定 UID 欄位,他/她必須確保它與繫結快照的 UID 匹配。如果指定的 UID 與繫結快照的 UID 不匹配,則該內容被視為孤立物件,控制器將刪除它及其關聯的快照。
  • snapshotClassName - 此欄位是可選的。外部快照器控制器將在繫結後自動更新該欄位。
apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshotContent
metadata:
  name: static-snapshot-content
spec:
  csiVolumeSnapshotSource:
    driver: com.example.csi-driver
    snapshotHandle: snapshotcontent-example-id
  volumeSnapshotRef:
    kind: VolumeSnapshot
    name: static-snapshot-demo
    namespace: demo-namespace

應該建立一個 VolumeSnapshot 物件以允許使用者使用快照:

  • snapshotClassName - 卷快照類的名稱。此欄位是可選的。如果設定,快照類中的快照器欄位必須與快照控制器的快照器名稱匹配。如果未設定,快照控制器將嘗試查詢預設快照類。
  • snapshotContentName - 卷快照內容的名稱。此欄位對於預置卷是必需的。
apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshot
metadata:
  name: static-snapshot-demo
  namespace: demo-namespace
spec:
  snapshotClassName: csi-snapclass
  snapshotContentName: static-snapshot-content

建立這些物件後,快照控制器會將它們繫結在一起,並將 Ready 欄位(在 Status 下)設定為 True,表示快照已準備好使用。

使用 Kubernetes 從快照置備新卷

要置備從快照物件預填充資料的新卷,請使用 PersistentVolumeClaim 中的新 dataSource 欄位。它有三個引數:

  • name - 表示用作源快照的 VolumeSnapshot 物件的名稱
  • kind - 必須是 VolumeSnapshot
  • apiGroup - 必須是 snapshot.storage.k8s.io

VolumeSnapshot 物件的名稱空間假定與 PersistentVolumeClaim 物件的名稱空間相同。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-restore
  Namespace: demo-namespace
spec:
  storageClassName: csi-storageclass
  dataSource:
    name: new-snapshot-demo
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

建立 PersistentVolumeClaim 物件時,它將觸發新卷的置備,該卷預填充了指定快照中的資料。

作為儲存供應商,我如何將快照支援新增到我的 CSI 驅動程式?

要實現快照功能,CSI 驅動程式必須新增對附加控制器功能 CREATE_DELETE_SNAPSHOTLIST_SNAPSHOTS 的支援,並實現附加控制器 RPC:CreateSnapshotDeleteSnapshotListSnapshots。有關詳細資訊,請參閱 CSI 規範

儘管 Kubernetes 在 CSI 卷驅動程式的打包和部署方面儘量不進行規定,但它提供了一種建議機制,用於在 Kubernetes 上部署任意容器化 CSI 驅動程式,以簡化容器化 CSI 相容卷驅動程式的部署。

作為此推薦部署過程的一部分,Kubernetes 團隊提供了許多 sidecar(輔助)容器,包括一個新的 external-snapshotter sidecar 容器。

external-snapshotter 監視 Kubernetes API 伺服器中的 VolumeSnapshotVolumeSnapshotContent 物件,並觸發針對 CSI 端點的 CreateSnapshot 和 DeleteSnapshot 操作。CSI external-provisioner sidecar 容器也已更新,以支援使用新的 dataSource PVC 欄位從快照恢復卷。

為了支援快照功能,建議儲存供應商除了 external provisioner 和 external attacher 之外,還將其 CSI 驅動程式與 external-snapshotter sidecar 容器一起部署在有狀態集中,如下圖所示。

在此示例部署 yaml 檔案中,兩個 sidecar 容器(external provisioner 和 external snapshotter)以及 CSI 驅動程式與 hostpath CSI 外掛一起部署在有狀態集 pod 中。Hostpath CSI 外掛是一個示例外掛,不適用於生產環境。

Alpha 版本的侷限性是什麼?

Kubernetes 快照的 alpha 實現具有以下限制:

  • 不支援將現有卷恢復到快照表示的早期狀態(alpha 僅支援從快照置備新卷)。
  • 不支援從快照“就地恢復”現有 PersistentVolumeClaim:即從快照置備新卷,但更新現有 PersistentVolumeClaim 以指向新卷並有效地使 PVC 看起來恢復到早期狀態(alpha 僅支援透過新的 PV/PVC 使用從快照置備的新卷)。
  • 除了儲存系統提供的任何保證(例如崩潰一致性)之外,沒有快照一致性保證。

下一步是什麼?

根據反饋和採用情況,Kubernetes 團隊計劃在 1.13 或 1.14 中將 CSI 快照實現推向 beta 版。

我如何瞭解更多資訊?

在此處檢視有關快照功能的其他文件:http://k8s.io/docs/concepts/storage/volume-snapshotshttps://kubernetes-csi.github.io/docs/

我如何參與?

這個專案,和所有 Kubernetes 專案一樣,是許多來自不同背景的貢獻者共同努力的結果。

除了為快照功能做出貢獻的貢獻者之外:

我們衷心感謝 Kubernetes 儲存 SIG 和 CSI 社群的所有貢獻者,他們幫助審查了專案的設計和實施,包括但不限於以下人員:

如果您有興趣參與 CSI 或 Kubernetes 儲存系統的任何部分的設計和開發,請加入 Kubernetes 儲存特別興趣小組 (SIG)。我們正在迅速發展,並始終歡迎新的貢獻者。