友快網

導航選單

【一文讀懂】k8s程式碼與三方儲存廠商的程式碼強耦合:更改儲存程式碼

導讀:在《一文讀懂 K8s 持久化儲存流程》一文我們重點介紹了 K8s 內部的儲存流程,以及 PV、PVC、StorageClass、Kubelet 等之間的呼叫關係。接下來本文將將重點放在 CSI(Container Storage Interface)容器儲存介面上,探究什麼是 CSI 及其內部工作原理。

背景

K8s 原生支援一些儲存型別的 PV,如 iSCSI、NFS、CephFS 等等(詳見連結),這些 in-tree 型別的儲存程式碼放在 Kubernetes 程式碼倉庫中。這裡帶來的問題是 K8s 程式碼與三方儲存廠商的程式碼強耦合:

更改 in-tree 型別的儲存程式碼,使用者必須更新 K8s 元件,成本較高

in-tree 儲存程式碼中的 bug 會引發 K8s 元件不穩定

K8s 社群需要負責維護及測試 in-tree 型別的儲存功能

in-tree 儲存外掛享有與 K8s 核心元件同等的特權,存在安全隱患

三方儲存開發者必須遵循 K8s 社群的規則開發 in-tree 型別儲存程式碼

CSI 容器儲存介面標準的出現解決了上述問題,將三方儲存程式碼與 K8s 程式碼解耦,使得三方儲存廠商研發人員只需實現 CSI 介面(無需關注容器平臺是 K8s 還是 Swarm 等)。

CSI 核心流程介紹

在詳細介紹 CSI 元件及其介面之前,我們先對 K8s 中 CSI 儲存流程進行一個介紹。《一文讀懂 K8s 持久化儲存流程》一文介紹了 K8s 中的 Pod 在掛載儲存卷時需經歷三個的階段:Provision/Delete(創盤/刪盤)、Attach/Detach(掛接/摘除)和 Mount/Unmount(掛載/解除安裝),下面以圖文的方式講解 K8s 在這三個階段使用 CSI 的流程。

1。 Provisioning Volumes

1。叢集管理員建立 StorageClass 資源,該 StorageClass 中包含 CSI 外掛名稱(provisioner:pangu。csi。alibabacloud。com)以及儲存類必須的引數(parameters: type=cloud_ssd)。sc。yaml 檔案如下:

2。使用者建立 PersistentVolumeClaim 資源,PVC 指定儲存大小及 StorageClass(如上)。pvc。yaml 檔案如下:

3。卷控制器(PersistentVolumeController)觀察到叢集中新建立的 PVC 沒有與之匹配的 PV,且其使用的儲存型別為 out-of-tree,於是為 PVC 打 annotation:volume。beta。kubernetes。io/storage-provisioner=[out-of-tree CSI 外掛名稱](本例中即為 provisioner:pangu。csi。alibabacloud。com)。

4。External Provisioner 元件觀察到 PVC 的 annotation 中包含 “volume。beta。kubernetes。io/storage-provisioner” 且其 value 是自己,於是開始創盤流程。

獲取相關 StorageClass 資源並從中獲取引數(本例中 parameters 為 type=cloud_ssd),用於後面 CSI 函式呼叫。

透過 unix domain socket 呼叫外部 CSI 外掛的CreateVolume 函式。

5。外部 CSI 外掛返回成功後表示盤建立完成,此時External Provisioner 元件會在叢集建立一個 PersistentVolume 資源。

6。卷控制器會將 PV 與 PVC 進行繫結。

2。 Attaching Volumes

1。AD 控制器(AttachDetachController)觀察到使用 CSI 型別 PV 的 Pod 被排程到某一節點,此時AD 控制器會呼叫內部 in-tree CSI 外掛(csiAttacher)的 Attach 函式。

2。內部 in-tree CSI 外掛(csiAttacher)會建立一個 VolumeAttachment 物件到叢集中。

3。External Attacher 觀察到該 VolumeAttachment 物件,並呼叫外部 CSI外掛的ControllerPublish 函式以將卷掛接到對應節點上。外部 CSI 外掛掛載成功後,External Attacher會更新相關 VolumeAttachment 物件的 。Status。Attached 為 true。

4。AD 控制器內部 in-tree CSI 外掛(csiAttacher)觀察到 VolumeAttachment 物件的 。Status。Attached 設定為 true,於是更新AD 控制器內部狀態(ActualStateOfWorld),該狀態會顯示在 Node 資源的 。Status。VolumesAttached 上。

3。 Mounting Volumes

1。Volume Manager(Kubelet 元件)觀察到有新的使用 CSI 型別 PV 的 Pod 排程到本節點上,於是呼叫內部 in-tree CSI 外掛(csiAttacher)的 WaitForAttach 函式。

2。內部 in-tree CSI 外掛(csiAttacher)等待叢集中 VolumeAttachment 物件狀態 。Status。Attached 變為 true。

3。in-tree CSI 外掛(csiAttacher)呼叫 MountDevice 函式,該函式內部透過 unix domain socket 呼叫外部 CSI 外掛的NodeStageVolume 函式;之後外掛(csiAttacher)呼叫內部 in-tree CSI 外掛(csiMountMgr)的 SetUp 函式,該函式內部會透過 unix domain socket 呼叫外部 CSI 外掛的NodePublishVolume 函式。

4。 Unmounting Volumes

1。使用者刪除相關 Pod。

2。Volume Manager(Kubelet 元件)觀察到包含 CSI 儲存卷的 Pod 被刪除,於是呼叫內部 in-tree CSI 外掛(csiMountMgr)的 TearDown 函式,該函式內部會透過 unix domain socket 呼叫外部 CSI 外掛的 NodeUnpublishVolume 函式。

3。Volume Manager(Kubelet 元件)呼叫內部 in-tree CSI 外掛(csiAttacher)的 UnmountDevice 函式,該函式內部會透過 unix domain socket 呼叫外部 CSI 外掛的 NodeUnpublishVolume 函式。

5。 Detaching Volumes

1。AD 控制器觀察到包含 CSI 儲存卷的 Pod 被刪除,此時該控制器會呼叫內部 in-tree CSI 外掛(csiAttacher)的 Detach 函式。

2。csiAttacher會刪除叢集中相關 VolumeAttachment 物件(但由於存在 finalizer,va 物件不會立即刪除)。

3。External Attacher觀察到叢集中 VolumeAttachment 物件的 DeletionTimestamp 非空,於是呼叫外部 CSI 外掛的ControllerUnpublish 函式以將卷從對應節點上摘除。外部 CSI 外掛摘除成功後,External Attacher會移除相關 VolumeAttachment 物件的 finalizer 欄位,此時 VolumeAttachment 物件被徹底刪除。

4。AD 控制器中內部 in-tree CSI 外掛(csiAttacher)觀察到 VolumeAttachment 物件已刪除,於是更新AD 控制器中的內部狀態;同時AD 控制器更新 Node 資源,此時 Node 資源的 。Status。VolumesAttached 上已沒有相關掛接資訊。

6。 Deleting Volumes

1。使用者刪除相關 PVC。

2。External Provisioner 元件觀察到 PVC 刪除事件,根據 PVC 的回收策略(Reclaim)執行不同操作:

Delete:呼叫外部 CSI 外掛的DeleteVolume 函式以刪除卷;一旦捲成功刪除,Provisioner會刪除叢集中對應 PV 物件。

Retain:Provisioner不執行卷刪除操作。

CSI Sidecar 元件介紹

為使 K8s 適配 CSI 標準,社群將與 K8s 相關的儲存流程邏輯放在了 CSI Sidecar 元件中。

1。 Node Driver Registrar

1)功能

Node-Driver-Registrar 元件會將外部 CSI 外掛註冊到Kubelet,從而使Kubelet透過特定的 Unix Domain Socket 來呼叫外部 CSI 外掛函式(Kubelet 會呼叫外部 CSI 外掛的 NodeGetInfo、NodeStageVolume、NodePublishVolume、NodeGetVolumeStats 等函式)。

2)原理

Node-Driver-Registrar 元件透過Kubelet 外部外掛註冊機制實現註冊,註冊成功後:

