NFS(網路檔案系統, Network File System)是Linux核心提供的功能,可以透過遠端程序呼叫(RPC, Remote Procedure Call),來遠端掛載檔案系統。



調整Linux核心編譯參數

Linux作業系統對於NFS的支援與否,需看其使用的核心是否有開啟NFS的相關選項。

如果使用make menuconfig來設定Linux核心的編譯參數的話,可以在File System找到Network File Systems

ubuntu-server-18-04-nfs

ubuntu-server-18-04-nfs

想要讓Linux作業系統掛載NFS的話(NFS客戶端),就必須要啟用NFS Client Support(CONFIG_NFS_FS)。單純啟用這個選項所支援的NFS版本為2,如果需要支援版本3和4的話,也要啟用NFS Client Support for Version 3(CONFIG_NFS_V3)、NFS Client Support for Version 4(CONFIG_NFS_V4)。

ubuntu-server-18-04-nfs

想要讓Linux作業系統提供NFS的話(NFS伺服器),就必須要啟用NFS Server Support(CONFIG_NFSD)。單純啟用這個選項所支援的NFS版本為2,如果需要支援版本3和4的話,也要啟用NFS Server Support for Version 3(CONFIG_NFSD_V3)、NFS Server Support for Version 4(CONFIG_NFSD_V4)。

ubuntu-server-18-04-nfs

確認目前使用的Linux核心是否有NFS支援

在終端機執行以下指令:

grep CONFIG_NFS /boot/config-$(uname -r)

可以查看NFS的Linux核心有啟用的相關參數。

ubuntu-server-18-04-nfs

如果CONFIG_NFS_FS的值是m的話,可以使用以下指令來查看nfs模組目前是否有載入:

modprobe -n --first-time nfs && echo "未載入" || echo "已載入"

ubuntu-server-18-04-nfs

modprobe指令可以用來增減核心模組。-n參數代表「dry run」,只會模擬載入核心模組的步驟,不會真的去載入核心模組。--first-time參數可以確保這個核心模組的載入指令是在該核心模組還沒載入的時候才會執行成功。

如果沒有載入nfs模組,可以使用以下指令來載入:

sudo modprobe nfs

如果CONFIG_NFSD的值是m的話,可以使用以下指令來查看nfsd模組目前是否有載入:

modprobe -n --first-time nfsd && echo "未載入" || echo "已載入"

ubuntu-server-18-04-nfs

如果沒有載入nfsd模組,可以使用以下指令來載入:

sudo modprobe nfsd

ubuntu-server-18-04-nfs

NFS伺服器

安裝NFS伺服器

確認目前的Linux核心有啟用nfsd模組後,就可以在Ubuntu Server的終端機下輸入以下指令來安裝NFS伺服器了!

sudo apt install nfs-kernel-server

ubuntu-server-18-04-nfs

由於NFS伺服器是運行在RPC上的服務,因此先用以下指令來確定RPC伺服器是否有確實安裝成功。

sudo ss -tulnp | grep rpcbind

ss指令可以顯示出Socket相關的資訊。-l參數可以只顯示正在監聽中的連線。若使用ss指令時都沒給任何參數的話,會忽略掉監聽中的連線。-t參數可以只顯示TCP連線。-u參數可以只顯示UDP連線。-t參數和-u參數一起用時就表示可以只顯示TCP和UDP連線。-n參數可以讓連接埠數字直接被輸出,而不是用一個名稱代替。-p參數可以顯示佔用連線的行程。

ubuntu-server-18-04-nfs

如上圖,如果有看到TCP和UDP都有在監聽連接埠111的話,就表示RPC安裝成功了!另外您可能還會注意到還有其它的TCP和UDP的連接埠也正在被程式監聽,那些就是已經向RPC「註冊」過的服務所特別開啟的連接埠。

接著再使用以下指令來確定NFS伺服器是否有確實安裝成功。

sudo ss -tuln | grep :2049

ubuntu-server-18-04-nfs

如上圖,如果有看到TCP和UDP都有在監聽連接埠2049的話,就表示NFS伺服器安裝成功了!因為NFS服務使用的連接埠即為2049。

分享檔案系統的目錄

我們可以將允許被遠端掛載的檔案系統的目錄定義在/etc/exports設定檔內,如此一來該檔案系統就可以被NFS客戶端掛載。它預設的模樣長成這樣:

