---
# System prepended metadata

title: Run NFS Server with Podman Pod

---

# Run NFS Server with Podman Pod

## 1. 先決條件

1. Podman host kernel 必須載入以下 kernel modules
    ```
    printf "%s\n" nfs nfsd rpcsec_gss_krb5 | sudo tee /etc/modules-load.d/nfs.conf
    ```
2. 手動觸發載入服務
    ```
    sudo systemctl restart systemd-modules-load.service
    ```
3. 檢查模組是否已載入
    ```
    sudo lsmod | grep -E "nfs|nfsd|rpcsec_gss_krb5"
    ```
    執行結果：
    ```
    rpcsec_gss_krb5        40960  0
    nfs                   598016  0
    fscache               393216  1 nfs
    netfs                  65536  2 fscache,nfs
    nfsd                  897024  5
    auth_rpcgss           188416  2 nfsd,rpcsec_gss_krb5
    nfs_acl                12288  1 nfsd
    lockd                 184320  2 nfsd,nfs
    grace                  12288  2 nfsd,lockd
    sunrpc                839680  18 nfsd,auth_rpcgss,lockd,rpcsec_gss_krb5,nfs_acl,nfs
    ```

## 2. 注意事項

1. 此 container 需要以 `privileged` 來執行。這是必要的，因為 NFS 伺服器需要在 container **內部**掛載數個檔案系統以支援其運作，而若無這些權限，在 container 內部執行掛載（mount）是不可能的。
2. 此外，此 container 需要能存取到您想透過 NFS 分享的本機檔案。您可以使用 Podman volumes、綁定掛載（bind mounts）、將檔案直接建置在自訂的映像檔（custom image）中，或幾乎任何其他能將檔案提供給 Podman Container 的方式。

## 3. 規劃一顆硬碟給 NFS Server 用

```
# 1. 在 VM 新增一顆硬碟專門給 NFS Server 使用

# 2. 檢查新的硬碟名稱
$ lsblk
...
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
sdb               8:16   0  100G  0 disk

# 3. 將硬碟名稱設為變數
$ D="/dev/sdb"

# 4. 使用 parted 建立 GPT 分割區，從 1 MiB 到磁碟尾，並標記為 LVM 用途
$ sudo parted -s ${D} mklabel gpt
$ sudo parted -s ${D} unit MiB mkpart primary 1 100%

# 5. 將剛建立的分割區初始化為 LVM PV
$ sudo pvcreate ${D}1

# 6. 建立名為 vg-nfs 的 VG
$ sudo vgcreate vg-nfs ${D}1

# 7. 從 VG 中建立一 LV，利用全部剩餘空間並命名為 lv-nfs
$ sudo lvcreate -l +100%FREE -n lv-nfs /dev/vg-nfs

# 8. 格式化 LV 為 XFS 檔案系統，以提供穩健且高效的儲存
$ sudo mkfs.xfs /dev/vg-nfs/lv-nfs

# 9. 建立 NFS Server 要共享給 Client 的目錄
$ sudo mkdir -p /data/nfs

# 10. 修改目錄權限
$ sudo chown -R 65534:65534 /data/nfs

# 11. 將目錄設為開機自動掛載 lv 裝置上
$ echo '/dev/vg-nfs/lv-nfs      /data/nfs               xfs     defaults        0 0' | sudo tee -a /etc/fstab

# 12. 將目錄掛載到 lv 裝置上
$ sudo mount -a && sudo systemctl daemon-reload

# 13. 設定共享目錄
$ echo '/data/nfs 192.168.11.0/24(rw,sync,no_subtree_check,no_root_squash,fsid=0)' | sudo tee /etc/exports
```

## 4. 設定與部署 NFS Server Podman Pod

1. 建立工作目錄
    ```
    mkdir "$HOME"/nfs-server; cd "$HOME"/nfs-server
    ```
2. 設定 NFS Server Podman Pod YAML
    ```
    nano nfs-pod.yaml
    ```

    檔案內容如下

    ```
    apiVersion: v1
    kind: Pod
    metadata:
      name: nfs-server-pod
    spec:
      containers:
        - name: nfs-server-container
          image: docker.io/erichough/nfs-server
          securityContext:
            privileged: true

          ports:
            - name: nfs-tcp
              containerPort: 2049
              hostPort: 2049
              protocol: TCP

          # volume 掛載設定
          volumeMounts:
            - name: nfs-data-volume
              mountPath: /data/nfs
            - name: nfs-exports-config
              mountPath: /etc/exports

      # 定義 Pod 層級的 Volume
      volumes:
        - name: nfs-data-volume
          hostPath:
            path: /data/nfs # <-- 請替換成主機上的實際路徑
            type: Directory
        - name: nfs-exports-config
          hostPath:
            path: /etc/exports # <-- 請替換成主機上的實際路徑
            type: File
    ```
3. 部署 NFS Server 
    ```
    sudo podman kube play ./nfs-pod.yaml
    ```
4. 檢查運作狀態
    ```
    sudo podman ps -a --pod --filter pod=nfs-server-pod
    ```

    正確執行結果如下：

    ```
    CONTAINER ID  IMAGE                                    COMMAND     CREATED        STATUS        PORTS                   NAMES                                POD ID        PODNAME
    3b17c7f41587  localhost/podman-pause:4.9.5-1729598400              4 minutes ago  Up 4 minutes  0.0.0.0:2049->2049/tcp  3cf2e7b352a4-infra                   3cf2e7b352a4  nfs-server-pod
    87740e79d0e1  docker.io/erichough/nfs-server:latest                4 minutes ago  Up 4 minutes  0.0.0.0:2049->2049/tcp  nfs-server-pod-nfs-server-container  3cf2e7b352a4  nfs-server-pod
    ```

5. 在其他主機驗測是否可以掛載
    ```
    $ mkdir test
    $ sudo mount -t nfs 192.168.11.11:/ test
    $ sudo touch test/qqq

    # run command on nfs server host
    $ ls -l /data/nfs
    total 0
    -rw-r--r-- 1 root root 0 Aug 13 17:57 qqq
    $ sudo umount test
    ```
6. 停止 NFS Server 
    ```
    sudo podman kube down ./nfs-pod.yaml
    ```
7. 設定開機自動重啟
    ```
    # 1. 建立一個目錄，用來存放 Podman Quadlet 要使用的 Kubernetes YAML 設定檔
    sudo mkdir -p /etc/containers/kube

    # 2. 將預先定義好的 NFS Pod YAML 檔複製到上述目錄中
    sudo cp nfs-pod.yaml /etc/containers/kube/nfs-server.yaml

    # 3. 使用 "here document" 的方式，建立一個 systemd 的 Quadlet unit 檔案。
    # 這個 .kube 檔案會告訴 systemd 如何使用指定的 YAML 檔來管理一個 Pod。
    sudo tee /etc/containers/systemd/nfs-server-pod.kube >/dev/null <<'EOF'
    [Unit]
    Description=Podman Quadlet: NFS Server Pod (nfs-server-pod)
    # 指定此服務依賴於網路連線
    Wants=network-online.target
    After=network-online.target

    [Kube]
    # 指定要使用的 Kubernetes YAML 設定檔路徑
    Yaml=/etc/containers/kube/nfs-server.yaml
    # StopTimeout=120

    [Service]
    # 設定服務失敗時自動重啟
    Restart=always
    # 設定重啟間隔為 5 秒
    RestartSec=5s
    # 設定停止服務的等待時間為 120 秒
    TimeoutStopSec=120s

    [Install]
    # 設定此服務在系統開機後，進入多使用者模式時啟動
    WantedBy=multi-user.target
    EOF

    # 4. 重新載入 systemd 設定，讓系統讀取到剛剛建立的新服務檔案
    sudo systemctl daemon-reload

    # 5. 設定 nfs-server-pod 服務開機自動啟動，並立即啟動它
    sudo systemctl start nfs-server-pod.service

    # 6. 檢查 nfs-server-pod 服務目前的運行狀態
    sudo systemctl status nfs-server-pod.service
    ```
8. 確認運作狀態
    ```
    sudo podman ps -a --pod --filter pod=nfs-server-pod
    ```

    正確執行結果如下：

    ```
    CONTAINER ID  IMAGE                                    COMMAND     CREATED        STATUS        PORTS                   NAMES                                POD ID        PODNAME
    3b17c7f41587  localhost/podman-pause:4.9.5-1729598400              4 minutes ago  Up 4 minutes  0.0.0.0:2049->2049/tcp  3cf2e7b352a4-infra                   3cf2e7b352a4  nfs-server-pod
    87740e79d0e1  docker.io/erichough/nfs-server:latest                4 minutes ago  Up 4 minutes  0.0.0.0:2049->2049/tcp  nfs-server-pod-nfs-server-container  3cf2e7b352a4  nfs-server-pod
    ```


## 參考資料

- [erichough/nfs-server](https://hub.docker.com/r/erichough/nfs-server/)













