管理存儲和管理計算有着明顯的不一樣。PersistentVolume
子系統給用戶和管理員提供了一套API,從而抽象出存儲是如何提供和消耗的細節。在這裏,咱們介紹兩種新的API資源:PersistentVolume
(簡稱PV)和PersistentVolumeClaim
(簡稱PVC)。
PersistentVolume
(持久卷,簡稱PV)是集羣內,由管理員提供的網絡存儲的一部分。就像集羣中的節點同樣,PV也是集羣中的一種資源。它也像Volume同樣,是一種volume插件,可是它的生命週期倒是和使用它的Pod相互獨立的。PV這個API對象,捕獲了諸如NFS、ISCSI、或其餘雲存儲系統的實現細節。
PersistentVolumeClaim
(持久卷聲明,簡稱PVC)是用戶的一種存儲請求。它和Pod相似,Pod消耗Node資源,而PVC消耗PV資源。Pod可以請求特定的資源(如CPU和內存)。PVC可以請求指定的大小和訪問的模式(能夠被映射爲一次讀寫或者屢次只讀)。
PVC容許用戶消耗抽象的存儲資源,用戶也常常須要各類屬性(如性能)的PV。集羣管理員須要提供各類各樣、不一樣大小、不一樣訪問模式的PV,而不用向用戶暴露這些volume如何實現的細節。由於這種需求,就催生出一種StorageClass
資源。
StorageClass
提供了一種方式,使得管理員可以描述他提供的存儲的等級。集羣管理員能夠將不一樣的等級映射到不一樣的服務等級、不一樣的後端策略。
請查看detailed walkthrough with working examples。html
PV是集羣中的資源,PVC是對這些資源的請求,同時也是這些資源的「提取證」。PV和PVC的交互遵循如下生命週期:node
有兩種PV提供的方式:靜態和動態。nginx
集羣管理員建立多個PV,它們攜帶着真實存儲的詳細信息,這些存儲對於集羣用戶是可用的。它們存在於Kubernetes API中,並可用於存儲使用。git
當管理員建立的靜態PV都不匹配用戶的PVC時,集羣可能會嘗試專門地供給volume給PVC。這種供給基於StorageClass
:PVC必須請求這樣一個等級,而管理員必須已經建立和配置過這樣一個等級,以備發生這種動態供給的狀況。請求等級配置爲「」的PVC,有效地禁用了它自身的動態供給功能。github
用戶建立一個PVC(或者以前就已經就爲動態供給建立了),指定要求存儲的大小和訪問模式。master中有一個控制迴路用於監控新的PVC,查找匹配的PV(若是有),並把PVC和PV綁定在一塊兒。若是一個PV曾經動態供給到了一個新的PVC,那麼這個迴路會一直綁定這個PV和PVC。另外,用戶老是至少能獲得它們所要求的存儲,可是volume可能超過它們的請求。一旦綁定了,PVC綁定就是專屬的,不管它們的綁定模式是什麼。
若是沒找到匹配的PV,那麼PVC會無限期得處於unbound未綁定狀態,一旦PV可用了,PVC就會又變成綁定狀態。好比,若是一個供給了不少50G的PV集羣,不會匹配要求100G的PVC。直到100G的PV添加到該集羣時,PVC纔會被綁定。docker
Pod使用PVC就像使用volume同樣。集羣檢查PVC,查找綁定的PV,並映射PV給Pod。對於支持多種訪問模式的PV,用戶能夠指定想用的模式。
一旦用戶擁有了一個PVC,而且PVC被綁定,那麼只要用戶還須要,PV就一直屬於這個用戶。用戶調度Pod,經過在Pod的volume
塊中包含PVC來訪問PV。後端
當用戶使用PV完畢後,他們能夠經過API來刪除PVC對象。當PVC被刪除後,對應的PV就被認爲是已是「released」了,但還不能再給另一個PVC使用。前一個PVC的屬於還存在於該PV中,必須根據策略來處理掉。api
PV的回收策略告訴集羣,在PV被釋放以後集羣應該如何處理該PV。當前,PV能夠被Retained(保留)、 Recycled(再利用)或者Deleted(刪除)。保留容許手動地再次聲明資源。對於支持刪除操做的PV卷,刪除操做會從Kubernetes中移除PV對象,還有對應的外部存儲(如AWS EBS,GCE PD,Azure Disk,或者Cinder volume)。動態供給的卷老是會被刪除。服務器
若是PV卷支持再利用,再利用會在PV捲上執行一個基礎的擦除操做(rm -rf /thevolume/*),使得它能夠再次被其餘PVC聲明利用。
管理員能夠經過Kubernetes controller manager的命令行工具(點擊查看),來配置自定義的再利用Pod模板。自定義的再利用Pod模板必須包含PV卷的詳細內容,以下示例:網絡
apiVersion: v1 kind: Pod metadata: name: pv-recycler- namespace: default spec: restartPolicy: Never volumes: - name: vol hostPath: path: /any/path/it/will/be/replaced containers: - name: pv-recycler image: "gcr.io/google_containers/busybox" command: ["/bin/sh", "-c", "test -e /scrub && rm -rf /scrub/..?* /scrub/.[!.]* /scrub/* && test -z \"$(ls -A /scrub)\" || exit 1"] volumeMounts: - name: vol mountPath: /scrub
如上,在volumes
部分的指定路徑,應該被替換爲PV卷鬚要再利用的路徑。
PV類型使用插件的形式來實現。Kubernetes如今支持如下插件:
每一個PV都包含一個spec和狀態,即說明書和PV卷的狀態。
apiVersion: v1 kind: PersistentVolume metadata: name: pv0003 spec: capacity: storage: 5Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: slow nfs: path: /tmp server: 172.17.0.2
通常來講,PV會指定存儲的容量,使用PV的capacity
屬性來設置。查看Kubernetes的Resource Model來了解capacity
。
當前,存儲大小是惟一能被設置或請求的資源。將來可能包含IOPS,吞吐率等屬性。
PV可使用存儲資源提供商支持的任何方法來映射到host中。以下的表格中所示,提供商有着不一樣的功能,每一個PV的訪問模式被設置爲卷支持的指定模式。好比,NFS能夠支持多個讀/寫的客戶端,但能夠在服務器上指定一個只讀的NFS PV。每一個PV有它本身的訪問模式。
訪問模式包括:
▷ ReadWriteOnce —— 該volume只能被單個節點以讀寫的方式映射
▷ ReadOnlyMany —— 該volume能夠被多個節點以只讀方式映射
▷ ReadWriteMany —— 該volume只能被多個節點以讀寫的方式映射
在CLI中,訪問模式能夠簡寫爲:
▷ RWO - ReadWriteOnce
▷ ROX - ReadOnlyMany
▷ RWX - ReadWriteMany
注意:即便volume支持不少種訪問模式,但它同時只能使用一種方式來映射。好比,GCEPersistentDisk能夠被單個節點映射爲ReadWriteOnce,或者多個節點映射爲ReadOnlyMany,但不能同時使用這兩種方式來映射。
Volume Plugin | ReadWriteOnce | ReadOnlyMany | ReadWriteMany |
---|---|---|---|
AWSElasticBlockStore | ✓ | - | - |
AzureFile | ✓ | ✓ | ✓ |
AzureDisk | ✓ | - | - |
CephFS | ✓ | ✓ | ✓ |
Cinder | ✓ | - | - |
FC | ✓ | ✓ | - |
FlexVolume | ✓ | ✓ | - |
Flocker | ✓ | - | - |
GCEPersistentDisk | ✓ | ✓ | - |
Glusterfs | ✓ | ✓ | ✓ |
HostPath | ✓ | - | - |
iSCSI | ✓ | ✓ | - |
PhotonPersistentDisk | ✓ | - | - |
Quobyte | ✓ | ✓ | ✓ |
NFS | ✓ | ✓ | ✓ |
RBD | ✓ | ✓ | - |
VsphereVolume | ✓ | - | - |
PortworxVolume | ✓ | - | ✓ |
ScaleIO | ✓ | ✓ | - |
一個PV能夠有一種class,經過設置storageClassName
屬性來選擇指定的StorageClass
。有指定class的PV只能綁定給請求該class的PVC。沒有設置storageClassName
屬性的PV只能綁定給未請求class的PVC。
過去,使用volume.beta.kubernetes.io/storage-class
註解,而不是storageClassName
屬性。該註解如今依然能夠工做,但在Kubernetes的將來版本中已經被徹底棄用了。
當前的回收策略有:
▷ Retain:手動回收
▷ Recycle:須要擦出後才能再使用
▷ Delete:相關聯的存儲資產,如AWS EBS,GCE PD,Azure Disk,or OpenStack Cinder卷都會被刪除
當前,只有NFS和HostPath支持回收利用,AWS EBS,GCE PD,Azure Disk,or OpenStack Cinder卷支持刪除操做。
一個volume卷處於如下幾個階段之一:
▷ Available:空閒的資源,未綁定給PVC
▷ Bound:綁定給了某個PVC
▷ Released:PVC已經刪除了,可是PV尚未被集羣回收
▷ Failed:PV在自動回收中失敗了
CLI能夠顯示PV綁定的PVC名稱。
當PV被映射到一個node上時,Kubernetes管理員能夠指定額外的映射選項。能夠經過使用標註volume.beta.kubernetes.io/mount-options
來指定PV的映射選項。
好比:
apiVersion: "v1" kind: "PersistentVolume" metadata: name: gce-disk-1 annotations: volume.beta.kubernetes.io/mount-options: "discard" spec: capacity: storage: "10Gi" accessModes: - "ReadWriteOnce" gcePersistentDisk: fsType: "ext4" pdName: "gce-disk-1
映射選項是當映射PV到磁盤時,一個能夠被遞增地添加和使用的字符串。
注意,並不是全部的PV類型都支持映射選項。在Kubernetes v1.6中,如下的PV類型支持映射選項。
● GCEPersistentDisk
● AWSElasticBlockStore
● AzureFile
● AzureDisk
● NFS
● iSCSI
● RBD (Ceph Block Device)
● CephFS
● Cinder (OpenStack block storage)
● Glusterfs
● VsphereVolume
● Quobyte Volumes
● VMware Photon
每一個PVC都包含一個spec
和status
,即該PVC的規則說明和狀態。
kind: PersistentVolumeClaim apiVersion: v1 metadata: name: myclaim spec: accessModes: - ReadWriteOnce resources: requests: storage: 8Gi storageClassName: slow selector: matchLabels: release: "stable" matchExpressions: - {key: environment, operator: In, values: [dev]}
當請求指定訪問模式的存儲時,PVC使用的規則和PV相同。
PVC,就像pod同樣,能夠請求指定數量的資源。請求資源時,PV和PVC都使用相同的資源樣式。
PVC能夠指定標籤選擇器進行更深度的過濾PV,只有匹配了選擇器標籤的PV才能綁定給PVC。選擇器包含兩個字段:
● matchLabels(匹配標籤) - PV必須有一個包含該值得標籤
● matchExpressions(匹配表達式) - 一個請求列表,包含指定的鍵、值的列表、關聯鍵和值的操做符。合法的操做符包含In,NotIn,Exists,和DoesNotExist。
全部來自matchLabels
和matchExpressions
的請求,都是邏輯與關係的,它們必須所有知足才能匹配上。
PVC可使用屬性storageClassName
來指定StorageClass
的名稱,從而請求指定的等級。只有知足請求等級的PV,即那些包含了和PVC相同storageClassName
的PV,才能與PVC綁定。
PVC並不是必需要請求一個等級。設置storageClassName
爲「」的PVC老是被理解爲請求一個無等級的PV,所以它只能被綁定到無等級的PV(未設置對應的標註,或者設置爲「」)。未設置storageClassName
的PVC不太相同,DefaultStorageClass
的權限插件打開與否,集羣也會區別處理PVC。
• 若是權限插件被打開,管理員可能會指定一個默認的StorageClass
。全部沒有指定StorageClassName
的PVC只能被綁定到默認等級的PV。要指定默認的StorageClass
,須要在StorageClass
對象中將標註storageclass.kubernetes.io/is-default-class
設置爲「true」。若是管理員沒有指定這個默認值,集羣對PVC建立請求的迴應就和權限插件被關閉時同樣。若是指定了多個默認等級,那麼權限插件禁止PVC建立請求。
• 若是權限插件被關閉,那麼久沒有默認StorageClass
的概念。全部沒有設置StorageClassName
的PVC都只能綁定到沒有等級的PV。所以,沒有設置StorageClassName
的PVC就如同設置StorageClassName
爲「」的PVC同樣被對待。
根據安裝方法的不一樣,默認的StorageClass
可能會在安裝過程當中被插件管理默認的部署在Kubernetes集羣中。
當PVC指定selector
來請求StorageClass
時,全部請求都是與操做的。只有知足了指定等級和標籤的PV纔可能綁定給PVC。當前,一個非空selector
的PVC不能使用PV動態供給。
過去,使用volume.beta.kubernetes.io/storage-class註解,而不是storageClassName屬性。該註解如今依然能夠工做,但在Kubernetes的將來版本中已經被徹底棄用了。
Pod經過使用PVC(使用方式和volume同樣)來訪問存儲。PVC必須和使用它的pod在同一個命名空間,集羣發現pod命名空間的PVC,根據PVC獲得其後端的PV,而後PV被映射到host中,再提供給pod。
kind: Pod apiVersion: v1 metadata: name: mypod spec: containers: - name: myfrontend image: dockerfile/nginx volumeMounts: - mountPath: "/var/www/html" name: mypd volumes: - name: mypd persistentVolumeClaim: claimName: myclaim
PV綁定是獨有的,由於PVC是命名空間對象,映射PVC時只能在同一個命名空間中使用多種模式(ROX
,RWX
)。
每一個StorageClass
都包含字段provisioner
和parameters
,在所屬的PV須要動態供給時使用這些字段。
StorageClass
對象的命名是很是重要的,它是用戶請求指定等級的方式。當建立StorageClass
對象時,管理員設置等級的名稱和其餘參數,但對象不會在建立後立刻就被更新。
管理員能夠指定一個默認的StorageClass
,用於綁定到那些未請求指定等級的PVC。詳細信息可參考PersistentVolumeClaim章節。
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: standard provisioner: kubernetes.io/aws-ebs parameters: type: gp2
StorageClass
都有存儲供應商provisioner,用來決定哪一種volume插件提供給PV使用。必須制定該字段。
你不限於指定此處列出的「內部」供應商(其名稱前綴爲「kubernetes.io」並與Kubernetes一塊兒分發)。你還能夠運行和指定外部供應商,它們是遵循Kubernetes定義的規範的獨立程序。外部提供者的做者對代碼的生命週期,供應商的分發方式,運行情況以及使用的卷插件(包括Flex)等都有充分的自主權。庫kubernetes-incubator/external-storage存放了一個庫, 用於編寫外部存儲供應商,而這些提供者實現了大量的規範,而且是各類社區維護的。
StorageClass
有一些參數用於描述歸屬於該StorageClass
的volume。不一樣的存儲提供商可能須要不一樣的參數。好比,參數type
對應的值io1
,還有參數iopsPerGB
,都是EBS專用的參數。當參數省略時,就會使用它的默認值。
…
…
…
…
…
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast provisioner: kubernetes.io/rbd parameters: monitors: 10.16.153.105:6789 adminId: kube adminSecretName: ceph-secret adminSecretNamespace: kube-system pool: kube userId: kube userSecretName: ceph-secret-user
● monitors
:Ceph的monitor,逗號分隔。該參數是必須的。
● adminId
:Ceph的客戶端ID,可在pool中建立鏡像。默認的是「admin」。
● adminSecretNamespace
:adminSecret的命名空間,默認值是「default」。
● adminSecretName
:adminId
的Secret Name。改參數是必須的,提供的祕鑰必須有類型「kubernetes.io/rbd」。
● pool
:Ceph的RBD pool,默認值是「rbd」。
● userId
:Ceph的客戶ID,用於映射RBD鏡像的,默認值和adminId
參數相同。
● userSecretName
:Ceph Secret的名稱,userId
用該參數來映射RBD鏡像。它必須和PVC在相同的命名空間。該參數也是必須的。提供的祕鑰必須有類型「kubernetes.io/rbd」。好比,按照下面的方式來建立:
$ kubectl create secret generic ceph-secret --type="kubernetes.io/rbd" --from-literal=key='QVFEQ1pMdFhPUnQrSmhBQUFYaERWNHJsZ3BsMmNjcDR6RFZST0E9PQ==' --namespace=kube-system
…
…
…
…
若是你在寫配置模板和示例,用於在須要持久化存儲的集羣中使用,那麼,咱們建議你使用如下的一些模式:
● 在你的捆綁配置(如Deployment、ConfigMap胖)中包含PVC對象。
● 在配置中不要包含PersistentVolume對象,由於實例化配置的用戶可能沒有建立PersistentVolumes的權限
● 當用戶提供實例化模板時,給用戶提供存儲類名稱的選項。
▷ 若是用戶提供了一個StorageClass
名稱,而且Kubernetes版本是1.4及以上,那麼將該值設置在PVC的volume.beta.kubernetes.io/storage-class
標註上。這會使得PVC匹配到正確的StorageClass
。
▷ 若是用戶沒有提供StorageClass
名稱,或者集羣版本是1.3,那麼久須要在PVC配置中設置volume.alpha.kubernetes.io/storage-class: default
標註。
☞ 這會使得在一些默認配置健全的集羣中,PV能夠動態的提供給用戶。
☞ 儘管在名稱中包含了alpha
單詞,可是該標註對應的代碼有着beta
級別的支持。
☞ 不要使用volume.beta.kubernetes.io/storage-class
,不管設置什麼值,甚至是空字符串。由於它會阻止DefaultStorageClass許可控制器。
● 在你的工具中,要監視那些一段時間後尚未得到綁定的PVC,而且展現給用戶。由於這可能代表集羣沒有支持動態存儲(此時咱們應該建立匹配的PV),或者集羣沒有存儲系統(此時用戶不能部署須要PVC的狀況)。
● 將來,咱們指望大多數集羣均可以使能DefaultStorageClass
,而且能有一些可用的存儲形式。然而,可能沒有行在全部集羣都能運的StorageClass
,因此默認狀況下不要只設置一種。在某些時候,alpha標註將再也不具備意義,但復位PVC的storageClass
字段將具備所需的效果。