入門Kubernetes-資料儲存

chaney1992發表於2021-08-01

一、Volume介紹:

 在k8s中Pod的生命週期可能很短,會被頻繁地銷燬和建立。容器銷燬時,儲存在容器內部檔案系統中的資料都會被清除。

 為了持久化儲存容器資料,k8s 提供了卷(Volume)的抽象概念來解決上述問題。

 卷(Volume)的核心是一個目錄,其中可能存有資料,Pod 中的容器可以訪問該目錄中的資料。 所採用的特定的卷型別將決定該目錄如何形成的、使用何種介質儲存資料以及目錄中存放的內容。

 Kubernetes Volume 支援多種卷型別,包括 emptyDir、hostPath、nfs、local、configMap、AWSElasticBlockStore、Cinder、CSI等。

  按照儲存可大概劃分為:

  

  臨時儲存:emptydir   

  半持久化儲存:hostpath

  持久化儲存:nfs、ceph、Cinder等

 接下來分別介紹幾種常用型別:emptyDir、hostPath、nfs(PV、PVC)

二、Volume:emptyDir

 emptyDir 是最基礎的 Volume 型別。正如其名字所示,一個 emptyDir Volume 是 Host 上的一個空目錄。

 emptyDir Volume 對於容器來說是持久的,對於 Pod 則不是。當 Pod 從節點刪除時,Volume 的內容也會被刪除。但如果只是容器被銷燬而 Pod 還在,則 Volume 不受影響。(emptyDir Volume 的生命週期與 Pod 一致

 Pod 中的所有容器都可以共享 Volume,它們可以指定各自的掛載路徑。

 驗證示例:

apiVersion: v1
kind: Pod
metadata:
  name: producer-consumer
spec:
  containers:
    - image: busybox
      name: producer
      volumeMounts:
        - mountPath: /producer_dir #掛載到容器中的路徑
          name: shared-volume
      args:
        - /bin/sh
        - -c
        - echo "hello world" > /producer_dir/hello; sleep 3000
    - image: busybox
      name: consumer
      volumeMounts:
        - mountPath: /consumer_dir #掛載到容器中的路徑
          name: shared-volume
      args:
        - /bin/sh
        - -c
        - cat /consumer_dir/hello; sleep 3000
  volumes:
    - name: shared-volume
      emptyDir: {} #指定儲存方式為emptydir
  1. 建立一個名為[shared-volume]的emptyDir的卷
  2. 容器producer 將 shared-volume掛載到 producer_dir 目錄
  3. 容器producer 通過echo 命令向hello 檔案中寫入文字-hello world
  4. 容器consumer 將 shared-volume掛載到 consumer_dir目錄
  5. 容器consumer 通過cat命令讀取consumer_dir中hello檔案內容

  通過命令:kubectl logs 檢視讀取內容。

# 輸出producer-consumer Pod中容器 consumer 的日誌:
kubectl logs producer-consumer -c consumer
hello world

  顯示容器 consumer 成功讀取到 producer 寫入的資料,驗證了兩個容器共享 emptyDir Volume。

三、Volume:hostPath

 hostPath 卷能將主機節點檔案系統上的檔案或目錄掛載到你的 Pod 中。 雖然這不是大多數 Pod 需要的,但是它為一些應用程式提供了強大應急方式。

 hostPath 的一些用法有:

  • 執行一個需要訪問 Docker 內部機制的容器;可使用 hostPath 掛載 /var/lib/docker 路徑。
  • 在容器中執行 cAdvisor 時,以 hostPath 方式掛載 /sys
  • 允許 Pod 指定給定的 hostPath 在執行 Pod 之前是否應該存在,是否應該建立以及應該以什麼方式存在。

 除了必需的 path 屬性之外,使用者可以選擇性地為 hostPath 卷指定 type,下表為type取值

取值行為
  空字串(預設)用於向後相容,這意味著在安裝 hostPath 卷之前不會執行任何檢查。
DirectoryOrCreate 如果在給定路徑上什麼都不存在,那麼將根據需要建立空目錄,許可權設定為 0755,具有與 kubelet 相同的組和屬主資訊。
Directory 在給定路徑上必須存在的目錄。
FileOrCreate 如果在給定路徑上什麼都不存在,那麼將在那裡根據需要建立空檔案,許可權設定為 0644,具有與 kubelet 相同的組和所有權。
File 在給定路徑上必須存在的檔案。
Socket 在給定路徑上必須存在的 UNIX 套接字。
CharDevice 在給定路徑上必須存在的字元裝置。
BlockDevice 在給定路徑上必須存在的塊裝置。

 hostPath示例:

apiVersion: v1
kind: Pod
metadata:
  name: localpod
spec:
  containers:
    - image: busybox
      name: local
      volumeMounts:
        - mountPath: /localdir #掛載到容器中的路徑
          name: mydir
        - mountPath: loacl.txt
          name: myfile
      args:
        - /bin/sh
        - -c
        - echo "local dir test" > /localdir/test.txt; 
        - -c
        - cat loacl.txt; 
  volumes:
    - name: mydir
      hostPath:
        # 確保檔案所在目錄成功建立。
        path: /var/local
        type: DirectoryOrCreate
    - name: myfile
      hostPath:
        # 確保檔案建立成功
        path: /var/local/test.txt
        type: FileOrCreate

  步驟:

   1、建立兩個hostPath型別的Volume

   2、將這兩個卷都掛載到local容器中

   3、容器啟動時,寫入檔案內容“local dir test”,並讀取出來。

四、Volume:持久化儲存-nfs

 說到持久化儲存:就需要提k8s中提供的重要的幾種資源型別:

  • PersistentVolume (PV): 外部儲存系統中的一塊儲存空間,由管理員建立和維護。與 Volume 一樣,PV 具有永續性,生命週期獨立於 Pod。
  • StorageClass:另外一種提供儲存資源的方式, 提供更多的層級選型, 如iops等引數。 但是具體的引數與提供方是繫結的。 如aws和gce它們提供的storageclass的引數可選項是有不同的。
  • PersistentVolumeClaim (PVC):是對 PV 的申請 (Claim)。PVC 通常由普通使用者建立和維護。需要為 Pod 分配儲存資源時,使用者可以建立一個 PVC,指明儲存資源的容量大小和訪問模式(比如只讀)等資訊,Kubernetes 會查詢並提供滿足條件的 PV。

 PersistentVolume :

 生命週期:

  • Provisioning- 配置階段, 分為static, dynamic兩種方式。靜態的方式是建立一系列的pv,然後pvc從pv中請求。 動態的方式是基於storageclass的。
  • Binding - 繫結階段, pvc根據請求的條件篩選並繫結對應的pv。 一定pvc繫結pv後, 就會排斥其它繫結,即其它pvc無法再繫結同一個pv,即使這個pv設定的access mode允許多個node讀寫。 此外 ,pvc 如何匹配不到相應條件的pv, 那麼就會顯示unbound狀態, 直到匹配為止。 需要注意的是,pvc請求100Gi大小的儲存,即使使用者建立了很多50Gi大小的儲存, 也是無法被匹配的。
  • Using- 使用階段, pods 掛載儲存, 即在pod的template檔案中定義volumn使用某個pvc。
  • Releasing - 釋放階段, 當pvc物件被刪除後, 就處於釋放階段。 在這個階段, 使用的pv還不能被其它的pvc請求。 之前資料可能還會留存下來, 取決於使用者在pv中設定的policy, 見persistentVolumeReclaimPolicy。
  • Reclaiming - 重宣告階段。 到這個階段, 會告訴cluster如何處理釋放的pv。 資料可能被保留(需要手工清除), 回收和刪除。動態分配的儲存總是會被刪除掉的。
  • Recycling - 回收階段。回收階段會執行基本的遞迴刪除(取決於volumn plugins的支援),把pv上的資料刪除掉, 以使pv可以被新的pvc請求。 使用者也可以自定義一個 recycler pod , 對資料進行刪除。

 卷模式:

  PV支援兩種卷模式:

  • Filesystem  卷會被 Pod 掛載(Mount) 到某個目錄。 如果卷的儲存來自某塊裝置而該裝置目前為空,Kuberneretes 會在第一次掛載卷之前 在裝置上建立檔案系統。
  • Block將卷作為原始塊裝置來使用。 這類卷以塊裝置的方式交給 Pod 使用,其上沒有任何檔案系統。 這種模式對於為 Pod 提供一種使用最快可能方式來訪問卷而言很有幫助,Pod 和 卷之間不存在檔案系統層。另外,Pod 中執行的應用必須知道如何處理原始塊裝置。

 訪問模式:

  PersistentVolume 卷可以用資源提供者所支援的任何方式掛載到宿主系統上。 如下表所示,提供者(驅動)的能力不同,每個 PV 卷的訪問模式都會設定為 對應卷所支援的模式值。 例如,NFS 可以支援多個讀寫客戶,但是某個特定的 NFS PV 卷可能在伺服器 上以只讀的方式匯出。每個 PV 卷都會獲得自身的訪問模式集合,描述的是 特定 PV 卷的能力。

訪問模式有:

    • ReadWriteOnce (RWO)  -- 卷可以被一個節點以讀寫方式掛載;
    • ReadOnlyMany (ROX)    -- 卷可以被多個節點以只讀方式掛載;
    • ReadWriteMany (RWX)  -- 卷可以被多個節點以讀寫方式掛載
卷外掛ReadWriteOnceReadOnlyManyReadWriteMany
AWSElasticBlockStore - -
AzureFile
AzureDisk - -
CephFS
Cinder - -
CSI 取決於驅動 取決於驅動 取決於驅動
FC -
FlexVolume 取決於驅動
Flocker - -
GCEPersistentDisk -
Glusterfs
HostPath - -
iSCSI -
Quobyte
NFS
RBD -
VsphereVolume - - (Pod 執行於同一節點上時可行)
PortworxVolume -
ScaleIO -
StorageOS - -

 回收策略:

  目前的回收策略有:

  • Retain -- 手動回收
  • Recycle -- 基本擦除 (rm -rf /thevolume/*)
  • Delete -- 諸如 AWS EBS、GCE PD、Azure Disk 或 OpenStack Cinder 卷這類關聯儲存資產也被刪除

  目前,僅 NFS 和 HostPath 支援回收(Recycle)。 AWS EBS、GCE PD、Azure Disk 和 Cinder 卷都支援刪除(Delete)

 持久化儲存驗證:

  1、nfs服務搭建:

 所有節點安裝nfs

yum install -y nfs-common nfs-utils 

 在master節點建立共享目錄

[root@k8s-master k8s]# mkdir /nfsdata

 授權共享目錄

[root@k8s-master k8s]# chmod 666 /nfsdata

 編輯exports檔案

[root@k8s-master k8s]# cat /etc/exports
/nfsdata *(rw,no_root_squash,no_all_squash,sync)

 配置生效

  [root@k8s-master k8s]# export -r

 啟動rpc和nfs(注意順序)

[root@k8s-master k8s]# systemctl start rpcbind
[root@k8s-master k8s]# systemctl start nfs

2、建立PV:

#建立Pv:name-pv01
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv01
  labels:
    name: pv01
spec:
  # 所有節點可共享訪問
  accessModes: ["ReadWriteMany"]
# 回收策略:清除PV資料
persistentVolumeReclaimPolicy:Recycle
# 指定PV的Class為 nfs
storageClassName:nfs capacity:
# Pv大小1G storage: 1Gi #nfs 服務設定,以及目錄設定 nfs: server: 192.168.115.6 path: /home

  3、建立PVC:

#建立名為mypvc的PVC
apiVersion: v1
kind: PersisitentVolumeClaim
metadata:
  name: mypvc
  namespace: default
spec:
  accessmodes: ["ReadWriteMany"]   #所有節點可讀寫
  resources:                  #指定資源說明
    requests:                  #指定請求
      storage: 4Gi            #指定請求儲存空間的大小      

  4、建立POD使用PVC

#建立Pod並使用PVC
apiVersion: v1
kind: Pod
metadata:
  name: pvnginx
  labels:
    app: pvnginx
spec:
  containers:
    - name: my-pvnginx
      image: nginx
      ports:
        - name: http
          containerPort: 80
        - name: https
          containerPort: 443
       volumeMounts:
         - name: html
           mountPath: /data/html
  volumes:
    - name: html
      persistentVolumeClaim:    #指明使用pvc模式
        claimname: mypvc         #指明使用的pvc名稱

總結:  

 1、對於不需要持久化的資料可採用emptyDir型別捲來儲存相關資料,其生命週期同Pod相同

 2、當需要訪問當前主機檔案時,可以採用hostPath型別的捲來實現

 3、PV、PVC在實際場景中應用較多,需要了解透徹:包括PV的動/靜態建立、PVC、生命週期等基本概念

參考:

  https://kubernetes.io/zh/docs/concepts/storage/ 

https://kubernetes.io/zh/docs/concepts/storage/

相關文章