概述
Volume是對各種儲存資源的抽象、虛擬化。為管理、控制、使用儲存資源提供統一介面。Openstack中的volume為虛擬機器提供儲存,Docker中的volume為容器提供儲存。因為在kubernetes中可部署執行最小單位是pod ,所以kubernetes的volume為pod提供儲存。當然在部署pod時可以不為其提供volume,pod中的容器使用所在節點的硬碟,能同時讀寫資料的地方稱為可讀寫層。這種儲存是容器級的臨時儲存,不是pod級。其生命週期與容器相同,如果容器crash後被重啟,也就是舊容器被刪除而新容器啟動,則舊容器的可讀寫層與容器一起被刪除,其上資料丟失。同理如果pod在節點之間遷移排程,容器的可讀寫層並不會遷移排程。因此,kubernetes需要提供pod級volume,本文中的volume特指kubernetes。
Volume型別
Volume是抽象概念,有很多種具體實現,每種實現各具目的、特點、特性。差不多什麼東西都可以當成volume,型別如下:
- awsElasticBlockStore
- azureDisk
- azureFile
- cephfs
- configMap
- csi
- downwardAPI
- emptyDir
- fc (fibre channel)
- flocker
- gcePersistentDisk
- gitRepo (deprecated)
- glusterfs
- hostPath
- iscsi
- local
- nfs
- persistentVolumeClaim
- projected
- portworxVolume
- quobyte
- rbd
- scaleIO
- secret
- storageos
- vsphereVolume
這裡不對以上所有型別一一介紹,只對目前可能會用到的本地磁碟儲存和分散式儲存做簡單介紹說明
常見儲存型別說明及示例
cephfs
cephfs是一款優秀、流行的雲環境儲存解決方案,原因是它開源、高可用、彈性伸縮,對作業系統、硬體無特殊要求,使用者很容易搭建,使用它的節點也無特別要求。它具備awsElasticBlockStore陳述之所有特點,並且單個voluem可以被多個節點同時使用。使用者首先搭建自己的cephfs環境,然後配置kubernetes叢集與其對接,最後在pod中使用其提供的volume,詳細參考這裡。
configMap
使用者首先建立configMap並建立資料儲存其中,此時資料儲存在kubernetes的etcd資料庫中,volume還不存在。當使用者在pod中引用建立的configMap時,系統首先在節點上建立volume並將資料儲存其中,這個volume佔用的是節佔的儲存空間。此後就可以像使用普通volume一樣使用它。
configMap是kubernetes中的一種物件型別,核心本質是以volume的方式將單獨管理的配置資訊傳遞給pod中的容器,並非用來儲存持久化資料。詳細參考這裡。
downwardAPI
與configMap類似,以volume的方式向pod中的容器傳遞資訊。configMap中的資訊由使用者在建立物件時傳遞,而downwardAPI的資訊就來自pod物件本身,downwardAPI不需要建立,它是pod Spec中的一個欄位,內容指向pod物件本身的其它欄位,如pod的metadata、image等資訊。在建立pod時系統首先將指向的欄位提取出來,然後建立volume並儲存提取出來的欄位並掛載,容器就可以讀取這些欄位了。
downwardAPI的目的是為將pod本身的欄位資訊如label、annotation等傳遞給容器的一種手段。詳細參考這裡。
emptyDir
在節點上執行pod例項時才會建立emptyDir volume。它首先是節點上的一個空目錄,pod中的任何容器都可以用volume的形式掛載使用它。如果容器因為某種原因被刪除並重新啟動,建立的emptyDir不會刪除也不會被清空。當pod例項離開節點排程到其它節點或因為縮容被刪除時,emptyDir被刪除,相當於pod還在但資料丟了。示例:
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
glusterfs
與cephfs一樣,流行的雲環境下的儲存解決方案,詳細參考這裡,示例參考這裡。
hostPath
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
iscsi
網際網路小型計算機系統介面,其特點是便宜。示例參考這裡。
local
與emptyDir相似,它也佔用節點的儲存空間。不同點是它是kubernetes中的一種物件型別,使用者可以像管理普通物件一樣管理它。emptyDir在pod例項開時執行時分配,當pod離節點時刪除。local型別的volume則由使用者建立,系統在合適的節點上為其分配資源,排程到這個節點上的pod可以掛載它,pod離開時它也不會消失,除非使用者刪除。示例:
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: Delete
storageClassName: local-storage
local:
path: /mnt/disks/ssd1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- example-node
nfs
nfs
網路檔案系統,詳細參考這裡。
persistentVolumeClaim
與flocker相似,用來遮蔽不同雲環境,詳細參考這裡。
projected
如果一個容器需要掛開多個已經存在的volume比如Secret、ConfigMap、DownwardAPI等,原本每個這種型別的volume需要各自佔用一個掛載目錄,而projected能將它們整合在一起,並只掛開到一個目錄下,示例:
apiVersion: v1
kind: Pod
metadata:
name: volume-test
spec:
containers:
- name: container-test
image: busybox
volumeMounts:
- name: all-in-one
mountPath: "/projected-volume"
readOnly: true
volumes:
- name: all-in-one
projected:
sources:
- secret:
name: mysecret
items:
- key: username
path: my-group/my-username
- downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "cpu_limit"
resourceFieldRef:
containerName: container-test
resource: limits.cpu
- configMap:
name: myconfigmap
items:
- key: config
path: my-group/my-config