Kubelet為本節點 Node 資源打 annotation:Kubelet呼叫外部 CSI 外掛的NodeGetInfo 函式,其返回值 [nodeID]、[driverName] 將作為值用於 “csi。volume。kubernetes。io/nodeid” 鍵。

Kubelet更新 Node Label:將NodeGetInfo 函式返回的 [AccessibleTopology] 值用於節點的 Label。

Kubelet更新 Node Status:將NodeGetInfo 函式返回的 maxAttachLimit(節點最大可掛載卷數量)更新到 Node 資源的 Status。Allocatable:attachable-volumes-csi-[driverName]=[maxAttachLimit]。

Kubelet更新 CSINode 資源(沒有則建立):將 [driverName]、[nodeID]、[maxAttachLimit]、[AccessibleTopology] 更新到 Spec 中(拓撲僅保留 Key 值)。

2。 External Provisioner

1)功能

建立/刪除實際的儲存卷,以及代表儲存卷的 PV 資源。

2)原理

External-Provisioner在啟動時需指定引數 —— provisioner,該引數指定 Provisioner 名稱,與 StorageClass 中的 provisioner 欄位對應。

External-Provisioner啟動後會 watch 叢集中的 PVC 和 PV 資源。

對於叢集中的 PVC 資源:

判斷 PVC 是否需要動態建立儲存卷,標準如下:PVC 的 annotation 中是否包含 “volume。beta。kubernetes。io/storage-provisioner” 鍵(由卷控制器建立),並且其值是否與 Provisioner 名稱相等。PVC 對應 StorageClass 的 VolumeBindingMode 欄位若為 WaitForFirstConsumer,則 PVC 的 annotation 中必須包含 “volume。kubernetes。io/selected-node” 鍵(詳見排程器如何處理 WaitForFirstConsumer),且其值不為空;若為 Immediate 則表示需要 Provisioner 立即提供動態儲存卷。

透過特定的 Unix Domain Socket 呼叫外部 CSI 外掛的 CreateVolume 函式。

建立 PV 資源,PV 名稱為 [Provisioner 指定的 PV 字首] - [PVC uuid]。

對於叢集中的 PV 資源:

判斷 PV 是否需要刪除,標準如下:判斷其 。Status。Phase 是否為 Release。判斷其 。Spec。PersistentVolumeReclaimPolicy 是否為 Delete。判斷其是否包含 annotation(pv。kubernetes。io/provisioned-by),且其值是否為自己。

透過特定的 Unix Domain Socket 呼叫外部 CSI 外掛的 DeleteVolume 介面。

刪除叢集中的 PV 資源。

3。 External Attacher

1)功能

掛接/摘除儲存卷。

2)原理

External-Attacher 內部會時刻 watch 叢集中的 VolumeAttachment 資源和 PersistentVolume 資源。

對於 VolumeAttachment 資源:

從 VolumeAttachment 資源中獲得 PV 的所有資訊,如 volume ID、node ID、掛載 Secret 等。

判斷 VolumeAttachment 的 DeletionTimestamp 欄位是否為空來判斷其為卷掛接或卷摘除:若為卷掛接則透過特定的 Unix Domain Socket 呼叫外部 CSI 外掛的ControllerPublishVolume 介面;若為卷摘除則透過特定的 Unix Domain Socket 呼叫外部 CSI 外掛的ControllerUnpublishVolume 介面。

對於 PersistentVolume 資源:

在掛接時為相關 PV 打上 Finalizer:external-attacher/[driver 名稱]。

當 PV 處於刪除狀態時(DeletionTimestamp 非空),刪除 Finalizer:external-attacher/[driver 名稱]。

4。 External Resizer

1)功能

擴容儲存卷。

2)原理

External-Resizer內部會 watch 叢集中的 PersistentVolumeClaim 資源。

對於 PersistentVolumeClaim 資源:

判斷 PersistentVolumeClaim 資源是否需要擴容:PVC 狀態需要是 Bound 且 。Status。Capacity 與 。Spec。Resources。Requests 不等。

更新 PVC 的 。Status。Conditions,表明此時處於 Resizing 狀態。