ubuntu-server-18-04-nfs

每行的設定格式如下:

要分享的目錄路徑 允許存取的NFS客戶端(一些選項)

NFS客戶端可以指定一個以上,使用空白字元分隔。支援IP位址、主機名稱(hostname),可用星號表示任意數量的任意字元(wildcard)或是以小老鼠@開頭來使用NIS群組名稱。如果沒有指定允許存取的NFS客戶端的話,那麼任何的NFS客戶端都可以掛載這個檔案系統的目錄。這邊要注意的是,NFS客戶端的Linux作業系統的使用者和其所屬群組即為存取NFS伺服器檔案系統的使用者和其所屬群組,會以使用者的UID和GID來做對應,而不是名稱,如果NFS客戶端的UID或是GID並不在NFS伺服器中,就會被視為65534,代表「匿名者」(nobody)或是「匿名群組」(nogroup)。

例如:

/home/magiclen/shared-files 192.168.56.104(rw,sync,no_subtree_check) 192.168.100.0/24(ro,sync,no_subtree_check) *.magiclen.org(ro,sync,no_subtree_check)

注意選項的括號和NFS客戶端的名稱之間不可以有空格。括號中的選項,也不能使用空格。雖然NFS支援任意目錄的分享,但是分享的目錄路徑會直接影響到NFS客戶端要存取NFS伺服器端資源的路徑,因此通常我們會在NFS伺服器端上建立一個實體目錄(例如建立一個/exports目錄)作為分享目錄的根目錄,接著再把要分享的目錄給「綁定掛載」(mount --bind)到這個目錄的子目錄中(例如把/home/magiclen/shared-files綁定掛載到/exports/files上),再把綁定掛載後的目錄(例如/exports/files)讓NFS分享出去。

選項的部份,常用的設定項目如下:

  • rw允許讀寫。
  • ro唯讀。這個是預設值。
  • root_squashNFS的客戶端如果是root使用者(UID為0)或是root群組(GID=0),那麼NFS伺服器端會將其UID或是GID視為65534,代表「匿名者」或是「匿名群組」。這是預設值。
  • no_root_squashNFS的客戶端如果是root使用者或是root群組,就會直接在NFS伺服器上使用這個身份。
  • all_squashFS的客戶端如果不是root使用者或是root群組,NFS伺服器端會將其UID或是GID視為65534,代表「匿名者」或是「匿名群組」。
  • no_all_squashNFS的客戶端如果不是root使用者或是root群組,就會直接在NFS伺服器上使用這個身份。這是預設值。
  • no_subtree_check不進行子樹檢查(subtree_check)。當分享的目錄路徑不是整個檔案系統,而是其中的一個目錄的話,啟用「subtree_check」就可以在存取這個目錄的文件時,也去檢查其在檔案系統中上層目錄的權限,以及其在/etc/exports設定檔所形成的「exported tree」中的權限。
  • nohide「exported tree」中,如果某分享的目錄(例如「/exports/home」)是在另一個分享的目錄(例如/exports)之下,則這兩個目錄都需要被掛載,該分享的目錄(/exports/home)才可以被存取到。除非在該分享的目錄(/exports/home)選項中加上nohide,這樣才能使單純只掛載其上層目錄(/exports)時,也可以去存取到該分享的目錄(/exports/home)。
  • crossmnt這個選項可以讓該目錄在被掛載時,使其在「exported tree」中的下層目錄也自動加上nohide選項。換句話說,只要掛載上層目錄,就可以存取到下層目錄,下層目錄不必明確加上nohide選項。
  • fsid這個選項可以設定每個NFS的ID,大部分的情況下不需要自己設定ID。0或是root表示分享目錄的根目錄的ID,也就是說可以藉由設定fsid=0或是fsid=root,來讓某個目錄變成是NFS的根目錄。如果有透過綁定掛載來製作分享目錄的結構,可以使用這個選項把要當作根目錄的分享目錄(例如/exports)設定為NFS的目錄。

設定好/etc/exports後必須重新載入設定檔,可以使用以下指令來重新載入:

sudo exportfs -r

