本文環境為Kubernetes V1.11,操作系統版本為 CentOs 7.3,Kubernetes集群安裝可以參考 kubeadm安裝kubernetes V1.11.1 集群
容器中的存儲都是臨時的,因此Pod重啟的時候,內部的數據會發生丟失。實際應用中,我們有些應用是無狀態,有些應用則需要保持狀態數據,確保Pod重啟之后能夠讀取到之前的狀態數據,有些應用則作為集群提供服務。這三種服務歸納為無狀態服務、有狀態服務以及有狀態的集群服務,其中后面兩個存在數據保存與共享的需求,因此就要采用容器外的存儲方案。
Kubernetes中存儲中有四個重要的概念:Volume、PersistentVolume PV、PersistentVolumeClaim PVC、StorageClass。掌握了這四個概念,就掌握了Kubernetes中存儲系統的核心。我用一張圖來說明這四者之間的關系。
- Volumes是最基礎的存儲抽象,其支持多種類型,包括本地存儲、NFS、FC以及眾多的雲存儲,我們也可以編寫自己的存儲插件來支持特定的存儲系統。Volume可以被Pod直接使用,也可以被PV使用。普通的Volume和Pod之間是一種靜態的綁定關系,在定義Pod的同時,通過
volume
屬性來定義存儲的類型,通過volumeMount
來定義容器內的掛載點。 - PersistentVolume。與普通的Volume不同,PV是Kubernetes中的一個資源對象,創建一個PV相當於創建了一個存儲資源對象,這個資源的使用要通過PVC來請求。
- PersistentVolumeClaim。PVC是用戶對存儲資源PV的請求,根據PVC中指定的條件Kubernetes動態的尋找系統中的PV資源並進行綁定。目前PVC與PV匹配可以通過
StorageClassName
、matchLabels
或者matchExpressions
三種方式。 - StorageClass。
Volumes
Docker提供了Volumes,Volume 是磁盤上的文件夾並且沒有生命周期的管理。Kubernetes 中的 Volume 是存儲的抽象,並且能夠為Pod提供多種存儲解決方案。Volume 最終會映射為Pod中容器可訪問的一個文件夾或裸設備,但是背后的實現方式可以有很多種。
Volumes的類型
- cephfs
- configMap
- emptyDir
- hostPath
- local
- nfs
- persistentVolumeClaim
emptyDir
emptyDir在Pod被分配到Node上之后創建,並且在Pod運行期間一直存在。初始的時候為一個空文件夾,當Pod從Node中移除時,emptyDir將被永久刪除。Container的意外退出並不會導致emptyDir被刪除。emptyDir適用於一些臨時存放數據的場景。默認情況下,emptyDir存儲在Node支持的介質上,不管是磁盤、SSD還是網絡存儲,也可以設置為Memory
。
apiVersion: v1
kind: Pod
metadata:
name: tomcat-ccb
namespace: default
labels:
app: tomcat
node: devops-103
spec:
containers:
- name: tomcat
image: docker.io/tomcat
volumeMounts:
- name: tomcat-storage
mountPath: /data/tomcat
- name: cache-storage
mountPath: /data/cache
ports:
- containerPort: 8080
protocol: TCP
env:
- name: GREETING
value: "Hello from devops-103"
volumes:
- name: tomcat-storage
hostPath:
path: /home/es
- name: cache-storage
emptyDir: {}
hostPath
hostPath就是將Node節點的文件系統掛載到Pod中,在之前的例子中也可以看到用法。
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
# directory location on host
path: /data
# this field is optional
type: Directory
local
A local volume represents a mounted local storage device such as a disk, partition or directory.
local類型作為靜態資源被PersistentVolume使用,不支持Dynamic provisioning。與hostPath相比,因為能夠通過PersistentVolume的節點親和策略來進行調度,因此比hostPath類型更加適用。local類型也存在一些問題,如果Node的狀態異常,那么local存儲將無法訪問,從而導致Pod運行狀態異常。使用這種類型存儲的應用必須能夠承受可用性的降低、可能的數據丟失等。
apiVersion: v1
kind: PersistentVolume
metadata:
name: www
spec:
capacity:
storage: 100Mi
volumeMode: Filesystem
accessModes: ["ReadWriteOnce"]
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /home/es
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- devops-102
- devops-103
對於使用了PV的Pod,Kubernetes會調度到具有對應PV的Node上,因此PV的節點親和性 nodeAffinity 屬性是必須的。
PersistentVolume nodeAffinity is required when using local volumes. It enables the Kubernetes scheduler to correctly schedule Pods using local volumes to the correct node.
Persistent Volumes
Persistent Volumes 提供了一個抽象層,向用戶屏蔽了具體的存儲實現形式。
- PersistentVolume PV:集群管理員提供的一塊存儲,是Volumes的插件。類似於Pod,但是具有獨立於Pod的生命周期。具體存儲可以是NFS、雲服務商提供的存儲服務。
- PersistentVolumeClaim PVC:PVC是用戶的存儲請求,PVC消耗PV資源。
生命周期:
- 供給
- 靜態供給
- 動態供給:動態供給的請求基於StorageClass,集群針對用戶的PVC請求,可以產生動態供給。
- 綁定 Binding
- 使用
- 在用對象保護:對於正在使用的PV提供了保護機制,正在使用的PV如果被用戶刪除,PV的刪除會推遲到用戶對PV的使用結束。
- 重用 Reclaim 策略
- 保留 Retain:保留現場,Kubernetes等待用戶手工處理數據。
- 刪除 Delete:Kubernetes會自動刪除數據
- 重用:這個策略已經不推薦使用了,應該使用 Dynamic Provisioning 代替。
- 擴容。主要是對於一些雲存儲類型,例如gcePersistentDisk、Azure Disk提供了擴容特性,在1.11版本還處於測試階段。
PersistenVolume 這個功能目前是通過Plugin插件的形式實現的,目前的版本V1.11.1有19中,特別關注了一下HostPath。
HostPath (Single node testing only – local storage is not supported in any way and WILL NOT WORK in a multi-node cluster)
Persistent Volumes 的一些屬性
- Capacity:一般情況PV擁有固定的容量
- Volume Mode:在1.9版本中是alpha特性,允許設置 filesystem 使用文件系統(默認),設置 raw 使用裸設備。
- Access Modes
- Class:可以設置成StorageClass的名稱。具有Class屬性的PV只能綁定到還有相同CLASS名稱的PVC上。沒有CLASS的PV只能綁定到沒有CLASS的PVC上。
- Reclaim Policy
狀態
- Available:未被任何PVC使用
- Bound:綁定到了PVC上
- Released:PVC被刪掉,資源未被使用
- Failed:自動回收失敗
PersistentVolumeClaims
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 8Gi
storageClassName: slow
selector:
matchLabels:
release: "stable"
matchExpressions:
- {key: environment, operator: In, values: [dev]}
一些屬性
- Access Modes
- Volume Modes
- Resources
- Selector:PVC可以通過標簽選擇器選擇PV資源。可以包含兩個字段
matchLabels
和matchExpressions
。 - storageClassName 類似標簽選擇器,通過storagClassName 來確定PV資源。
Storage Class
StorageClass為管理員提供了一種描述存儲類型的方法。通常情況下,管理員需要手工創建所需的存儲資源。利用動態容量供給的功能,就可以實現動態創建PV的能力。動態容量供給 Dynamic Volume Provisioning 主要依靠StorageClass。
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer