溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何理解Kubernetes存儲體系

發(fā)布時間:2021-11-23 17:28:25 來源:億速云 閱讀:125 作者:柒染 欄目:云計算

今天就跟大家聊聊有關(guān)詳解Kubernetes存儲體系,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

Volume、PV、PVC、StorageClass由來

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

“  

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

”  

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

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

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

“  

答案是否定的,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ù)卷類型,你都可以按照如上方式進(jìn)行直接在Yaml編排文件中定義使用。如何理解Kubernetes存儲體系

看到這里其實已經(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
 

看到這里,我們還會認(rèn)為僅僅是PVVolume多了一層抽象,并不見得比直接在Yaml中聲明Volume高明多少。仔細(xì)思考下,我們?yōu)槭裁茨軌蛑苯釉?code>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,如果沒有聲明,那么默認(rèn)為"".具體交互流程如下所示:

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

 

動態(tài)PV使用

Dynamic Provisioning上面提到過,運維人員不再預(yù)分配PV,而只是創(chuàng)建一個模板文件,這個模板文件正是StorageClass。下面以NFS為例進(jìn)行說明,動態(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)建存儲的時候,需要指定的一些細(xì)節(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)建     PV和     PVC。
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:存儲對象的大?。?/p>

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

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

 

Kubernetes存儲架構(gòu)

如何理解Kubernetes存儲體系  
存儲架構(gòu)圖
  • PV Controller: 負(fù)責(zé)     PV PVC的綁定、生命周期管理,并根據(jù)需求進(jìn)行數(shù)據(jù)卷的     Provision Delete操作
  • AD Controller:負(fù)責(zé)存儲設(shè)備的     Attach Detach操作,將設(shè)備掛載到目標(biāo)節(jié)點
  • Volume Manager:管理卷的     Mount Unmount操作、卷設(shè)備的格式化以及掛載到一些公用目錄上的操作
  • Volume Plugins:它主要是對上面所有掛載功能的實現(xiàn)。     PV Controller、AD Controller、Volume Manager 主要是進(jìn)行操作的調(diào)用,而具體操作則是由     Volume Plugins實現(xiàn)的。根據(jù)源碼的位置可將     Volume Plugins分為     In-Tree和     Out-of-Tree兩類:     In-Tree表示源碼是放在     Kubernetes內(nèi)部的(常見的     NFS、cephfs等),和     Kubernetes一起發(fā)布、管理與迭代,缺點是迭代速度慢、靈活性差;     Out-of-Tree的     Volume 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存儲體系  
Kubernetes掛載Volume過程
  1. 用戶創(chuàng)建一個包含     PVC的     Pod
  2. PV Controller會觀察     ApiServer,如果它發(fā)現(xiàn)一個     PVC已經(jīng)創(chuàng)建完畢但仍然是未綁定的狀態(tài),它就會試圖把一個     PV和     PVC綁定
  3. Provision就是從遠(yuǎn)端上一個具體的存儲介質(zhì)創(chuàng)建一個     Volume,并且在集群中創(chuàng)建一個     PV對象,然后將此     PV和     PVC進(jìn)行綁定
  4. Scheduler進(jìn)行多個維度考量完成后,把     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,把遠(yuǎn)端的     Volume掛載到目標(biāo)節(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映射到容器中

看完上述內(nèi)容,你們對詳解Kubernetes存儲體系有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI