第 7 章:為 Pods 建立 Storage
Volume 卷
容器中的文件在磁碟上是暫時存放的,這會為在容器中執行較重要的應用程式帶來一些問題。 當容器崩潰或停止時會出現一個問題。 此時容器狀態未儲存, 因此在容器生命週期內建立或修改的所有檔案都會遺失。 在崩潰期間,kubelet 會以乾淨的狀態重新啟動容器。 當多個容器在一個 Pod 中運作並且需要共用檔案時,會出現另一個問題。 跨所有容器設定和存取共用檔案系統具有一定的挑戰性
Volume 卷兩大分類
Volume 非持久化的存儲
- 只是為了一個 Pod 中的多個 container 之間可以共享數據,它具有和 pod 相同的生命週期
Persistent Volume 持久化的存儲
- 能夠將資料進行持久化儲存的一種資源對象,生命週期與 Pod 無關,因此 PersistentVolume 不應該依附於任何一個宿主機節點,否則必然會對Pod 調度產生限制
使用 Persistent Volumes 持久化的存儲
Static Provisionling Workflow
- 建立 PersistentVolume
- 由 Cluster 管理者建立
- 建立 PersistentVolumeClaim
- 由 pod 使用者申請使用 PersistentVolume
- 在 Pod 中的定義 PersistentVolumeClaim 來使用 Persistent Volume
建立 PersistentVolume
建立 PersistentVolume
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs
spec:
capacity:
storage: 4Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
server: 192.168.56.20
path: "/export/volumes/pod
建立 PersistentVolumeClaim
建立 PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-nfs
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
- 宣告事項
- Size
- Access mode ( Node 層級設定 )
ReadWriteOnce
:通過單一節點以 read-write 方式掛載ReadWriteMany
:通過多節點以 read-write 方式掛載ReadOnlyMany
:通過多節點以 read-only 模式掛載
- Storage Class
在 Pod 中的定義 PersistentVolumeClaim 來使用 Persistent Volume
根據 PVC 的 request 和 PV 的 properties,將最合適的 PV 及 PVC 結合起來
使用 PersistentVolumeClaim
apiVersion: apps/v1
kind: Deployment
spec:
volumes:
- name: webcontent
persistentVolumeClaim:
claimName: pvc-nfs
Persistent Volume Lifecycle 生命週期
- Binding ( PVC created, match PVC to PV )
- Using ( pod lifetime )
- Reclaim (PVC deleted, the pv will be reclaimed based on the recalimd policy: delete or retain)
- delete, 一旦 pvc 刪除了,那麼實際這塊 pv 也會被清理,裡面的資料會被刪除,然後這塊空間會等待下一次的 pvc
- retain, pvc 雖然刪除了,但是這塊 pv 裡的資料會保留,pv 的狀態會變成 released,這是無法馬上被下一次的 pvc 使用,管理員必須手動清理刪除
當Pod 使用 Volume
時,需要在 Pod YAML 中定義 Volume
的 configuration。隨著 K8S 的集群環境增大,大量的使用者需求佈署大量的 Pod,這樣就會導致一個情況,那就是使用者每次創建一個Pod時都需要為Pod重新config一個Volume
。當某個Volume
被某一使用者使用了,所有Pod的configuration file都需要重 新config,如此就會讓整個集群的運作非常沒有效率,因此需要有個集中式管理的storage solution,方法類似讓集群管理者可以創建一個storage pool
,使用者根據需求從storage pool
中擷取一部分使用,這就是Persistent Volumes(PV)
& Persistent Volumes Claim(PVC)
PV
和PVC
是兩個獨立的object,由adminstrator創造PV
;PVC
則由使用者創造,用以使用PV
當PV
和PVC
創建完成後,。在binding過程中,K8s會為PVC
挑選最合適的PV
,除了容量外,也會考量accessModes
、vloumeModes
和storage class
等等。
StorageClass
自動產生 Persistent volume
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
parameters:
csi.storage.k8s.io/fstype: xfs
type: io1
iopsPerGB: "50"
encrypted: "true"
allowedTopologies:
- matchLabelExpressions:
- key: topology.ebs.csi.aws.com/zone
values:
- us-east-2c
Types of Persistent Volumes 持久存儲卷類型
PersistentVolume types are implemented as plugins. Kubernetes currently supports the following plugins:
- csi :Container Storage Interface (CSI)
- fc:Fibre Channel (FC) storage
- hostPath:HostPath volume (for single node testing only; WILL NOT WORK in a multi-node cluster; consider using
local
volume instead) - iscsi:iSCSI (SCSI over IP) storage
- local:local storage devices mounted on nodes.
- nfs:Network File System (NFS) storage
emptyDir
定義 emptyDir 磁碟區的 Pod,在 Pod 被指派到某節點時此磁碟區會被建立。 儘管 Pod 中的容器掛載 emptyDir 磁碟區的路徑可能相同也可能不同,但這些容器都可以讀取和寫入 emptyDir 磁碟區中相同的檔案。 當 Pod 因某些原因被從節點上刪除時,emptyDir 磁碟區中的資料也會被永久刪除。容器崩潰並不會導致 Pod 從節點上移除,因此容器崩潰期間 emptyDir 磁碟區中的資料是安全的。
- emptyDir 用途
- 快取空間,例如基於磁碟的歸併排序
- 為耗時較長的運算任務提供檢查點,以便任務能方便地從崩潰前狀態復原執行
- 在 Web 伺服器容器服務資料時,儲存內容管理器容器所取得的文件
可以透過為預設媒體指定大小限制,來限制 emptyDir 磁碟區的儲存容量。 此存儲是從節點臨時存儲中分配的。 如果來自其他來源(如日誌檔案或鏡像分層資料)的資料佔滿了存儲,emptyDir 可能會在達到此限制之前發生儲存容量不足的問題。
- 當 Pod 被創建時,emptyDir 會被創建在 Node 中直到 Pod 被刪除
emptyDir
apiVersion: v1
kind: Pod
metadata:
name: multicontainer-pod
spec:
volumes:
- name: webcontent
emptyDir: {}
containers:
- name: nginx
iamge: nginx
volumeMounts:
- mountPath: /mydata-data
name: datavol
hostPath
HostPath 磁碟區有許多安全風險,最佳做法是盡可能避免使用 HostPath。 當必須使用 HostPath 磁碟區時,它的範圍應僅限於所需的檔案或目錄,並以唯讀方式掛載。hostPath 磁碟區能將主機節點檔案系統上的檔案或目錄掛載到你的 Pod 中。
例如,hostPath 的一些用法有:
執行一個需要存取 Docker 內部機制的容器;可使用 hostPath 掛載 /var/lib/docker 路徑。 在容器中執行 cAdvisor 時,以 hostPath 方式掛載 /sys。 允許 Pod 指定給定的 hostPath 在運行 Pod 之前是否應該存在,是否應該創建以及應該以什 麼方式存在。
HostPath
apiVersion: v1
kind: Pod
metadata:
name: multicontainer-pod
spec:
volumes:
- name: webcontent
hostPath:
path: /tmp
type: Directory
local
local 磁碟區所代表的是 某個被掛載的本機儲存設備,例如磁碟、分割區或目錄。local 磁碟區只能用作靜態建立的持久性磁碟區。 不支援動態配置。
與 hostPath 磁碟區相比,local 磁碟區能夠以持久且可移植的方式使用,而無需手動將 Pod 調度到節點。 系統透過查看 PersistentVolume 的節點親和性配置,就能了解磁碟區的節點約束。
然而,local 磁碟區仍取決於底層節點的可用性,並非適用於所有應用程式。 如果節點變得不健康,那麼 local 卷也將變得無法被 Pod 存取。 使用它的 Pod 將無法運作。 使用 local 磁碟區的應用程式必須能夠容忍這種可用性的降低,以及因底層磁碟的耐用性特徵而帶來的潛在的資料遺失風險。
local
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
spec:
capacity:
storage: 100Gi
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 (網路檔案系統) 掛載到你的 Pod 中。 不像 emptyDir 會在刪除 Pod 的同時也會被刪 除,nfs 卷的內容在刪除 Pod 時會被保存,卷只是被卸載。 這意味著 nfs 卷可以預先填充數據,並且這些數據可以在 Pod 之間共享。
Pod 容器共享 Volume
Pod 容器共享 Volume
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: web
name: web
spec:
containers:
- image: nginx
name: web
ports:
- containerport: 8080
volumeMounts:
- mountPath: /mydata-data
name: app-logs
- image: busybox
name: logreader
command: ["sh", "-c", "tail -f /log/catalina*.log"]
volumeMounts:
- mountPath: /logs
name: app-logs
volumes:
- name: app-logs
emptyDir: {}
status: {}