iT邦幫忙

2025 iThome 鐵人賽

DAY 15
1

牧場主今日工作

今天要為我們的數位牧場建立現代化的「智能倉庫系統」!還記得 Day 6 我們在 bastion 上建立了基本的 NFS 服務嗎?那就像是搭建了倉庫的骨架,今天我們要為它裝上自動化設備!透過 NFS CSI Provisioner,我們的 Kubernetes 叢集就能像有了智能機器人一樣,自動分配儲存空間給需要的應用程式。不用再手動建立 PV,一切都交給 CSI 來處理!

理解動態儲存管理

傳統儲存 vs 動態儲存

在沒有動態儲存之前,管理 Kubernetes 儲存就像經營傳統倉庫:

# 傳統方式:手動管理
1. 管理員手動建立 PersistentVolume (PV)
2. 開發者申請 PersistentVolumeClaim (PVC) 
3. Kubernetes 嘗試配對 PV 和 PVC
4. 如果沒有適合的 PV,PVC 就會一直等待

有了動態儲存,就像有了智能倉庫:

# 動態方式:自動化管理  
1. 開發者直接申請 PVC
2. StorageClass 定義儲存類型和參數
3. CSI Provisioner 自動建立對應的 PV
4. 自動完成 PV 和 PVC 的綁定

NFS CSI 的優勢

相較於傳統的 NFS Volume,NFS CSI Provisioner 提供:

  • 動態配置:按需自動建立儲存卷
  • 生命週期管理:自動刪除不再使用的 PV
  • 配額控制:可以設定儲存大小限制
  • 統一介面:透過標準 CSI 介面管理

https://ithelp.ithome.com.tw/upload/images/20250828/201417949VXjzLQ6Py.png

NFS CSI Provisioner 部署

添加 Helm Repository

首先新增 NFS Subdir External Provisioner 的 Helm repository:

# 新增 Helm repository
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/

# 更新 repository
helm repo update

# 檢查可用版本
helm search repo nfs-subdir-external-provisioner

準備部署參數

為什麼需要 values.yaml?

雖然可以直接使用預設值部署,但建立 values.yaml 有以下重要意義:

  • 環境適配:每個環境的 NFS 伺服器位址都不同
  • 版本控制:配置檔可以納入 Git 管理,追蹤變更歷史
  • 重複部署:日後重新部署或升級時有明確的參數紀錄
  • 團隊協作:其他人可以清楚了解部署的具體設定

建立最小必要的 values 檔案:

# 建立設定檔
cat <<EOF > nfs-provisioner-values.yaml
# NFS 伺服器設定
nfs:
  server: 192.168.0.135        # NFS 伺服器 IP
  path: /nfs/nfs-client        # NFS 匯出路徑

# StorageClass 設定
storageClass:
  name: nfs-client             # StorageClass 名稱
  defaultClass: true           # 設為預設 StorageClass
  archiveOnDelete: false       # 刪除 PVC 時直接刪除資料,不保留到 archived 目錄
EOF

重要提醒:請將這個檔案納入版本控制系統!

準備 Kubernetes 節點

在部署 Provisioner 之前,需要確保所有 Kubernetes 節點都安裝了 NFS 客戶端:

# 在所有 Kubernetes 節點上安裝 NFS 工具
# 包括 master 和 worker 節點

# 以 rancher-master-1 為例
ssh rancher-master-1
sudo apt update
sudo apt install -y nfs-common
exit

# 重複在所有節點執行
ssh rancher-worker-1
sudo apt update  
sudo apt install -y nfs-common
exit

# 如果有更多節點,請逐一安裝

為什麼需要這個步驟?

  • NFS CSI Provisioner 需要在節點上掛載 NFS 卷
  • 沒有 nfs-common 套件會導致 mount 失敗
  • 錯誤訊息:bad option; for several filesystems (e.g. nfs, cifs) you might need a /sbin/mount.<type> helper program

部署 NFS CSI Provisioner

透過 Helm 部署 Provisioner:

# 建立專用 namespace
kubectl create namespace nfs-system

# 部署 NFS Provisioner
helm install nfs-subdir-external-provisioner \
  nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
  -n nfs-system \
  -f nfs-provisioner-values.yaml

# 檢查部署狀態
kubectl get pods -n nfs-system
kubectl get storageclass

驗證 StorageClass

確認動態儲存類別已正確建立:

# 檢查 StorageClass
kubectl get storageclass nfs-client -o yaml

# 預期輸出應該包含:
# metadata:
#   name: nfs-client
#   annotations:
#     storageclass.kubernetes.io/is-default-class: "true"
# provisioner: cluster.local/nfs-subdir-external-provisioner

動態儲存測試

建立測試 PVC

建立一個簡單的 PVC 來測試動態配置:

# 建立測試 PVC
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: nfs-client
  resources:
    requests:
      storage: 1Gi
EOF

驗證動態配置

檢查 PVC 和 PV 的自動建立:

# 檢查 PVC 狀態
kubectl get pvc test-pvc

# 檢查對應的 PV
kubectl get pv

# 檢查 NFS 伺服器上的目錄
ssh bastion-infra-server "ls -la /nfs/nfs-client/"

