今天要為我們的數位牧場建立現代化的「智能倉庫系統」!還記得 Day 6 我們在 bastion 上建立了基本的 NFS 服務嗎?那就像是搭建了倉庫的骨架,今天我們要為它裝上自動化設備!透過 NFS CSI Provisioner,我們的 Kubernetes 叢集就能像有了智能機器人一樣,自動分配儲存空間給需要的應用程式。不用再手動建立 PV,一切都交給 CSI 來處理!
在沒有動態儲存之前,管理 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 Volume,NFS CSI Provisioner 提供:
首先新增 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 有以下重要意義:
建立最小必要的 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
重要提醒:請將這個檔案納入版本控制系統!
在部署 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-common
套件會導致 mount 失敗bad option; for several filesystems (e.g. nfs, cifs) you might need a /sbin/mount.<type> helper program
透過 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
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
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/"
預期結果:
Bound
建立一個使用動態儲存的測試 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 為不同 Project 設定儲存配額更直觀:
data
Project- Persistent Volume Claims: 5, default: 1
- Storage Reservation: 10000MiB, default: 1
這樣可以限制該 Project 下所有 Namespace 的總儲存使用量。
重要提醒:NFS Subdir External Provisioner 有以下重要限制:
雖然無法精確監控,但仍可以進行基本檢查:
# 檢查 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 叢集現在可以自動管理儲存分配,大幅提升了儲存管理的效率和靈活性。
重點回顧:
明天我們要建立「資源帝國的財政部」!學習如何透過 ResourceQuota 精確控制各個 Project 和 Namespace 的資源使用量,確保每個租戶都能公平分配到應有的資源,避免資源濫用和相互影響。準備好成為資源分配大師了嗎?
💡 牧場主小提示:動態儲存就像牧場的自動餵食系統,設定好參數後就能自動分配資源!但要記住 NFS CSI 有個小缺點,就是無法真正限制使用量。定期檢查 NFS 伺服器的磁碟容量很重要,避免「倉庫爆滿」的尷尬情況!