入門Kubernetes-數據存儲

一、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)  – 卷可以被多個節點以讀寫方式掛載
卷插件 ReadWriteOnce ReadOnlyMany ReadWriteMany
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、生命周期等基本概念

參考:

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

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