<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          詳解Kubernetes存儲體系

          共 7842字,需瀏覽 16分鐘

           ·

          2020-11-01 09:29


          Volume、PV、PVC、StorageClass由來

          先思考一個問題,為什么會引入Volume這樣一個概念?

          答案很簡單,為了實現(xiàn)數(shù)據(jù)持久化,數(shù)據(jù)的生命周期不隨著容器的消亡而消亡。

          在沒有介紹Kubernetes Volume之前,先來回顧下Docker VolumeDocker Volume常用使用方式有兩種,

          • volumes通過這種方式,Docker管理宿主機文件系統(tǒng)的一部分,默認位于/var/lib/docker/volumes目錄中,由于在創(chuàng)建時沒有創(chuàng)建指定數(shù)據(jù)卷,docker自身會創(chuàng)建默認數(shù)據(jù)卷;
          • bind mounts通過這種方式,可以把容器內(nèi)文件掛載到宿主機任意目錄。

          既然有了Docker Volume,為啥Kubernetes又搞出了自己的Volume?谷歌的標新立異?

          答案是否定的,Kubernetes VolumeDocker Volume概念相似,但是又有不同的地方,Kubernetes VolumePod的生命周期相同,但與容器的生命周期不相關(guān)。當(dāng)容器終止或重啟時,Volume中的數(shù)據(jù)也不會丟失。當(dāng)Pod被刪除時,Volume才會被清理。并且數(shù)據(jù)是否丟失取決于Volume的具體類型,比如emptyDir類型的Volume數(shù)據(jù)會丟失,而持久化類型的數(shù)據(jù)則不會丟失。另外Kubernetes提供了將近20Volume類型。

          現(xiàn)在有了KubernetesVolume,我們就可以完全可以在Yaml編排文件中填寫上Volume是字段,如下nfs所示:

          ....
          volumes:
          ????-?name:?static-nfs
          ??????nfs:
          ??????????server:?12.18.17.240
          ??????????path:?/nfs/data/static

          如果你使用ceph作為存儲插件,你可以在編排文件中這樣定義:

          volumes:
          ????-?name:?ceph-vol
          ??????cephfs:
          ????????monitors:
          ????????-?12.18.17.241:6789
          ????????-?12.18.17.242:6789
          ????????user:?admin
          ????????secretRef:
          ??????????name:?ceph-secret
          ????????readOnly:?true

          當(dāng)然只要是Kubernetes已經(jīng)實現(xiàn)的數(shù)據(jù)卷類型,你都可以按照如上方式進行直接在Yaml編排文件中定義使用。

          看到這里其實已經(jīng)完成了80%的工作,那么為什么還要設(shè)計多此一舉的PV呢?這個問題先擱置下,后面會有說明。

          在沒有說明為什么要設(shè)計多此一舉的PV PVC之前,先來看看什么是PV PVC

          PV是對持久化存儲數(shù)據(jù)卷的一種描述。

          PV通常是由運維人員提前在集群里面創(chuàng)建等待使用的一種數(shù)據(jù)卷。如下所示:

          apiVersion:?v1
          kind:?PersistentVolume
          metadata:
          ??name:?nfs
          spec:
          ??capacity:
          ????storage:?10Gi
          ??accessModes:
          ????-?ReadWriteMany
          ??nfs:
          ????server:?10.244.1.4
          ????path:?"/nfs"

          PVC描述的是持久化存儲的屬性,比如大小、讀寫權(quán)限等。

          PVC通常由開發(fā)人員創(chuàng)建,如下所示:

          apiVersion:?v1
          kind:?PersistentVolumeClaim
          metadata:
          ??name:?nfs
          spec:
          ??accessModes:
          ????-?ReadWriteMany
          ??resources:
          ????requests:
          ??????storage:?10Gi

          而用戶創(chuàng)建的PV PVC必須綁定完成之后才能被利用起來。而PV PVC綁定起來的前提是PVspec中聲明字段大小、權(quán)限等必須滿足PVC的要求。

          成功綁定之后,就可以在Pod Yaml編排文件中定義和使用。如下所示:

          apiVersion:?v1
          kind:?Pod
          metadata:
          ??labels:
          ????role:?web
          spec:
          ??containers:
          ??-?name:?web
          ????image:?nginx
          ????ports:
          ??????-?name:?web
          ????????containerPort:?80
          ????volumeMounts:
          ????????-?name:?nfs
          ??????????mountPath:?"/usr/share/nginx/html"
          ??volumes:
          ??-?name:?nfs
          ????persistentVolumeClaim:
          ??????claimName:?nfs

          看到這里,我們還會認為僅僅是PVVolume多了一層抽象,并不見得比直接在Yaml中聲明Volume高明多少。仔細思考下,我們?yōu)槭裁茨軌蛑苯釉?code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(271, 93, 108);">Yaml中直接定義Volume?因為Kubernetes已經(jīng)幫助我們實現(xiàn)了這種Volume類型,如果我們有自己的存儲類型,而Kubernetes中并沒有實現(xiàn),這種是沒有辦法直接在Yaml編排文件中直接定義Volume的。這個時候PV PVC面向?qū)ο蟮脑O(shè)計就體現(xiàn)出其價值了。這也是在軟件開發(fā)領(lǐng)域經(jīng)常碰到的問題,開源軟件無法滿足要求,但也沒有提供出可擴展的接口,沒辦法,只能重新造輪子。

          我們在開發(fā)過程中經(jīng)常碰到這樣一個問題,在Pod中聲明一個PVC之后,發(fā)現(xiàn)Pod不能被調(diào)度成功,原因是因為PVC沒有綁定到合適的PV,這個時候要求運維人員創(chuàng)建一個PV,緊接著Pod調(diào)度成功。剛才上在介紹PV PVC,它們的創(chuàng)建過程都是手動,如果集群中需要成千上萬的PV,那么運維人員豈不累死?在實際操作中,這種方式根本行不通。所以Kubernetes給我們提供了一套自動創(chuàng)建PV的機制Dynamic Provisioning.在沒有介紹這套自動創(chuàng)建機制之前,先看看Static Provisioning,什么是Static Provisioning?剛才人工創(chuàng)建PV PVC的方式就是Static Provisioning。你可以在PV PVC編排文件中聲明StorageClass,如果沒有聲明,那么默認為"".具體交互流程如下所示:

          靜態(tài)分配流程

          首先由集群管理員事先去規(guī)劃這個集群中的用戶會怎樣使用存儲,它會先預(yù)分配一些存儲,也就是預(yù)先創(chuàng)建一些 PV;然后用戶在提交自己的存儲需求(PVC)的時候,Kubernetes內(nèi)部相關(guān)組件會幫助它把PVC PV 做綁定;最后pod使用存儲的時候,就可以通過PVC找到相應(yīng)的PV,它就可以使用了。不足之處也非常清楚,首先繁瑣,然后運維人員無法預(yù)知開發(fā)人員的真實存儲需求,比如運維人員創(chuàng)建了多個100GiPV存儲,但是在實際開發(fā)過程中,開發(fā)人員只能使用10Gi,這就造成了資源的浪費。當(dāng)然Kubernetes也為我們提供更好的使用方式,即Dynamic Provisioning它是什么呢?

          Dynamic Provisioning包含了創(chuàng)建某種PV所需要的參數(shù)信息,類似于一個創(chuàng)建PV的模板。具體交互流程如下所示:

          Kubernetes集群中的控制器,會結(jié)合PVCStorageClass的信息動態(tài)生成用戶所需要的PV,將PVC PV進行綁定后,pod就可以使用PV了。通過 StorageClass配置生成存儲所需要的存儲模板,再結(jié)合用戶的需求動態(tài)創(chuàng)建PV對象,做到按需分配,在沒有增加用戶使用難度的同時也解放了集群管理員的運維工作。

          動態(tài)PV使用

          Dynamic Provisioning上面提到過,運維人員不再預(yù)分配PV,而只是創(chuàng)建一個模板文件,這個模板文件正是StorageClass。下面以NFS為例進行說明,動態(tài)PV的整個使用過程。

          • 安裝NFS服務(wù)
          #安裝nfs
          yum?-y?install?nfs-utils?rpcbind
          #開機自啟動
          systemctl?enable?rpcbind?nfs-server
          #配置nfs?文件
          echo?"/nfs/data?*(rw,no_root_squash,sync)"?>/etc/exports
          • 部署置備程序
          apiVersion:?v1
          kind:?ServiceAccount
          metadata:
          ??name:?nfs-provisioner
          ---
          kind:?ClusterRole
          apiVersion:?rbac.authorization.k8s.io/v1
          metadata:
          ???name:?nfs-provisioner-runner
          rules:
          ???-??apiGroups:?[""]
          ??????resources:?["persistentvolumes"]
          ??????verbs:?["get",?"list",?"watch",?"create",?"delete"]
          ???-??apiGroups:?[""]
          ??????resources:?["persistentvolumeclaims"]
          ??????verbs:?["get",?"list",?"watch",?"update"]
          ???-??apiGroups:?["storage.k8s.io"]
          ??????resources:?["storageclasses"]
          ??????verbs:?["get",?"list",?"watch"]
          ???-??apiGroups:?[""]
          ??????resources:?["events"]
          ??????verbs:?["watch",?"create",?"update",?"patch"]
          ???-??apiGroups:?[""]
          ??????resources:?["services",?"endpoints"]
          ??????verbs:?["get","create","list",?"watch","update"]
          ???-??apiGroups:?["extensions"]
          ??????resources:?["podsecuritypolicies"]
          ??????resourceNames:?["nfs-provisioner"]
          ??????verbs:?["use"]
          ---
          kind:?ClusterRoleBinding
          apiVersion:?rbac.authorization.k8s.io/v1
          metadata:
          ??name:?run-nfs-provisioner
          subjects:
          ??-?kind:?ServiceAccount
          ????name:?nfs-provisioner
          ????namespace:?logging
          roleRef:
          ??kind:?ClusterRole
          ??name:?nfs-provisioner-runner
          ??apiGroup:?rbac.authorization.k8s.io
          ---
          kind:?Deployment
          apiVersion:?apps/v1
          metadata:
          ??name:?nfs-client-provisioner
          spec:
          ??selector:
          ????matchLabels:
          ??????app:?nfs-client-provisioner
          ??replicas:?1
          ??strategy:
          ????type:?Recreate
          ??template:
          ????metadata:
          ??????labels:
          ????????app:?nfs-client-provisioner
          ????spec:
          ??????serviceAccount:?nfs-provisioner
          ??????containers:
          ????????-?name:?nfs-client-provisioner
          ??????????image:?quay.io/external_storage/nfs-client-provisioner:latest
          ??????????imagePullPolicy:?IfNotPresent
          ??????????volumeMounts:
          ????????????-?name:?nfs-client
          ??????????????mountPath:?/persistentvolumes
          ??????????env:
          ????????????-?name:?PROVISIONER_NAME
          ??????????????value:?fuseim.pri/ifs
          ????????????-?name:?NFS_SERVER
          ??????????????value:?12.18.7.20
          ????????????-?name:?NFS_PATH
          ??????????????value:?/nfs/data
          ??????volumes:
          ????????-?name:?nfs-client
          ??????????nfs:
          ????????????server:?12.18.7.20
          ????????????path:?/nfs/data
          • 創(chuàng)建StorageClass模板
          apiVersion:?storage.k8s.io/v1
          kind:?StorageClass
          metadata:
          ??name:?nfs-storage
          provisioner:?fuseim.pri/ifs
          reclaimPolicy:?Retain

          這些參數(shù)是通過Kubernetes創(chuàng)建存儲的時候,需要指定的一些細節(jié)參數(shù)。對于這些參數(shù),用戶是不需要關(guān)心的,像這里provisioner指的是使用nfs的置備程序。ReclaimPolicy就是說動態(tài)創(chuàng)建出來的PV,當(dāng)使用方使用結(jié)束、PodPVC被刪除后,這塊PV應(yīng)該怎么處理,我們這個地方寫的是Retain,意思就是說當(dāng)使用方pod PVC被刪除之后,這個PV會保留。

          • 提交完成模板文件之后,用戶只需要在Pod yaml文件定義PVC,即可自動創(chuàng)建PVPVC
          apiVersion:?apps/v1
          kind:?StatefulSet
          metadata:
          ??name:?es
          spec:
          ??........
          ??template:
          ????metadata:
          ??????labels:?
          ????????app:?elasticsearch
          ????spec:
          ??????.........
          ??????initContainers:
          ??????........
          ??????containers:
          ??????-?name:?elasticsearch
          ????????image:?docker.elastic.co/elasticsearch/elasticsearch:7.6.2
          ????????.......
          ??volumeClaimTemplates:
          ??-?metadata:
          ??????name:?data
          ??????labels:
          ????????app:?elasticsearch
          ????spec:
          ??????accessModes:?[?"ReadWriteOnce"?]
          ??????storageClassName:?nfs-storage
          ??????resources:
          ????????requests:
          ??????????storage:?50Gi`

          Capacity:存儲對象的大小;

          AccessModes:也是用戶需要關(guān)心的,就是說使用這個PV的方式。它有三種使用方式:ReadWriteOnce是單node讀寫訪問;ReadOnlyMany是多個node只讀訪問,常見的一種數(shù)據(jù)共享方式;ReadWriteMany是多個node上讀寫訪問;

          StorageClassNameStorageClassName這個我們剛才說了,動態(tài)Provisioning時必須指定的一個字段,就是說我們要指定到底用哪一個模板文件來生成PV

          Kubernetes存儲架構(gòu)

          存儲架構(gòu)圖
          • PV Controller: 負責(zé)PV PVC的綁定、生命周期管理,并根據(jù)需求進行數(shù)據(jù)卷的Provision Delete操作
          • AD Controller:負責(zé)存儲設(shè)備的Attach Detach操作,將設(shè)備掛載到目標節(jié)點
          • Volume Manager:管理卷的Mount Unmount操作、卷設(shè)備的格式化以及掛載到一些公用目錄上的操作
          • Volume Plugins:它主要是對上面所有掛載功能的實現(xiàn)。PV Controller、AD Controller、Volume Manager 主要是進行操作的調(diào)用,而具體操作則是由Volume Plugins實現(xiàn)的。根據(jù)源碼的位置可將Volume Plugins分為In-TreeOut-of-Tree兩類:In-Tree表示源碼是放在Kubernetes內(nèi)部的(常見的NFS、cephfs等),和Kubernetes一起發(fā)布、管理與迭代,缺點是迭代速度慢、靈活性差;Out-of-TreeVolume Plugins的代碼獨立于Kubernetes,它是由存儲提供商實現(xiàn)的,目前主要有Flexvolume CSI兩種實現(xiàn)機制,可以根據(jù)存儲類型實現(xiàn)不同的存儲插件
          • Scheduler:實現(xiàn)對Pod的調(diào)度能力,會根據(jù)一些存儲相關(guān)的的定義去做存儲相關(guān)的調(diào)度

          動態(tài)PV交互流程

          Kubernetes掛載Volume過程
          1. 用戶創(chuàng)建一個包含PVCPod
          2. PV Controller會觀察ApiServer,如果它發(fā)現(xiàn)一個PVC已經(jīng)創(chuàng)建完畢但仍然是未綁定的狀態(tài),它就會試圖把一個PVPVC綁定
          3. Provision就是從遠端上一個具體的存儲介質(zhì)創(chuàng)建一個Volume,并且在集群中創(chuàng)建一個PV對象,然后將此PVPVC進行綁定
          4. Scheduler進行多個維度考量完成后,把Pod調(diào)度到一個合適的Node
          5. Kubelet不斷watch APIServer是否有Pod要調(diào)度到當(dāng)前所在節(jié)點
          6. Pod調(diào)度到某個節(jié)點之后,它所定義的PV還沒有被掛載(Attach),此時AD Controller就會調(diào)用VolumePlugin,把遠端的Volume掛載到目標節(jié)點中的設(shè)備上(/dev/vdb);當(dāng)Volum Manager 發(fā)現(xiàn)一個Pod調(diào)度到自己的節(jié)點上并且Volume已經(jīng)完成了掛載,它就會執(zhí)行mount操作,將本地設(shè)備(也就是剛才得到的/dev/vdb)掛載到 Pod在節(jié)點上的一個子目錄中
          7. 啟動容器,并將已經(jīng)掛載到本地的Volume映射到容器中

          總結(jié)

          本文主要扯了如下內(nèi)容,首先介紹KubernetesVolume、PV、PVC、StorageClass由來,然后介紹了StorageClass使用,最后簡單介紹了Kubernetes存儲架構(gòu)以及動態(tài)存儲交互流程。當(dāng)然還有很多細節(jié)邏輯沒有提到,如有興趣,歡迎關(guān)注公眾號,加我微信,一起討論!

          瀏覽 40
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  11一12周岁女毛片 | 日韩精品A片一区二区三区妖精 | Ts另类人妖一二三 | 中文AV天堂 | 亚洲黄片在线免费看 |