exportfs指令可以用來分享或是停止分享/etc/exports設定檔案所撰寫的檔案系統目錄。-a-r參數都可以用來重新載入設定檔,並分享所有設定檔內指定的檔案系統目錄。-ua參數用來停止分享所有目錄。

ubuntu-server-18-04-nfs

直接使用以下指令來查看目錄的分享狀態:

sudo exportfs

ubuntu-server-18-04-nfs

查看目前分享的目錄的掛載情形

使用showmount指令可以查看目前分享的目錄的掛載情形。

可以加上以下參數:

  • --exports查看目錄的分享狀態。
  • --directories顯示哪些目錄正在被掛載。
  • --all顯示哪些目錄正在被哪些客戶端名稱掛載。

如果未使用任何參數,則會顯示哪些哪些客戶端名稱正在掛載這個NFS伺服器上的檔案系統目錄。

NFS客戶端

安裝NFS客戶端

確認目前的Linux核心有啟用nfs模組後,就可以在Ubuntu Server的終端機下輸入以下指令來安裝NFS客戶端了!

sudo apt install nfs-common

ubuntu-server-18-04-nfs

掛載NFS

有了NFS客戶端後,就可以使用mount指令來手動掛載NFS了。檔案系統的部份必須使用nfs,指令格式如下:

sudo mount -t nfs NFS伺服器的主機名稱:分享的目錄路徑 掛載點

例如:

sudo mount -t nfs 192.168.56.103:/home/magiclen/shared-files /mnt/nfs

ubuntu-server-18-04-nfs

有需要的話,mount指令的-o參數可以設定NFS的掛載選項,常用的項目如下:

  • rw允許讀寫。
  • ro唯讀。
  • rsize設定每次從NFS客戶端傳給NFS伺服器的資料量,最常用的值為4096。愈可靠的網路可以將這個值設高一點,增加傳輸效率。
  • wsize設定每次從NFS伺服器傳給NFS客戶端的資料量,最常用的值為4096。愈可靠的網路可以將這個值設高一點,增加傳輸效率。
  • udp對於支援UDP和TCP的NFS第3版,可以指定要使用UDP來傳送檔案。
  • tcp對於支援UDP和TCP的NFS第3版,可以指定要使用TCP來傳送檔案。
  • nfsvers設定NFS伺服器的版本。
  • retry設定要允許多長的時間來重新嘗試掛載,單位是分鐘。預設值是10000分鐘。
  • timeo設定每次嘗試掛載時,經過多久就算是逾時,單位是0.1秒。預設值是0.7秒。
  • hard不管RPC逾時,一直嘗試掛載。為預設值。
  • soft嘗試掛載,直到RPC逾時。
  • fg在前景嘗試掛載。為預設值。
  • bg在背景嘗試掛載。
  • intr嘗試掛載時可以被使用者中斷。
  • nointr嘗試掛載時不可以被使用者中斷。為預設值。

如果要自動掛載的話,可以在/etc/fstab設定檔中加上如以下格式的資料:

NFS伺服器的主機名稱:分享的目錄路徑 掛載點 nfs _netdev 0 0

/etc/fstab設定檔的選項欄位中,_netdev可以讓該檔案系統在網路功能可以使用的時候才被掛載。

RPC資訊顯示

rpcinfo指令可以用來顯示RPC的資訊。使用以下指令可以顯示出所有已註冊給RPC的服務:

rpcinfo -p

ubuntu-server-18-04-nfs

以上指令還可以遠端使用,只要在-p後加上主機名稱即可。例如:

rpcinfo -p 192.168.56.103

ubuntu-server-18-04-nfs

如果要測試遠端的RPC的服務,可以使用-u或是-t參數再加上主機名稱即可,前者走UDP,後者走TCP。

ubuntu-server-18-04-nfs

RPC和NFS狀態顯示

nfsstat指令可以用來顯示RPC伺服器、RPC客戶端、NFS伺服器和NFS客戶端的狀態。

ubuntu-server-18-04-nfs

可以加上參數來控制到底要篩選的狀態。-sr參數,只顯示RPC伺服器的狀態。-cr參數,只顯示RPC客戶端的狀態。-sn參數,只顯示NFS伺服器的狀態。-cn參數,只顯示NFS客戶端的狀態。-s參數,只顯示RPC與NFS伺服器的狀態。-c參數,只顯示RPC與NFS客戶端的狀態。