本文釋出已超過一年。較早的文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已不正確。

Kubernetes 1.17 功能:Kubernetes 卷快照升至 Beta 版

Kubernetes 卷快照功能現已在 Kubernetes v1.17 中進入 Beta 階段。它在 Kubernetes v1.12 中作為 Alpha 版 引入,並在 Kubernetes v1.13 中釋出了包含重大更改的 第二個 Alpha 版。本文總結了 Beta 版中的更改。

什麼是卷快照?

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

為什麼要將卷快照新增到 Kubernetes?

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

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

Kubernetes Storage SIG 認為快照操作是許多有狀態工作負載的關鍵功能。例如,資料庫管理員可能希望在啟動資料庫操作之前對資料庫捲進行快照。

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

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

此外,這些 Kubernetes 快照原語充當了基本構建塊,可以開發用於 Kubernetes 的高階企業級儲存管理功能:包括應用程式或叢集級別的備份解決方案。

Beta 版中的新功能是什麼?

隨著卷快照升級到 Beta 版,該功能現在預設在標準 Kubernetes 部署中啟用,而不是選擇加入。

Kubernetes 卷快照功能升級到 Beta 版還意味著:

  • 卷快照 API 的改版。
  • CSI external-snapshotter sidecar 被拆分為兩個控制器,一個通用快照控制器和一個 CSI external-snapshotter sidecar。
  • 刪除 Secret 作為註解新增到卷快照內容中。
  • 一個新終結器被新增到卷快照 API 物件中,以防止它在繫結到卷快照內容 API 物件時被刪除。

Kubernetes 卷快照要求

如上所述,隨著卷快照升級到 Beta 版,該功能現在預設在標準 Kubernetes 部署中啟用,而不是選擇加入。

為了使用 Kubernetes 卷快照功能,您必須確保已在 Kubernetes 叢集上部署以下元件:

有關詳細資訊,請參閱下面的部署部分。

哪些驅動程式支援 Kubernetes 卷快照?

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

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

閱讀“Kubernetes 的容器儲存介面 (CSI) GA”部落格文章,瞭解有關 CSI 以及如何部署 CSI 驅動程式的更多資訊。

截至本部落格釋出時,以下 CSI 驅動程式已更新以支援卷快照 Beta 版:

其他 CSI 驅動程式 的 Beta 級卷快照支援即將推出,應該很快就會可用。

Kubernetes 卷快照 Beta API

在 Kubernetes 卷快照 API 的 Alpha 版到 Beta 版之間進行了多項更改。這些更改不向後相容。這些更改的目的是使 API 定義更清晰、更易於使用。

進行了以下更改:

  • `DeletionPolicy` 現在是 `VolumeSnapshotClass` 和 `VolumeSnapshotContent` 中的必需欄位,而不是可選欄位。這樣使用者必須明確指定它,避免混淆。
  • `VolumeSnapshotSpec` 有一個新的必需 `Source` 欄位。`Source` 可以是 `PersistentVolumeClaimName`(如果動態供應快照)或 `VolumeSnapshotContentName`(如果預供應快照)。
  • `VolumeSnapshotContentSpec` 也有一個新的必需 `Source` 欄位。此 `Source` 可以是 `VolumeHandle`(如果動態供應快照)或 `SnapshotHandle`(如果預供應卷快照)。
  • `VolumeSnapshotStatus` 現在包含 `BoundVolumeSnapshotContentName`,表示 `VolumeSnapshot` 物件繫結到 `VolumeSnapshotContent`。
  • `VolumeSnapshotContent` 現在包含 `Status`,表示內容的當前狀態。它有一個 `SnapshotHandle` 欄位,表示 `VolumeSnapshotContent` 代表儲存系統上的快照。

Beta 版 Kubernetes VolumeSnapshot API 物件

