iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0
Kubernetes

從零到 CKA:30 天掌握 Kubernetes 核心觀念與實作系列 第 9

Day 09|PV 與 PVC — Kubernetes 如何讓「無狀態 Pod」支援「有狀態資料」

  • 分享至 

  • xImage
  •  

前言

昨天我們用 Secret 將密碼、API Key、憑證等機密資訊與一般設定分開管理

不過,還有一個更根本的問題沒有處理:

Pod 重啟後,裡面的資料去哪了?

答案是:消失了。 Container 的檔案系統是暫時性的(ephemeral),Pod 一旦被刪除重建,所有寫入的資料都會跟著消失

Kubernetes 提供了 PersistentVolume(PV) 和 PersistentVolumeClaim(PVC) 來解決這個問題——讓儲存與 Pod 的生命週期脫鉤,資料不會因為 Pod 被刪除或重建而遺失

今天會學:

  1. Pod 裡的資料為什麼會消失? — 先親手驗證這個問題
  2. PV 與 PVC 的關係 — 理解 Kubernetes 的儲存架構
  3. 手動建立 PV 與 PVC — Static Provisioning 實作
  4. 掛載 PVC 到 Pod — 驗證資料持久化
  5. 回收策略與存取模式 — 理解 PV 的生命週期管理

以下操作皆在 master 節點 執行。


一、先看問題:Pod 裡的資料為什麼會消失?

在介紹 PV 與 PVC 之前,我們先親手驗證一次「資料消失」的問題:

Step 1:建立一個 Pod,寫入資料

vim pod-ephemeral.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-ephemeral
spec:
  containers:
  - name: app
    image: nginx
    command: ["/bin/sh", "-c"]
    args:
    - |
      echo "這筆資料很重要!寫入時間:$(date)" > /usr/share/nginx/html/data.txt
      nginx -g 'daemon off;'
kubectl apply -f pod-ephemeral.yaml

確認資料有寫入:

kubectl exec pod-ephemeral -- cat /usr/share/nginx/html/data.txt

會看到資料確實存在

https://ithelp.ithome.com.tw/upload/images/20260811/20181928TUqplT1A7j.png

Step 2:刪掉 Pod,重新建立

kubectl delete pod pod-ephemeral
kubectl apply -f pod-ephemeral.yaml

再看一次資料:

kubectl exec pod-ephemeral -- cat /usr/share/nginx/html/data.txt

資料還在嗎? 在,但是時間戳變了 — 因為這是一個全新的 Container,舊的檔案系統早就消失了,data.txt 是重新執行 echo 產生的新檔案。

https://ithelp.ithome.com.tw/upload/images/20260811/20181928esoPL93AqE.png

如果應用程式是在運行過程中持續寫入資料(例如資料庫),那 Pod 一重建,所有累積的資料都會歸零。

⚠️ Container 的檔案系統是 ephemeral 的

每個 Container 啟動時,都會在 Image 之上建立自己的可寫層(writable layer)。

這個可寫層的生命週期與 Container 綁定;當 Container 被刪除並重新建立時,原本寫在可寫層中的資料也會消失。


二、Kubernetes 的解法:把儲存抽離 Pod

既然 Pod 可能被刪除或重新建立,那解法就是:把儲存獨立出來,不跟 Pod 的生命週期綁定

Kubernetes 用三個核心概念來實現這件事:

概念 角色 類比
PersistentVolume(PV) 叢集中的儲存資源 停車場裡的車位
PersistentVolumeClaim(PVC) 對儲存資源的需求申請 你的停車需求單
StorageClass(SC) 定義儲存類型與動態供應方式 自動分配車位的管理規則

它們的關係是這樣的:

  • 管理員建立 PV(準備車位)→ 開發者建立 PVC(提出儲存需求)→ Kubernetes 自動配對(Binding)→ Pod 掛載 PVC 使用儲存
  • 今天我們先學 PV + PVC 的手動供應方式(Static Provisioning),StorageClass 的動態供應(Dynamic Provisioning)留到明天再介紹。

💡 為什麼要分成 PV 和 PVC?

這正體現了 Kubernetes 的核心設計哲學之一:關注點分離(Separation of Concerns)

  • 管理員負責準備儲存資源(PV),不需要知道實際會由哪個應用程式使用
  • 開發者只需要透過 PVC 描述需要多少容量、存取模式等需求,不需要了解底層儲存細節

這樣可以把「儲存資源管理」與「應用程式使用需求」分開處理,彼此降低耦合。


三、手動建立 PV — 管理員視角

PV 是**叢集層級(Cluster-scoped)**的資源,不屬於任何 Namespace,通常由叢集管理員負責建立與管理。

首先,在 Node 上建立一個目錄,作為這次實驗使用的儲存空間:

⚠️ hostPath 不適合一般生產環境

如果叢集有多個 Node,hostPath 會直接使用某一台 Node 上的本機目錄,因此資料會綁定在特定 Node。

這裡我們先用 master 節點示範;生產環境通常不建議直接使用 hostPath,後面會再說明原因。

建立 PV:

