過去,當Kubernetes版本還很低(v1.0.0左右)時,就有了卷插件。他們須要將持久數據存儲卷鏈接到Kubernetes。當時數量還不多。 GCE PD,Ceph,AWS EBS和其餘一些存儲服務提供商都是最先的存儲提供商。json
一般,它們與Kubernetes綁定在一塊兒。所以,它們被稱爲「in-tree plugins」。可是,許多開發人員認爲可用插件是有侷限性的。所以,他們建立了本身的解決方案,經過補丁將它們集成到Kubernetes核心中,編譯了本身的Kubernetes版本並將其安裝在服務器上。可是隨着時間的流逝,Kubernetes開發人員已經意識到,您不能經過給「一我的一條魚」來解決問題-您必須教他「釣魚」。所以,他們決定在1.2.0版本中爲須要的人添加「釣魚竿」…bash
Kubernetes開發人員建立了FlexVolume插件,該插件是用於使用第三方FlexVolume驅動程序的變量和方法的邏輯封裝。 服務器
讓咱們仔細看看什麼是FlexVolume驅動程序。它是一個可執行文件(二進制文件,Python腳本,Bash腳本等),將命令行參數做爲輸入並以JSON格式返回包含預約義字段的消息。按照約定,第一個參數是方法,全部其餘參數是其參數。dom
FlexVolume驅動程序必須實現如下基本方法集:學習
flexvolume_driver mount # mounts volume to a directory in the pod # expected output: { "status": "Success"/"Failure"/"Not supported", "message": "<Reason for success/failure>", } flexvolume_driver unmount # unmounts volume from a directory in the pod # expected output: { "status": "Success"/"Failure"/"Not supported", "message": "<Reason for success/failure>", } flexvolume_driver init # initializes the plugin # expected output: { "status": "Success"/"Failure"/"Not supported", "message": "<Reason for success/failure>", // defines if attach/detach methods are supported "capabilities":{"attach": True/False} }
attach
和detach
方法肯定調用驅動程序時kubelet
的行爲。一樣,有兩種特定的方法,expandvolume
和expandfs
,它們容許動態調整卷大小。 您能夠在Rook Ceph運算符中使用咱們的pull請求,做爲expandvolume
方法提供的更改的示例,以及動態調整卷大小的功能。flex
這是用於NFS的FlexVolume驅動程序的示例:google
usage() { err "Invalid usage. Usage: " err "\t$0 init" err "\t$0 mount <mount dir> <json params>" err "\t$0 unmount <mount dir>" exit 1 } err() { echo -ne $* 1>&2 } log() { echo -ne $* >&1 } ismounted() { MOUNT=`findmnt -n ${MNTPATH} 2>/dev/null | cut -d' ' -f1` if [ "${MOUNT}" == "${MNTPATH}"]; then echo "1" else echo "0" fi } domount() { MNTPATH=$1 NFS_SERVER=$(echo $2 | jq -r '.server') SHARE=$(echo $2 | jq -r '.share') if[ $(ismounted) -eq 1] ; then log '{"status": "Success"}' exit 0 fi mkdir -p ${MNTPATH} &> /dev/nullmount -t nfs ${NFS_SERVER}:${SHARE} ${MNTPATH} &> /dev/null if [ $? -ne 0]; then err "{ \"status\": \"Failure\", \"message\": \"Failed to mount ${NFS_SERVER}:${SHARE} at ${MNTPATH}\"}" exit 1 fi log '{"status": "Success"}' exit 0 } unmount() { MNTPATH=$1 if [ $(ismounted) -eq 0 ] ; then log '{"status": "Success"}' exit 0 fi umount ${MNTPATH} &> /dev/null if [ $? -ne 0 ]; then err "{ \"status\": \"Failed\", \"message\": \"Failed to unmount volume at ${MNTPATH}\"}" exit 1 fi log '{"status": "Success"}' exit 0 } op=$1 if [ "$op" = "init" ]; then log '{"status": "Success", "capabilities": {"attach": false}}' exit 0 fi if [ $# -lt 2 ]; then usage fi shift case "$op" in mount) domount $* ;; unmount) unmount $* ;; *) log '{"status": "Not supported"}' exit 0 esac exit 1
建立可執行文件後,必須將驅動程序部署到Kubernetes集羣。該驅動程序必須存在於每一個羣集節點上的預約義路徑中。默認路徑是
/usr/libexec/kubernetes/kubelet-plugins/volume/exec/vendor_name〜driver_name/spa
…可是,路徑可能在各類Kubernetes發行版(OpenShift,Rancher等)中有所不一樣。插件
將FlexVolume驅動程序部署到羣集節點是一項艱鉅的任務。您能夠手動執行此操做,可是,因爲添加新節點,自動水平縮放,或者因爲節點故障而替換節點時,羣集中出現新節點的可能性很高。在這種狀況下,除非在此處手動複製FlexVolume驅動程序,不然根本不可能在這些節點上使用永久性存儲。命令行
可是,Kubernetes的資源之一DaemonSet能夠解決此問題。在集羣中建立新節點時,它將自動獲取DaemonSet中定義的新容器。而後,將本地卷安裝到與FlexVolume驅動程序的路徑匹配的本地目錄中。成功建立後,Pod將驅動程序所需的文件複製到磁盤。
這是用於部署FlexVolume插件的DaemonSet的示例:
以及用於複製FlexVolume驅動程序的Bash腳本示例:
請注意,複製操做不是原子操做。在kubelet的準備過程完成以前,確實存在kubelet開始使用該驅動程序的風險,從而致使錯誤。正確的方法是使用不一樣的名稱複製驅動程序文件,而後重命名它們(由於重命名操做是原子的)。
使用FlexVolume驅動程序時的下一個問題是,您必須爲大多數類型的卷安裝一些先決條件(例如,用於Ceph的ceph-common軟件包)。最初,FlexVolume插件並非爲如此複雜的系統設計的。
針對Rook運算符的FlexVolume驅動程序實現了針對此問題的創新解決方案。驅動程序自己是RPC客戶端。用於通訊的IPC套接字位於驅動程序的目錄中。如上所述,DaemonSet是交付驅動程序文件的理想選擇,由於它會自動將Rook驅動程序做爲卷掛載目錄。複製完成後,此Pod經過已安裝的卷做爲功能齊全的RPC服務器鏈接到IPC套接字。 ceph-common軟件包已經安裝在pod的容器中。 IPC套接字確保kubelet將與同一節點中的相應pod通訊。很棒的主意,不是嗎?
在某個時候,Kubernetes開發人員發現有20個用於存儲卷的in-tree插件。它們中的每一個(甚至很小)更改都必須通過整個Kubernetes發行週期。
事實證實,您必須更新整個集羣才能使用新的插件版本!此外,您可能會遇到不愉快的驚喜:新的Kubernetes版本可能與當前的Linux內核不兼容!所以,您擦乾眼淚,懇求老闆和客戶得到更新Linux內核和Kubernetes集羣的許可(可能會致使停機)…
這不是很奇怪又有趣嗎?隨着時間的流逝,對於整個社區來講,現有的方法已經行不通了。所以,Kubernetes開發人員已決定中止在覈心中包含新的卷插件。
CSI是核心中包含的最後一個插件,旨在完全解決持久性存儲的問題。 Kubernetes 1.9中宣佈了其alpha版本,簡稱爲Out-of-Tree CSI卷插件。
首先,咱們要強調的是,CSI不是一個卷插件,它是用於建立自定義組件以與數據存儲一塊兒使用的成熟標準。容器編排系統(例如Kubernetes和Mesos)應該「學習」如何使用根據此標準實現組件。好吧,Kubernetes已經成功作到了。
Kubernetes CSI插件如何工做? CSI插件使用由第三方開發人員建立的自定義驅動程序(CSI驅動程序)。 Kubernetes的CSI驅動程序必須至少包含如下兩個組件(pod):
StatefulSet
部署形式實現爲gRPC服務器。DaemonSet
部署形式實現爲gRPC服務器。
您能夠在本文中得到有關其工做原理的更多詳細信息:瞭解CSI。
您以爲這個清單熟悉嗎?正確,CSI的優點彌補了FlexVolume插件的不足。
做爲建立用於數據存儲的自定義插件的標準,CSI受到了社區的熱烈歡迎。此外,因爲其優點和多功能性,甚至對於Ceph或AWS EBS也已經實現了CSI驅動程序,而Ceph或AWS EBS以前已經擁有本身的插件(從一開始就集成到Kubernetes中)。
在2019年初,in-tree插件被宣佈棄用。 Kubernetes開發人員將維護FlexVolume插件,可是新功能只會添加到CSI,而不會添加到FlexVolume。