透過特定的 Unix Domain Socket 呼叫外部 CSI 外掛的 ControllerExpandVolume 介面。

更新 PV 的 。Spec。Capacity。

若 CSI 支援檔案系統線上擴容,ControllerExpandVolume 介面返回值中 NodeExpansionRequired 欄位為 true,External-Resizer更新 PVC 的 。Status。Conditions 為 FileSystemResizePending 狀態;若不支援則擴容成功,External-Resizer更新 PVC 的 。Status。Conditions 為空,且更新 PVC 的 。Status。Capacity。

Volume Manager(Kubelet 元件)觀察到儲存卷需線上擴容,於是透過特定的 Unix Domain Socket 呼叫外部 CSI 外掛的NodeExpandVolume 介面實現檔案系統擴容。

5。 livenessprobe

1)功能

檢查 CSI 外掛是否正常。

2)原理

透過對外暴露一個 / healthz HTTP 埠以服務 kubelet 的探針探測器,內部是透過特定的 Unix Domain Socket 呼叫外部 CSI 外掛的 Probe 介面。

CSI 介面介紹

三方儲存廠商需實現 CSI 外掛的三大介面:IdentityServer、ControllerServer、NodeServer。

1。 IdentityServer

IdentityServer 主要用於認證 CSI 外掛的身份資訊。

// IdentityServer is the server API for Identity service。type IdentityServer interface { // 獲取CSI外掛的資訊,比如名稱、版本號 GetPluginInfo(context。Context, *GetPluginInfoRequest) (*GetPluginInfoResponse, error) // 獲取CSI外掛提供的能力,比如是否提供ControllerService能力 GetPluginCapabilities(context。Context, *GetPluginCapabilitiesRequest) (*GetPluginCapabilitiesResponse, error) // 獲取CSI外掛健康狀況 Probe(context。Context, *ProbeRequest) (*ProbeResponse, error)}

2。 ControllerServer

ControllerServer 主要負責儲存卷及快照的建立/刪除以及掛接/摘除操作。

// ControllerServer is the server API for Controller service。type ControllerServer interface { // 建立儲存卷 CreateVolume(context。Context, *CreateVolumeRequest) (*CreateVolumeResponse, error) // 刪除儲存卷 DeleteVolume(context。Context, *DeleteVolumeRequest) (*DeleteVolumeResponse, error) // 掛接儲存捲到特定節點 ControllerPublishVolume(context。Context, *ControllerPublishVolumeRequest) (*ControllerPublishVolumeResponse, error) // 從特定節點摘除儲存卷 ControllerUnpublishVolume(context。Context, *ControllerUnpublishVolumeRequest) (*ControllerUnpublishVolumeResponse, error) // 驗證儲存卷能力是否滿足要求,比如是否支援跨節點多讀多寫 ValidateVolumeCapabilities(context。Context, *ValidateVolumeCapabilitiesRequest) (*ValidateVolumeCapabilitiesResponse, error) // 列舉全部儲存卷資訊 ListVolumes(context。Context, *ListVolumesRequest) (*ListVolumesResponse, error) // 獲取儲存資源池可用空間大小 GetCapacity(context。Context, *GetCapacityRequest) (*GetCapacityResponse, error) // 獲取ControllerServer支援功能點,比如是否支援快照能力 ControllerGetCapabilities(context。Context, *ControllerGetCapabilitiesRequest) (*ControllerGetCapabilitiesResponse, error) // 建立快照 CreateSnapshot(context。Context, *CreateSnapshotRequest) (*CreateSnapshotResponse, error) // 刪除快照 DeleteSnapshot(context。Context, *DeleteSnapshotRequest) (*DeleteSnapshotResponse, error) // 獲取所有快照資訊 ListSnapshots(context。Context, *ListSnapshotsRequest) (*ListSnapshotsResponse, error) // 擴容儲存卷 ControllerExpandVolume(context。Context, *ControllerExpandVolumeRequest) (*ControllerExpandVolumeResponse, error)}

3。 NodeServer

NodeServer 主要負責儲存卷掛載/解除安裝操作。

