k8s通過ceph-csi接入存儲的概要分析


kubernetes ceph-csi分析目錄導航

概述

下面的分析是k8s通過ceph-csi(csi plugin)接入ceph存儲(csi相關組件的分析以rbd為例進行分析),對csi系統結構、所涉及的k8s對象與組件進行了簡單的介紹,以及k8s對存儲進行相關操作的流程分析,存儲相關操作包括了存儲創建、存儲擴容、存儲掛載、解除存儲掛載以及存儲刪除操作。

csi系統結構

這是一張k8s csi的系統架構圖,圖中所畫的組件以及k8s對象,接下來會一一進行分析。

csi簡介

CSI是Container Storage Interface(容器存儲接口)的簡寫。

CSI的目的是定義行業標准“容器存儲接口”,使存儲供應商(SP)能夠開發一個符合CSI標准的插件並使其可以在多個容器編排(CO)系統中工作。CO包括Cloud Foundry, Kubernetes, Mesos等。

CSI組件一般采用容器化部署,減少了環境依賴。

涉及k8s對象

1. PersistentVolume

持久存儲卷,集群級別資源,代表了存儲卷資源,記錄了該存儲卷資源的相關信息。

回收策略

(1)retain:保留策略,當刪除PVC的時候,PV與外部存儲資源仍然存在。

(2)delete:刪除策略,當與pv綁定的pvc被刪除的時候,會從k8s集群中刪除PV對象,並執行外部存儲資源的刪除操作。

(3)resycle(已廢棄)

pv狀態遷移

available --> bound --> released

2. PersistentVolumeClaim

持久存儲卷聲明,namespace級別資源,代表了用戶對於存儲卷的使用需求聲明。

示例:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test
  namespace: test
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  storageClassName: csi-cephfs-sc
  volumeMode: Filesystem
pvc狀態遷移

pending --> bound

3. StorageClass

定義了創建pv的模板信息,集群級別資源,用於動態創建pv。

示例:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: csi-rbd-sc
parameters:
  clusterID: ceph01
  imageFeatures: layering
  imageFormat: "2"
  mounter: rbd
  pool: kubernetes
provisioner: rbd.csi.ceph.com
reclaimPolicy: Delete
volumeBindingMode: Immediate

4. VolumeAttachment

VolumeAttachment 記錄了pv的相關掛載信息,如掛載到哪個node節點,由哪個volume plugin來掛載等。

AD Controller 創建一個 VolumeAttachment,而 External-attacher 則通過觀察該 VolumeAttachment,根據其狀態屬性來進行存儲的掛載和卸載操作。

示例:

apiVersion: storage.k8s.io/v1
kind: VolumeAttachment
metadata:
  name: csi-123456
spec:
  attacher: cephfs.csi.ceph.com
  nodeName: 192.168.1.10
  source:
    persistentVolumeName: pvc-123456
status:
  attached: true

5. CSINode

CSINode 記錄了csi plugin的相關信息(如nodeId、driverName、拓撲信息等)。

當Node Driver Registrar向kubelet注冊一個csi plugin后,會創建(或更新)一個CSINode對象,記錄csi plugin的相關信息。

示例:

apiVersion: storage.k8s.io/v1
kind: CSINode
metadata:
  name: 192.168.1.10
spec:
  drivers:
  - name: cephfs.csi.ceph.com
    nodeID: 192.168.1.10
    topologyKeys: null
  - name: rbd.csi.ceph.com
    nodeID: 192.168.1.10
    topologyKeys: null

涉及組件與作用

下面先簡單介紹下涉及的組件與作用,后面會有單獨詳細的介紹各個組件的作用。

1. volume plugin

擴展各種存儲類型的卷的管理能力,實現第三方存儲的各種操作能力與k8s存儲系統的結合。調用第三方存儲的接口或命令,從而提供數據卷的創建/刪除、attach/detach、mount/umount的具體操作實現,可以認為是第三方存儲的代理人。前面分析組件中的對於數據卷的創建/刪除、attach/detach、mount/umount操作,全是調用volume plugin來完成。