預期結果:

  • PVC 狀態為 Bound
  • 自動建立對應的 PV
  • NFS 伺服器上出現新的子目錄

建立使用儲存的 Pod

建立一個使用動態儲存的測試 Pod:

# 建立測試 Pod
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: storage-test-pod
spec:
  containers:
  - name: test-container
    image: busybox
    command: [ "sleep", "3600" ]
    volumeMounts:
    - name: storage
      mountPath: /data
  volumes:
  - name: storage
    persistentVolumeClaim:
      claimName: test-pvc
EOF

測試讀寫功能

驗證儲存的讀寫功能:

# 寫入測試檔案
kubectl exec storage-test-pod -- sh -c "echo 'Hello NFS CSI' > /data/test.txt"

# 讀取測試檔案
kubectl exec storage-test-pod -- cat /data/test.txt

# 從 NFS 伺服器直接檢查
ssh bastion-server "find /nfs/nfs-client -name 'test.txt' -exec cat {} \;"

多租戶儲存配置

透過 Rancher UI 設定儲存配額

使用 Rancher UI 為不同 Project 設定儲存配額更直觀:

  1. 進入目標 Project:選擇 data Project
  2. 前往 Resource Quotas 設定:Resources → Resource Quotas
  3. 設定儲存限制
    - Persistent Volume Claims: 5, default: 1
    - Storage Reservation: 10000MiB, default: 1
    
  4. 套用設定:點選 Create

這樣可以限制該 Project 下所有 Namespace 的總儲存使用量。

儲存監控與維護

NFS CSI Provisioner 的限制

重要提醒:NFS Subdir External Provisioner 有以下重要限制:

  • 無法真正限制 PVC 大小:雖然可以在 PVC 中設定 storage 大小,但實際使用時可以超過這個限制
  • 無法監控實際使用量:Kubernetes 無法準確回報 NFS 卷的實際使用情況
  • 適合開發測試環境:對於生產環境,建議使用商業級的儲存解決方案或雲端提供的 CSI

基本儲存檢查

雖然無法精確監控,但仍可以進行基本檢查:

# 檢查 PVC 狀態和宣告大小
kubectl get pvc --all-namespaces

# 檢查 PV 的狀態  
kubectl get pv

# 檢查 NFS 伺服器的實際磁碟使用量
ssh bastion-infra-server "df -h /nfs"

# 檢查各專案目錄的實際大小
ssh bastion-infra-server "du -sh /nfs/nfs-client/*"

清理測試資源

完成測試後清理資源:

# 刪除測試 Pod
kubectl delete pod storage-test-pod

# 刪除測試 PVC(會自動刪除 PV)
kubectl delete pvc test-pvc

# 驗證 PV 已被清理
kubectl get pv

故障排除

常見問題診斷

Provisioner Pod 啟動失敗 (Mount 錯誤):

# 錯誤訊息範例:
# MountVolume.SetUp failed for volume "nfs-subdir-external-provisioner-root" : mount failed: exit status 32
# bad option; for several filesystems (e.g. nfs, cifs) you might need a /sbin/mount.<type> helper program

# 解決方案:在所有節點安裝 NFS 客戶端
ssh <node-name>
sudo apt update && sudo apt install -y nfs-common

PVC 一直處於 Pending 狀態:

# 檢查 PVC 事件
kubectl describe pvc <pvc-name>

# 檢查 Provisioner Pod 日誌
kubectl logs -n nfs-system deployment/nfs-subdir-external-provisioner

# 檢查 NFS 連線
kubectl exec -it <any-pod> -- showmount -e 192.168.0.135

Pod 無法掛載 PVC:

# 檢查 Pod 事件
kubectl describe pod <pod-name>

# 檢查 NFS 伺服器服務狀態
ssh bastion-infra-server "sudo systemctl status nfs-kernel-server"

今日總結與明日預告

今天我們成功建立了現代化的動態儲存系統!透過 NFS CSI Provisioner,我們的 Kubernetes 叢集現在可以自動管理儲存分配,大幅提升了儲存管理的效率和靈活性。

重點回顧:

  • ✅ 理解動態儲存 vs 傳統儲存的差異
  • ✅ 部署 NFS CSI Provisioner
  • ✅ 測試動態儲存的配置和使用
  • ✅ 透過 Rancher UI 設定儲存配額
  • ✅ 了解 NFS CSI 的限制和適用場景

明天我們要建立「資源帝國的財政部」!學習如何透過 ResourceQuota 精確控制各個 Project 和 Namespace 的資源使用量,確保每個租戶都能公平分配到應有的資源,避免資源濫用和相互影響。準備好成為資源分配大師了嗎?


💡 牧場主小提示:動態儲存就像牧場的自動餵食系統,設定好參數後就能自動分配資源!但要記住 NFS CSI 有個小缺點,就是無法真正限制使用量。定期檢查 NFS 伺服器的磁碟容量很重要,避免「倉庫爆滿」的尷尬情況!


上一篇
Day 14: Project 管理與使用者權限實戰
下一篇
Day 16: ResourceQuota 資源配額控制 - 牧場飼料分配大作戰
系列文
牧場主的 K8s 放牧日記18
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言