# 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/)