后續對volume plugin的詳細分析,以通過ceph-csi操作rbd為例進行分析。

根據源碼所在位置,volume plugin分為in-tree與out-of-tree。

in-tree

在k8s源碼內部實現,和k8s一起發布、管理,更新迭代慢、靈活性差。

out-of-tree

代碼獨立於k8s,由存儲廠商實現,有csi、flexvolume兩種實現。

csi plugin

本次的分析為k8s通過ceph-csi來使用ceph存儲,ceph-csi屬於csi plugin。csi plugin分為ControllerServer與NodeServer,各負責不同的存儲操作。

external plugin

external plugin包括了external-provisioner、external-attacher、external-resizer、external-snapshotter等,external plugin輔助csi plugin組件,共同完成了存儲相關操作。external plugin負責watch pvc、volumeAttachment等對象,然后調用volume plugin來完成存儲的相關操作。如external-provisioner watch pvc對象,然后調用csi plugin來創建存儲,最后創建pv對象;external-attacher watch volumeAttachment對象,然后調用csi plugin來做attach/dettach操作;external-resizer watch pvc對象,然后調用csi plugin來做存儲的擴容操作等。

Node-Driver-Registrar

Node-Driver-Registrar組件負責實現csi plugin(NodeServer)的注冊,讓kubelet感知csi plugin的存在。

組件部署方式

csi plugin controllerServer與external plugin作為容器,使用deployment部署,多副本可實現高可用;而csi plugin NodeServer與Node-Driver-Registrar作為容器,使用daemonset部署,即每個node節點都有。

2. kube-controller-manager

PV controller

負責pv、pvc的綁定與生命周期管理(如創建/刪除底層存儲,創建/刪除pv對象,pv與pvc對象的狀態變更)。

創建/刪除底層存儲、創建/刪除pv對象的操作,由PV controller調用volume plugin(in-tree)來完成。本次分析的是k8s通過ceph-csi來使用ceph存儲,volume plugin為ceph-csi,屬於out-tree,所以創建/刪除底層存儲、創建/刪除pv對象的操作由external-provisioner來完成。

AD controller

AD Cotroller全稱Attachment/Detachment 控制器,主要負責創建、刪除VolumeAttachment對象,並調用volume plugin來做存儲設備的Attach/Detach操作(將數據卷掛載到特定node節點上/從特定node節點上解除掛載),以及更新node.Status.VolumesAttached等。

不同的volume plugin的Attach/Detach操作邏輯有所不同,如通過ceph-csi(out-tree volume plugin)來使用ceph存儲,則的Attach/Detach操作只是修改VolumeAttachment對象的狀態,而不會真正的將數據卷掛載到節點/從節點上解除掛載,真正的節點存儲掛載/解除掛載操作由kubelet中volume manager調用rc.operationExecutor.MountVolume/rc.operationExecutor.UnmountDevice方法時,調用ceph-csi來完成,后面會有博文詳細做介紹。

3. kubelet

volume manager

主要是管理卷的Attach/Detach(與AD controller作用相同,通過kubelet啟動參數控制哪個組件來做該操作,后續會詳細介紹)、mount/umount等操作。

本次的分析為k8s通過ceph-csi來使用ceph存儲。本次分析中,volume manager的Attach/Detach操作只創建/刪除VolumeAttachment對象,而不會真正的將數據卷掛載到節點/從節點上解除掛載;csi-attacer組件也不會做掛載/解除掛載操作,只是更新VolumeAttachment對象,真正的節點掛載/解除掛載操作由kubelet中volume manager調用rc.operationExecutor.MountVolume/rc.operationExecutor.UnmountDevice方法時,調用ceph-csi來完成,后面會有博文詳細做介紹。

kubernetes創建與掛載volume(in-tree volume plugin)

