Volume - PV & PVC
什麼是 Storage Class?
在 Kubernetes 中,Storage Class(存儲類別)是一種資源物件,定義了如何動態配置持久性存儲(Persistent Volume, PV)。 它為不同的存儲需求提供抽象,允許用戶定義存儲的配置細節,例如性能、備份策略或存儲類型(如 SSD 或 HDD)。
Storage Class 的優勢
- 動態配置 PV:透過 Storage Class,可以根據 Persistent Volume Claim(PVC)的需求,自動創建 PV。
- 靈活性:支持不同的存儲後端(如雲提供商的磁碟、分佈式存 儲)。
- 簡化操作:用戶不需手動創建 PV,只需定義存儲需求,Kubernetes 會自動匹配。
Storage Class 的結構
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-storage
provisioner: kubernetes.io/aws-ebs # 使用 AWS EBS 作為存儲後端。
parameters:
type: gp2 # 使用 AWS 的通用 SSD 磁碟。
fsType: ext4 # 文件系統格式。
reclaimPolicy: Retain # 設定為 Retain,表示 PV 被釋放後不會自動刪除。
allowVolumeExpansion: true # 允許 PVC 動態擴展存儲大小。
volumeBindingMode: WaitForFirstConsumer # 設定為 WaitForFirstConsumer,PV 會在 Pod 需要時才進行綁定。
- provisioner:指定存儲後端插件(例如 AWS EBS、GCE PD、NFS 等)。
- parameters:定義與存儲後端相關的配置細節。
- reclaimPolicy:定義 PV 被釋放後的處理策略(例如
Delete或Retain)。 - allowVolumeExpansion:允許動態擴展卷的大小(選擇性)。
- volumeBindingMode:定義 PV 的綁定模式,可設為
Immediate(立即綁定)或WaitForFirstConsumer(等待消費者)。
常見的 Provisioner
以下是一些常見的 Storage Class provisioner:
- AWS:
kubernetes.io/aws-ebs - Google Cloud:
kubernetes.io/gce-pd - Azure:
kubernetes.io/azure-disk - NFS:
kubernetes.io/nfs - Ceph:
ceph.com/rbd
reclaimPolicy 詳細介紹
reclaimPolicy 是 Kubernetes 中 Persistent Volume (PV) 的一個屬性,定義了當 PV 與 Persistent Volume Claim (PVC) 解綁後,該 PV 的回收策略。回收策略主要有以下兩種常見類型:
| 策略類型 | 說明 | 適用場景 | 優勢 | 注意事項 |
|---|---|---|---|---|
| Retain | 保留 PV 和數據,用戶需手動管理 | 數據需保留或重新使用的場景 | 提供更多控制權 | 需要手動處理 PV 和數據清理 |
| Delete | 自動刪除 PV 和底層存儲 | 臨時存儲、不需要長期保存的場景 | 操作簡單,自動清理 | 數據會被永久刪除 |
1. Retain
Retain 策略表示當 PVC 釋放 PV 時,PV 不會自動刪除,並保留其原始的數據,這使得用戶可以手動處理該存儲資源。
特點
- 數據保留:PV 的數據會被保留,即使 PVC 被刪除。
- 手動管理:用戶需要手動刪除或重新配置該 PV。
- 適合場景:
- 敏感數據的保存,例如需要備份或恢復的應用。
- 想要重新使用 PV 的數據,但需要手動驗證和配置。
流程
- 用戶刪除 PVC。
- PV 狀態變為
Released。 - Kubernetes 不會自動刪除 PV 或其數據。
- 管理員可以手動刪除 PV 或重設其狀態,使其能再次綁定到新的 PVC。
使用 Retain 策略的 PV 配置範例
apiVersion: v1
kind: PersistentVolume
metadata:
name: retain-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
hostPath:
path: /data/retain-pv
2. Delete
Delete 策略表示當 PVC 被刪除時,與其綁定的 PV 及其底層存儲資源(例如磁碟)會自動被清除。
特點
- 自動清理:PV 和底層存儲會自動被 Kubernetes 刪除。
- 簡化操作:適合不需要保留數據的場景,避免手動清理存儲。
- 適合場景:
- 開發測試環境,數據不需要長期保留。
- 臨時存儲,例如緩存數據或臨時文件。
流程
- 用戶刪除 PVC。
- Kubernetes 自動刪除 PV 和其底層存儲(如雲端磁碟、NFS 文件等)。
- 整個資源被回收,無需額外操作。
注意事項
- 如果底層存儲是雲服務(如 AWS EBS 或 GCE PD),這些資源會隨 PVC 刪除而一起釋放。
- 避免使用
Delete策略於需要長期保留或敏感數據的場景。
使用 Delete 策略的 PV 配置範例
apiVersion: v1
kind: PersistentVolume
metadata:
name: delete-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
// highlihgt-next-line
persistentVolumeReclaimPolicy: Delete
hostPath:
path: /data/delete-pv
Storage Class 的使用流程
- 創建 Storage Class:管理員定義不同的 Storage Class 來支持多種存儲需求。
- 創建 PVC:用戶在 PVC 中指定所需的 Storage Class 名稱。
- 動態配置 PV:Kubernetes 根據 Storage Class 的配置自動創建 PV,並與 PVC 進行綁定。
什麼是 PV(Persistent Volume)?
PV 是 Kubernetes 中的一種資源,表示集群中的存儲,可以獨立於 Pod 的生命週期進行管理。PV 提供了存儲的抽象層,允許用戶以統一的方式訪問底層存儲資源(如 NFS、iSCSI、雲存儲等)。
PV 的特性
- 獨立於 Pod:PV 是集群範圍的資源,可 以被多個 Pod 使用(視具體配置而定)。
- 多種存儲後端支持:支持各種存儲類型(如本地存儲、分佈式存儲和雲存儲)。
- 存儲大小可定義:可根據需求定義不同大小的存儲空間。
PV 的生命周期狀態
- Available(可用)
- PV 已創建但未與 PVC 綁定,處於空閒狀態。
- 可被 PVC 請求並綁定。
- Bound(已綁定)
- PV 已與某個 PVC 綁定,正在被 Pod 使用。
- 一個 PV 只能與一個 PVC 綁定。
- Released(已釋放)
- PVC 被刪除後,PV 狀態變為釋放,但數據仍保留。
- 視回收策略,PV 可重新使用(
Retain)或刪除(Delete)。
- Failed(失敗)
- PV 回收或刪除過程失敗。
- 需管理員檢查並修復。
狀態遷移
- Available → Bound:當 PV 被某個 PVC 綁定後,狀態從 Available 轉為 Bound。
- Bound → Released:當 PVC 被刪除後,PV 狀態轉為 Released。
- Released → Available:如果 PV 被回收並清空,狀態可重置為 Available。
- Released → Failed:如果 PV 的回收策略執行失敗,狀態變為 Failed。
什麼是 PVC(Persistent Volume Claim)?
PVC 是用戶對存儲需求的聲明,是一種對 PV 的請求。用戶不需要關注底層存儲的實現,只需通過 PVC 定義所需的存儲大小與訪問模式即可。
PVC 的特性
- 簡化用戶操作:用戶只需定義需求,Kubernetes 負責匹配合適的 PV。
- 動態或靜態綁定:可以與事先創建的 PV 綁定,也可以根據 PVC 請求動態創建 PV。
- 多種訪問模式:支持單一 Pod 訪問(ReadWriteOnce)、多個 Pod 同時讀寫(ReadWriteMany)、只讀訪問(ReadOnlyMany)、只允許單個 Pod 讀寫(ReadWriteOncePod)。
PVC 訪問模式介紹
PVC 支持多種訪問模式,這些模式定義了存儲資源的使用方式,即如何允許 Pod 訪問 Persistent Volume (PV)。以下是每種訪問模式的詳細說明:
1. ReadWriteOnce (RWO)
ReadWriteOnce 允許存儲卷在單個節點上以讀寫模式掛載,可被多個 Pod 同時使用,但僅限於同一節點。
特性
- 單節點多 Pod:在同一節點上,該存儲卷可以被多個 Pod 掛載並共享讀寫權限。
- 跨節點限制:存儲卷無法同時掛載到多個節點。
- 常見場景:
- 單節點應用,如資料庫或需要高效存儲訪問的應用程序。
限制
- 存儲卷只能在單個節點上掛載,無法支持跨節點的讀寫操作。
- 底層存儲後端必須支持
RWO模式。
2. ReadWriteMany (RWX)
ReadWriteMany 允許存儲卷被多個 Pod 同時掛載,並支持跨多個節點以讀寫模式訪問。
特性
- 多節點多 Pod 共享:允許多個 Pod 同時讀寫存儲卷,無論 Pod 位於同一節點還是不同節點。
- 常見場景:
- 多實例應用需要共享數據(例如基於 NFS 的存儲)。
- 分布式系統、共享緩存或需要共享存儲的應用程序。
限制
- 存儲後端需要支持共享訪問(例如 NFS、CephFS 或其他分佈式文件系統)。
- 同時訪問的 Pod 數量增多可能會影響性能。
3. ReadOnlyMany (ROX)
ReadOnlyMany 允許存儲卷被多個 Pod 同時掛載,並且支持跨多個節點以只讀模式訪問。
特性
- 只讀共享:允許多個 Pod 同時掛載 存儲卷,但只能讀取數據,無法進行任何修改。
- 跨節點支持:Pod 可以分佈在多個節點上,同時訪問相同的存儲卷。
- 常見場景:
- 靜態資源共享,如配置文件或靜態數據(例如訓練數據集)。
- 容器需要訪問相同的數據源但無需修改。
限制
- 不支持寫入操作。
- 存儲後端需支持多節點掛載(例如 NFS 或其他共享存儲系統)。
4. ReadWriteOncePod (RWOP) (Kubernetes v1.22 及之後的版本)
ReadWriteOncePod 是一種更嚴格的模式,表示該存儲卷只能被一個 Pod 掛載,且具有讀寫權限。
特性
- 單 Pod 限制:與 RWO 不同,RWOP 保證存儲卷僅被單一 Pod 掛載,即使該 Pod 被調度到不同的節點,這一限制依然有效。
- 常見場景:
- 需要強一致性和單一消費者的場景。
- 避免存儲卷在多個 Pod 之間意外被重複使用。
限制
- 僅適用於需要絕對保證單 Pod 訪問的場景。
- 與 RWO 不同,RWOP 會在調度層面進行強約束。
PVC 訪問模式比較
| 訪問模式 | 是否支持多 Pod 掛載 | 是否支持讀寫 | 常見場景 | 限制 |
|---|---|---|---|---|
| ReadWriteOnce (RWO) | 單節點多 Pod 支持 | 是 | 單節點應用、資料庫 | 只能單節點掛載 |
| ReadWriteMany (RWX) | 是(跨節點支持) | 是 | 多節點共享應用、分布式存儲 | 存儲後端需支持共享訪問 |
| ReadOnlyMany (ROX) | 是(跨節點支持) | 否 | 多節點讀取靜態數據 | 無法寫入 |
| ReadWriteOncePod (RWOP) | 否(僅單 Pod) | 是 | 單 Pod 強一致性數據訪問 | 僅允許一個 Pod 掛載 |
PVC 儲存類型介紹
Persistent Volume Claim (PVC) 可以通過不同的存儲後端提供多種儲存類型,滿足各種應用場景需求。以下是主要的 PVC 儲存類型:
1. 塊存儲 (Block Storage)
說明
塊存儲是一種低層次的存儲類型,為應用提供裸磁碟(Block Device),應用可以直接對其進行格式化、分區和管理。
特性
- 高性能:適合 I/O 密集型應用。
- 靈活性:應用可自行決定文件系統的格式化和掛載方式。
- 強一致性:每個存儲塊的操作均為獨立且原子性。
常見 場景
- 資料庫應用(如 MySQL、PostgreSQL)。
- 日誌記錄(如 ElasticSearch)。
支援的後端
- AWS EBS (Elastic Block Store)。
- GCE PD (Persistent Disk)。
- Azure Disk。
2. 文件存儲 (File Storage)
說明
文件存儲為應用提供文件系統接口,適合需要共享存取的應用場景。應用無需處理底層分區或格式化。
特性
- 共享性:多個 Pod 可同時掛載並訪問文件系統。
- 簡化管理:存儲後端自動管理文件系統。
- 靈活共享:支持多 Pod 同時讀取或寫入。
常見場景
- 共享配置文件或靜態資源。
- 應用程序中需要多實例共享文件的場景。
支援的後端
- NFS (Network File System)。
- Azure File。
- Google Filestore。
3. 物件存儲 (Object Storage)
說明
物件存儲是針對非結構化數據的存儲類型,通常用於存儲大量文件或二進制數據(如圖片、影片等)。Kubernetes 通過 CSI(Container Storage Interface)插件,將物件存儲與 PVC 集成。
特性
- 非結構化數據支持:適合存儲文件、備份數據。
- 高度可擴展:支持海量數據存儲。
- 網路存取:通過 HTTP/S 協議訪問數據。
常見場景
- 圖片或視頻存儲。
- 備份和恢復數據。
支援的後端
- AWS S3。
- Google Cloud Storage。
- MinIO(開源 S3 兼容存儲)。
4. 本地存儲 (Local Storage)
說明
本地存儲使用 Kubernetes 節點的本地磁碟或存儲設備作為 PV,通常僅限於單節點訪問。
特性
- 高性能:因為數據存儲於本地磁碟,延遲極低。
- 節點限制:PVC 僅能與其所屬的節點上的 PV 綁定。
- 易於部署:不依賴雲端存儲服務。
常見場景
- 測試環境。
- 不需要共享數據的本地應用。
支援的後端
- 節點本地磁碟。
- NVMe 或 SSD 本地存儲。
5. 動態存儲 (Dynamic Provisioning)
說明
動態存儲類型允許 Kubernetes 根據 PVC 自動創建 PV,而不需要用戶預先創建 PV。需要使用 StorageClass 來定義存儲後端配置。
特性
- 自動化:PV 的創建和管理完全由 Kubernetes 處理。
- 靈活性:支持多種存儲後端。
- 簡化操作:用戶只需定義 PVC,無需關注 PV 的配置。
常見場景
- 多租戶環境。
- 需要快速調整存儲需求的應用。
支援的後端
- 任何支持 StorageClass 的存儲插件(如 CSI 插件)。
PVC 儲存類型比較
| 儲存類型 | 特性 | 常見場景 | 支援後端 |
|---|---|---|---|
| 塊存儲 | 高性能、低延遲、裸磁碟 | 資料庫、日誌記錄 | AWS EBS、GCE PD、Azure Disk |
| 文件存儲 | 文件共享、多 Pod 訪問 | 共享配置、靜態資源共享 | NFS、Azure File |
| 物件存儲 | 高度可擴展、HTTP/S 訪問 | 文件存儲、備份和恢復 | AWS S3、Google Cloud Storage |
| 本地存儲 | 高性能、低延遲、本地磁碟 | 測試環境、本地應用 | 本地磁碟、NVMe |
| 動態存儲 | 自動化創建 PV,支持多種後端 | 多租戶環境、動態調整存儲需求 | 任意支持 StorageClass 的後端 |
PVC 的使用流程
- 用戶聲明:用戶定義 PVC,描述所需的存儲大小和訪問模式。
- 綁定 PV:Kubernetes 自動尋找與 PVC 匹配的 PV。
- Pod 使用:Pod 通過掛載 PVC 間接訪問 PV 提供的存儲資源。
三者之間的關係
- StorageClass:定義存儲的類型和配置細節。
- PersistentVolume(PV):提供實際的存儲資源,是存儲的具體實現。
- PersistentVolumeClaim(PVC):用戶的存儲請求,通過 PVC 使用 PV。
流程順序
- 管理者設定 PV:管理者首先會設定 PersistentVolume (PV),並定義存儲大小、存取模式(如只讀或讀寫)及其他屬性,或配置 StorageClass 來支援動態創建 PV。
- 用戶提交 PVC:用戶通過 PersistentVolumeClaim (PVC) 提交存儲請求,指定所需的存儲大小、存取模式以及所需的 StorageClass(如果需要)。
- PVC 與 PV 綁定:Kubernetes 會尋找一個符合條件的 PV 與 PVC 綁定。如果沒有現有的 PV,且指定了 StorageClass,Kubernetes 會使用該 StorageClass 動態創建一個新的 PV。
- PVC 掛載到 Pod:綁定成功後,PVC 就可以被 Pod 使用,並掛載到 Pod 上的指定路徑。
實作 PV & PVC
預設的 StorageClass
- 首先我們可以查看 StorageClass,我們會發現 kubernetes 有幫我們預設一個 StorageClass
kubectl.exe get storageclasses.storage.k8s.io hostpath
---
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
hostpath (default) docker.io/hostpath Delete Immediate false 99d
建立 PVC
-
接著我們可以建立 PVC 的設定檔,因為我們在單一節點,並且後續有多個 Pod 需要寫入和讀取,因此 accessModes 我們使用
ReadWriteOnce。 -
在 storageClassName 我們指定上面的預設
hostpath,如果不想使用預設要在 storageClassName 留上""。 -
另外增加資源限制,最大儲存空間是 1 GibiByte。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-demo
spec:
accessModes:
- ReadWriteOnce
storageClassName: hostpath
resources:
requests:
storage: 1Gi
- 使用指令執行他,並且我們可以查看 PV 是否自動建立,並且可以看到狀態是否是 Bound,另外 PVC 也會建立。
kubectl.exe apply -f pvc-demo.yaml
---
persistentvolumeclaim/pvc-demo created
kubectl.exe get pv
---
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-9bb1ea11-b8ff-4b4d-b217-5fe68d31b1a0 1Gi RWO Delete Bound default/pvc-demo hostpath 21s
kubectl.exe get pvc
---
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-demo Bound pvc-9bb1ea11-b8ff-4b4d-b217-5fe68d31b1a0 1Gi RWO hostpath 50s
建立兩個服務使用相同 PVC
-
首先我們像之前 實作 EmptyDir 一樣,需要建立 alpine 和 nginx, alpine 負責每 10 秒寫入一筆資料到 index.html,nginx 則將 index.html 回應給請求。
-
在兩個設定檔中的 volume,我們使用 persistentVolumeClaim 來指定剛剛的 PVC 名稱。
apiVersion: v1
kind: Pod
metadata:
name: alpine-pod
spec:
containers:
- name: alpine
image: alpine:latest
command: ["sh", "-c"]
args: # 每 10 秒向 index.html 寫入資料
- while true; do
echo $(hostname) $(date) >> /html/index.html;
sleep 10;
done
volumeMounts:
- name: html
mountPath: /html
volumes:
- name: html
persistentVolumeClaim:
claimName: pvc-demo
readOnly: false
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
persistentVolumeClaim:
claimName: pvc-demo
readOnly: false
- 接著透過指令將兩個 Pod 運行起來。
kubectl.exe apply -f alpine-pod.yaml,nginx-pod.yaml
---
pod/alpine-pod created
pod/nginx-pod created
- 接著我們使用 port-forward 將 nginx 導向本機,我們才能呼叫到他。
kubectl.exe port-forward pod/nginx-pod 8080:80
---
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
- 透過指令呼叫 nignx,並且查看回應,就會發現不同的 Pod 卻能共用同一個 volume,不需要手動先創立 PV,直接指定 PVC 就完成了,超級方便的!
(Invoke-WebRequest -Uri http://localhost:8080 -UseBasicParsing).Content
---
alpine-pod Thu Jan 23 18:13:45 UTC 2025
alpine-pod Thu Jan 23 18:13:55 UTC 2025
alpine-pod Thu Jan 23 18:14:05 UTC 2025
alpine-pod Thu Jan 23 18:14:15 UTC 2025
alpine-pod Thu Jan 23 18:14:25 UTC 2025
刪除 PVC 後 PV 自動刪除
- 首先我們先刪除兩個 Pod。
kubectl.exe delete -f alpine-pod.yaml,nginx-pod.yaml
---
pod "alpine-pod" deleted
pod "nginx-pod" deleted
- 接著我們刪除定義的 PVC,我們會發現原本的 PV 也被刪除,因為預設 hostpath PVC 的 reclaimPolicy 是
DELETE。
kubectl.exe delete -f pvc-demo.yaml
---
persistentvolumeclaim "pvc-demo" deleted
kubectl.exe get pv
---
No resources found
結論
PV 和 PVC 是 Kubernetes 中處理持久化存儲的重要機制。透過 PV 和 PVC,用戶可以方便地管理和使用存儲資源,從而提升應用的靈活性與可擴展性。