具有存儲容量追蹤的臨時卷:類固醇上的 EmptyDir

具有存儲容量追蹤的臨時卷:類固醇上的 EmptyDir

有些應用程式也需要儲存數據,但他們對重啟後不會保存數據這一事實感到非常滿意。

例如,快取服務受到 RAM 的限制,但也可以將很少使用的資料移動到比 RAM 慢的儲存中,對整體效能影響很小。 其他應用程式需要注意文件中可能存在一些唯讀輸入,例如設定或金鑰。

Kubernetes 已經有幾種類型 短暫的捲,但它們的功能僅限於 K8s 中實現的功能。

短暫的 CSI 卷 允許使用 CSI 驅動程式擴充 Kubernetes,以提供對輕量級本機磁碟區的支援。 這樣就可以使用 任意結構:設定、秘密、識別資料、變數等。 必須修改 CSI 驅動程式才能支援此 Kubernetes 功能,因為假定常規標準化驅動程式將無法運作 - 但假定此類磁碟區可以在為 pod 選擇的任何節點上使用。

對於消耗大量主機資源的磁碟區或僅在某些主機上可用的儲存空間來說,這可能是一個問題。 這就是為什麼 Kubernetes 1.19 引入了兩個新的 alpha 測試卷功能,它們在概念上類似於 EmptyDir 卷:

  • 通用臨時卷;

  • CSI 儲存容量追蹤。

新方法的優點:

  • 儲存可以是本地的或透過網路連接的;

  • 卷可以具有應用程式不能超過的指定大小;

  • 與任何支援持久性磁碟區配置並(支援容量追蹤)實作呼叫的 CSI 驅動程式配合使用 GetCapacity;

  • 卷可能有一些初始數據,具體取決於驅動程式和設定;

  • 支援磁碟區的所有標準操作(建立快照、調整大小等);

  • 磁碟區可以與任何接受模組或磁碟區規範的應用程式控制器一起使用;

  • Kubernetes 排程器會自行選擇適當的節點,因此不再需要預配和設定排程器擴充或修改 Webhooks。

應用選項

因此,通用臨時磁碟區適用於以下用例:

持久記憶體作為 memcached RAM 的替代品

memcached 的最新版本 增加了支持 使用持久記憶體(Intel Optane等, 約譯員)而不是常規 RAM。 透過應用程式控制器部署 memcached 時,您可以使用通用臨時磁碟區來要求使用 CSI 驅動程式從 PMEM 指派給定大小的捲,例如 PMEM-CSI.

LVM 本地儲存作為工作區

處理大於 RAM 的資料的應用程式可能需要具有 Kubernetes 的常規 EmptyDir 磁碟區無法提供的大小或效能指標的本機儲存。 例如,為了這個目的,寫了 拓樸LVM.

資料卷的唯讀訪問

在以下情況下,分配磁碟區可能會導致建立完整磁碟區:

這些磁碟區可以以唯讀模式安裝。

Какэтоработает

通用臨時卷

通用臨時磁碟區的一個關鍵特徵是新的磁碟區來源, EphemeralVolumeSource,包含建立磁碟區請求(歷史上稱為持久性磁碟區請求,PVC)的所有欄位。 新控制器在 kube-controller-manager 查看建立此類磁碟區來源的 pod,然後為這些 pod 建立 PVC。 對於 CSI 驅動程序,此請求看起來與其他請求相同,因此這裡不需要特殊支援。

只要此類 P​​VC 存在,就可以像磁碟區上的任何其他請求一樣使用它們。 特別是,在複製磁碟區或從磁碟區建立快照時,它們可以被引用為資料來源。 PVC 物件也包含磁碟區的目前狀態。

自動建立的 PVC 的名稱是預先定義的:它們是 pod 名稱和磁碟區名稱的組合,並以連字號分隔。 預先定義的名稱使與 PVC 的互動變得更加容易,因為如果您知道 pod 名稱和磁碟區名稱,則無需查找它。 缺點是該名稱可能已被使用,這是由 Kubernetes 檢測到的,因此 pod 無法啟動。

為了確保磁碟區與 Pod 一起刪除,控制器會向擁有者下的磁碟區發出請求。 當 Pod 被刪除時,標準垃圾收集機制就會起作用,它會刪除請求和磁碟區。

儲存驅動程式透過儲存類別的正常機制來匹配請求。 儘管具有立即綁定和後期綁定的類別(又名 WaitForFirstConsumer)受支持,對於臨時卷,使用它是有意義的 WaitForFirstConsumer,那麼調度器在選擇節點時可以同時考慮節點使用情況和儲存可用性。 這裡出現了一個新功能。

