在同一個(gè)Pod中的多個(gè)容器能夠共享Pod級(jí)別的存儲(chǔ)卷Volume。Volume可以被定義為各種類(lèi)型,多個(gè)容器各自進(jìn)行掛載操作,將一個(gè)volume 掛載為容器內(nèi)部需要的目錄。
kubernetes 管理的宿主機(jī)本地存儲(chǔ)類(lèi)型:
- EmptyDir:臨時(shí)存儲(chǔ)
- HostPath:宿主機(jī)目錄
持久化存儲(chǔ)(PV)和網(wǎng)絡(luò)共享存儲(chǔ)類(lèi)型:
- CephFS:一種開(kāi)源共享存儲(chǔ)系統(tǒng)
- Cinder:一種開(kāi)源共享存儲(chǔ)系統(tǒng)
- CSI:容器存儲(chǔ)接口
- FC(Fibre Channel):光纖存儲(chǔ)設(shè)備
- Flocker:一種開(kāi)源共享存儲(chǔ)系統(tǒng)
- Glusterfs:一種開(kāi)源共享存儲(chǔ)系統(tǒng)
- iSCSI:iSCSI存儲(chǔ)設(shè)備
- Local:本地持久化存儲(chǔ)
- NFS:網(wǎng)絡(luò)文件系統(tǒng)
- PersistentVolumeChaim:簡(jiǎn)稱PVC,持久化存儲(chǔ)的申請(qǐng)空間
- Portworx Volumes:Portworx 提供的存儲(chǔ)服務(wù)
- Quobyte Volumes:Quobyte 提供的存儲(chǔ)服務(wù)
- RBD(Ceph Block Device):Ceph 塊存儲(chǔ)
Node 本地存儲(chǔ)卷
kubernetes 管理的 Node 本地存儲(chǔ)卷(Volume)的類(lèi)型:
- EmptyDir:與 Pod 同生命周期的Node 臨時(shí)存儲(chǔ)
- HostPath: Node 目錄
- Local:基于持久卷(PV)管理的 Node 目錄
emptyDir
當(dāng) Pod 分派到某個(gè) Node 上時(shí),emptyDir
卷會(huì)被創(chuàng)建,并且在 Pod 在該節(jié)點(diǎn)上運(yùn)行期間,卷一直存在。 就像其名稱表示的那樣,卷最初是空的。 盡管 Pod 中的容器掛載 emptyDir
卷的路徑可能相同也可能不同,這些容器都可以讀寫(xiě) emptyDir
卷中相同的文件。 當(dāng) Pod 因?yàn)槟承┰虮粡墓?jié)點(diǎn)上刪除時(shí),emptyDir
卷中的數(shù)據(jù)也會(huì)被永久刪除。
下面是使用 EmptyDir 類(lèi)型的存儲(chǔ)卷的 Pod 的YAML 配置示例,該類(lèi)型的存儲(chǔ)卷的參數(shù)只有一對(duì)花括號(hào)"{}"
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- image: busybox
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
hostPath
hostPath
類(lèi)型的存儲(chǔ)卷將主機(jī)節(jié)點(diǎn)文件系統(tǒng)上的文件或目錄掛載到容器中。
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- image: busybox
name: test-container
volumeMounts:
- mountPath: /host-data
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /data # 宿主上目錄位置
type: Directory # 此字段為可選, Directory 表示該目錄必須存在
HostPath 的 type 配置參數(shù):
- 空:系統(tǒng)默認(rèn)值。為向后兼容的設(shè)置,意為系統(tǒng)在掛載 path 時(shí)不做任何校驗(yàn)
- DirectoryOrCreate:path 指定的路徑必須是目錄,如果不存在,則系統(tǒng)將自動(dòng)創(chuàng)建該目錄,將權(quán)限設(shè)置為 0755,與kubelet具有相同的 owner 和 group
- Directory:path 指定的目錄必須存在,否則掛載失敗
- FileOrCreate:path 指定的路徑必須是文件,如果不存在,則系統(tǒng)將自動(dòng)創(chuàng)建該文件,將權(quán)限設(shè)置為 0644,與kubelet 具有相同的 owner 和group
- File:path 指定的文件必須存在,否則掛載失敗
- Socket:path 指定的 UNIX socket 必須存在,否則掛載失敗
- CharDevice:path 指定的字符設(shè)備(character device)必須存在,否則掛載失敗
- BlockDevice:path 指定的塊設(shè)備(block device)必須存在,否則掛載失敗
持久卷
為了能夠屏蔽底層存儲(chǔ)實(shí)現(xiàn)的細(xì)節(jié),讓用戶方便使用及管理員方便管理,Kubernetes 從1.0版本就引入了 Persistent Volume (PV) 和 Persistent Volume Claim(PVC) 兩個(gè)資源對(duì)象來(lái)實(shí)現(xiàn)存儲(chǔ)管理子系統(tǒng)。
PV 描述的,是持久化存儲(chǔ)數(shù)據(jù)卷。
PVC 則是用戶對(duì)存儲(chǔ)資源的一個(gè)申請(qǐng)。
NFS
centos 8 安裝
$ yum install nfs-utls -y
$ cat /etc/exports # 配置 exports
/data/nfs/192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash)
$ systemctl start nfs-server
PV、PVC
定義一個(gè)NFS 類(lèi)型的PV,如下:
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
storageClassName: manual
nfs:
path: /
server: 172.17.0.2
定義聲明一個(gè)1GIB 大小的PVC,如下:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs
spec:
resources:
requests:
storage: 1Gi
storageClassName: manual
accessModes:
- ReadWriteMany
用戶創(chuàng)建的 PVC 必須和符合條件的 PV進(jìn)行綁定,檢查條件包括兩部分:
- PV 和 PVC 的 spec 字段,比如 PV 的存儲(chǔ)(storage)大小,必須滿足 PVC 的要求。
- PV 和 PVC 的 storageClassName 字段必須一致。
PVC 和 PV 綁定之后,Pod 就可以使用這個(gè) PVC了,YAML 如下:
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
role: web-frontend
spec:
containers:
- name: web
image: nginx
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 80
volumeMounts:
- name: nfs
mountPath: "/usr/share/nginx/html"
volumes:
- name: nfs
persistentVolumeClaim:
claimName: nfs
pod 在volumes 字段聲明使用 PVC 名字,等 Pod 創(chuàng)建之后,kubelet 就會(huì)把 PVC 所對(duì)應(yīng)的 PV 的 Volume,掛載到 Pod 容器的目錄上。
StorageClass
PV 的創(chuàng)建,是由運(yùn)維人員完成的。在大規(guī)模的生產(chǎn)環(huán)境里,這是一個(gè)非常麻煩的工作。
這是因?yàn)椋粋€(gè)大規(guī)則的 Kubernetes 集群里很可能有成千上萬(wàn)個(gè) PVC,這就意味著運(yùn)維人員必須事先創(chuàng)建出成千上萬(wàn)個(gè)PV。更麻煩的是,隨著新的 PVC 不斷被提交,運(yùn)維人員不得不繼續(xù)添加新的、能滿足條件的PV,否則新的 Pod 就會(huì)因?yàn)?PVC 綁定不到 PV而失敗。在實(shí)際操作中,這幾乎沒(méi)辦法靠人工做到。
所以,Kubernetes 為我們提供了一套可以自動(dòng)創(chuàng)建 PV 的機(jī)制,即 Dynamic Provisioning。
相比之下,前面人工管理的 PV 的方式就叫做 Staic Provisioning。
Dynamic Provisioning 機(jī)制工作的核心,在于一個(gè)名叫 StorageClass 的 API 對(duì)象。
StorageClass 對(duì)象會(huì)定義兩部分內(nèi)容:
- PV的屬性,比如,存儲(chǔ)類(lèi)型、Volume 的大小等。
- 創(chuàng)建 PV 需要用到的存儲(chǔ)插件。比如,Ceph 等
有了這兩個(gè)信息后,Kubernetes 就能夠根據(jù)用戶提交的 PVC,找到一個(gè)對(duì)應(yīng)的 StorageClass 了。然后,Kubernetes 就會(huì)調(diào)用 StorageClass 聲明的存儲(chǔ)插件,創(chuàng)建出需要的 PV。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: block-service
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-ssd
provisioner:描述存儲(chǔ)資源的提供者,用于提供具體的 PV 資源。provisioner的值為:kubernetes.io/gce-pd,表示Kubernetes 內(nèi)置的 GCE PD 存儲(chǔ)插件的名字。
parameters 字段就是 PV 的參數(shù)。type=pd-ssd,指的是這個(gè) PV 的類(lèi)型是SSD 格式的 GCE 遠(yuǎn)程磁盤(pán)。
目前 StorageClass 資源對(duì)象支持設(shè)置的存儲(chǔ)參數(shù)最多為 512 個(gè),全部 key 和 value 所占的空間不能超過(guò) 256KB。
如果你使用部署在本地的 Kubernetes 集群以及 Rook 存儲(chǔ)服務(wù)的話,YAML 如下:
apiVersion: ceph.rook.io/v1
kind: Pool
metadata:
name: replicapool
namespace: rook-ceph
spec:
replicated:
size: 3
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: block-service
provisioner: ceph.rook.io/block
parameters:
pool: replicapool
clusterNamespace: rook-ceph
創(chuàng)建 StorageClass
$ kubectl apply -f sv.yaml
PVC 指定使用 StorageClass 名字即可,YAML 如下:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc
spec:
resources:
requests:
storage: 1Gi
storageClassName: block-service
accessModes:
- ReadWriteOnce
有了 Dynamic Provisioning 機(jī)制,運(yùn)維人員只需要在 Kubernetes 集群里創(chuàng)建出數(shù)量有限的 StorageClass 對(duì)象就可以了。