// NodeServer is the server API for Node service。type NodeServer interface { // 將儲存卷格式化並掛載至臨時全域性目錄 NodeStageVolume(context。Context, *NodeStageVolumeRequest) (*NodeStageVolumeResponse, error) // 將儲存卷從臨時全域性目錄解除安裝 NodeUnstageVolume(context。Context, *NodeUnstageVolumeRequest) (*NodeUnstageVolumeResponse, error) // 將儲存卷從臨時目錄bind-mount到目標目錄 NodePublishVolume(context。Context, *NodePublishVolumeRequest) (*NodePublishVolumeResponse, error) // 將儲存卷從目標目錄解除安裝 NodeUnpublishVolume(context。Context, *NodeUnpublishVolumeRequest) (*NodeUnpublishVolumeResponse, error) // 獲取儲存卷的容量資訊 NodeGetVolumeStats(context。Context, *NodeGetVolumeStatsRequest) (*NodeGetVolumeStatsResponse, error) // 儲存卷擴容 NodeExpandVolume(context。Context, *NodeExpandVolumeRequest) (*NodeExpandVolumeResponse, error) // 獲取NodeServer支援功能點,比如是否支援獲取儲存卷容量資訊 NodeGetCapabilities(context。Context, *NodeGetCapabilitiesRequest) (*NodeGetCapabilitiesResponse, error) // 獲取CSI節點資訊,比如最大支援卷個數 NodeGetInfo(context。Context, *NodeGetInfoRequest) (*NodeGetInfoResponse, error)}

K8s CSI API 物件

K8s 為支援 CSI 標準,包含如下 API 物件:

CSINode

CSIDriver

VolumeAttachment

1。 CSINode

apiVersion: storage。k8s。io/v1beta1kind: CSINodemetadata: name: node-10。212。101。210spec: drivers: - name: yodaplugin。csi。alibabacloud。com nodeID: node-10。212。101。210 topologyKeys: - kubernetes。io/hostname - name: pangu。csi。alibabacloud。com nodeID: a5441fd9013042ee8104a674e4a9666a topologyKeys: - topology。pangu。csi。alibabacloud。com/zone

作用:

判斷外部 CSI 外掛是否註冊成功。在 Node Driver Registrar 元件向 Kubelet 註冊完畢後,Kubelet 會建立該資源,故不需要顯式建立 CSINode 資源。

將 Kubernetes 中 Node 資源名稱與三方儲存系統中節點名稱(nodeID)一一對應。此處Kubelet會呼叫外部 CSI 外掛NodeServer 的 GetNodeInfo 函式獲取 nodeID。

顯示卷拓撲資訊。CSINode 中 topologyKeys 用來表示儲存節點的拓撲資訊,卷拓撲資訊會使得Scheduler在 Pod 排程時選擇合適的儲存節點。

2。 CSIDriver

apiVersion: storage。k8s。io/v1beta1kind: CSIDrivermetadata: name: pangu。csi。alibabacloud。comspec: # 外掛是否支援卷掛接(VolumeAttach) attachRequired: true # Mount階段是否CSI外掛需要Pod資訊 podInfoOnMount: true # 指定CSI支援的卷模式 volumeLifecycleModes: - Persistent

作用:

簡化外部 CSI 外掛的發現。由叢集管理員建立,透過 kubectl get csidriver 即可得知環境上有哪些 CSI 外掛。

自定 義Kubernetes 行為,如一些外部 CSI 外掛不需要執行卷掛接(VolumeAttach)操作,則可以設定 。spec。attachRequired 為 false。

3。 VolumeAttachment

apiVersion: storage。k8s。io/v1kind: VolumeAttachmentmetadata: annotations: csi。alpha。kubernetes。io/node-id: 21481ae252a2457f9abcb86a3d02ba05 finalizers: - external-attacher/pangu-csi-alibabacloud-com name: csi-0996e5e9459e1ccc1b3a7aba07df4ef7301c8e283d99eabc1b69626b119ce750spec: attacher: pangu。csi。alibabacloud。com nodeName: node-10。212。101。241 source: persistentVolumeName: pangu-39aa24e7-8877-11eb-b02f-021234350de1status: attached: true

作用:VolumeAttachment 記錄了儲存卷的掛接/摘除資訊以及節點資訊。

支援特性

1。 拓撲支援

在 StorageClass 中有 AllowedTopologies 欄位:

apiVersion: storage。k8s。io/v1kind: StorageClassmetadata: name: csi-panguprovisioner: pangu。csi。alibabacloud。comparameters: type: cloud_ssdvolumeBindingMode: ImmediateallowedTopologies:- matchLabelExpressions: - key: topology。pangu。csi。alibabacloud。com/zone values: - zone-1 - zone-2

外部 CSI 外掛部署後會為每個節點打標,打標內容NodeGetInfo 函式返回的 [AccessibleTopology] 值(詳見 Node Driver Registrar 部分)。

External Provisioner在呼叫 CSI 外掛的 CreateVolume 介面之前,會在請求引數設定 AccessibilityRequirements:

對於 WaitForFirstConsumer當 PVC 的 anno 中包含 “volume。kubernetes。io/selected-node” 且不為空,則先獲取對應節點 CSINode 的 TopologyKeys,然後根據該 TopologyKeys 鍵從 Node 資源的 Label 獲取 Values 值,最後拿該 Values 值與 StorageClass 的 AllowedTopologies 比對,判斷其是否包含於其中;若不包含則報錯。

對於 Immediately將 StorageClass 的 AllowedTopologies 的值填進來,若 StorageClass 沒有設定 AllowedTopologies 則將所有包含 TopologyKeys 鍵的節點 Value 添進來。

Scheduler 如何處理使用儲存卷排程

基於社群 1。18 版本排程器

排程器的排程過程主要有如下三步:

預選(Filter):篩選滿足 Pod 排程要求的節點列表。

優選(Score):透過內部的優選演算法為節點打分,獲得最高分數的節點即為選中的節點。

繫結(Bind):排程器將排程結果通知給 kube-apiserver,更新 Pod 的 。spec。nodeName 欄位。

排程器預選階段:處理 Pod 的 PVC/PV 繫結關係以及動態供應 PV(Dynamic Provisioning),同時使排程器排程時考慮 Pod 所使用 PV 的節點親和性。詳細排程過程如下:

Pod 不包含 PVC 直接跳過。

FindPodVolumes獲取 Pod 的 boundClaims、claimsToBind 以及 unboundClaimsImmediate。boundClaims:已 Bound 的 PVCclaimsToBind:PVC 對應 StorageClass 的 VolumeBindingMode 為 VolumeBindingWaitForFirstConsumerunboundClaimsImmediate:PVC 對應 StorageClass 的 VolumeBindingMode 為 VolumeBindingImmediate若 len(unboundClaimsImmediate) 不為空,表示這種 PVC 需要立即繫結 PV(即存 PVC 建立後,立刻動態建立 PV 並將其繫結到 PVC,該過程不走排程),若 PVC 處於 unbound 階段則報錯。若 len(boundClaims) 不為空,則檢查 PVC 對應 PV 的節點親和性與當前節點的 Label 是否衝突,若衝突則報錯(可檢查 Immediate 型別的 PV 拓撲)。若 len(claimsToBind) 不為空先檢查環境中已有的 PV 能否與該 PVC 匹配(findMatchingVolumes),將能夠匹配 PVC 的 PV 記錄在排程器的 cache 中。未匹配到 PV 的 PVC 走動態排程流程,動態排程主要透過 StorageClass 的 AllowedTopologies 欄位判斷當前排程節點是否滿足拓撲要求(針對 WaitForFirstConsumer 型別的 PVC)。

排程器優選階段不討論。

排程器 Assume 階段

排程器會先 Assume PV/PVC,再 Assume Pod。

將當前待排程的 Pod 進行深複製。

AssumePodVolumes(針對 WaitForFirstConsumer 型別的 PVC)更改排程器 cache 中已經 Match 的 PV 資訊:設定 annotation:pv。kubernetes。io/bound-by-controller=“yes”。更改排程器 cache 中未匹配到 PV 的 PVC,設定 annotation:volume。kubernetes。io/selected-node=【所選節點】。