儲存容量追蹤

通常,調度程式不知道 CSI 驅動程式將在何處建立磁碟區。 調度程式也無法直接聯繫驅動程式來請求此資訊。 因此,調度程式會輪詢節點,直到找到可以存取磁碟區的節點(後期綁定)或將位置選擇完全留給驅動程式(立即綁定)。

API CSIStorageCapacity處於 alpha 階段,允許將必要的資料儲存在 etcd 中,以便調度程序可用。 與通用臨時磁碟區的支援不同,部署驅動程式時,必須啟用儲存容量追蹤: external-provisioner 應透過正常方式發布從驅動程式收到的容量訊息 GetCapacity.

如果調度程式需要為具有使用後期綁定的未綁定磁碟區的 pod 選擇節點,並且驅動程式在部署期間透過設定標誌啟用了此功能 CSIDriver.storageCapacity,那麼沒有足夠儲存容量的節點將自動丟棄。 這適用於通用臨時捲和持久卷,但不適用於 CSI 臨時卷,因為 Kubernetes 無法讀取它們的參數。

與往常一樣,立即連結的捲是在調度 Pod 之前創建的,並且它們的位置由儲存驅動程式選擇,因此在配置時 external-provisioner 預設情況下,會跳過具有立即綁定的儲存類,因為無論如何都不會使用此資料。

由於 kubernetes 調度程序被迫使用可能過時的信息,因此無法保證在創建卷時在每種情況下容量都可用,但在不重試的情況下創建卷的可能性仍然會增加。

注: 您可以獲得更詳細的信息,以及安全地“貓站練習”,並且在完全無法理解的情況下,在強化課程中獲得合格的技術支持幫助 - Kubernetes 基地 將於 28 月 30 日至 XNUMX 日舉行,對於更高級的專家 Kubernetes Mega 14 月 16 日至 XNUMX 日。

安全

CSI儲存容量

CSIStorageCapacity 物件駐留在命名空間中;在其自己的命名空間中推出每個 CSI 驅動程式時,建議限制對該空間中的 CSIStorageCapacity 的 RBAC 權限,因為資料的來源顯而易見。 無論如何,Kubernetes 不會檢查這一點,通常驅動程式會放在同一個命名空間中,因此最終驅動程式應該能夠工作並且不會發布錯誤的資料(這就是我的卡失敗的地方, 約。 譯者根據一個大鬍子笑話改編)

通用臨時卷

如果使用者有權(直接或間接)建立 pod,那麼即使他們無權在磁碟區上建立請求,他們也將能夠建立通用臨時磁碟區。 這是因為 RBAC 權限檢查會套用於建立 PVC 的控制器,而不是使用者。 這是要添加的主要更改 到您的帳戶,然後在叢集上啟用此功能,其中不受信任的使用者不應有權建立磁碟區。

例子

分離 PMEM-CSI 包含在 QEMU 虛擬機器內執行 Kubernetes 1.19 叢集所需的所有更改,並具有 alpha 階段的所有功能。 驅動程式程式碼沒有改變,只是部署發生了變化。

在合適的機器上(Linux,普通用戶可以使用 碼頭工人, 看 這裡 詳細資訊)這些命令將啟動叢集並安裝 PMEM-CSI 驅動程式:

git clone --branch=kubernetes-1-19-blog-post https://github.com/intel/pmem-csi.git
cd pmem-csi
export TEST_KUBERNETES_VERSION=1.19 TEST_FEATURE_GATES=CSIStorageCapacity=true,GenericEphemeralVolume=true TEST_PMEM_REGISTRY=intel
make start && echo && test/setup-deployment.sh

一切正常後,輸出將包含使用說明:

The test cluster is ready. Log in with [...]/pmem-csi/_work/pmem-govm/ssh.0, run
kubectl once logged in.  Alternatively, use kubectl directly with the
following env variable:
   KUBECONFIG=[...]/pmem-csi/_work/pmem-govm/kube.config

secret/pmem-csi-registry-secrets created
secret/pmem-csi-node-secrets created
serviceaccount/pmem-csi-controller created
...
To try out the pmem-csi driver ephemeral volumes:
   cat deploy/kubernetes-1.19/pmem-app-ephemeral.yaml |
   [...]/pmem-csi/_work/pmem-govm/ssh.0 kubectl create -f -

CSIStorageCapacity 物件不適合人類讀取,因此需要進行一些處理。 Golang 範本過濾器將顯示儲存類別,此範例將顯示名稱、拓撲和容量:

$ kubectl get 
        -o go-template='{{range .items}}{{if eq .storageClassName "pmem-csi-sc-late-binding"}}{{.metadata.name}} {{.nodeTopology.matchLabels}} {{.capacity}}
{{end}}{{end}}' 
        csistoragecapacities
csisc-2js6n map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker2] 30716Mi
csisc-sqdnt map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker1] 30716Mi
csisc-ws4bv map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker3] 30716Mi

單一物件具有以下內容:

$ kubectl describe csistoragecapacities/csisc-6cw8j
Name:         csisc-sqdnt
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  storage.k8s.io/v1alpha1
Capacity:     30716Mi
Kind:         CSIStorageCapacity
Metadata:
  Creation Timestamp:  2020-08-11T15:41:03Z
  Generate Name:       csisc-
  Managed Fields:
    ...
  Owner References:
    API Version:     apps/v1
    Controller:      true
    Kind:            StatefulSet
    Name:            pmem-csi-controller
    UID:             590237f9-1eb4-4208-b37b-5f7eab4597d1
  Resource Version:  2994
  Self Link:         /apis/storage.k8s.io/v1alpha1/namespaces/default/csistoragecapacities/csisc-sqdnt
  UID:               da36215b-3b9d-404a-a4c7-3f1c3502ab13
Node Topology:
  Match Labels:
    pmem-csi.intel.com/node:  pmem-csi-pmem-govm-worker1
Storage Class Name:           pmem-csi-sc-late-binding
Events:                       <none>

讓我們嘗試建立一個具有單一通用臨時磁碟區的示範應用程式。 文件內容 pmem-app-ephemeral.yaml:

# This example Pod definition demonstrates
# how to use generic ephemeral inline volumes
# with a PMEM-CSI storage class.
kind: Pod
apiVersion: v1
metadata:
  name: my-csi-app-inline-volume
spec:
  containers:
    - name: my-frontend
      image: intel/pmem-csi-driver-test:v0.7.14
      command: [ "sleep", "100000" ]
      volumeMounts:
      - mountPath: "/data"
        name: my-csi-volume
  volumes:
  - name: my-csi-volume
    ephemeral:
      volumeClaimTemplate:
        spec:
          accessModes:
          - ReadWriteOnce
          resources:
            requests:
              storage: 4Gi
          storageClassName: pmem-csi-sc-late-binding

創建完成後,如上面的說明所示,我們現在有了一個額外的 pod 和 PVC:

$ kubectl get pods/my-csi-app-inline-volume -o wide
NAME                       READY   STATUS    RESTARTS   AGE     IP          NODE                         NOMINATED NODE   READINESS GATES
my-csi-app-inline-volume   1/1     Running   0          6m58s   10.36.0.2   pmem-csi-pmem-govm-worker1   <none>           <none>
$ kubectl get pvc/my-csi-app-inline-volume-my-csi-volume
NAME                                     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS               AGE
my-csi-app-inline-volume-my-csi-volume   Bound    pvc-c11eb7ab-a4fa-46fe-b515-b366be908823   4Gi        RWO            pmem-csi-sc-late-binding   9m21s

PVC 擁有者 - 下:

$ kubectl get -o yaml pvc/my-csi-app-inline-volume-my-csi-volume
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  annotations:
    pv.kubernetes.io/bind-completed: "yes"
    pv.kubernetes.io/bound-by-controller: "yes"
    volume.beta.kubernetes.io/storage-provisioner: pmem-csi.intel.com
    volume.kubernetes.io/selected-node: pmem-csi-pmem-govm-worker1
  creationTimestamp: "2020-08-11T15:44:57Z"
  finalizers:
  - kubernetes.io/pvc-protection
  managedFields:
    ...
  name: my-csi-app-inline-volume-my-csi-volume
  namespace: default
  ownerReferences:
  - apiVersion: v1
    blockOwnerDeletion: true
    controller: true
    kind: Pod
    name: my-csi-app-inline-volume
    uid: 75c925bf-ca8e-441a-ac67-f190b7a2265f
...

預計更新資訊為 pmem-csi-pmem-govm-worker1:

csisc-2js6n map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker2] 30716Mi
csisc-sqdnt map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker1] 26620Mi
csisc-ws4bv map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker3] 30716Mi

如果另一個應用程式需要超過26620Mi,調度程式將不會考慮 pmem-csi-pmem-govm-worker1 任何狀況之下。

接下來是什麼?

這兩個功能仍在開發中。 在 alpha 測試期間開啟了多個應用程式。 改進提案連結記錄了進入測試階段需要完成的工作,以及已經考慮和拒絕的替代方案:

來源: www.habr.com

添加評論