先來看下kubernetes通過in-tree volume plugin來創建與掛載volume的流程

(1)用戶創建pvc;
(2)PV controller watch到pvc的創建,尋找合適的pv與之綁定。
(3)(4)當找不到合適的pv時,將調用volume plugin來創建volume,並創建pv對象,之后該pv對象與pvc對象綁定。
(5)用戶創建掛載pvc的pod;
(6)kube-scheduler watch到pod的創建,為其尋找合適的node調度。
(7)(8)pod調度完成后,AD controller/volume manager watch到pod聲明的volume沒有進行attach操作,將調用volume plugin來做attach操作。
(9)volume plugin進行attach操作,將volume掛載到pod所在node節點,成為如/dev/vdb的設備。
(10)(11)attach操作完成后,volume manager watch到pod聲明的volume沒有進行mount操作,將調用volume plugin來做mount操作。
(12)volume plugin進行mount操作,將node節點上的第(9)步得到的/dev/vdb設備掛載到指定目錄。

kubernetes創建與掛載volume(out-of-tree volume plugin)

再來看下kubernetes通過out-of-tree volume plugin來創建與掛載volume的流程,以csi-plugin為例。

(1)用戶創建pvc;
(2)PV controller watch到pvc的創建,尋找合適的pv與之綁定。當尋找不到合適的pv時,將更新pvc對象,添加annotation:volume.beta.kubernetes.io/storage-provisioner,讓external-provisioner組件開始開始創建存儲與pv對象的操作。
(3)external-provisioner組件watch到pvc的創建,判斷annotation:volume.beta.kubernetes.io/storage-provisioner的值,即判斷是否是自己來負責做創建操作,是則調用csi-plugin ControllerServer來創建存儲,並創建pv對象。
(4)PV controller watch到pvc,尋找合適的pv(上一步中創建)與之綁定。
(5)用戶創建掛載pvc的pod;
(6)kube-scheduler watch到pod的創建,為其尋找合適的node調度。
(7)(8)pod調度完成后,AD controller/volume manager watch到pod聲明的volume沒有進行attach操作,將調用csi-attacher來做attach操作(實際上只是創建volumeAttachement對象)。
(9)external-attacher組件watch到volumeAttachment對象的新建,調用csi-plugin進行attach操作(如果volume plugin是ceph-csi,external-attacher組件watch到volumeAttachment對象的新建后,只是修改該對象的狀態屬性,不會做attach操作,真正的attach操作由kubelet中的volume manager調用volume plugin ceph-csi來完成)。
(10)csi-plugin ControllerServer進行attach操作,將volume掛載到pod所在node節點,成為如/dev/vdb的設備。
(11)(12)attach操作完成后,volume manager watch到pod聲明的volume沒有進行mount操作,將調用csi-mounter來做mount操作。
(13)csi-mounter調用csi-plugin NodeServer進行mount操作,將node節點上的第(10)步得到的/dev/vdb設備掛載到指定目錄。

kubernetes存儲相關操作流程具體分析(out-of-tree volume plugin,以ceph-csi為例)

下面來看下kubernetes通過out-of-tree volume plugin來創建/刪除、掛載/解除掛載volume的流程。

下面先對每個操作的整體流程進行分析,后面會對涉及的每個組件進行源碼分析。

1. 存儲創建

流程圖

流程分析

(1)用戶創建pvc對象;

(2)pv controller監聽pvc對象,尋找現存的合適的pv對象,與pvc對象綁定。當找不到現存合適的pv對象時,將更新pvc對象,添加annotation:volume.beta.kubernetes.io/storage-provisioner,讓external-provisioner組件開始開始創建存儲與pv對象的操作;當找到時,將pvc與pv綁定,結束操作。

(3)external-provisioner組件監聽到pvc的新增事件,判斷pvc的annotation:volume.beta.kubernetes.io/storage-provisioner的值,即判斷是否是自己來負責做創建操作,是則調用ceph-csi組件進行存儲的創建;