type VolumeSnapshot struct {
        metav1.TypeMeta
        metav1.ObjectMeta

        Spec VolumeSnapshotSpec
        Status *VolumeSnapshotStatus
}
type VolumeSnapshotSpec struct {
	Source VolumeSnapshotSource
	VolumeSnapshotClassName *string
}
// Exactly one of its members MUST be specified
type VolumeSnapshotSource struct {
	// +optional
	PersistentVolumeClaimName *string
	// +optional
	VolumeSnapshotContentName *string
}
type VolumeSnapshotStatus struct {
	BoundVolumeSnapshotContentName *string
	CreationTime *metav1.Time
	ReadyToUse *bool
	RestoreSize *resource.Quantity
	Error *VolumeSnapshotError
}

Beta 版 Kubernetes VolumeSnapshotContent API 物件

type VolumeSnapshotContent struct {
        metav1.TypeMeta
        metav1.ObjectMeta

        Spec VolumeSnapshotContentSpec
        Status *VolumeSnapshotContentStatus
}
type VolumeSnapshotContentSpec struct {
         VolumeSnapshotRef core_v1.ObjectReference
         Source VolumeSnapshotContentSource
         DeletionPolicy DeletionPolicy
         Driver string
         VolumeSnapshotClassName *string
}
type VolumeSnapshotContentSource struct {
	// +optional
	VolumeHandle *string
	// +optional
	SnapshotHandle *string
}
type VolumeSnapshotContentStatus struct {
  CreationTime *int64
  ReadyToUse *bool
  RestoreSize *int64
  Error *VolumeSnapshotError
  SnapshotHandle *string
}

Beta 版 Kubernetes VolumeSnapshotClass API 物件

type VolumeSnapshotClass struct {
        metav1.TypeMeta
        metav1.ObjectMeta

        Driver string
        Parameters map[string]string
        DeletionPolicy DeletionPolicy
}

如何在 Kubernetes 叢集上部署卷快照支援?

請注意,卷快照功能現在除了卷快照 CRD 之外,還依賴於一個新的通用卷快照控制器。卷快照控制器和 CRD 都獨立於任何 CSI 驅動程式。無論叢集上部署了多少 CSI 驅動程式,每個叢集都必須只有一個卷快照控制器例項執行,並且安裝一組卷快照 CRD。

因此,強烈建議 Kubernetes 分發商將其 Kubernetes 叢集管理過程的一部分(獨立於任何 CSI 驅動程式)捆綁和部署控制器和 CRD。

如果您的叢集沒有預裝正確的元件,您可以按照以下步驟手動安裝這些元件。

安裝快照 Beta CRD

安裝通用快照控制器

安裝 CSI 驅動程式

請遵循 CSI 驅動程式供應商提供的說明。

如何使用 Kubernetes 卷快照?

假設所有必需元件(包括 CSI 驅動程式)都已部署並在叢集上執行,您可以使用 VolumeSnapshot API 物件建立卷快照,並透過在 PVC 上指定 VolumeSnapshot 資料來源來恢復它們。

使用 Kubernetes 建立新卷快照

您可以透過建立指向支援卷快照的 CSI 驅動程式的 VolumeSnapshotClass API 物件,在 Kubernetes 叢集中啟用卷快照的建立/刪除。

例如,以下 VolumeSnapshotClass 告訴 Kubernetes 叢集,一個 CSI 驅動程式 `testdriver.csi.k8s.io` 可以處理卷快照,並且當這些快照被建立時,它們的刪除策略應該是刪除。

apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshotClass
metadata:
  name: test-snapclass
driver: testdriver.csi.k8s.io
deletionPolicy: Delete
parameters:
  csi.storage.k8s.io/snapshotter-secret-name: mysecret
  csi.storage.k8s.io/snapshotter-secret-namespace: mysecretnamespace

通用快照控制器保留引數鍵 `csi.storage.k8s.io/snapshotter-secret-name` 和 `csi.storage.k8s.io/snapshotter-secret-namespace`。如果指定,它將獲取引用的 Kubernetes secret 並將其設定為卷快照內容物件上的註解。CSI external-snapshotter sidecar 從內容註解中檢索它,並在快照建立期間將其傳遞給 CSI 驅動程式。

