跳至主要内容

Volume - PV & PVC

什麼是 Storage Class?​

在 Kubernetes 中,Storage Class(存儲類別)是一種資源物件,定義了如何動態配置持久性存儲(Persistent Volume, PV)。 它為不同的存儲需求提供抽象,允許用戶定義存儲的配置細節,例如性能、備份策略或存儲類型(如 SSD 或 HDD)。

Storage Class 的優勢​

  1. 動態配置 PV:透過 Storage Class,可以根據 Persistent Volume Claim(PVC)的需求,自動創建 PV。
  2. 靈活性:支持不同的存儲後端(如雲提供商的磁碟、分佈式存儲)。
  3. 簡化操作:用戶不需手動創建 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 的數據,但需要手動驗證和配置。

流程

  1. 用戶刪除 PVC。
  2. PV 狀態變為 Released。
  3. Kubernetes 不會自動刪除 PV 或其數據。
  4. 管理員可以手動刪除 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 刪除。
  • 簡化操作:適合不需要保留數據的場景,避免手動清理存儲。
  • 適合場景:
    • 開發測試環境,數據不需要長期保留。
    • 臨時存儲,例如緩存數據或臨時文件。

流程

  1. 用戶刪除 PVC。
  2. Kubernetes 自動刪除 PV 和其底層存儲(如雲端磁碟、NFS 文件等)。
  3. 整個資源被回收,無需額外操作。

注意事項

  • 如果底層存儲是雲服務(如 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 的使用流程​

  1. 創建 Storage Class:管理員定義不同的 Storage Class 來支持多種存儲需求。
  2. 創建 PVC:用戶在 PVC 中指定所需的 Storage Class 名稱。
  3. 動態配置 PV:Kubernetes 根據 Storage Class 的配置自動創建 PV,並與 PVC 進行綁定。

什麼是 PV(Persistent Volume)?​

PV 是 Kubernetes 中的一種資源,表示集群中的存儲,可以獨立於 Pod 的生命週期進行管理。PV 提供了存儲的抽象層,允許用戶以統一的方式訪問底層存儲資源(如 NFS、iSCSI、雲存儲等)。

PV 的特性​

  1. 獨立於 Pod:PV 是集群範圍的資源,可以被多個 Pod 使用(視具體配置而定)。
  2. 多種存儲後端支持:支持各種存儲類型(如本地存儲、分佈式存儲和雲存儲)。
  3. 存儲大小可定義:可根據需求定義不同大小的存儲空間。

PV 的生命周期狀態​

  1. Available(可用)
    • PV 已創建但未與 PVC 綁定,處於空閒狀態。
    • 可被 PVC 請求並綁定。
  2. Bound(已綁定)
    • PV 已與某個 PVC 綁定,正在被 Pod 使用。
    • 一個 PV 只能與一個 PVC 綁定。
  3. Released(已釋放)
    • PVC 被刪除後,PV 狀態變為釋放,但數據仍保留。
    • 視回收策略,PV 可重新使用(Retain)或刪除(Delete)。
  4. Failed(失敗)
    • PV 回收或刪除過程失敗。
    • 需管理員檢查並修復。

狀態遷移​

  1. Available → Bound:當 PV 被某個 PVC 綁定後,狀態從 Available 轉為 Bound。
  2. Bound → Released:當 PVC 被刪除後,PV 狀態轉為 Released。
  3. Released → Available:如果 PV 被回收並清空,狀態可重置為 Available。
  4. Released → Failed:如果 PV 的回收策略執行失敗,狀態變為 Failed。

什麼是 PVC(Persistent Volume Claim)?​

PVC 是用戶對存儲需求的聲明,是一種對 PV 的請求。用戶不需要關注底層存儲的實現,只需通過 PVC 定義所需的存儲大小與訪問模式即可。

PVC 的特性​

  1. 簡化用戶操作:用戶只需定義需求,Kubernetes 負責匹配合適的 PV。
  2. 動態或靜態綁定:可以與事先創建的 PV 綁定,也可以根據 PVC 請求動態創建 PV。
  3. 多種訪問模式:支持單一 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 的使用流程​

  1. 用戶聲明:用戶定義 PVC,描述所需的存儲大小和訪問模式。
  2. 綁定 PV:Kubernetes 自動尋找與 PVC 匹配的 PV。
  3. Pod 使用:Pod 通過掛載 PVC 間接訪問 PV 提供的存儲資源。

三者之間的關係​

  • StorageClass:定義存儲的類型和配置細節。
  • PersistentVolume(PV):提供實際的存儲資源,是存儲的具體實現。
  • PersistentVolumeClaim(PVC):用戶的存儲請求,通過 PVC 使用 PV。

流程順序​

pv-relation

  1. 管理者設定 PV:管理者首先會設定 PersistentVolume (PV),並定義存儲大小、存取模式(如只讀或讀寫)及其他屬性,或配置 StorageClass 來支援動態創建 PV。
  2. 用戶提交 PVC:用戶通過 PersistentVolumeClaim (PVC) 提交存儲請求,指定所需的存儲大小、存取模式以及所需的 StorageClass(如果需要)。
  3. PVC 與 PV 綁定:Kubernetes 會尋找一個符合條件的 PV 與 PVC 綁定。如果沒有現有的 PV,且指定了 StorageClass,Kubernetes 會使用該 StorageClass 動態創建一個新的 PV。
  4. PVC 掛載到 Pod:綁定成功後,PVC 就可以被 Pod 使用,並掛載到 Pod 上的指定路徑。

實作 PV & PVC​

預設的 StorageClass​

  1. 首先我們可以查看 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​

  1. 接著我們可以建立 PVC 的設定檔,因為我們在單一節點,並且後續有多個 Pod 需要寫入和讀取,因此 accessModes 我們使用ReadWriteOnce。

  2. 在 storageClassName 我們指定上面的預設hostpath,如果不想使用預設要在 storageClassName 留上""。

  3. 另外增加資源限制,最大儲存空間是 1 GibiByte。

pvc-demo.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-demo
spec:
accessModes:
- ReadWriteOnce
storageClassName: hostpath
resources:
requests:
storage: 1Gi
  1. 使用指令執行他,並且我們可以查看 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​

  1. 首先我們像之前 實作 EmptyDir 一樣,需要建立 alpine 和 nginx, alpine 負責每 10 秒寫入一筆資料到 index.html,nginx 則將 index.html 回應給請求。

  2. 在兩個設定檔中的 volume,我們使用 persistentVolumeClaim 來指定剛剛的 PVC 名稱。

alpine-pod.yaml
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
nginx-pod.yaml
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
  1. 接著透過指令將兩個 Pod 運行起來。
kubectl.exe apply -f alpine-pod.yaml,nginx-pod.yaml
---

pod/alpine-pod created
pod/nginx-pod created
  1. 接著我們使用 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
  1. 透過指令呼叫 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 自動刪除​

  1. 首先我們先刪除兩個 Pod。
kubectl.exe delete -f alpine-pod.yaml,nginx-pod.yaml
---

pod "alpine-pod" deleted
pod "nginx-pod" deleted
  1. 接著我們刪除定義的 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,用戶可以方便地管理和使用存儲資源,從而提升應用的靈活性與可擴展性。