Kubernetes存儲(chǔ)架構(gòu)及插件使用是怎樣的,相信很多沒有經(jīng)驗(yàn)的人對(duì)此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
成都網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)公司!專注于網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)公司、微信開發(fā)、微信小程序、集團(tuán)成都定制網(wǎng)頁設(shè)計(jì)等服務(wù)項(xiàng)目。核心團(tuán)隊(duì)均擁有互聯(lián)網(wǎng)行業(yè)多年經(jīng)驗(yàn),服務(wù)眾多知名企業(yè)客戶;涵蓋的客戶類型包括:成都人造霧等眾多領(lǐng)域,積累了大量豐富的經(jīng)驗(yàn),同時(shí)也獲得了客戶的一致贊美!
一、Kubernetes 存儲(chǔ)體系架構(gòu)
首先以一個(gè) Volume 的掛載例子來作為引入。
如下圖所示,左邊的 YAML 模板定義了一個(gè) StatefulSet 的一個(gè)應(yīng)用,其中定義了一個(gè)名為 disk-pvc 的 volume,掛載到 Pod 內(nèi)部的目錄是 /data。disk-pvc 是一個(gè) PVC 類型的數(shù)據(jù)卷,其中定義了一個(gè) storageClassName。
因此這個(gè)模板是一個(gè)典型的動(dòng)態(tài)存儲(chǔ)的模板。右圖是數(shù)據(jù)卷掛載的過程,主要分為 6 步:
第一步:用戶創(chuàng)建一個(gè)包含 PVC的 Pod;
第二步:PV Controller 會(huì)不斷觀察 ApiServer,如果它發(fā)現(xiàn)一個(gè) PVC 已經(jīng)創(chuàng)建完畢但仍然是未綁定的狀態(tài),它就會(huì)試圖把一個(gè) PV 和 PVC 綁定;
PV Controller 首先會(huì)在集群內(nèi)部找到一個(gè)適合的 PV 進(jìn)行綁定,如果未找到相應(yīng)的 PV,就調(diào)用 Volume Plugin 去做 Provision。Provision 就是從遠(yuǎn)端上一個(gè)具體的存儲(chǔ)介質(zhì)創(chuàng)建一個(gè) Volume,并且在集群中創(chuàng)建一個(gè) PV 對(duì)象,然后將此 PV 和 PVC 進(jìn)行綁定;
第三步:通過 Scheduler 完成一個(gè)調(diào)度功能;
我們知道,當(dāng)一個(gè) Pod 運(yùn)行的時(shí)候,需要選擇一個(gè) Node,這個(gè)節(jié)點(diǎn)的選擇就是由 Scheduler 來完成的。Scheduler 進(jìn)行調(diào)度的時(shí)候會(huì)有多個(gè)參考量,比如 Pod 內(nèi)部所定義的 nodeSelector、nodeAffinity 這些定義以及 Volume 中所定義的一些標(biāo)簽等。
我們可以在數(shù)據(jù)卷中添加一些標(biāo)簽,這樣使用這個(gè) pv 的 Pod 就會(huì)由于標(biāo)簽的限制,被調(diào)度器調(diào)度到期望的節(jié)點(diǎn)上。
第四步:如果有一個(gè) Pod 調(diào)度到某個(gè)節(jié)點(diǎn)之后,它所定義的 PV 還沒有被掛載(Attach),此時(shí) AD Controller 就會(huì)調(diào)用 VolumePlugin,把遠(yuǎn)端的 Volume 掛載到目標(biāo)節(jié)點(diǎn)中的設(shè)備上(如:/dev/vdb);
第五步:當(dāng) Volum Manager 發(fā)現(xiàn)一個(gè) Pod 調(diào)度到自己的節(jié)點(diǎn)上并且 Volume 已經(jīng)完成了掛載,它就會(huì)執(zhí)行 mount 操作,將本地設(shè)備(也就是剛才得到的 /dev/vdb)掛載到 Pod 在節(jié)點(diǎn)上的一個(gè)子目錄中。同時(shí)它也可能會(huì)做一些像格式化、是否掛載到 GlobalPath 等這樣的附加操作。
第六步:綁定操作,就是將已經(jīng)掛載到本地的 Volume 映射到容器中。
接下來,我們一起看一下 Kubernetes 的存儲(chǔ)架構(gòu)。
PV Controller: 負(fù)責(zé) PV/PVC 的綁定、生命周期管理,并根據(jù)需求進(jìn)行數(shù)據(jù)卷的 Provision/Delete 操作;
AD Controller:負(fù)責(zé)存儲(chǔ)設(shè)備的 Attach/Detach 操作,將設(shè)備掛載到目標(biāo)節(jié)點(diǎn);
Volume Manager:管理卷的 Mount/Unmount 操作、卷設(shè)備的格式化以及掛載到一些公用目錄上的操作;
Volume Plugins:它主要是對(duì)上面所有掛載功能的實(shí)現(xiàn);
PV Controller、AD Controller、Volume Manager 主要是進(jìn)行操作的調(diào)用,而具體操作則是由 Volume Plugins 實(shí)現(xiàn)的。
Scheduler:實(shí)現(xiàn)對(duì) Pod 的調(diào)度能力,會(huì)根據(jù)一些存儲(chǔ)相關(guān)的的定義去做一些存儲(chǔ)相關(guān)的調(diào)度;
接下來,我們分別介紹上面這幾部分的功能。
首先我們先來回顧一下幾個(gè)基本概念:
Persistent Volume (PV): 持久化存儲(chǔ)卷,詳細(xì)定義了預(yù)掛載存儲(chǔ)空間的各項(xiàng)參數(shù);
例如,我們?nèi)燧d一個(gè)遠(yuǎn)端的 NAS 的時(shí)候,這個(gè) NAS 的具體參數(shù)就要定義在 PV 中。一個(gè) PV 是沒有 NameSpace 限制的,它一般由 Admin 來創(chuàng)建與維護(hù);
Persistent Volume Claim (PVC):持久化存儲(chǔ)聲明;
它是用戶所使用的存儲(chǔ)接口,對(duì)存儲(chǔ)細(xì)節(jié)無感知,主要是定義一些基本存儲(chǔ)的 Size、AccessMode 參數(shù)在里面,并且它是屬于某個(gè) NameSpace 內(nèi)部的。
StorageClass:存儲(chǔ)類;
一個(gè)動(dòng)態(tài)存儲(chǔ)卷會(huì)按照 StorageClass 所定義的模板來創(chuàng)建一個(gè) PV,其中定義了創(chuàng)建模板所需要的一些參數(shù)和創(chuàng)建 PV 的一個(gè) Provisioner(就是由誰去創(chuàng)建的)。
PV Controller 的主要任務(wù)就是完成 PV、PVC 的生命周期管理,比如創(chuàng)建、刪除 PV 對(duì)象,負(fù)責(zé) PV、PVC 的狀態(tài)遷移;另一個(gè)任務(wù)就是綁定 PVC 與 PV 對(duì)象,一個(gè) PVC 必須和一個(gè) PV 綁定后才能被應(yīng)用使用,它們是一一綁定的,一個(gè) PV 只能被一個(gè) PVC 綁定,反之亦然。
接下來,我們看一下一個(gè) PV 的狀態(tài)遷移圖。
創(chuàng)建好一個(gè) PV 以后,我們就處于一個(gè) Available 的狀態(tài),當(dāng)一個(gè) PVC 和一個(gè) PV 綁定的時(shí)候,這個(gè) PV 就進(jìn)入了 Bound 的狀態(tài),此時(shí)如果我們把 PVC 刪掉,Bound 狀態(tài)的 PV 就會(huì)進(jìn)入 Released 的狀態(tài)。
一個(gè) Released 狀態(tài)的 PV 會(huì)根據(jù)自己定義的 ReclaimPolicy 字段來決定自己是進(jìn)入一個(gè) Available 的狀態(tài)還是進(jìn)入一個(gè) Deleted 的狀態(tài)。如果 ReclaimPolicy 定義的是 “recycle” 類型,它會(huì)進(jìn)入一個(gè) Available 狀態(tài),如果轉(zhuǎn)變失敗,就會(huì)進(jìn)入 Failed 的狀態(tài)。
相對(duì)而言,PVC 的狀態(tài)遷移圖就比較簡(jiǎn)單。
一個(gè)創(chuàng)建好的 PVC 會(huì)處于 Pending 狀態(tài),當(dāng)一個(gè) PVC 與 PV 綁定之后,PVC 就會(huì)進(jìn)入 Bound 的狀態(tài),當(dāng)一個(gè) Bound 狀態(tài)的 PVC 的 PV 被刪掉之后,該 PVC 就會(huì)進(jìn)入一個(gè) Lost 的狀態(tài)。對(duì)于一個(gè) Lost 狀態(tài)的 PVC,它的 PV 如果又被重新創(chuàng)建,并且重新與該 PVC 綁定之后,該 PVC 就會(huì)重新回到 Bound 狀態(tài)。
下圖是一個(gè) PVC 去綁定 PV 時(shí)對(duì) PV 篩選的一個(gè)流程圖。就是說一個(gè) PVC 去綁定一個(gè) PV 的時(shí)候,應(yīng)該選擇一個(gè)什么樣的 PV 進(jìn)行綁定。
首先它會(huì)檢查 VolumeMode 這個(gè)標(biāo)簽,PV 與 PVC 的 VolumeMode 標(biāo)簽必須相匹配。VolumeMode 主要定義的是我們這個(gè)數(shù)據(jù)卷是文件系統(tǒng) (FileSystem) 類型還是一個(gè)塊 (Block) 類型;
第二個(gè)部分是 LabelSelector。當(dāng) PVC 中定義了 LabelSelector 之后,我們就會(huì)選擇那些有 Label 并且與 PVC 的 LabelSelector 相匹配的 PV 進(jìn)行綁定;
第三個(gè)部分是 StorageClassName 的檢查。如果 PVC 中定義了一個(gè) StorageClassName,則必須有此相同類名的 PV 才可以被篩選中。
這里再具體解釋一下 StorageClassName 這個(gè)標(biāo)簽,該標(biāo)簽的目的就是說,當(dāng)一個(gè) PVC 找不到相應(yīng)的 PV 時(shí),我們就會(huì)用該標(biāo)簽所指定的 StorageClass 去做一個(gè)動(dòng)態(tài)創(chuàng)建 PV 的操作,同時(shí)它也是一個(gè)綁定條件,當(dāng)存在一個(gè)滿足該條件的 PV 時(shí),就會(huì)直接使用現(xiàn)有的 PV,而不再去動(dòng)態(tài)創(chuàng)建。
第四個(gè)部分是 AccessMode 檢查。
AccessMode 就是平時(shí)我們?cè)?PVC 中定義的如 “ReadWriteOnce”、”RearWriteMany” 這樣的標(biāo)簽。該綁定條件就是要求 PVC 和 PV 必須有匹配的 AccessMode,即 PVC 所需求的 AccessMode 類型,PV 必須具有。
最后一個(gè)部分是 Size 的檢查。
一個(gè) PVC 的 Size 必須小于等于 PV 的 Size,這是因?yàn)?PVC 是一個(gè)聲明的 Volume,實(shí)際的 Volume 必須要大于等于聲明的 Volume,才能進(jìn)行綁定。
接下來,我們看一個(gè) PV Controller 的一個(gè)實(shí)現(xiàn)。
PV Controller 中主要有兩個(gè)實(shí)現(xiàn)邏輯:一個(gè)是 ClaimWorker;一個(gè)是 VolumeWorker。
ClaimWorker 實(shí)現(xiàn)的是 PVC 的狀態(tài)遷移。
通過系統(tǒng)標(biāo)簽 “pv.kubernetes.io/bind-completed” 來標(biāo)識(shí)一個(gè) PVC 的狀態(tài)。
如果該標(biāo)簽為 True,說明我們的 PVC 已經(jīng)綁定完成,此時(shí)我們只需要去同步一些內(nèi)部的狀態(tài);
如果該標(biāo)簽為 False,就說明我們的 PVC 處于未綁定狀態(tài)。
這個(gè)時(shí)候就需要檢查整個(gè)集群中的 PV 去進(jìn)行篩選。通過 findBestMatch 就可以去篩選所有的 PV,也就是按照之前提到的五個(gè)綁定條件來進(jìn)行篩選。如果篩選到 PV,就執(zhí)行一個(gè) Bound 操作,否則就去做一個(gè) Provision 的操作,自己去創(chuàng)建一個(gè) PV。
再看 VolumeWorker 的操作。它實(shí)現(xiàn)的則是 PV 的狀態(tài)遷移。
通過 PV 中的 ClaimRef 標(biāo)簽來進(jìn)行判斷,如果該標(biāo)簽為空,就說明該 PV 是一個(gè) Available 的狀態(tài),此時(shí)只需要做一個(gè)同步就可以了;如果該標(biāo)簽非空,這個(gè)值是 PVC 的一個(gè)值,我們就會(huì)去集群中查找對(duì)應(yīng)的 PVC。如果存在該 PVC,就說明該 PV 處于一個(gè) Bound 的狀態(tài),此時(shí)會(huì)做一些相應(yīng)的狀態(tài)同步;如果找不到該 PVC,就說明該 PV 處于一個(gè)綁定過的狀態(tài),相應(yīng)的 PVC 已經(jīng)被刪掉了,這時(shí) PV 就處于一個(gè) Released 的狀態(tài)。此時(shí)再根據(jù) ReclaimPolicy 是否是 Delete 來決定是刪掉還是只做一些狀態(tài)的同步。
以上就是 PV Controller 的簡(jiǎn)要實(shí)現(xiàn)邏輯。
AD Controller 是 Attach/Detach Controller 的一個(gè)簡(jiǎn)稱。
它有兩個(gè)核心對(duì)象,即 DesiredStateofWorld 和 ActualStateOfWorld。
DesiredStateofWorld 是集群中預(yù)期要達(dá)到的數(shù)據(jù)卷的掛載狀態(tài);
ActualStateOfWorld 則是集群內(nèi)部實(shí)際存在的數(shù)據(jù)卷掛載狀態(tài)。
它有兩個(gè)核心邏輯,desiredStateOfWorldPopulator 和 Reconcile。
desiredStateOfWorldPopulator 主要是用來同步集群的一些數(shù)據(jù)以及 DSW、ASW 數(shù)據(jù)的更新,它會(huì)把集群里面,比如說我們創(chuàng)建一個(gè)新的 PVC、創(chuàng)建一個(gè)新的 Pod 的時(shí)候,我們會(huì)把這些數(shù)據(jù)的狀態(tài)同步到 DSW 中;
Reconcile 則會(huì)根據(jù) DSW 和 ASW 對(duì)象的狀態(tài)做狀態(tài)同步。它會(huì)把 ASW 狀態(tài)變成 DSW 狀態(tài),在這個(gè)狀態(tài)的轉(zhuǎn)變過程中,它會(huì)去執(zhí)行 Attach、Detach 等操作。
下面這個(gè)表分別給出了 desiredStateOfWorld 以及 actualStateOfWorld 對(duì)象的一個(gè)具體例子。
desiredStateOfWorld 會(huì)對(duì)每一個(gè) Worker 進(jìn)行定義,包括 Worker 所包含的 Volume 以及一些試圖掛載的信息;
actualStateOfWorl 會(huì)把所有的 Volume 進(jìn)行一次定義,包括每一個(gè) Volume 期望掛載到哪個(gè)節(jié)點(diǎn)上、掛載的狀態(tài)是什么樣子的等等。
下圖是 AD Controller 實(shí)現(xiàn)的邏輯框圖。
從中我們可以看到,AD Controller 中有很多 Informer,Informer 會(huì)把集群中的 Pod 狀態(tài)、PV 狀態(tài)、Node 狀態(tài)、PVC 狀態(tài)同步到本地。
在初始化的時(shí)候會(huì)調(diào)用 populateDesireStateofWorld 以及 populateActualStateofWorld 將 desireStateofWorld、actualStateofWorld 兩個(gè)對(duì)象進(jìn)行初始化。
在執(zhí)行的時(shí)候,通過 desiredStateOfWorldPopulator 進(jìn)行數(shù)據(jù)同步,即把集群中的數(shù)據(jù)狀態(tài)同步到 desireStateofWorld 中。reconciler 則通過輪詢的方式把 actualStateofWorld 和 desireStateofWorld 這兩個(gè)對(duì)象進(jìn)行數(shù)據(jù)同步,在同步的時(shí)候,會(huì)通過調(diào)用 Volume Plugin 進(jìn)行 attach 和 detach 操作,同時(shí)它也會(huì)調(diào)用 nodeStatusUpdater 對(duì) Node 的狀態(tài)進(jìn)行更新。
以上就是 AD Controller 的簡(jiǎn)要實(shí)現(xiàn)邏輯。
Volume Manager 實(shí)際上是 Kubelet 中一部分,是 Kubelet 中眾多 Manager 的一個(gè)。它主要是用來做本節(jié)點(diǎn) Volume 的 Attach/Detach/Mount/Unmount 操作。
它和 AD Controller 一樣包含有 desireStateofWorld 以及 actualStateofWorld,同時(shí)還有一個(gè) volumePluginManager 對(duì)象,主要進(jìn)行節(jié)點(diǎn)上插件的管理。在核心邏輯上和 AD Controller 也類似,通過 desiredStateOfWorldPopulator 進(jìn)行數(shù)據(jù)的同步以及通過 Reconciler 進(jìn)行接口的調(diào)用。
這里我們需要講一下 Attach/Detach 這兩個(gè)操作:
之前我們提到 AD Controller 也會(huì)做 Attach/Detach 操作,所以到底是由誰來做呢?我們可以通過 “—enable-controller-attach-detach” 標(biāo)簽進(jìn)行定義,如果它為 True,則由 AD Controller 來控制;若為 False,就由 Volume Manager 來做。
它是 Kubelet 的一個(gè)標(biāo)簽,只能定義某個(gè)節(jié)點(diǎn)的行為,所以如果假設(shè)一個(gè)有 10 個(gè)節(jié)點(diǎn)的集群,它有 5 個(gè)節(jié)點(diǎn)定義該標(biāo)簽為 False,說明這 5 個(gè)節(jié)點(diǎn)是由節(jié)點(diǎn)上的 Kubelet 來做掛載,而其它 5 個(gè)節(jié)點(diǎn)是由 AD Controller 來做掛載。
下圖是 Volume Manager 實(shí)現(xiàn)邏輯圖。
我們可以看到,最外層是一個(gè)循環(huán),內(nèi)部則是根據(jù)不同的對(duì)象,包括 desireStateofWorld, actualStateofWorld 的不同對(duì)象做一個(gè)輪詢。
例如,對(duì) actualStateofWorld 中的 MountedVolumes 對(duì)象做輪詢,對(duì)其中的某一個(gè) Volume,如果它同時(shí)存在于 desireStateofWorld,這就說明實(shí)際的和期望的 Volume 均是處于掛載狀態(tài),因此我們不會(huì)做任何處理。如果它不存在于 desireStateofWorld,說明期望狀態(tài)中該 Volume 應(yīng)該處于 Umounted 狀態(tài),就執(zhí)行 UnmountVolume,將其狀態(tài)轉(zhuǎn)變?yōu)?desireStateofWorld 中相同的狀態(tài)。
所以我們可以看到:實(shí)際上,該過程就是根據(jù) desireStateofWorld 和 actualStateofWorld 的對(duì)比,再調(diào)用底層的接口來執(zhí)行相應(yīng)的操作,下面的 desireStateofWorld.UnmountVolumes 和 actualStateofWorld.AttachedVolumes 的操作也是同樣的道理。
我們之前提到的 PV Controller、AD Controller 以及 Volume Manager 其實(shí)都是通過調(diào)用 Volume Plugin 提供的接口,比如 Provision、Delete、Attach、Detach 等去做一些 PV、PVC 的管理。而這些接口的具體實(shí)現(xiàn)邏輯是放在 VolumePlugin 中的
根據(jù)源碼的位置可將 Volume Plugins 分為 In-Tree 和 Out-of-Tree 兩類:
In-Tree 表示源碼是放在 Kubernetes 內(nèi)部的,和 Kubernetes 一起發(fā)布、管理與迭代,缺點(diǎn)及時(shí)迭代速度慢、靈活性差;
Out-of-Tree 類的 Volume Plugins 的代碼獨(dú)立于 Kubernetes,它是由存儲(chǔ)商提供實(shí)現(xiàn)的,目前主要有 Flexvolume 和 CSI 兩種實(shí)現(xiàn)機(jī)制,可以根據(jù)存儲(chǔ)類型實(shí)現(xiàn)不同的存儲(chǔ)插件。所以我們比較推崇 Out-of-Tree 這種實(shí)現(xiàn)邏輯。
從位置上我們可以看到,Volume Plugins 實(shí)際上就是 PV Controller、AD Controller 以及 Volume Manager 所調(diào)用的一個(gè)庫,分為 In-Tree 和 Out-of-Tree 兩類 Plugins。它通過這些實(shí)現(xiàn)來調(diào)用遠(yuǎn)端的存儲(chǔ),比如說掛載一個(gè) NAS 的操作 “mount -t nfs *“,該命令其實(shí)就是在 Volume Plugins 中實(shí)現(xiàn)的,它會(huì)去調(diào)用遠(yuǎn)程的一個(gè)存儲(chǔ)掛載到本地。
從類型上來看,Volume Plugins 可以分為很多種。In-Tree 中就包含了 幾十種常見的存儲(chǔ)實(shí)現(xiàn),但一些公司的自己定義私有類型,有自己的 API 和參數(shù),公共存儲(chǔ)插件是無法支持的,這時(shí)就需要 Out-of-Tree 類的存儲(chǔ)實(shí)現(xiàn),比如 CSI、FlexVolume。
Volume Plugins 的具體實(shí)現(xiàn)會(huì)放到后面去講。這里主要看一下 Volume Plugins 的插件管理。
Kubernetes會(huì)在 PV Controller、AD Controller 以及 Volume Manager 中來做插件管理。通過 VolumePlguinMg 對(duì)象進(jìn)行管理。主要包含 Plugins 和 Prober 兩個(gè)數(shù)據(jù)結(jié)構(gòu)。
Plugins 主要是用來保存 Plugins 列表的一個(gè)對(duì)象,而 Prober 是一個(gè)探針,用于發(fā)現(xiàn)新的 Plugin,比如 FlexVolume、CSI 是擴(kuò)展的一種插件,它們是動(dòng)態(tài)創(chuàng)建和生成的,所以一開始我們是無法預(yù)知的,因此需要一個(gè)探針來發(fā)現(xiàn)新的 Plugin。
下圖是插件管理的整個(gè)過程。
PV Controller、AD Controller 以及 Volume Manager 在啟動(dòng)的時(shí)候會(huì)執(zhí)行一個(gè) InitPlugins 方法來對(duì) VolumePluginsMgr 做一些初始化。
它首先會(huì)將所有 In-Tree 的 Plugins 加入到我們的插件列表中。同時(shí)會(huì)調(diào)用 Prober 的 init 方法,該方法會(huì)首先調(diào)用一個(gè) InitWatcher,它會(huì)時(shí)刻觀察著某一個(gè)目錄 (比如圖中的 /usr/libexec/kubernetes/kubelet-plugins/volume/exec/),當(dāng)這個(gè)目錄每生成一個(gè)新文件的時(shí)候,也就是創(chuàng)建了一個(gè)新的 Plugins,此時(shí)就會(huì)生成一個(gè)新的 FsNotify.Create 事件,并將其加入到 EventsMap 中;同理,如果刪除了一個(gè)文件,就生成一個(gè) FsNotify.Remove 事件加入到 EventsMap 中。
當(dāng)上層調(diào)用 refreshProbedPlugins 時(shí),Prober 就會(huì)把這些事件進(jìn)行一個(gè)更新,如果是 Create,就將其添加到插件列表;如果是 Remove,就從插件列表中刪除一個(gè)插件。
以上就是 Volume Plugins 的插件管理機(jī)制。
我們之前說到 Pod 必須被調(diào)度到某個(gè) Worker 上才能去運(yùn)行。在調(diào)度 Pod 時(shí),我們會(huì)使用不同的調(diào)度器來進(jìn)行篩選,其中有一些與 Volume 相關(guān)的調(diào)度器。例如 VolumeZonePredicate、VolumeBindingPredicate、CSIMaxVolumLimitPredicate 等。
VolumeZonePredicate 會(huì)檢查 PV 中的 Label,比如 failure-domain.beta.kubernetes.io/zone 標(biāo)簽,如果該標(biāo)簽定義了 zone 的信息,VolumeZonePredicate 就會(huì)做相應(yīng)的判斷,即必須符合相應(yīng)的 zone 的節(jié)點(diǎn)才能被調(diào)度。
比如下圖左側(cè)的例子,定義了一個(gè) label 的 zone 為 cn-shenzhen-a。右側(cè)的 PV 則定義了一個(gè) nodeAffinity,其中定義了 PV 所期望的節(jié)點(diǎn)的 Label,該 Label 是通過 VolumeBindingPredicate 進(jìn)行篩選的。
存儲(chǔ)卷具體調(diào)度信息的實(shí)現(xiàn)可以參考《 從零開始入門 K8s | 應(yīng)用存儲(chǔ)和持久化數(shù)據(jù)卷:存儲(chǔ)快照與拓?fù)湔{(diào)度》,這里會(huì)有一個(gè)更加詳細(xì)的介紹。
Flexvolume 是 Volume Plugins 的一個(gè)擴(kuò)展,主要實(shí)現(xiàn) Attach/Detach/Mount/Unmount 這些接口。我們知道這些功能本是由 Volume Plugins 實(shí)現(xiàn)的,但是對(duì)于某些存儲(chǔ)類型,我們需要將其擴(kuò)展到 Volume Plugins 以外,所以我們需要把接口的具體實(shí)現(xiàn)放到外面。
在下圖中我們可以看到,Volume Plugins 其實(shí)包含了一部分 Flexvolume 的實(shí)現(xiàn)代碼,但這部分代碼其實(shí)只有一個(gè) “Proxy”的功能。
比如當(dāng) AD Controller 調(diào)用插件的一個(gè) Attach 時(shí),它首先會(huì)調(diào)用 Volume Plugins 中 Flexvolume 的 Attach 接口,但這個(gè)接口只是把調(diào)用轉(zhuǎn)到相應(yīng)的 Flexvolume 的Out-Of-Tree實(shí)現(xiàn)上。
Flexvolume是可被 Kubelet 驅(qū)動(dòng)的可執(zhí)行文件,每一次調(diào)用相當(dāng)于執(zhí)行一次 shell 的 ls 這樣的腳本,都是可執(zhí)行文件的命令行調(diào)用,因此它不是一個(gè)常駐內(nèi)存的守護(hù)進(jìn)程。
Flexvolume 的 Stdout 作為 Kubelet 調(diào)用的返回結(jié)果,這個(gè)結(jié)果需要是 JSON 格式。
Flexvolume默認(rèn)的存放地址為 “/usr/libexec/kubernetes/kubelet-plugins/volume/exec/alicloud~disk/disk”。
下面是一個(gè)命令格式和調(diào)用的實(shí)例。
Flexvolum 包含以下接口:
init: 主要做一些初始化的操作,比如部署插件、更新插件的時(shí)候做 init 操作,返回的時(shí)候會(huì)返回剛才我們所說的 DriveCapabilities 類型的數(shù)據(jù)結(jié)構(gòu),用來說明我們的 Flexvolume 插件有哪些功能;
GetVolumeName: 返回插件名;
Attach: 掛載功能的實(shí)現(xiàn)。根據(jù) —enable-controller-attach-detach 標(biāo)簽來決定是由 AD Controller 還是 Kubelet 來發(fā)起掛載操作;
WaitforAttach: Attach 經(jīng)常是異步操作,因此需要等待掛載完成,才能需要進(jìn)行下面的操作;
MountDevice:它是 mount 的一部分。這里我們將 mount 分為 MountDevice 和 SetUp 兩部分,MountDevice 主要做一些簡(jiǎn)單的預(yù)處理工作,比如將設(shè)備格式化、掛載到 GlobalMount 目錄中等;
GetPath:獲取每個(gè) Pod 對(duì)應(yīng)的本地掛載目錄;
Setup:使用 Bind 方式將 GlobalPath 中的設(shè)備掛載到 Pod 的本地目錄;
TearDown、UnmountDevice、Detach實(shí)現(xiàn)的是上面一些借口的逆過程;
ExpandVolumeDevice:擴(kuò)容存儲(chǔ)卷,由 Expand Controller 發(fā)起調(diào)用;
NodeExpand: 擴(kuò)容文件系統(tǒng),由 Kubelet 發(fā)起調(diào)用。
上面這些接口不一定需要全部實(shí)現(xiàn),如果某個(gè)接口沒有實(shí)現(xiàn)的話,可以將返回結(jié)果定義成:
{ "status": "Not supported", "message": "error message" }
告訴調(diào)用者沒有實(shí)現(xiàn)這個(gè)接口。此外,Volume Plugins 中的 Flexvolume 接口除了作為一個(gè) Proxy 外,它也提供了一些默認(rèn)實(shí)現(xiàn),比如 Mount 操作。所以如果你的 Flexvolume 中沒有定義該接口,該默認(rèn)實(shí)現(xiàn)就會(huì)被調(diào)用。
在定義 PV 時(shí)可以通過 secretRef 字段來定義一些 secret 的功能。比如掛載時(shí)所需的用戶名和密碼,就可以通過 secretRef 傳入。
從掛載流程和卸載流程兩個(gè)方向來分析 Flexvolume 的掛載過程。
我們首先看 Attach 操作,它調(diào)用了一個(gè)遠(yuǎn)端的 API 把我們的 Storage 掛載到目標(biāo)節(jié)點(diǎn)中的某個(gè)設(shè)備上去。然后通過 MountDevice 將本地設(shè)備掛載到 GlobalPath 中,同時(shí)也會(huì)做一些格式化這樣的操作。Mount 操作(SetUp),它會(huì)把 GlobalPath 掛載 PodPath 中,PodPath 就是 Pod 啟動(dòng)時(shí)所映射的一個(gè)目錄。
下圖給出了一個(gè)例子,比如我們一個(gè)云盤,其 Volume ID 為 d-8vb4fflsonz21h41cmss,在執(zhí)行完 Attach 和 WaitForAttach 操作之后,就會(huì)將其掛載到目標(biāo)節(jié)點(diǎn)上的 /dec/vdc 設(shè)備中。執(zhí)行 MountDevice 之后,就會(huì)把上述設(shè)備格式化,掛載到一個(gè)本地的 GlobalPath 中。而執(zhí)行完 Mount 之后,就會(huì)將 GlobalPath 映射到 Pod 相關(guān)的一個(gè)子目錄中。最后執(zhí)行 Bind 操作,將我們的本地目錄映射到容器中。這樣完成一次掛載過程。
卸載流程就是一個(gè)逆過程。上述過程描述的是一個(gè)塊設(shè)備的掛載過程,對(duì)于文件存儲(chǔ)類型,就無需 Attach、MountDevice操作,只需要 Mount 操作,因此文件系統(tǒng)的 Flexvolume 實(shí)現(xiàn)較為簡(jiǎn)單,只需要 Mount 和 Unmount 過程即可。
其中主要實(shí)現(xiàn)的是 init()、doMount()、doUnmount() 方法。在執(zhí)行該腳本的時(shí)候?qū)魅氲膮?shù)進(jìn)行判斷來決定執(zhí)行哪一個(gè)命令。
在 Github 上還有很多 Flexvolume 的示例,大家可以自行參考查閱。阿里云提供了一個(gè)
Flexvolume 的實(shí)現(xiàn),有興趣的可以參考一下。
下圖給出了一個(gè) Flexvolume 類型的 PV 模板。它和其它模板實(shí)際上沒有什么區(qū)別,只不過類型被定義為 flexVolume 類型。flexVolume 中定義了 driver、fsType、options。
driver 定義的是我們實(shí)現(xiàn)的某種驅(qū)動(dòng),比如圖中的是 aliclound/disk,也可以是 aliclound/nas 等;
fsType 定義的是文件系統(tǒng)類型,比如 “ext4”;
options 包含了一些具體的參數(shù),比如定義云盤的 id 等。
我們也可以像其它類型一樣,通過 selector 中的 matchLabels 定義一些篩選條件。同樣也可以定義一些相應(yīng)的調(diào)度信息,比如定義 zone 為 cn-shenzhen-a。
下面是一個(gè)具體的運(yùn)行結(jié)果。在 Pod 內(nèi)部我們掛載了一個(gè)云盤,其所在本地設(shè)備為 /dev/vdb。通過 mount | grep disk 我們可以看到相應(yīng)的掛載目錄,首先它會(huì)將 /dev/vdb 掛載到 GlobalPath 中;其次會(huì)將 GlobalPath 通過 mount 命令掛載到一個(gè) Pod 所定義的本地子目錄中去;最后會(huì)把該本地子目錄映射到 /data 上。
和 Flexvolume 類似,CSI 也是為第三方存儲(chǔ)提供數(shù)據(jù)卷實(shí)現(xiàn)的抽象接口。
有了 Flexvolume,為何還要 CSI 呢?
Flexvolume 只是給 kubernetes 這一個(gè)編排系統(tǒng)來使用的,而 CSI 可以滿足不同編排系統(tǒng)的需求,比如 Mesos,Swarm。
其次 CSI 是容器化部署,可以減少環(huán)境依賴,增強(qiáng)安全性,豐富插件的功能。我們知道,F(xiàn)lexvolume 是在 host 空間一個(gè)二進(jìn)制文件,執(zhí)行 Flexvolum 時(shí)相當(dāng)于執(zhí)行了本地的一個(gè) shell 命令,這使得我們?cè)诎惭b Flexvolume 的時(shí)候需要同時(shí)安裝某些依賴,而這些依賴可能會(huì)對(duì)客戶的應(yīng)用產(chǎn)生一些影響。因此在安全性上、環(huán)境依賴上,就會(huì)有一個(gè)不好的影響。
同時(shí)對(duì)于豐富插件功能這一點(diǎn),我們?cè)?Kubernetes 生態(tài)中實(shí)現(xiàn) operator 的時(shí)候,經(jīng)常會(huì)通過 RBAC 這種方式去調(diào)用 Kubernetes 的一些接口來實(shí)現(xiàn)某些功能,而這些功能必須要在容器內(nèi)部實(shí)現(xiàn),因此像 Flexvolume 這種環(huán)境,由于它是 host 空間中的二進(jìn)制程序,就沒法實(shí)現(xiàn)這些功能。而 CSI 這種容器化部署的方式,可以通過 RBAC 的方式來實(shí)現(xiàn)這些功能。
CSI 主要包含兩個(gè)部分:CSI Controller Server 與 CSI Node Server。
Controller Server 是控制端的功能,主要實(shí)現(xiàn)創(chuàng)建、刪除、掛載、卸載等功能;
Node Server 主要實(shí)現(xiàn)的是節(jié)點(diǎn)上的 mount、Unmount 功能。
下圖給出了 CSI 接口通信的描述。CSI Controller Server 和 External CSI SideCar 是通過 Unix Socket 來進(jìn)行通信的,CSI Node Server 和 Kubelet 也是通過 Unix Socket 來通信,之后我們會(huì)講一下 External CSI SiderCar 的具體概念。
下圖給出了 CSI 的接口。主要分為三類:通用管控接口、節(jié)點(diǎn)管控接口、中心管控接口。
通用管控接口主要返回 CSI 的一些通用信息,像插件的名字、Driver 的身份信息、插件所提供的能力等;
節(jié)點(diǎn)管控接口的 NodeStageVolume 和 NodeUnstageVolume 就相當(dāng)于 Flexvolume 中的 MountDevice 和 UnmountDevice。NodePublishVolume 和 NodeUnpublishVolume 就相當(dāng)于 SetUp 和 TearDown 接口;
中心管控接口的 CreateVolume 和 DeleteVolume 就是我們的 Provision 和 Delete 存儲(chǔ)卷的一個(gè)接口,ControllerPublishVolume 和 ControllerUnPublishVolume 則分別是 Attach 和 Detach 的接口。
CSI 是通過 CRD 的形式實(shí)現(xiàn)的,所以 CSI 引入了這么幾個(gè)對(duì)象類型:VolumeAttachment、CSINode、CSIDriver 以及 CSI Controller Server 與 CSI Node Server 的一個(gè)實(shí)現(xiàn)。
在 CSI Controller Server 中,有傳統(tǒng)的類似 Kubernetes 中的 AD Controller 和 Volume Plugins,VolumeAttachment 對(duì)象就是由它們所創(chuàng)建的。
此外,還包含多個(gè) External Plugin組件,每個(gè)組件和 CSI Plugin 組合的時(shí)候會(huì)完成某種功能。比如:
External Provisioner 和 Controller Server 組合的時(shí)候就會(huì)完成數(shù)據(jù)卷的創(chuàng)建與刪除功能;
External Attacher 和 Controller Server 組合起來可以執(zhí)行數(shù)據(jù)卷的掛載和操作;
External Resizer 和 Controller Server 組合起來可以執(zhí)行數(shù)據(jù)卷的擴(kuò)容操作;
External Snapshotter 和 Controller Server 組合則可以完成快照的創(chuàng)建和刪除。
CSI Node Server 中主要包含 Kubelet 組件,包括 VolumeManager 和 VolumePlugin,它們會(huì)去調(diào)用 CSI Plugin 去做 mount 和 unmount 操作;另外一個(gè)組件 Driver Registrar 主要實(shí)現(xiàn)的是 CSI Plugin 注冊(cè)的功能。
以上就是 CSI 的整個(gè)拓?fù)浣Y(jié)構(gòu),接下來我們將分別介紹不同的對(duì)象和組件。
我們將介紹 3 種對(duì)象:VolumeAttachment,CSIDriver,CSINode。
VolumeAttachment 描述一個(gè) Volume 卷在一個(gè) Pod 使用中掛載、卸載的相關(guān)信息。例如,對(duì)一個(gè)卷在某個(gè)節(jié)點(diǎn)上的掛載,我們通過 VolumeAttachment 對(duì)該掛載進(jìn)行跟蹤。AD Controller 創(chuàng)建一個(gè) VolumeAttachment,而 External-attacher 則通過觀察該 VolumeAttachment,根據(jù)其狀態(tài)來進(jìn)行掛載和卸載操作。
下圖就是一個(gè) VolumeAttachment 的例子,其類別 (kind) 為 VolumeAttachment,spec 中指定了 attacher 為 ossplugin.csi.alibabacloud.com,即指定掛載是由誰操作的;指定了 nodeName 為 cn-zhangjiakou.192.168.1.53,即該掛載是發(fā)生在哪個(gè)節(jié)點(diǎn)上的;指定了 source 為 persistentVolumeName 為 oss-csi-pv,即指定了哪一個(gè)數(shù)據(jù)卷進(jìn)行掛載和卸載。
status 中 attached 指示了掛載的狀態(tài),如果是 False, External-attacher 就會(huì)執(zhí)行一個(gè)掛載操作。
第二個(gè)對(duì)象是 CSIDriver,它描述了集群中所部署的 CSI Plugin 列表,需要管理員根據(jù)插件類型進(jìn)行創(chuàng)建。
例如下圖中創(chuàng)建了一些 CSI Driver,通過
kuberctl get csidriver
我們可以看到集群里面創(chuàng)建的 3 種類型的 CSI Driver:一個(gè)是云盤;一個(gè)是 NAS;一個(gè)是 OSS。
在 CSI Driver 中,我們定義了它的名字,在 spec 中還定義了 attachRequired 和 podInfoOnMount 兩個(gè)標(biāo)簽。
attachRequired 定義一個(gè) Plugin 是否支持 Attach 功能,主要是為了對(duì)塊存儲(chǔ)和文件存儲(chǔ)做區(qū)分。比如文件存儲(chǔ)不需要 Attach 操作,因此我們將該標(biāo)簽定義為 False;
podInfoOnMount 則是定義 Kubernetes 在調(diào)用 Mount 接口時(shí)是否帶上 Pod 信息。
第三個(gè)對(duì)象是 CSINode,它是集群中的節(jié)點(diǎn)信息,由 node-driver-registrar 在啟動(dòng)時(shí)創(chuàng)建。它的作用是每一個(gè)新的 CSI Plugin 注冊(cè)后,都會(huì)在 CSINode 列表里添加一個(gè) CSINode 信息。
例如下圖,定義了 CSINode 列表,每一個(gè) CSINode 都有一個(gè)具體的信息(左側(cè)的 YAML)。以 一 cn-zhangjiakou.192.168.1.49 為例,它包含一個(gè)云盤的 CSI Driver,還包含一個(gè) NAS 的 CSI Driver。每個(gè) Driver 都有自己的 nodeID 和它的拓?fù)湫畔?topologyKeys。如果沒有拓?fù)湫畔?,可以?topologyKeys 設(shè)置為 “null”。也就是說,假如有一個(gè)有 10 個(gè)節(jié)點(diǎn)的集群,我們可以只定義一部分節(jié)點(diǎn)擁有 CSINode。
Node-Driver-Registrar 主要實(shí)現(xiàn)了 CSI Plugin 注冊(cè)的一個(gè)機(jī)制。我們來看一下下圖中的流程圖。
第 1 步,在啟動(dòng)的時(shí)候有一個(gè)約定,比如說在 /var/lib/kuberlet/plugins_registry 這個(gè)目錄每新加一個(gè)文件,就相當(dāng)于每新加了一個(gè) Plugin;
啟動(dòng) Node-Driver-Registrar,它首先會(huì)向 CSI-Plugin 發(fā)起一個(gè)接口調(diào)用 GetPluginInfo,這個(gè)接口會(huì)返回 CSI 所監(jiān)聽的地址以及 CSI-Plugin 的一個(gè) Driver name;
第 2 步,Node-Driver-Registrar 會(huì)監(jiān)聽 GetInfo 和 NotifyRegistrationStatus 兩個(gè)接口;
第 3 步,會(huì)在
/var/lib/kuberlet/plugins_registry
這個(gè)目錄下啟動(dòng)一個(gè) Socket,生成一個(gè) Socket 文件 ,例如:”diskplugin.csi.alibabacloud.com-reg.sock”,此時(shí) Kubelet 通過 Watcher 發(fā)現(xiàn)這個(gè) Socket 后,它會(huì)通過該 Socket 向 Node-Driver-Registrar 的 GetInfo 接口進(jìn)行調(diào)用。GetInfo 會(huì)把剛才我們所獲得的的 CSI-Plugin 的信息返回給 Kubelet,該信息包含了 CSI-Plugin 的監(jiān)聽地址以及它的 Driver name;
第 4 步,Kubelet 通過得到的監(jiān)聽地址對(duì) CSI-Plugin 的 NodeGetInfo 接口進(jìn)行調(diào)用;
第 5 步,調(diào)用成功之后,Kubelet 會(huì)去更新一些狀態(tài)信息,比如節(jié)點(diǎn)的 Annotations、Labels、status.allocatable 等信息,同時(shí)會(huì)創(chuàng)建一個(gè) CSINode 對(duì)象;
第 6 步,通過對(duì) Node-Driver-Registrar 的 NotifyRegistrationStatus 接口的調(diào)用告訴它我們已經(jīng)把 CSI-Plugin 注冊(cè)成功了。
通過以上 6 步就實(shí)現(xiàn)了 CSI Plugin 注冊(cè)機(jī)制。
External-Attacher 主要是通過 CSI Plugin 的接口來實(shí)現(xiàn)數(shù)據(jù)卷的掛載與卸載功能。它通過觀察 VolumeAttachment 對(duì)象來實(shí)現(xiàn)狀態(tài)的判斷。VolumeAttachment 對(duì)象則是通過 AD Controller 來調(diào)用 Volume Plugin 中的 CSI Attacher 來創(chuàng)建的。CSI Attacher 是一個(gè) In-Tree 類,也就是說這部分是 Kubernetes 完成的。
當(dāng) VolumeAttachment 的狀態(tài)是 False 時(shí),External-Attacher 就去調(diào)用底層的一個(gè) Attach 功能;若期望值為 False,就通過底層的 ControllerPublishVolume 接口實(shí)現(xiàn) Detach 功能。同時(shí),External-Attacher 也會(huì)同步一些 PV 的信息在里面。
我們現(xiàn)在來看一下塊存儲(chǔ)的部署情況。
之前提到 CSI 的 Controller 分為兩部分,一個(gè)是 Controller Server Pod,一個(gè)是 Node Server Pod。
我們只需要部署一個(gè) Controller Server,如果是多備份的,可以部署兩個(gè)。Controller Server 主要是通過多個(gè)外部插件來實(shí)現(xiàn)的,比如說一個(gè) Pod 中可以定義多個(gè) External 的 Container 和一個(gè)包含 CSI Controller Server 的 Container,這時(shí)候不同的 External 組件會(huì)和 Controller Server 組成不同的功能。
而 Node Server Pod 是個(gè) DaemonSet,它會(huì)在每個(gè)節(jié)點(diǎn)上進(jìn)行注冊(cè)。Kubelet 會(huì)直接通過 Socket 的方式直接和 CSI Node Server 進(jìn)行通信、調(diào)用 Attach/Detach/Mount/Unmount 等。
Driver Registrar 只是做一個(gè)注冊(cè)的功能,會(huì)在每個(gè)節(jié)點(diǎn)上進(jìn)行部署。
文件存儲(chǔ)和塊存儲(chǔ)的部署情況是類似的。只不過它會(huì)把 Attacher 去掉,也沒有 VolumeAttachment 對(duì)象。
和 Flexvolume 一樣,我們看一下它的定義模板。
可以看到,它和其它的定義并沒什么區(qū)別。主要的區(qū)別在于類型為 CSI,里面會(huì)定義 driver,volumeHandle,volumeAttribute,nodeAffinity 等。
driver 就是定義是由哪一個(gè)插件來去實(shí)現(xiàn)掛載;
volumeHandle 主要是指示 PV 的唯一標(biāo)簽;
volumeAttribute 用于附加參數(shù),比如 PV 如果定義的是 OSS,那么就可以在 volumeAttribute 定義 bucket、訪問的地址等信息在里面;
nodeAffinity 則可以定義一些調(diào)度信息。與 Flexvolume 類似,還可以通過 selector 和 Label 定義一些綁定條件。
中間的圖給出了一個(gè)動(dòng)態(tài)調(diào)度的例子,它和其它類型的動(dòng)態(tài)調(diào)度是一樣的。只不過在定義 provisioner 的時(shí)候指定了一個(gè) CSI 的 provisioner。
下面給出了一個(gè)具體的掛載例子。
Pod 啟動(dòng)之后,我們可以看到 Pod 已經(jīng)把一個(gè) /dev/vdb 掛載到 /data 上了。同理,它有一個(gè) GlobalPath 和一個(gè) PodPath 的集群在里面。我們可以把一個(gè) /dev/vdb 掛載到一個(gè) GlobalPath 里面,它就是一個(gè) CSI 的一個(gè) PV 在本節(jié)點(diǎn)上唯一確定的目錄。一個(gè) PodPath 就是一個(gè) Pod 所確定的一個(gè)本地節(jié)點(diǎn)的目錄,它會(huì)把 Pod 所對(duì)應(yīng)的目錄映射到我們的容器中去。
除了掛載、卸載之外,CSI 化提供了一些附加的功能。例如,在定義模板的時(shí)候往往需要一些用戶名和密碼信息,此時(shí)我們就可通過 Secret來進(jìn)行定義。之前我們所講的 Flexvolume 也支持這個(gè)功能,只不過 CSI 可以根據(jù)不同的階段定義不同的 Secret 類型,比如掛載階段的 Secret、Mount 階段的 Secret、Provision 階段的 Secret。
Topology是一個(gè)拓?fù)涓兄墓δ?。?dāng)我們定義一個(gè)數(shù)據(jù)卷的時(shí)候,集群中并不是所有節(jié)點(diǎn)都能滿足該數(shù)據(jù)卷的需求,比如我們需要掛載不同的 zone 的信息在里面,這就是一個(gè)拓?fù)涓兄墓δ堋_@部分在第 10 講已有詳細(xì)的介紹,大家可以進(jìn)行參考。
Block Volume就是 volumeMode 的一個(gè)定義,它可以定義成 Block 類型,也可以定義成文件系統(tǒng)類型,CSI 支持 Block 類型的 Volume,就是說掛載到 Pod 內(nèi)部時(shí),它是一個(gè)塊設(shè)備,而不是一個(gè)目錄。
Skip Attach和 PodInfo On Mount是剛才我們所講過的 CSI Driver 中的兩個(gè)功能。
CSI 還是一個(gè)比較新的實(shí)現(xiàn)方式。近期也有了很多更新,比如 ExpandCSIVolumes 可以實(shí)現(xiàn)文件系統(tǒng)擴(kuò)容的功能;VolumeSnapshotDataSource 可以實(shí)現(xiàn)數(shù)據(jù)卷的快照功能;VolumePVCDataSource 實(shí)現(xiàn)的是可以定義 PVC 的數(shù)據(jù)源;我們以前在使用 CSI 的時(shí)候只能通過 PVC、PV 的方式定義,而不能直接在 Pod 里面定義 Volume,CSIInlineVolume 則可以讓我們可以直接在 Volume 中定義一些 CSI 的驅(qū)動(dòng)。
阿里云在 GitHub 上開源了 CSI 的實(shí)現(xiàn),大家有興趣的可以看一下,做一些參考。
主要介紹了 Kubernetes 集群中存儲(chǔ)卷相關(guān)的知識(shí),主要有以下三點(diǎn)內(nèi)容:
第一部分講述了 Kubernetes 存儲(chǔ)架構(gòu),主要包括存儲(chǔ)卷概念、掛載流程、系統(tǒng)組件等相關(guān)知識(shí);
第二部分講述了 Flexvolume 插件的實(shí)現(xiàn)原理、部署架構(gòu)、使用示例等;
第三部分講述了 CSI 插件的實(shí)現(xiàn)原理、資源對(duì)象、功能組件、使用示例等;
看完上述內(nèi)容,你們掌握Kubernetes存儲(chǔ)架構(gòu)及插件使用是怎樣的的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!
新聞名稱:Kubernetes存儲(chǔ)架構(gòu)及插件使用是怎樣的
本文網(wǎng)址:http://www.rwnh.cn/article36/jispsg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、App設(shè)計(jì)、網(wǎng)站策劃、營(yíng)銷型網(wǎng)站建設(shè)、靜態(tài)網(wǎng)站、云服務(wù)器
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)