透過建立 VolumeSnapshot API 物件觸發卷快照的建立。

VolumeSnapshot 物件必須指定以下源型別:`persistentVolumeClaimName` - 要快照的 PVC 的名稱。請注意,VolumeSnapshot 物件的源 PVC、PV 和 VolumeSnapshotClass 必須指向相同的 CSI 驅動程式。

例如,以下 VolumeSnapshot 使用上面的 VolumeSnapshotClass 觸發為名為 `test-pvc` 的 PVC 建立快照。

apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshot
metadata:
  name: test-snapshot
spec:
  volumeSnapshotClassName: test-snapclass
  source:
    persistentVolumeClaimName: test-pvc

當呼叫卷快照建立時,通用快照控制器首先建立一個 VolumeSnapshotContent 物件,其中包含 `volumeSnapshotRef`、源 `volumeHandle`、如果指定了 `volumeSnapshotClassName`、`driver` 和 `deletionPolicy`。

CSI external-snapshotter sidecar 隨後透過 CSI `CreateSnapshot` 呼叫將 VolumeSnapshotClass 引數、源卷 ID 和任何引用的 secret 傳遞給 CSI 驅動程式(在本例中為 `testdriver.csi.k8s.io`)。作為響應,CSI 驅動程式為指定卷建立一個新快照,並返回該快照的 ID。CSI external-snapshotter sidecar 隨後更新代表新快照的 VolumeSnapshotContent 物件的 status 欄位中的 `snapshotHandle`、`creationTime`、`restoreSize` 和 `readyToUse`。對於需要上傳快照(已剪下)的儲存系統,CSI external-snapshotter sidecar 將繼續呼叫 CSI `CreateSnapshot` 以檢查狀態,直到上傳完成並將 `readyToUse` 設定為 true。

通用快照控制器將 VolumeSnapshotContent 物件繫結到 VolumeSnapshot(設定 `BoundVolumeSnapshotContentName`),並根據 VolumeSnapshotContent 物件的 status 欄位更新 VolumeSnapshot 物件的 status 欄位中的 `creationTime`、`restoreSize` 和 `readyToUse`。

如果未指定 `volumeSnapshotClassName`,則自動選擇如下:

從源卷的 PVC 或 PV 中獲取 `StorageClass`。如果可用,則獲取預設 VolumeSnapshotClass。預設 VolumeSnapshotClass 是管理員使用 `snapshot.storage.kubernetes.io/is-default-class` 註解建立的快照類。如果預設 VolumeSnapshotClass 的 `Driver` 欄位與 StorageClass 中的 `Provisioner` 欄位相同,則使用預設 VolumeSnapshotClass。如果沒有預設 VolumeSnapshotClass 或快照有多個預設 VolumeSnapshotClass,則返回錯誤。

請注意,Kubernetes 快照 API 不提供任何一致性保證。您必須手動或使用其他更高級別的 API/控制器在拍攝快照之前準備您的應用程式(暫停應用程式、凍結檔案系統等),以實現資料一致性。

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

`Bound Volume Snapshot Content Name` - `Status` 欄位中的欄位表示卷繫結到指定的 VolumeSnapshotContent。`Ready To Use` - `Status` 欄位中的欄位表示此卷快照已準備好使用。`Creation Time` - `Status` 欄位中的欄位表示快照實際建立(剪下)的時間。`Restore Size` - `Status` 欄位中的欄位表示從該快照恢復卷時所需的最小卷大小。

Name:         test-snapshot
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  snapshot.storage.k8s.io/v1beta1
Kind:         VolumeSnapshot
Metadata:
  Creation Timestamp:  2019-11-16T00:36:04Z
  Finalizers:
    snapshot.storage.kubernetes.io/volumesnapshot-as-source-protection
    snapshot.storage.kubernetes.io/volumesnapshot-bound-protection
  Generation:        1
  Resource Version:  1294
  Self Link:         /apis/snapshot.storage.k8s.io/v1beta1/namespaces/default/volumesnapshots/new-snapshot-demo
  UID:               32ceaa2a-3802-4edd-a808-58c4f1bd7869
Spec:
  Source:
    Persistent Volume Claim Name:  test-pvc
  Volume Snapshot Class Name:      test-snapclass
Status:
  Bound Volume Snapshot Content Name:  snapcontent-32ceaa2a-3802-4edd-a808-58c4f1bd7869
  Creation Time:                       2019-11-16T00:36:04Z
  Ready To Use:                        true
  Restore Size:                        1Gi

提醒所有使用卷快照 API 構建控制器的開發人員:在使用 VolumeSnapshot API 物件之前,驗證 VolumeSnapshot 和它所繫結到的 VolumeSnapshotContent 之間的雙向繫結,以確保繫結是完整且正確的(不這樣做可能會導致安全問題)。

kubectl describe volumesnapshotcontent
Name:         snapcontent-32ceaa2a-3802-4edd-a808-58c4f1bd7869
Namespace:
Labels:       <none>
Annotations:  <none>
API Version:  snapshot.storage.k8s.io/v1beta1
Kind:         VolumeSnapshotContent
Metadata:
  Creation Timestamp:  2019-11-16T00:36:04Z
  Finalizers:
    snapshot.storage.kubernetes.io/volumesnapshotcontent-bound-protection
  Generation:        1
  Resource Version:  1292
  Self Link:         /apis/snapshot.storage.k8s.io/v1beta1/volumesnapshotcontents/snapcontent-32ceaa2a-3802-4edd-a808-58c4f1bd7869
  UID:               7dfdf22e-0b0c-4b71-9ddf-2f1612ca2aed
Spec:
  Deletion Policy:  Delete
  Driver:           testdriver.csi.k8s.io
  Source:
    Volume Handle:             d1b34a5f-0808-11ea-808a-0242ac110003
  Volume Snapshot Class Name:  test-snapclass
  Volume Snapshot Ref:
    API Version:       snapshot.storage.k8s.io/v1beta1
    Kind:              VolumeSnapshot
    Name:              test-snapshot
    Namespace:         default
    Resource Version:  1286
    UID:               32ceaa2a-3802-4edd-a808-58c4f1bd7869
Status:
  Creation Time:    1573864564608810101
  Ready To Use:     true
  Restore Size:     1073741824
  Snapshot Handle:  127c5798-0809-11ea-808a-0242ac110003
Events:             <none>

在 Kubernetes 中匯入現有卷快照

您始終可以透過手動建立 VolumeSnapshotContent 物件來表示現有卷快照,從而在 Kubernetes 中公開預先存在的卷快照。由於 VolumeSnapshotContent 是一個非名稱空間 API 物件,因此只有叢集管理員才可能擁有建立它的許可權。透過指定 volumeSnapshotRef,叢集管理員可以精確指定哪些使用者可以使用該快照。

例如,以下 VolumeSnapshotContent 公開了一個名為 7bdd0de3-aaeb-11e8-9aae-0242ac110002 的卷快照,它屬於一個名為 testdriver.csi.k8s.io 的 CSI 驅動。

叢集管理員應建立具有以下欄位的 VolumeSnapshotContent 物件,以表示現有快照:

  • driver - 用於處理此卷的 CSI 驅動。此欄位為必填項。
  • source - 快照識別資訊
  • snapshotHandle - 快照的名稱/識別符號。此欄位為必填項。
  • volumeSnapshotRef - 指向此內容應繫結到的 VolumeSnapshot 物件的指標。
  • namenamespace - 指定內容繫結到的 VolumeSnapshot 物件的名稱和名稱空間。
  • deletionPolicy - 有效值為 DeleteRetain。如果 deletionPolicyDelete,則底層儲存快照將與 VolumeSnapshotContent 物件一起刪除。如果 deletionPolicyRetain,則底層快照和 VolumeSnapshotContent 都將保留。
apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshotContent
metadata:
  name: manually-created-snapshot-content
spec:
  deletionPolicy: Delete
  driver: testdriver.csi.k8s.io
  source:
    snapshotHandle: 7bdd0de3-aaeb-11e8-9aae-0242ac110002
  volumeSnapshotRef:
    name: test-snapshot
    namespace: default

建立 VolumeSnapshotContent 物件後,使用者可以建立一個指向 VolumeSnapshotContent 物件的 VolumeSnapshot 物件。VolumeSnapshot 物件的名稱和名稱空間必須與 VolumeSnapshotContent 的 volumeSnapshotRef 中指定的名稱/名稱空間匹配。它指定以下欄位:volumeSnapshotContentName - 上述卷快照內容的名稱。此欄位為必填項。volumeSnapshotClassName - 卷快照類的名稱。此欄位為可選。

apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshot
metadata:
  name: manually-created-snapshot
spec:
  source:
        volumeSnapshotContentName: test-content

建立這兩個物件後,通用快照控制器會驗證 VolumeSnapshot 和 VolumeSnapshotContent 物件之間的繫結是否正確,並將 VolumeSnapshot 標記為就緒(如果 CSI 驅動支援 ListSnapshots 呼叫,控制器還會驗證引用的快照是否存在)。CSI external-snapshotter Sidecar 會檢查快照是否存在(如果實現了 ListSnapshots CSI 方法),否則它會假定快照存在。external-snapshotter Sidecar 將 VolumeSnapshotContent 的 status 欄位中的 readyToUse 設定為 true。通用快照控制器相應地將快照標記為就緒。

從快照建立卷

一旦您擁有一個已繫結且就緒的 VolumeSnapshot 物件,您就可以使用該物件來預配一個新卷,該新卷預先填充了來自快照的資料。

要預配一個預先填充了來自快照資料的新卷,請使用 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: testdriver.csi.k8s.io
  dataSource:
    name: manually-created-snapshot
    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 卷驅動程式的打包和部署儘可能少地進行規定,但它提供了一種建議的機制,用於在 Kubernetes 上部署任意容器化的 CSI 驅動程式,以簡化容器化 CSI 相容卷驅動程式的部署。

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

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

為了支援快照功能,建議儲存供應商除了 external provisioner 之外,還部署 external-snapshotter Sidecar 容器以及他們的 CSI 驅動程式。

Beta 版本的限制是什麼?

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

  • 不支援將現有卷恢復到快照所表示的早期狀態(Beta 版本僅支援從快照預配新卷)。
  • 除了儲存系統提供的任何保證(例如崩潰一致性)之外,沒有快照一致性保證。這些是更高級別 API/控制器的責任。

下一步是什麼?

根據反饋和採用情況,Kubernetes 團隊計劃在 1.18 或 1.19 版本中將 CSI 快照實現推向 GA。我們感興趣支援的一些功能包括一致性組、應用程式一致性快照、工作負載暫停、就地恢復、卷備份等等。

我如何瞭解更多資訊?

您還可以檢視 external-snapshotter 原始碼倉庫

請查閱 此處此處 有關快照功能的更多文件。

我如何參與?

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

我們非常感謝在過去幾個季度裡挺身而出,幫助專案達到 Beta 版本的貢獻者:

  • Xing Yang (xing-yang)
  • Xiangqian Yu (yuxiangqian)
  • Jing Xu (jingxu97)
  • Grant Griffiths (ggriffiths)
  • Can Zhu (zhucan)

特別感謝以下人員對設計進行了富有洞察力的評審和周密的考慮:

  • Michelle Au (msau42)
  • Saad Ali (saadali)
  • Patrick Ohly (pohly)
  • Tim Hockin (thockin)
  • Jordan Liggitt (liggitt)。

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

我們還定期舉行 SIG-Storage 快照工作組會議。歡迎新成員加入設計和開發討論。