昨天我們用 Secret 將密碼、API Key、憑證等機密資訊與一般設定分開管理
不過,還有一個更根本的問題沒有處理:
Pod 重啟後,裡面的資料去哪了?
答案是:消失了。 Container 的檔案系統是暫時性的(ephemeral),Pod 一旦被刪除重建,所有寫入的資料都會跟著消失
Kubernetes 提供了 PersistentVolume(PV) 和 PersistentVolumeClaim(PVC) 來解決這個問題——讓儲存與 Pod 的生命週期脫鉤,資料不會因為 Pod 被刪除或重建而遺失
今天會學:
以下操作皆在 master 節點 執行。
在介紹 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
會看到資料確實存在

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 產生的新檔案。

如果應用程式是在運行過程中持續寫入資料(例如資料庫),那 Pod 一重建,所有累積的資料都會歸零。
⚠️ Container 的檔案系統是 ephemeral 的
每個 Container 啟動時,都會在 Image 之上建立自己的可寫層(writable layer)。
這個可寫層的生命週期與 Container 綁定;當 Container 被刪除並重新建立時,原本寫在可寫層中的資料也會消失。
既然 Pod 可能被刪除或重新建立,那解法就是:把儲存獨立出來,不跟 Pod 的生命週期綁定
Kubernetes 用三個核心概念來實現這件事:
| 概念 | 角色 | 類比 |
|---|---|---|
| PersistentVolume(PV) | 叢集中的儲存資源 | 停車場裡的車位 |
| PersistentVolumeClaim(PVC) | 對儲存資源的需求申請 | 你的停車需求單 |
| StorageClass(SC) | 定義儲存類型與動態供應方式 | 自動分配車位的管理規則 |
它們的關係是這樣的:
💡 為什麼要分成 PV 和 PVC?
這正體現了 Kubernetes 的核心設計哲學之一:關注點分離(Separation of Concerns):
- 管理員負責準備儲存資源(PV),不需要知道實際會由哪個應用程式使用
- 開發者只需要透過 PVC 描述需要多少容量、存取模式等需求,不需要了解底層儲存細節
這樣可以把「儲存資源管理」與「應用程式使用需求」分開處理,彼此降低耦合。
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
你會看到 STATUS 是 Available,表示這個 PV 目前尚未綁定任何 PVC,正在等待符合條件的 PVC 進行綁定

欄位說明:
| 欄位 | 值 | 說明 |
|---|---|---|
| capacity.storage | 1Gi | 這個 PV 提供的儲存容量 |
| accessModes | ReadWriteOnce | 可由單一 Node 以讀寫模式掛載 |
| persistentVolumeReclaimPolicy | Retain | PVC 刪除後,PV 與底層資料會保留,不會自動刪除 |
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
會看到:
STATUS 變成 Bound — 表示已成功綁定到符合條件的 PVSTATUS 也會變成 Bound — CLAIM 欄位會顯示目前綁定的 PVC
💡 PVC 怎麼找到對應的 PV?
Kubernetes 會根據以下條件尋找符合的 PV:
- 容量:PV 的容量 ≥ PVC 要求的容量
- 存取模式:PV 必須支援 PVC 要求的
accessModes- StorageClass:PV 與 PVC 的
storageClassName必須相符如果找不到符合條件的 PV,PVC 會停留在
Pending狀態。
現在來驗證最重要的一件事: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

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

資料還在! 因為資料是寫在 PV 對應的儲存空間中,而不是 Container 的可寫層,只要 PV 與底層儲存仍然存在,Pod 被刪除並重新建立後,資料就可以繼續保留。
也可以直接到 Node 上驗證。先確認 Pod 跑在哪個 Node:
kubectl get pod pod-pvc-demo -o wide
然後 SSH 到該 Node,查看 PV 底層目錄:
cat /mnt/data/data.txt

一樣看得到內容,因為 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,但用途不同。
當 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 與底層資料仍然保留

⚠️
Released狀態的 PV 不能被新的 PVC 自動綁定即使新的 PVC 條件完全符合,Kubernetes 也不會自動把
Released狀態的 PV 配給新的 PVC。這可以避免舊資料被新的工作負載意外存取。
如果要重新使用這個 PV,需要先確認資料已經妥善處理,再手動移除原本的
claimRef:kubectl patch pv pv-demo -p '{"spec":{"claimRef": null}}'移除
claimRef後,PV 會回到Available狀態,就可以再次被新的 PVC 綁定。
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 提供的持久化儲存
生產環境應該用什麼?
💡
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 的建立全自動化!