深度解析Kubernetes Local Persistent Volume

摘要:本文分析了hostPath volume缺陷,而後對local persistent volume的使用場景、基本的工做機制進行了分析,介紹了使用時的注意事項,並簡單介紹local volume manager如何幫助administrator進行local persistent volume的生命週期管理的。node

hostPath volume存在的問題

過去咱們常常會經過hostPath volume讓Pod可以使用本地存儲,將Node文件系統中的文件或者目錄掛載到容器內,可是hostPath volume的使用是很難受的,並不適合在生產環境中使用。git

咱們先看看hostPath Type有哪些類型:github

Value Behavior
Empty string (default) is for backward compatibility, which means that no checks will be performed before mounting the hostPath volume.
DirectoryOrCreate If nothing exists at the given path, an empty directory will be created there as needed with permission set to 0755, having the same group and ownership with Kubelet.
Directory A directory must exist at the given path
FileOrCreate If nothing exists at the given path, an empty file will be created there as needed with permission set to 0644, having the same group and ownership with Kubelet.
File A file must exist at the given path
Socket A UNIX socket must exist at the given path
CharDevice A character device must exist at the given path
BlockDevice A block device must exist at the given path

看起來支持這麼多type仍是挺好的,但爲何說不適合在生產環境中使用呢?api

  • 因爲集羣內每一個節點的差別化,要使用hostPath Volume,咱們須要經過NodeSelector等方式進行精確調度,這種事情多了,你就會不耐煩了。網絡

  • 注意DirectoryOrCreateFileOrCreate兩種類型的hostPath,當Node上沒有對應的File/Directory時,你須要保證kubelet有在Node上Create File/Directory的權限。socket

  • 另外,若是Node上的文件或目錄是由root建立的,掛載到容器內以後,你一般還要保證容器內進程有權限對該文件或者目錄進行寫入,好比你須要以root用戶啓動進程並運行於privileged容器,或者你須要事先修改好Node上的文件權限配置。分佈式

  • Scheduler並不會考慮hostPath volume的大小,hostPath也不能申明須要的storage size,這樣調度時存儲的考慮,就須要人爲檢查並保證。源碼分析

  • StatefulSet沒法使用hostPath volume,已經寫好的使用共享存儲的Helm Chart不能兼容hostPath volume,須要修改的地方還很多,這也挺難受的。ui

local persistent volume工做機制

FEATURE STATE: Kubernetes v1.11 Betacode

Local persistent volume就是用來解決hostPath volume面臨的**portability, disk accounting, and scheduling**的缺陷。PV Controller和Scheduler會對local PV作特殊的邏輯處理,以實現Pod使用本地存儲時發生Pod re-schedule的狀況下能再次調度到local volume所在的Node。

local pv在生產中使用,也是須要謹慎的,畢竟它本質上仍是使用的是節點上的本地存儲,若是沒有相應的存儲副本機制,那意味着一旦節點或者磁盤異常,使用該volume的Pod也會異常,甚至出現數據丟失,除非你明確知道這個風險不會對你的應用形成很大影響或者容許數據丟失。

那麼一般什麼狀況會使用Local PV呢?

  • 好比節點上的目錄數據是從遠程的網絡存儲上掛載或者預先讀取到本地的,爲了能加速Pod讀取這些數據的速度,至關於起Cache做用,這種狀況下由於只讀,不存在害怕數據丟失。這種AI訓練中存在須要重複利用而且訓練數據巨大的時候可能會採起的方式。
  • 若是本地節點上目錄/磁盤實際是具備副本/分片機制的分佈式存儲(好比gluster, ceph等)掛載過來的,這種狀況也可使用local pv。

Local volume容許掛載本地的disk, partition, directory到容器內某個掛載點。在Kuberentes 1.11仍然僅支持local pv的static provision,不支持dynamic provision。

  • Kubernetes使用PersistentVolume的.spec.nodeAffinityfield來描述local volume與Node的綁定關係。

  • 使用volumeBindingMode: WaitForFirstConsumer的local-storage StorageClass來實現PVC的延遲綁定,使得PV Controller並不會馬上爲PVC作Bound,而是等待某個須要使用該local pv的Pod完成調度後,纔去作Bound。

下面是定義local pv的Sample:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
spec:
  capacity:
    storage: 100Gi
  # volumeMode field requires BlockVolume Alpha feature gate to be enabled.
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /mnt/disks/ssd1
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - example-node

對應的local-storage storageClass定義以下:

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

使用local persistent volume注意事項

  • 使用local pv時必須定義nodeAffinity,Kubernetes Scheduler須要使用PV的nodeAffinity描述信息來保證Pod可以調度到有對應local volume的Node上。

  • volumeMode能夠是FileSystem(Default)和Block,而且須要enable BlockVolume Alpha feature gate。

  • 建立local PV以前,你須要先保證有對應的storageClass已經建立。而且該storageClass的volumeBindingMode必須是WaitForFirstConsumer以標識延遲Volume Binding。WaitForFirstConsumer能夠保證正常的Pod調度要求(resource requirements, node selectors, Pod affinity, and Pod anti-affinity等),又能保證Pod須要的Local PV的nodeAffinity獲得知足,實際上,一共有如下兩種volumeBindingMode:

    // VolumeBindingImmediate indicates that PersistentVolumeClaims should be
    	// immediately provisioned and bound.
    	VolumeBindingImmediate VolumeBindingMode = "Immediate"
    
    	// VolumeBindingWaitForFirstConsumer indicates that PersistentVolumeClaims
    	// should not be provisioned and bound until the first Pod is created that
    	// references the PeristentVolumeClaim.  The volume provisioning and
    	// binding will occur during Pod scheduing.
    	VolumeBindingWaitForFirstConsumer VolumeBindingMode = "WaitForFirstConsumer"
  • 節點上local volume的初始化須要咱們人爲去完成(好比local disk須要pre-partitioned, formatted, and mounted. 共享存儲對應的Directories也須要pre-created),而且人工建立這個local PV,當Pod結束,咱們還須要手動的清理local volume,而後手動刪除該local PV對象。所以,persistentVolumeReclaimPolicy只能是Retain。

local volume manager

上面這麼多事情須要人爲的去作預處理的工做,咱們必需要有解決方案幫咱們自動完成local volume的create和cleanup的工做。官方給出了一個簡單的local volume manager,注意它仍然只是一個static provisioner,目前主要幫咱們作兩件事:

  • local volume manager 監控配置好的discovery directory的新的掛載點,併爲每一個掛載點根據對應的storageClassName, path, nodeAffinity, and capacity建立PersistentVolume object。

  • 當Pod結束並刪除了使用local volume的PVC,local volume manager將自動清理該local mount上的全部文件, 而後刪除對應的PersistentVolume object.

所以,除了須要人爲的完成local volume的mount操做,local PV的生命週期管理就所有交給local volume manager了。下面咱們專門介紹下這個Static Local Volume Provisioner。

後面我會單獨寫一個博文對local volume manager進行深度剖析。

總結

本文對hostPath volume不能在生產環境中很好使用的緣由進行了闡述,而後對local persistent volume的使用場景、基本的工做機制進行了分析,介紹了使用時的注意事項,最後簡單介紹了local volume manager如何幫助administrator進行local persistent volume的生命週期管理的。接下來,我會再寫兩篇博客,分別對scheduler和pv controller如何對local persistent volume的處理邏輯進行源碼分析,對local volume manager進行深度剖析。

相關文章
相關標籤/搜索