---
# System prepended metadata

title: '[元件][儲存] StorageClass'
tags: [k8s, StorageClass, K8s / 元件, Kubernetes]

---

[元件][儲存] 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 %}
