iT邦幫忙

2026 iThome 鐵人賽

DAY 16
0
Kubernetes

從零開始的雲端實戰:30 天 Kubernetes 核心觀念與部署指南系列 第 16

【Day 16】資料持久化:PersistentVolume (PV) 與 PersistentVolumeClaim (PVC)

  • 分享至 

  • xImage
  •  

今日目標

  • 理解容器的無狀態(Stateless)天性與資料持久化(Persistent Storage)的必要性。
  • 搞懂 Kubernetes 儲存三劍客:PV(實體磁區)PVC(資源申請單)StorageClass(自動化配置) 的職責分工。
  • 掌握 PV 的存取模式(Access Modes)與回收策略(Reclaim Policies)。
  • 實戰操作:建立 PVC 綁定儲存空間,並驗證「Pod 銷毀重啟後資料依然健在」。

痛點場景:容器內的資料為什麼會消失?

預設情況下,Docker 容器與 Pod 內部的檔案系統都是短暫且易逝的(Ephemeral)

  • 當容器發生錯誤 Crash 重啟,或 Deployment 進行滾動升級時,容器會被砍掉重建,容器內部產生的所有新檔案或資料庫資料都會隨之蒸發

對於 Web 前端或無狀態 API 來說這不是問題;但如果我們要運行的是 MySQL、PostgreSQL、Redis 或使用者上傳的圖片檔案,我們就必須將資料存放在獨立於 Pod 生命週期之外的外部儲存空間


儲存解耦設計:PV、PVC 與 StorageClass

Kubernetes 為了讓「底層基礎設施維運人員(Admin)」與「應用程式開發者(Developer)」各司其職,設計了一套非常優雅的解耦抽象層:

元件 角色定位 生活比喻 誰負責管理
PV (PersistentVolume) 實際的實體儲存空間(如 AWS EBS、NFS、本機硬碟) 實際蓋好的空房子 集群管理員 / 雲端平台
PVC (PersistentVolumeClaim) 開發者提出的一張「儲存需求申請單」(例如:我要 5Gi、讀寫模式) 租屋者的租屋需求單 應用程式開發者
StorageClass (SC) 自動化房屋仲介:當沒有合適的現成房子(PV)時,自動依需求去雲端「蓋一棟新的房子(Dynamic Provisioning)」 房屋仲介與建商 集群管理員

運作邏輯:開發者只需撰寫一份 PVC,Kubernetes 就會自動尋找符合規格的 PV 進行綁定(Bound),並掛載進 Pod 容器中使用。


關鍵概念:Access Modes 與 Reclaim Policy

1. 存取模式(Access Modes)

  • ReadWriteOnce (RWO):只能被單一節點(Node)以讀寫模式掛載(最常見,如 AWS EBS 虛擬硬碟)。
  • ReadOnlyMany (ROX):可被多個節點以唯讀模式同時掛載。
  • ReadWriteMany (RWX):可被多個節點同時以讀寫模式掛載(通常需要 NFS 或分散式檔案系統如 Ceph)。

2. 回收策略(Reclaim Policy)

當 PVC 被刪除後,背後關聯的實體 PV 資料該如何處理?

  • Retain(保留):PV 不會被刪除,資料完整保留,需管理員手動介入清理(最安全)。
  • Delete(刪除):自動將背後的實體雲端硬碟一起刪除釋放。

實戰演練:PVC 建立與資料持久化驗證

在 Minikube 環境中,系統已經內建了一個預設的 standard StorageClass(以 HostPath 為底層)。當我們建立 PVC 時,K8s 會自動幫我們動態建立出對應的 PV!

步驟 1:建立儲存申請單(PVC)

建立 my-pvc.yaml,申請 1Gi 的空間:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: demo-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

套用配置並檢查狀態:

kubectl apply -f my-pvc.yaml
kubectl get pvc

預期輸出 STATUSBound,代表已經成功綁定到一個自動生成的 PV!


步驟 2:建立掛載 PVC 的 Pod 並寫入資料

建立 writer-pod.yaml,將 PVC 掛載到容器內的 /data 目錄:

apiVersion: v1
kind: Pod
metadata:
  name: writer-pod
spec:
  containers:
    - name: app
      image: busybox
      command: ["sh", "-c", "sleep 3600"]
      volumeMounts:
        - name: storage-volume
          mountPath: /data
  volumes:
    - name: storage-volume
      persistentVolumeClaim:
        claimName: demo-pvc

套用配置並在 /data 目錄寫入一行測試文字:

kubectl apply -f writer-pod.yaml

# 進入容器寫入資料到持久化磁碟中
kubectl exec writer-pod -- sh -c "echo 'K8s Data Persistence Success!' > /data/message.txt"

# 驗證資料是否寫入成功
kubectl exec writer-pod -- cat /data/message.txt

步驟 3:極限測試:手動銷毀 Pod 並建立新 Pod 讀取

現在我們狠心地把 writer-pod 徹底刪除:

kubectl delete pod writer-pod

接著建立一個全新的 reader-pod.yaml,同樣掛載這份 demo-pvc

apiVersion: v1
kind: Pod
metadata:
  name: reader-pod
spec:
  containers:
    - name: app
      image: busybox
      command: ["sh", "-c", "sleep 3600"]
      volumeMounts:
        - name: storage-volume
          mountPath: /data
  volumes:
    - name: storage-volume
      persistentVolumeClaim:
        claimName: demo-pvc

套用並檢查新 Pod 是否能讀到上一代留下來的遺產:

kubectl apply -f reader-pod.yaml

# 查看新 Pod 裡面的檔案內容
kubectl exec reader-pod -- cat /data/message.txt

預期輸出:

K8s Data Persistence Success!

即便舊的 Pod 早已被摧毀,資料依然完好如初地被新 Pod 繼承!


本日小結

今天我們成功解鎖了資料持久化技能:

  • 搞懂了 PV(實體提供)PVC(邏輯需求)StorageClass(動態供給) 的三層儲存架構。
  • 親自驗證了 Pod 銷毀重啟後,資料依然安全留存的過程。

有了 PVC 做後盾,我們終於有能力在 Kubernetes 上運行資料庫了!但如果用傳統的 Deployment 跑 MySQL / Redis,在多副本擴展時會遇到「網路識別碼混亂」與「磁區共用衝突」的問題。

明天 Day 17,我們將探討專門管理有狀態資料庫的守護神:「有狀態應用:StatefulSet 如何管理 MySQL / Redis 等資料庫?」


上一篇
【Day 15】機密資料管理:Secret 的加密機制與安全掛載
下一篇
【Day 17】有狀態應用:StatefulSet 如何管理 MySQL / Redis 等資料庫?
系列文
從零開始的雲端實戰:30 天 Kubernetes 核心觀念與部署指南30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言