vim pv-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-demo
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /mnt/data
kubectl apply -f pv-demo.yaml

查看 PV 狀態:

kubectl get pv

你會看到 STATUSAvailable,表示這個 PV 目前尚未綁定任何 PVC,正在等待符合條件的 PVC 進行綁定

https://ithelp.ithome.com.tw/upload/images/20260811/201819283uOPGoyRgS.png

欄位說明:

欄位 說明
capacity.storage 1Gi 這個 PV 提供的儲存容量
accessModes ReadWriteOnce 可由單一 Node 以讀寫模式掛載
persistentVolumeReclaimPolicy Retain PVC 刪除後,PV 與底層資料會保留,不會自動刪除

四、建立 PVC — 開發者視角

PVC 是 Namespace 層級的資源,用來描述應用程式需要的儲存條件,例如容量與存取模式

建立 PVC 後,Kubernetes 會尋找符合條件的 PV,並將兩者進行綁定(Binding)

vim pvc-demo.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-demo
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
kubectl apply -f pvc-demo.yaml

查看 PVC 和 PV 的狀態:

kubectl get pvc
kubectl get pv

會看到:

  • PVC 的 STATUS 變成 Bound — 表示已成功綁定到符合條件的 PV
  • PV 的 STATUS 也會變成 BoundCLAIM 欄位會顯示目前綁定的 PVC

https://ithelp.ithome.com.tw/upload/images/20260811/20181928AfMUO41gYJ.png

💡 PVC 怎麼找到對應的 PV?

Kubernetes 會根據以下條件尋找符合的 PV:

  1. 容量:PV 的容量 ≥ PVC 要求的容量
  2. 存取模式:PV 必須支援 PVC 要求的 accessModes
  3. StorageClass:PV 與 PVC 的 storageClassName 必須相符

如果找不到符合條件的 PV,PVC 會停留在 Pending 狀態。


五、把 PVC 掛載到 Pod — 驗證資料持久化

現在來驗證最重要的一件事:Pod 被刪除並重新建立後,資料還在不在?

Step 1:建立一個 Pod,掛載 PVC 並寫入資料

vim pod-pvc.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-pvc-demo
spec:
  containers:
  - name: app
    image: nginx
    volumeMounts:
    - name: my-storage
      mountPath: /usr/share/nginx/html
  volumes:
  - name: my-storage
    persistentVolumeClaim:
      claimName: pvc-demo
kubectl apply -f pod-pvc.yaml

寫入一筆資料:

kubectl exec pod-pvc-demo -- sh -c 'echo "這筆資料不會消失!寫入時間:$(date)" > /usr/share/nginx/html/data.txt'

確認資料存在:

kubectl exec pod-pvc-demo -- cat /usr/share/nginx/html/data.txt

https://ithelp.ithome.com.tw/upload/images/20260811/20181928LutKpnx1E5.png

Step 2:刪掉 Pod,重新建立

kubectl delete pod pod-pvc-demo
kubectl apply -f pod-pvc.yaml

再看一次資料:

kubectl exec pod-pvc-demo -- cat /usr/share/nginx/html/data.txt

https://ithelp.ithome.com.tw/upload/images/20260811/20181928BHBWs3ko3K.png

資料還在! 因為資料是寫在 PV 對應的儲存空間中,而不是 Container 的可寫層,只要 PV 與底層儲存仍然存在,Pod 被刪除並重新建立後,資料就可以繼續保留。

也可以直接到 Node 上驗證。先確認 Pod 跑在哪個 Node:

kubectl get pod pod-pvc-demo -o wide

然後 SSH 到該 Node,查看 PV 底層目錄:

cat /mnt/data/data.txt

https://ithelp.ithome.com.tw/upload/images/20260811/20181928X22RjkbbmJ.png

一樣看得到內容,因為 PV 的底層就是這個目錄。

一樣可以看到內容,因為這個 PV 的底層儲存就是 Node 上的 /mnt/data 目錄。

⚠️ 注意:要到 Pod 所在的 Node 上查看

hostPath 會直接使用 Pod 所在 Node 的本機目錄。

如果 Pod 被調度到 worker 節點,但你卻在 master 節點執行:

cat /mnt/data/data.txt

就可能看到 No such file or directory

可以先用以下指令確認 Pod 所在的 Node:

kubectl get pod -o wide

💡 跟 ConfigMap / Secret 的 Volume 掛載有什麼不同?

  • ConfigMap / Secret:主要提供設定或機密資料,通常以唯讀方式給應用程式使用,不適合拿來當一般資料儲存空間
  • PVC:提供可持久化的儲存空間,應用程式可以依需求讀寫資料

三者都會使用 volumes + volumeMounts,但用途不同。


六、PV 的回收策略(Reclaim Policy)

當 PVC 被刪除後,PV 與底層儲存要怎麼處理,取決於 回收策略(Reclaim Policy)

策略 行為 適用場景
Retain PV 不會自動刪除,底層資料保留,需由管理員手動處理 需要避免資料被自動刪除的場景
Delete PV 對應的底層儲存會一併刪除 常見於 Dynamic Provisioning
Recycle 清除資料後讓 PV 重新變成 Available ⚠️ 已棄用,不建議使用

來實際看看 Retain 的行為:

# 先刪掉 Pod(要先把 PVC 從使用中釋放)
kubectl delete pod pod-pvc-demo

# 刪掉 PVC
kubectl delete pvc pvc-demo

# 查看 PV 狀態
kubectl get pv

會看到 PV 的狀態變成 Released,表示原本綁定的 PVC 已經被刪除,但 PV 與底層資料仍然保留

https://ithelp.ithome.com.tw/upload/images/20260811/2018192804PRSFHpSt.png

⚠️ Released 狀態的 PV 不能被新的 PVC 自動綁定

即使新的 PVC 條件完全符合,Kubernetes 也不會自動把 Released 狀態的 PV 配給新的 PVC。

這可以避免舊資料被新的工作負載意外存取。

如果要重新使用這個 PV,需要先確認資料已經妥善處理,再手動移除原本的 claimRef

kubectl patch pv pv-demo -p '{"spec":{"claimRef": null}}'

移除 claimRef 後,PV 會回到 Available 狀態,就可以再次被新的 PVC 綁定。


七、存取模式(Access Modes)

PV 的 Access Mode 用來描述儲存可以如何被掛載:

模式 縮寫 說明
ReadWriteOnce RWO 可由單一 Node 以讀寫模式掛載
ReadOnlyMany ROX 可由多個 Node 以唯讀模式掛載
ReadWriteMany RWX 可由多個 Node 以讀寫模式掛載
ReadWriteOncePod RWOP 只能由單一 Pod 以讀寫模式掛載

💡 Access Modes 限制的是 Node,不一定是 Pod

ReadWriteOnce(RWO) 的意思是「只能由一個 Node 以讀寫模式掛載」,但同一個 Node 上的多個 Pod 仍可能同時使用這個 Volume。

如果要限制只能由單一 Pod 使用,則要看 ReadWriteOncePod(RWOP)

不同的儲存後端,支援的 Access Mode 也不同:

儲存類型 RWO ROX RWX
hostPath
AWS EBS
AWS EFS
NFS
GCP Persistent Disk

💡 實際支援的 Access Mode,仍需以使用的 Storage Driver 與底層儲存系統為準。

選擇 Access Mode 時,要根據應用程式的存取需求與底層儲存能力來決定。


八、為什麼生產環境不建議使用 hostPath

前面的範例使用 hostPath,因為設定簡單、不需要額外的儲存系統。但在生產環境中,hostPath 有明顯限制:

問題 說明
綁定 Node 資料存在特定 Node 的本機磁碟上,Pod 被調度到其他 Node 時可能無法取得原本的資料
無法跨 Node 共享 不適合需要多個 Node 同時存取相同資料的場景
缺乏高可用性 如果 Node 或本機磁碟故障,資料可能無法存取,甚至遺失
安全風險 如果掛載到敏感的 Host 路徑,Pod 可能存取或修改 Node 上的重要檔案

因此,生產環境通常會使用 NFS、雲端磁碟或其他 CSI Storage Driver 提供的持久化儲存

生產環境應該用什麼?

  • 雲端環境:AWS EBS、AWS EFS、GCP Persistent Disk、Azure Disk 等雲端儲存服務
  • 自建叢集:NFS、Ceph、Longhorn 等共享或分散式儲存方案
  • 搭配 StorageClass:讓 Kubernetes 依需求動態建立 PV(Dynamic Provisioning)

💡 hostPath 的適合用途

hostPath 比較適合用在:

  • 本地開發與學習環境
  • 需要存取 Node 上特定檔案或目錄的系統元件
  • 單 Node 的測試叢集,例如 Minikube

一般應用程式的持久化資料,則不建議直接使用 hostPath


小結

今天我們學會了使用 PV 和 PVC,讓資料不會因為 Pod 被重建而消失:

概念 重點 一句話說明
Ephemeral Storage 暫時性儲存 Container 被刪除後,可寫層中的資料也會消失
PersistentVolume(PV) 叢集層級儲存 提供獨立於 Pod 生命週期之外的儲存資源
PersistentVolumeClaim(PVC) 儲存需求申請 描述容量與存取模式等需求,並與符合條件的 PV 綁定
Reclaim Policy 回收策略 決定 PVC 刪除後,PV 與底層資料如何處理
Access Modes 存取模式 RWO / ROX / RWX / RWOP,實際支援取決於底層儲存

到目前為止,我們的 PV 都是手動建立的(Static Provisioning)。但想像一下 — 如果你有 100 個應用程式都需要儲存,難道要手動建 100 個 PV 嗎?

明天我們來學 StorageClass — Kubernetes 的動態儲存供應機制,讓 PV 的建立全自動化!


參考資源


上一篇
Day 08|Secret — 別再把密碼寫進 YAML!Secret 的正確使用方式
下一篇
Day 10|StorageClass — Kubernetes 如何自動建立儲存?
系列文
從零到 CKA:30 天掌握 Kubernetes 核心觀念與實作10
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言