(4)ceph-csi組件調用ceph創建底層存儲;

(5)底層存儲創建完成后,external-provisioner根據存儲信息,拼接pv對象,創建pv對象;

(6)pv controller監聽pvc對象,尋找合適的pv對象,與pvc對象綁定。

2. 存儲擴容

流程圖

image

流程分析

(1)修改pvc對象,修改申請存儲大小(pvc.spec.resources.requests.storage);

(2)修改成功后,external-resizer監聽到該pvc的update事件,發現pvc.Spec.Resources.Requests.storgage比pvc.Status.Capacity.storgage大,於是調ceph-csi組件進行 controller端擴容;

(3)ceph-csi組件調用ceph存儲,進行底層存儲擴容;

(4)底層存儲擴容完成后,external-resizer組件更新pv對象的.Spec.Capacity.storgage的值為擴容后的存儲大小;

(5)kubelet的volume manager在reconcile()調諧過程中發現pv.Spec.Capacity.storage大於pvc.Status.Capacity.storage,於是調ceph-csi組件進行 node端擴容;

(6)ceph-csi組件對dnode上存儲對應的文件系統擴容;

(7)擴容完成后,kubelet更新pvc.Status.Capacity.storage的值為擴容后的存儲大小。

3. 存儲掛載

流程圖

kubelet啟動參數--enable-controller-attach-detach,該啟動參數設置為 true 表示啟用 Attach/Detach controller進行Attach/Detach 操作,同時禁用 kubelet 執行 Attach/Detach 操作(默認值為 true)。實際上Attach/Detach 操作就是創建/刪除VolumeAttachment對象。

(1)kubelet啟動參數--enable-controller-attach-detach=true,Attach/Detach controller進行Attach/Detach 操作

(2)kubelet啟動參數--enable-controller-attach-detach=false,kubelet端volume manager進行Attach/Detach 操作

流程分析

(1)用戶創建一個掛載了pvc的pod;

(2)AD controller或volume manager中的reconcile()發現有volume未執行attach操作,於是進行attach操作,即創建VolumeAttachment對象;

(3)external-attacher組件list/watch VolumeAttachement對象,更新VolumeAttachment.status.attached=true;

(4)AD controller更新node對象的.Status.VolumesAttached屬性值,將該volume記為attached;

(5)kubelet中的volume manager獲取node.Status.VolumesAttached屬性值,發現volume已被標記為attached;

(6)於是volume manager中的reconcile()調用ceph-csi組件的NodeStageVolume與NodePublishVolume完成掛載。

4. 解除存儲掛載

流程圖

(1)AD controller

(2)volume manager

流程分析

(1)用戶刪除聲明了pvc的pod;

(2)AD controller或volume manager中的reconcile()發現有volume未執行dettach操作,於是進行dettach操作,即刪除VolumeAttachment對象;

(3)AD controller或volume manager等待VolumeAttachment對象刪除成功;

(4)AD controller更新新node對象的.Status.VolumesAttached屬性值,將標記為attached的該volume從屬性值中去除;

(5)kubelet中的volume manager獲取node.Status.VolumesAttached屬性值,找不到相關的volume信息;

(6)於是volume manager中的reconcile()調用ceph-csi組件的NodeUnpublishVolume與NodeUnstageVolume完成解除掛載。

5. 刪除存儲

流程圖

流程分析

(1)用戶刪除pvc對象;

(2)pv controller發現與pv綁定的pvc對象被刪除,於是更新pv的狀態為released;

(3)external-provisioner watch到pv更新事件,並檢查pv的狀態是否為released,以及回收策略是否為delete;

(4)接下來external-provisioner組件會調用ceph-csi的DeleteVolume來刪除存儲;

(5)ceph-csi組件的DeleteVolume方法,調用ceph集群命令,刪除底層存儲;

(6)external-provisioner組件刪除pv對象。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM