Kubernetes Volume 使用指南
什麼是 Volume?
Kubernetes Volume 是一個 API 物件,用於為 Pod 中的容器提供持久化或共享的儲存空間。Volume 解決了容器檔案系統的臨時性問題,讓資料能夠在容器重啟後保留,或在多個容器之間進行共享。
Volume 的主要功能:
- 資料持久化:確保重要資料在容器重啟或 Pod 重新調度後不會遺失
- 容器間共享:讓同一 Pod 內的多個容器能夠共享資料
- 外部儲存整合:連接到各種外部儲存系統,如雲端儲存、網路檔案系統等
- 臨時儲存管理:提供高效能的臨時工作空間
為什麼使用 Volume?
相較於依賴容器內建的檔案系統,Volume 提供了更可靠的資料管理方式:
- 資料安全性:避免因容器故障導致的資料遺失
- 靈活性:支援多種儲存後端,適應不同的應用需求
- 效能最佳化:可選擇適合的儲存介質來提升應用效能
- 統一管理:集中管理所有持久化資料的儲存策略
Volume 類型介紹
Kubernetes 提供了多種不同的 Volume 類型,包括 emptyDir、hostPath、PersistentVolume、ConfigMap、Secret、NFS 等數十種選項。每種類型都有其特定的用途和適用場景。由於 Volume 類型眾多,本指南將重點介紹作者認為在日常開發和運維工作中最重要且最常用的幾種類型,幫助讀者快速掌握核心概念和實用技能。
emptyDir
emptyDir 類型的 Volume 會在 Pod 被分配到節點時建立,當 Pod 從節點刪除時,emptyDir 中的資料也會一併刪除。它的生命週期與 Pod 綁定,適合用來存放暫存檔、快取資料,或像應用程式日誌這類不需要跨 Pod 長期保留的檔案。
使用場景:
- 多容器 Pod 中容器間共享資料
- 快取儲存,提升應用程式效能
- 臨時工作目錄或暫存檔案
- 應用程式產生的暫時性日誌檔案
特性:
- 資料儲存在節點的本地磁碟或記憶體中
- 容器重啟時資料通常會保留,但 Pod 刪除後資料會消失
- 可以設定儲存介質為磁碟或記憶體(Memory)
- 支援容量限制設定
注意事項:
- 資料不具持久性,Pod 刪除後資料會消失
- 如果使用記憶體作為儲存介質,需注意記憶體限制
- 適合臨時資料儲存,不適合重要資料持久化
emptyDir 實作範例
以下範例展示如何在 Spring Boot Deployment 中使用 emptyDir,將 Pod 暫存磁碟掛載到應用程式日誌目錄,供 logback 寫入檔案日誌:
1 | # 部署 Spring Boot 應用程式,並設定容器映像、環境變數與健康檢查。 |
配置說明
volumeMounts: 定義容器內的掛載點
name: 對應volumes中定義的 Volume 名稱mountPath: 容器內的掛載路徑,範例中為/var/log/app/logs
volumes: 定義 Pod 可使用的儲存卷
name: Volume 名稱,必須與volumeMounts.name相同emptyDir: 使用 Pod 暫存儲存空間,Pod 刪除後內容會一併移除
部署與驗證
部署應用
本次驗證使用的部署檔會一併建立 namespace、registry Secret、Deployment 與 Service:
1 | kubectl apply -f apply_secret.yml |
驗證 Volume 掛載
可以開一個終端機持續觀察 dockertest namespace 中的資源狀態,確認 Deployment、ReplicaSet、Pod 與 Service 都已建立:
1 | watch -n 2 kubectl get all -n dockertest |
接著查看應用程式啟動日誌,確認 logback 使用的檔案日誌路徑為 /var/log/app/logs/dockertest.log:
1 | kubectl logs -f -n dockertest <pod-name> |
應用程式啟動後,進入 Pod 檢查 emptyDir 掛載的日誌目錄,並直接讀取檔案日誌:
1 | kubectl exec -it -n dockertest <pod-name> -- sh |
驗證 emptyDir 生命週期
emptyDir 的生命週期與 Pod 綁定,而不是與容器行程綁定。因此可以先終止容器中的 Java 行程,讓 Kubernetes 重新啟動容器,再觀察同一個 Pod 的 RESTARTS 數量增加。此時 Pod 沒有被刪除,所以 emptyDir 中的 dockertest.log 仍會保留。
1 | kubectl exec -it -n dockertest <pod-name> -- sh -c "kill -TERM 7" |
如果刪除整個 Pod,Deployment 會重新建立新的 Pod,而新的 Pod 會取得新的 emptyDir,原本 emptyDir 內的檔案就不會保留。這點與上面的「容器重啟」不同。
hostPath
hostPath 類型的 Volume 會將 Kubernetes 節點檔案系統上的檔案或目錄掛載到 Pod 中。這種類型適合需要讀寫節點本機路徑的情境,例如在單節點開發環境中保留應用程式日誌。需要注意的是,hostPath 與特定節點綁定,Pod 重新調度到其他節點時,資料不會跟著移動。
使用場景:
- 需要訪問節點上的檔案或目錄
- 單節點開發或測試環境
- 應用程式日誌需要保留在節點目錄中
- 日誌收集系統需要讀取主機日誌
注意事項:
- 資料與特定節點綁定,Pod 遷移時資料不會跟隨
- 存在安全風險,應謹慎限制可掛載的路徑
- 不建議作為多節點生產環境的一般持久化方案
hostPath 實作範例
以下範例展示如何在 Spring Boot Deployment 中使用 hostPath,將節點上的固定目錄掛載到應用程式日誌目錄,讓 Pod 重建後仍可在同一個節點保留日誌檔案:
1 | # 部署 Spring Boot 應用程式,並設定容器映像、環境變數與健康檢查。 |
配置說明
volumeMounts: 定義容器內的掛載點
name: 對應volumes中定義的 Volume 名稱mountPath: 容器內的掛載路徑,範例中為/var/log/app/logs
env.LOG_PATH: 明確指定應用程式寫入檔案日誌的位置,需與
volumeMounts.mountPath保持一致volumes: 定義 Pod 可使用的儲存卷
name: Volume 名稱,必須與volumeMounts.name相同hostPath.path: 節點上的實體目錄,範例中為/var/log/k8s-logshostPath.type: 路徑類型,DirectoryOrCreate表示如果目錄不存在,Kubernetes 會自動建立
部署與驗證
部署應用
本次 hostPath 驗證使用另一份部署檔,差異在於 volumes 改成掛載節點上的固定目錄:
1 | kubectl apply -f apply_secret_hostpath.yml |
驗證 Volume 掛載
可以開一個終端機持續觀察 dockertest namespace 中的資源狀態:
1 | watch -n 2 kubectl get all -n dockertest |
另開一個終端機查看 Pod 的應用程式啟動日誌,確認 logback 寫入的檔案路徑為 /var/log/app/logs/dockertest.log:
1 | kubectl logs -f -n dockertest <pod-name> |
驗證資料持久性
接著回到 Kubernetes 節點上,進入 hostPath 對應的主機目錄。本次實際驗證環境使用的是家目錄下的 k8s-logs,如果你的 YAML 設定為 /var/log/k8s-logs,就改到該路徑檢查。
1 | cd ~/k8s-logs |
當應用程式收到請求或重新啟動時,可以同時在 kubectl logs -f 與節點上的 tail -f dockertest.log 看到日誌持續寫入。這代表容器內的 /var/log/app/logs/dockertest.log 實際上已經寫到節點的 hostPath 目錄。
若刪除 Pod 後 Deployment 在同一個節點重新建立 Pod,hostPath 目錄中的 dockertest.log 仍會保留,新的 Pod 會繼續寫入同一個節點目錄:
1 | kubectl delete pod -n dockertest <pod-name> |
最佳實務建議
- 開發環境使用: hostPath 主要適用於開發和測試環境,或需要讀取節點特定檔案的系統元件
- 路徑管理: 確保節點路徑具有適當的權限設定,避免掛載過大的系統範圍
- 資料備份: 如果日誌或資料具有保留需求,仍需搭配備份或集中式日誌收集
- 生產環境替代: 在生產環境中,建議使用 PersistentVolume、StorageClass 或雲端儲存解決方案
清理資源
如果是透過前面的部署檔建立資源,建議直接使用同一份 YAML 清理,避免只刪除 Deployment 卻留下 Service、Secret 或 namespace 等資源:
1 | kubectl delete -f apply_secret.yml |
如果目前套用的是 hostPath 版本,則改刪除 hostPath 對應的部署檔:
1 | kubectl delete -f apply_secret_hostpath.yml |
也可以手動刪除 dockertest namespace,連同 namespace 內的 Deployment、Pod、Service 與 Secret 一併清除:
1 | kubectl delete namespace dockertest |
需要注意的是,hostPath 寫入節點上的檔案不會因為刪除 Kubernetes 資源而自動移除。如果要清掉測試時產生的日誌,需要到節點上的 hostPath 目錄手動刪除,例如:
1 | rm -f ~/k8s-logs/dockertest.log |
Volume 類型總覽
以下表格整理了 Kubernetes 中常見的 Volume 類型及其主要用途:
| Volume 類型 | 持久性 | 用途說明 | 適用場景 |
|---|---|---|---|
| emptyDir | 臨時 | Pod 內容器間共享資料,Pod 刪除後資料消失 | 臨時檔案、快取、容器間通訊 |
| hostPath | 節點綁定 | 掛載主機檔案系統到容器中 | 開發測試、系統監控、日誌收集 |
| PersistentVolume (PV) | 持久 | 獨立於 Pod 生命週期的持久化儲存 | 資料庫、檔案儲存、狀態應用 |
| ConfigMap | 組態 | 以檔案形式提供組態資料 | 應用程式組態、環境變數 |
| Secret | 機密 | 以檔案形式提供敏感資料 | 密碼、憑證、API 金鑰 |
| NFS | 網路共享 | 透過 NFS 協定共享網路儲存 | 多 Pod 共享資料、檔案伺服器 |
| AWS EBS | 雲端持久 | 使用 AWS Elastic Block Store | AWS 環境的持久化儲存 |
| Azure Disk | 雲端持久 | 使用 Azure 磁碟儲存 | Azure 環境的持久化儲存 |
| GCE PD | 雲端持久 | 使用 Google Cloud 持久磁碟 | GCP 環境的持久化儲存 |
| CSI | 彈性 | Container Storage Interface 標準介面 | 第三方儲存解決方案整合 |
選擇建議
開發階段:
- 使用
emptyDir進行容器間資料共享 - 使用
hostPath進行本地開發和測試 - 使用
ConfigMap和Secret管理組態和敏感資料
生產環境:
- 使用
PersistentVolume確保資料持久性 - 根據雲端平台選擇對應的儲存類型(AWS EBS、Azure Disk、GCE PD)
- 使用
CSI整合企業級儲存解決方案
注意事項:
- 避免在生產環境使用
hostPath,除非有特殊需求 emptyDir適合臨時資料,不應用於重要資料儲存- 選擇 Volume 類型時需考慮效能、成本和可用性需求