Assume Pod 完畢更改排程器 cache 中 Pod 的 。Spec。NodeName 為【所選節點】。

排程器 Bind 階段

BindPodVolumes:

呼叫 Kubernetes 的 API 更新叢集中 PV/PVC 資源,使其與排程器 Cache 中的 PV/PVC 一致。

檢查 PV/PVC 狀態:檢查所有 PVC 是否已處於 Bound 狀態。檢查所有 PV 的 NodeAffinity 是否與節點 Label 衝突。

排程器執行 Bind 操作:呼叫 Kubernetes 的 API 更新 Pod 的 。Spec。NodeName 欄位。

2。 儲存卷擴容

儲存卷擴容部分在 External Resizer 部分已提到,故不再贅述。使用者只需要編輯 PVC 的 。Spec。Resources。Requests。Storage 欄位即可,注意只可擴容不可縮容。

若 PV 擴容失敗,此時 PVC 無法重新編輯 spec 欄位的 storage 為原來的值(只可擴容不可縮容)。

3。 單節點卷數量限制

卷數量限制在 Node Driver Registrar 部分已提到,故不再贅述。

4。 儲存卷監控

儲存商需實現 CSI 外掛的 NodeGetVolumeStats 介面,Kubelet 會呼叫該函式,並反映在其 metrics上:

kubelet_volume_stats_capacity_bytes:儲存卷容量

kubelet_volume_stats_used_bytes:儲存卷已使用容量

kubelet_volume_stats_available_bytes:儲存卷可使用容量

kubelet_volume_stats_inodes:儲存卷 inode 總量

kubelet_volume_stats_inodes_used:儲存卷 inode 使用量

kubelet_volume_stats_inodes_free:儲存卷 inode 剩餘量

5。 Secret

CSI 儲存卷支援傳入 Secret 來處理不同流程中所需要的私密資料,目前 StorageClass 支援如下 Parameter:

csi。storage。k8s。io/provisioner-secret-name

csi。storage。k8s。io/provisioner-secret-namespace

csi。storage。k8s。io/controller-publish-secret-name

csi。storage。k8s。io/controller-publish-secret-namespace

csi。storage。k8s。io/node-stage-secret-name

csi。storage。k8s。io/node-stage-secret-namespace

csi。storage。k8s。io/node-publish-secret-name

csi。storage。k8s。io/node-publish-secret-namespace

csi。storage。k8s。io/controller-expand-secret-name

csi。storage。k8s。io/controller-expand-secret-namespace

Secret 會包含在對應 CSI 介面的引數中,如對於 CreateVolume 介面而言則包含在 CreateVolumeRequest。Secrets 中。

6。 塊裝置

apiVersion: apps/v1kind: StatefulSetmetadata: name: nginx-examplespec: selector: matchLabels: app: nginx serviceName: “nginx” volumeClaimTemplates: - metadata: name: html spec: accessModes: - ReadWriteOnce volumeMode: Block storageClassName: csi-pangu resources: requests: storage: 40Gi template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx volumeDevices: - devicePath: “/dev/vdb” name: html

三方儲存廠商需實現 NodePublishVolume 介面。Kubernetes 提供了針對塊裝置的工具包(“k8s。io/kubernetes/pkg/util/mount”),在 NodePublishVolume 階段可呼叫該工具的 EnsureBlock 和 MountBlock 函式。

7。 卷快照/卷克隆能力

鑑於本文篇幅,此處不做過多原理性介紹。讀者感興趣見官方介紹:卷快照、卷克隆。

總結

本文首先對 CSI 核心流程進行了大體介紹,並結合 CSI Sidecar 元件、CSI 介面、API 物件對 CSI 標準進行了深度解析。在 K8s 上,使用任何一種 CSI 儲存卷都離不開上面的流程,環境上的容器儲存問題也一定是其中某個環節出現了問題。本文對其流程進行梳理,以便於廣大程式猿(媛)排查環境問題。

作者 | 惠志

上一篇:htc將在5月釋出vr一體機,但在遊戲方面沒有希望了,這是什麼原因?
下一篇:小米手環6和小米手環5的差異:真的只是螢幕變大嘛?| cbnweekly