[元件][儲存] StorageClass === ###### tags: `K8s / 元件` ###### tags: `Kubernetes`, `k8s`, `StorageClass` <br> [TOC] <br> ## 部署 SC(StorageClass) 策略 ### 建立兩個 sc (storage class): - ### CaseA ``` default-local <-- 預設,刪了 pvc ,自動刪除 pv default-local-retain <-- 刪了 pvc ,保留 pv ``` - ### CaseB ``` default-local-delete <-- 刪了 pvc ,自動刪除 pv default-local-retain <-- 刪了 pvc ,保留 pv ``` <br> --- ## 討論 - 基本用法 ### StorageClass 的主要用途 - ### gpt-o4-mini-high (2025/05/16) 在 Kubernetes 中,**StorageClass** 的主要用途是定義「儲存類別」(storage class),讓使用者可以根據不同的需求(效能、複本、區域性等)動態地佈署 PersistentVolume(PV)。具體來說,它的作用包含: 1. **動態供應 (Dynamic Provisioning)** - 使用者只要在 PersistentVolumeClaim (PVC) 中指定 `storageClassName`,系統就會自動呼叫對應的外掛程式(provisioner),動態建立符合需求的 PV,而不需事先手動建立 PV。 - 例如,對於 AWS EBS、GCE PD、NFS、Ceph 等不同儲存後端,都可以透過 StorageClass 抽象化,直接在申請 PVC 時自動佈署對應的資源。 2. **參數化設定** - 每個 StorageClass 可以帶入不同的 `parameters`,例如磁碟類型(`gp2` vs. `io1`)、IOPS 上限、檔案系統類型(`ext4`、`xfs`)等。 - 透過這些參數,使用者能夠針對不同工作負載(如資料庫、快取、檔案儲存)選擇最合適的儲存規格。 3. **回收策略 (Reclaim Policy)** - `reclaimPolicy` 可設定為 `Delete`(刪除底層資源)或 `Retain`(保留底層資源),決定在刪除 PVC 時,PV 應如何處理。 - 例如,對臨時性測試環境,可設定為 `Delete`;對要保留原始資料的情況,可設定為 `Retain`。 4. **卷綁定模式 (Volume Binding Mode)** - `Immediate`(預設):PVC 申請時立刻綁定 PV。 - `WaitForFirstConsumer`:等到有 Pod 要使用該 PVC 時,才真正建立並綁定 PV,可確保 PV 建立在 Pod 實際排程到的節點或可用區域(zone)中,減少跨區存取延遲。 5. **多樣化儲存類別管理** - 一個 Kubernetes 叢集裡,可以同時定義多個 StorageClass,例如「快速 SSD」、「一般 HDD」、「高可用 Quorum」、「冷資料」等,讓開發者依照應用需求自行選擇。 - 也可指定其中一個為預設 StorageClass,當 PVC 未指定 `storageClassName` 時自動使用。 --- ### 範例:定義一個 StorageClass ```yaml= apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast-ssd provisioner: kubernetes.io/aws-ebs # AWS EBS 外掛 parameters: type: gp3 # gp3 類型的 SSD iopsPerGB: "10" reclaimPolicy: Delete # PVC 刪除後,PV 也一併刪除 volumeBindingMode: WaitForFirstConsumer # 等 Pod 排程後再建立 PV ``` ### 範例:使用 StorageClass 的 PVC ```yaml= apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-fast-storage spec: storageClassName: fast-ssd accessModes: - ReadWriteOnce resources: requests: storage: 50Gi ``` Kubernetes 就會自動呼叫 AWS EBS provisioner,動態建立一顆 50Gi 的 gp3 SSD 並綁定給 PVC。這就是 StorageClass 在 Kubernetes 中的核心價值:**簡化管理、參數化配置、並支援動態供應**。 <br> ### 可以不用建立 PV ,就可以建立出 SC & PVC? - ### gpt-o4-mini-high (2025/05/16) ### 僅使用 StorageClass 與 PVC 動態供應 PV 是的,只要你的叢集中已經有支援「動態供應」的 StorageClass,就可以只建立 StorageClass 與 PVC,而不需要事先手動建立任何 PV。具體條件與流程如下: 1. **叢集必須有對應的 Provisioner** - 例如 AWS EBS、GCE PD、Ceph RBD、NFS CSI、長虹 CSI 等等,只要對應的 CSI 驅動(provisioner)已經安裝並註冊到 Kubernetes,就能動態供應 PV。 2. **建立好 StorageClass** - 定義好 `provisioner` 與必要的 `parameters`、`reclaimPolicy`、`volumeBindingMode` 等。 ```yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast-ssd provisioner: kubernetes.io/aws-ebs # AWS EBS CSI 或其他 CSI driver parameters: type: gp3 iopsPerGB: "10" reclaimPolicy: Delete volumeBindingMode: WaitForFirstConsumer ``` 3. **使用 PVC 指定該 StorageClass** - 只要在 PVC 裡指定 `storageClassName: fast-ssd`,就會自動向該 Provisioner 發出請求,並動態建立 PV 來綁定。 ```yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-fast-storage spec: storageClassName: fast-ssd accessModes: - ReadWriteOnce resources: requests: storage: 50Gi ``` 4. **系統自動完成 PV 建立與綁定** - 你不需要手動撰寫或維護任何 PV 資源。只要 PVC 建立後,Kubernetes 會立刻(或在 Pod 排程時)呼叫對應的 Provisioner 去動態配置底層儲存,並回傳一個 PV 綁定給你的 PVC。 --- > **注意** > - 如果你的叢集中沒有可用的 CSI driver/provisioner,或是指定的 StorageClass 不支援動態供應,那麼在 PVC 建立時就會找不到可用的 PV,狀態會一直保持 `Pending`。 > - 你也可以將某個 StorageClass 設為「預設」,這樣在 PVC 未指定 `storageClassName` 時,就會自動套用該預設 StorageClass 進行動態供應。 這樣一來,只要管理員先部署好 StorageClass,開發者就能單純透過 PVC 向 Kubernetes 申請儲存資源,而不再需要自行管理 PV,極大地簡化了儲存配置流程。 <br> ### 如果是 provisioner: kubernetes.io/no-provisioner ? - ### gpt-o4-mini-high (2025/05/16) ### 關閉動態供應 當你在 StorageClass 裡指定 ```yaml provisioner: kubernetes.io/no-provisioner ``` 就代表 **關閉動態供應**,這個 StorageClass 只用於「靜態供應」(static provisioning),也就是: 1. **不會自動建立 PV** - Kubernetes 不會呼叫任何 CSI driver 或外掛去做動態供應,PVC 必須去綁定已經事先由管理員 **手動建立**、且 `storageClassName` 相同的 PV。 - 如果叢集中沒有現成的 PV,PVC 會一直停在 `Pending`。 2. **常見應用場景:Local PV** - 例如把每台節點上的某個目錄(如 `/mnt/disks/ssd1`)當成卷,事先用 PV 定義好 `local` 協議並加上節點親和性(nodeAffinity),就配合這種 `no-provisioner` 的 StorageClass 使用。 3. **通常會搭配 `volumeBindingMode: WaitForFirstConsumer`** - 讓 PV 與 PVC 的綁定與 Pod 排程一起決策,確保所綁定的本地卷就在該 Pod 被排到的節點上。 --- ### 範例:用於 Local PV 的 StorageClass ```yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: local-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer ``` 接著,管理員要手動建立對應的 PV,例如: ```yaml apiVersion: v1 kind: PersistentVolume metadata: name: pv-node1-ssd labels: type: local spec: capacity: storage: 100Gi accessModes: - ReadWriteOnce storageClassName: local-storage local: path: /mnt/disks/ssd1 nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - node1 persistentVolumeReclaimPolicy: Delete ``` 最後,開發者只要在 PVC 指定同樣的 `storageClassName: local-storage` 就能綁定到這些靜態 PV: ```yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-local-data spec: storageClassName: local-storage accessModes: - ReadWriteOnce resources: requests: storage: 50Gi ``` --- ### 總結 - **`kubernetes.io/no-provisioner`**:完全關閉動態供應,PVC 只能綁定 **事先已存在** 的 PV。 - 如果你想要省掉「建立 PV」這一步,就必須使用能動態供應的 provisioner(如各雲提供的 CSI driver),而不能用 `no-provisioner`。 <br> --- <br> ## 討論 - 動態 PV 推薦方案 ### 提供動態 PV 的推薦套件 - ### Question - K8s 要透過 StorageClass 提供動態 PV,有推薦的套件? - 是否需要考慮在 pod 重啟後,被綁定到另一個 node 所面臨的 affinity 問題? - ### gpt-5.2 (2025/12/30) 可以,把「K8s 透過 StorageClass 動態供應 PV」拆成兩個面向來選:**(1) 你要的是本機磁碟(local)還是網路儲存(network/distributed)**、**(2) 你能不能接受 Pod 被排到別的 node 時資料仍可用**。Kubernetes 本身對動態供應的概念是:**PVC 指到某個 StorageClass,然後由對應的 CSI/Provisioner 自動建立 PV**。 ([Kubernetes][20251230-A-1]) --- ### 1) 推薦哪些「套件 / Provisioner」來做動態 PV? #### A. 你要「本機磁碟」動態 PV(效能佳,但天然有 node 綁定) 適合:cache、scratch、或允許「該 node 掛了就一起掛」的 stateful(例如單機資料庫測試) 1. **Rancher Local Path Provisioner(local-path-provisioner)** * 優點:最輕量、部署簡單,會在每個 node 用指定路徑自動生 PV(hostPath 或 local PV) ([GitHub][20251230-A-2]) * 缺點:資料就在那台 node 上,node 壞掉/被移走就無法在別台續用(除非你自己做資料搬遷) 2. **OpenEBS LocalPV(HostPath / LVM / ZFS / Device)** * 優點:也是 local 動態供應,但選項更多(例如 LVM/ZFS 這類更像「把本機磁碟做成可管理的本機卷」),且會自動帶 node affinity,讓 Pod 會被排回對應 node ([GitHub][20251230-A-3]) * 缺點:同樣是 local 的基本限制:資料跟 node 綁定。 > 如果你現在的情境是「沒有共享儲存,但想先讓 PVC 動起來」:local-path-provisioner 或 OpenEBS LocalPV 通常是最快落地的兩個。 --- #### B. 你要「Pod 可能換 node 也能用」的動態 PV(網路/分散式) 適合:真正 production 的 stateful(DB、metadata、共享檔案)、或你在意節點故障可用性 1. **Longhorn(分散式 block storage)** * 優點:偏「好上手的分散式 RWO block」,有副本/重建概念,K8s 透過 StorageClass 動態供應 ([Longhorn][20251230-A-4]) * 取捨:比 local 複雜、也會吃網路/磁碟,性能視你的環境與副本策略而定 2. **Rook-Ceph(Ceph RBD / CephFS)** * 優點:比較「全功能」: * **RBD** 常用於 RWO block * **CephFS** 可做 RWX(多人共享檔案) 都能用 StorageClass 動態供應 ([Rook][20251230-A-5]) * 取捨:維運成本較高(但能力也最強) 3. **NFS CSI Driver(若你已有 NFS/NAS)** * 優點:你只要有一台 NFS server(或 NAS),用 CSI driver 就能做 StorageClass 動態供應(常見 RWX) ([GitHub][20251230-A-6]) * 取捨:可用性/效能取決於 NFS 後端(單點、網路瓶頸等) --- ### 2) 你問的 affinity 問題:Pod 重啟後會不會綁到別的 node? #### 先釐清:「重啟」有兩種 * **容器重啟(container restart)**:Pod 還在同一個 node 上 → 通常不影響卷 * **Pod 被重新排程(Pod 重新建立/漂移到別台 node)**:才會遇到你說的 affinity/綁定問題 #### A. 用「網路/分散式儲存」(Ceph/Longhorn/NFS…) 通常 **不需要特別擔心 Pod 被排到別的 node**:因為卷本來就設計成可被 attach/mount 到別台(視 accessMode / driver 能力)。動態供應的流程也是 K8s/CSI 的標準路徑。 ([Kubernetes][20251230-A-1]) #### B. 用「local PV」(local-path-provisioner、OpenEBS LocalPV…) 這邊就**一定要考慮**:因為資料在某台 node 的磁碟上。 Kubernetes 對 local volume 的建議是:**StorageClass 設 `volumeBindingMode: WaitForFirstConsumer`**,讓「PV/PVC 綁定」延後到 Pod 確定要排到哪個 node 時再決定,避免先綁錯,並會一起考慮 Pod 的 nodeSelector / affinity 等限制。 ([Kubernetes][20251230-A-7]) 但重點是: * 一旦 PVC 綁到某個「在 node A 的 local PV」,**Pod 之後若被排到 node B,就會卡住(Pending / volume node affinity conflict 這類)**,因為卷只允許在 node A 使用(PV 會帶 nodeAffinity)。 ([GitHub][20251230-A-3]) * 這不是 bug,是 local storage 的本質。 --- ### 實務建議:怎麼選才不會踩雷? * **你要的是「可靠可搬」的持久資料(DB、SlurmDB、共享 home/work)」** → 優先選 **Rook-Ceph(CephFS/RBD)** 或 **Longhorn** 或 **NFS CSI(你已有 NAS/NFS)**。 ([Rook][20251230-A-5]) * **你要的是「高速但可犧牲」的本機資料(cache/scratch、某些工作目錄)」** → local-path-provisioner / OpenEBS LocalPV 可以,但要接受 node 綁定與 node 故障風險。 ([GitHub][20251230-A-2]) * 只要你走 local 路線,請把 StorageClass 設成 **WaitForFirstConsumer** 當作基本盤。 ([Kubernetes][20251230-A-7]) 如果你願意,我也可以依你「要 RWX 還是 RWO、資料重要性、現在有沒有 NFS/Ceph、以及你希望的維運複雜度」直接幫你把推薦方案收斂成 1~2 個最可能落地的選項,並附上對應的 StorageClass 範本。 [20251230-A-1]: https://kubernetes.io/docs/concepts/storage/dynamic-provisioning/?utm_source=chatgpt.com "Dynamic Volume Provisioning" [20251230-A-2]: https://github.com/rancher/local-path-provisioner?utm_source=chatgpt.com "rancher/local-path-provisioner: Dynamically provisioning ..." [20251230-A-3]: https://github.com/openebs/dynamic-localpv-provisioner?utm_source=chatgpt.com "openebs/dynamic-localpv-provisioner" [20251230-A-4]: https://longhorn.io/docs/latest/what-is-longhorn/?utm_source=chatgpt.com "Documentation - Longhorn" [20251230-A-5]: https://rook.io/docs/rook/v1.14/Storage-Configuration/Block-Storage-RBD/block-storage/?utm_source=chatgpt.com "Block Storage Overview - Rook Ceph Documentation" [20251230-A-6]: https://github.com/kubernetes-csi/csi-driver-nfs/blob/master/deploy/example/README.md?utm_source=chatgpt.com "csi-driver-nfs/deploy/example/README.md at master" [20251230-A-7]: https://kubernetes.io/docs/concepts/storage/volumes/?utm_source=chatgpt.com "Volumes" <br> --- ### [接續] RWX + 資料重要性 + NFS - ### gpt-5.2 (2025/12/30) 你這個條件(**RWX + 資料重要 + 已有 NFS**)我會建議走這條路線: ### 建議方案 #### 1) 優先用 **NFS CSI Driver(`nfs.csi.k8s.io`)** 做動態供應 * 這個 driver 的設計就是:**你先有一個已設定好的 NFSv3/NFSv4 Server**,K8s 透過 StorageClass 動態供應 PV(實作上通常是 **在 NFS share 底下自動建立子目錄** 給每個 PVC)。 ([GitHub][20251230-B-1]) * 如果你目前還在用 **`nfs-subdir-external-provisioner`**,它也能用,但新案子/長期維運通常會偏向 CSI driver。 ([GitHub][20251230-B-2]) --- ### 你問的 affinity 問題:要不要擔心 Pod 重啟跑到別台 node? **用 NFS(網路檔案系統)做 RWX 通常「不用」擔心 PV node affinity**(這個比較是 *local PV* 才會踩到的坑)。只要: * 所有可能被排程到的 node 都能連到 NFS(DNS / 路由 / 防火牆) * node 上有 NFS client 支援(常見是 nfs-utils / nfs-common) 那 Pod 被 reschedule 到另一台 node,一樣可以 mount 同一個 RWX PVC。 > `volumeBindingMode: WaitForFirstConsumer` 那套主要是為了 local volume / 有節點限制的 storage,NFS 通常不需要為了解 affinity 特別用它。K8s 官方在 local volumes 的章節才會特別強調 WaitForFirstConsumer。 ([Kubernetes][20251230-B-3]) --- ### 「資料重要性」下,用 NFS 時你一定要額外注意的 3 件事 #### A) **NFS 本身常是 SPOF**:請確認後端是 HA / 有備援 K8s 端做得再好,只要 NFS server(或背後 NAS)單點掛掉,RWX 也會一起受影響。建議你把「重要性」落在:NAS/伺服器 HA、備份、快照、異地備援等(這是儲存後端的責任)。 ([Amazon Web Services, Inc.][20251230-B-4]) #### B) **PVC 的 `storage: 100Gi` 不等於「真的只能寫 100Gi」** NFS CSI/傳統 NFS PV 多半是「目錄」的概念;PVC 的容量在很多情境下 **只用在 K8s 的配額/匹配與規劃,不會在 NFS 層強制限制實際可寫容量**。 ([GitHub][20251230-B-5]) 要真的限制,通常要靠: * NFS 後端的 quota(或把不同專案分不同 export / filesystem) * K8s Namespace 的 ResourceQuota / LimitRange 做「申請量」與「總量」治理(但它也不是直接限制 NFS 寫入,是治理 *claim 的配置*) ([Kubernetes][20251230-B-6]) #### C) 刪除策略(重要資料建議更保守) StorageClass 的 `reclaimPolicy` 你要想清楚: * `Delete`:PVC 刪掉時可能連子目錄也刪掉(依 provisioner 行為)→ 容易誤刪資料 * `Retain`:PVC 刪了資料還留著 → 需要你有「回收/清理 SOP」 (StorageClass 概念與 reclaimPolicy 是標準概念。) ([Kubernetes][20251230-B-7]) --- ### 最小可用的 YAML 範本(NFS CSI / RWX) > 下面示意「每個 PVC 建一個子目錄」的常見用法;`server/share` 換成你的 NFS 資訊。 ```yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-rwx provisioner: nfs.csi.k8s.io reclaimPolicy: Retain volumeBindingMode: Immediate parameters: server: 10.0.0.10 share: /exports/k8s mountOptions: - nfsvers=4.1 - hard ``` ```yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: data-rwx spec: accessModes: ["ReadWriteMany"] storageClassName: nfs-rwx resources: requests: storage: 100Gi ``` (NFS CSI driver 的 plugin 名稱、需要既有 NFS server、以及動態供應方式在官方 repo 有寫。) ([GitHub][20251230-B-1]) --- 如果你願意,我可以用你目前的情境(**NFS 是自建還是 NAS?要不要做專案隔離?要不要 quota?**)直接給你一套「production 版」的 StorageClass/PVC + 權限(fsGroup/runAsUser)+ 備份/回收 SOP 清單。 [20251230-B-1]: https://github.com/kubernetes-csi/csi-driver-nfs?utm_source=chatgpt.com "kubernetes-csi/csi-driver-nfs" [20251230-B-2]: https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner?utm_source=chatgpt.com "kubernetes-sigs/nfs-subdir-external-provisioner" [20251230-B-3]: https://kubernetes.io/docs/concepts/storage/volumes/?utm_source=chatgpt.com "Volumes" [20251230-B-4]: https://aws.amazon.com/blogs/storage/persistent-storage-for-kubernetes/?utm_source=chatgpt.com "Persistent storage for Kubernetes - AWS - Amazon.com" [20251230-B-5]: https://github.com/kubernetes-csi/csi-driver-nfs/issues/427?utm_source=chatgpt.com "how to really manage the capacity of pv pvc when use nfs ..." [20251230-B-6]: https://kubernetes.io/docs/tasks/administer-cluster/limit-storage-consumption/?utm_source=chatgpt.com "Limit Storage Consumption" [20251230-B-7]: https://kubernetes.io/docs/concepts/storage/storage-classes/?utm_source=chatgpt.com "Storage Classes" <br> --- ### `nfs.csi.k8s.io` 是 K8s 內建功能?還是 github 上的一個專案? - ### gpt-5.2 (2025/12/30) `nfs.csi.k8s.io` **不是 Kubernetes「內建就有、裝好就能用」的功能**;它是 **一個獨立的 CSI Driver 專案**(在 GitHub 的 `kubernetes-csi/csi-driver-nfs`),而 `nfs.csi.k8s.io` 是這個 Driver 的 **CSI plugin / provisioner 名稱**。 ([GitHub][20251230-C-1]) K8s **內建的是 CSI 框架能力**(例如 CSI volume 型別、kubelet 的 CSI driver 註冊/發現機制等),讓你可以「外掛」各家/各系統的 storage driver;但 **driver 本身通常要你另外部署**(以 Pod/DaemonSet/Deployment 形式跑在叢集裡)。 ([Kubernetes][20251230-C-2]) 所以實務上是這樣分工: * **Kubernetes(內建)**:提供 CSI 的介面與機制(能掛載 CSI volume、能讓 kubelet 發現 driver)。 ([Kubernetes][20251230-C-2]) * **NFS CSI Driver(外掛專案)**:你自行安裝到叢集(controller + node plugin),然後 StorageClass 才能寫 `provisioner: nfs.csi.k8s.io` 來做動態供應。 ([GitHub][20251230-C-1]) 補一點:這個 NFS CSI driver 的定位是「你**已經有** NFSv3/v4 server」,它會幫你做 **PVC 動態供應**(常見是每個 PVC 在 NFS share 底下建立子目錄)。 ([GitHub][20251230-C-1]) [20251230-C-1]: https://github.com/kubernetes-csi/csi-driver-nfs?utm_source=chatgpt.com "kubernetes-csi/csi-driver-nfs" [20251230-C-2]: https://kubernetes.io/blog/2019/01/15/container-storage-interface-ga/?utm_source=chatgpt.com "Container Storage Interface (CSI) for Kubernetes GA" <br> --- ### `nfs.csi.k8s.io` 有哪些優缺點和限制? - ### gpt-5.2 (2025/12/30) 下面我用「**`nfs.csi.k8s.io`(csi-driver-nfs)**」這條線來回答:它是不是內建、有哪些優缺點/限制,以及你前面提到的 **Pod 重啟換 node 的 affinity** 要不要擔心(你現在是 **RWX + 資料重要性 + NFS**)。 --- ### `nfs.csi.k8s.io` 是內建嗎? * **不是 Kubernetes 內建(in-tree)功能**;它是 **kubernetes-csi** 社群維護的 **NFS CSI Driver 專案**,你需要自己在叢集內安裝(Helm/manifest)。它的 CSI plugin name 就是 `nfs.csi.k8s.io`,並且 **要求你已經有 NFSv3/NFSv4 伺服器與 export**,動態供應 PV 的方式是「在 NFS share 底下建立子目錄」來對應 PVC。([GitHub][20251230-D-1]) * Kubernetes 本身也有 `nfs` volume 類型可以掛載既有 NFS share,但那是「直接掛載」的概念;要做到你說的「StorageClass 動態 PV」,通常會走 CSI Driver 這類外掛。([Kubernetes][20251230-D-2]) --- ### 你要不要擔心「Pod 重啟換到另一個 node」的 affinity 問題? **用 NFS(RWX)通常不用擔心 PV 綁 node 的 affinity。** 因為 NFS 是網路檔案系統,Pod 跑到哪個 node,只要那個 node **能連到 NFS server**,PVC 重新 mount 就能用。同時 Kubernetes 也明確說 NFS 可以被多個 writer 同時掛載。([Kubernetes][20251230-D-2]) 你真正要擔心的反而是: * **所有 node 到 NFS 的網路可達性 / DNS / firewall / MTU** * NFS server 的 **HA / 效能 / 斷線重連行為** * 權限與安全設定(下面會講) > 對照:**local PV** 才是那種「一定要綁特定 node」的典型(必須設定 PV 的 `nodeAffinity`,scheduler 會把 Pod 排到對的 node)。([Kubernetes][20251230-D-2]) --- ### `nfs.csi.k8s.io` 的優點 1. **RWX 很直覺**:多個 Pod/多個 node 可同時讀寫(共享工作目錄、共享模型檔、共享輸出等),且 Pod 漂到別的 node 也能再 mount 回來。([Kubernetes][20251230-D-2]) 2. **動態供應好上手**:你給 StorageClass 指到一個 NFS server/share,PVC 來了就自動建立對應目錄(不用人工先切一堆 PV)。([GitHub][20251230-D-1]) 3. **成本/相依性低**:你如果已經有 NFS(或公司既有 NAS),導入門檻低。 --- ### `nfs.csi.k8s.io` 的限制、缺點(你這種「資料重要」要特別留意) #### 1) **PVC 的容量(requests.storage)通常「不會被真的限制」** 很多人踩雷:PVC 寫 1Gi,但實際可以寫爆(因為底層就是同一個 NFS 檔案系統的目錄)。在 csi-driver-nfs 的討論裡也直說:容量主要只是拿來做 PV/PVC matching,**K8s 沒辦法直接限制 NFS 目錄的實際容量**,這不是 driver 單方面能解的。([GitHub][20251230-D-3]) **如果你需要「硬性配額」**:要在 NFS 端做(例如把每個 PVC 對應到不同 export/不同檔案系統,或用支援目錄 quota 的檔案系統/管理方式)。OKD 文件也提到一種務實作法:用「不同 partition/export」來達到 quota/size 約束的效果。([docs.okd.io][20251230-D-4]) --- #### 2) **快照/複製(VolumeSnapshot / clone)不是你想像的那種「儲存陣列快照」** Kubernetes 的 VolumeSnapshot 需要 cluster 端的 snapshot controller / CRDs,以及 CSI driver 支援 `CreateSnapshot` 這些能力。([Kubernetes][20251230-D-5]) 但對 **NFS 這種「目錄」** 來說,csi-driver-nfs 的快照/複製在實務上常見是**用打包/拷貝(例如 tar)** 去做,所以: * **很慢**(資料大就爆) * 可能**不夠一致**(應用程式仍在寫入時) * 也有人遇到 snapshot 失敗的案例與限制分析 例如有 OpenShift 社群文件就直接提醒「Snapshots are very slow,因為是用 tar 複製資料」。([examples.openshift.pub][20251230-D-6]) 👉 如果你要的是「真正快、可依賴的快照/備援」,更常見做法是:**用你的儲存廠商/檔案服務的 CSI(NetApp、Dell、EFS…)**,或是走 **NFS server 端快照/備份**。 --- #### 3) **權限/owner/chmod 常見坑(尤其 root_squash)** NFS export 常見預設 `root_squash`:client 端的 root 會被映射成低權限使用者,導致容器裡做 `chown/chmod` 可能噴 `operation not permitted`。([Server Fault][20251230-D-7]) 這對多租戶(multi-tenant)或需要改權限的 workload 很關鍵:你通常要設計好 **UID/GID、fsGroup、目錄預設權限**,不要指望容器啟動後再 chmod 一切。 --- #### 4) **安全性:傳輸加密/隔離要自己做** NFS(尤其 v3)在很多環境下是明文傳輸、仰賴網路隔離;你若是「資料重要」,至少要把 NFS 放在 **受控網段/VPC/VLAN**,並評估 NFSv4 + Kerberos 之類的做法。([vmware.com][20251230-D-8]) --- #### 5) **可用性與效能:NFS server 是核心單點** * NFS server 掛了:整個 RWX 共享盤等於一起掛(Pod 可能卡在 I/O 或 mount) * 高 IOPS、小檔案、大量 metadata 的場景,NFS 很容易成瓶頸 (這部分很吃你的 NFS 架構:單機 NFS、HA NFS、NAS、後端 SSD、cache、網路帶寬等。) --- ### 針對「RWX + 資料重要性 + NFS」的實務建議(精簡版) * **把重點放在 NFS server 的 HA 與備份**:driver 只負責「自動建目錄 + mount」,**不會替你把資料變安全**。([GitHub][20251230-D-1]) * **不要把 PVC size 當成配額**:要 quota 就在 NFS 端做(或改用能提供 quota/快照的儲存 CSI/檔案服務)。([GitHub][20251230-D-3]) * **先把權限模型定死(UID/GID/fsGroup)**,避免容器啟動時 chmod/chown 失敗。([Server Fault][20251230-D-7]) * **如果你需要快照/還原 SLA**:優先考慮「儲存廠商/managed file service 的 CSI」,不要期待 NFS CSI 的 snapshot 是瞬間快照。([examples.openshift.pub][20251230-D-6]) --- 如果你願意貼一下你預期的 usage(例如:Slurm 的 `/work`、使用者家目錄、模型共享、log 共享、DB data 之類),我可以直接幫你把它們分成「適合 NFS RWX」vs「應該用 RWO block」並給一個 StorageClass / mountOptions / 權限策略的建議組合。 [20251230-D-1]: https://github.com/kubernetes-csi/csi-driver-nfs?utm_source=chatgpt.com "kubernetes-csi/csi-driver-nfs" [20251230-D-2]: https://kubernetes.io/docs/concepts/storage/volumes/ "Volumes | Kubernetes" [20251230-D-3]: https://github.com/kubernetes-csi/csi-driver-nfs/issues/427?utm_source=chatgpt.com "how to really manage the capacity of pv pvc when use nfs ..." [20251230-D-4]: https://docs.okd.io/4.18/storage/persistent_storage/persistent-storage-nfs.html?utm_source=chatgpt.com "Persistent storage using NFS - OKD 4.18" [20251230-D-5]: https://kubernetes.io/docs/concepts/storage/volume-snapshots/?utm_source=chatgpt.com "Volume Snapshots" [20251230-D-6]: https://examples.openshift.pub/cluster-configuration/storage/csi-driver-nfs/?utm_source=chatgpt.com "CSI Driver NFS - OpenShift Examples" [20251230-D-7]: https://serverfault.com/questions/212178/chown-on-a-mounted-nfs-partition-gives-operation-not-permitted?utm_source=chatgpt.com "chown on a mounted NFS partition gives \"Operation not ..." [20251230-D-8]: https://www.vmware.com/docs/vmw-best-practices-running-nfs-vmware-vsphere?utm_source=chatgpt.com "Best Practices For Running NFS with VMware vSphere" <br> <br> {%hackmd vaaMgNRPS4KGJDSFG0ZE0w %}
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up