前言
說起NFS,我估計很多搞運維的兄弟都有一肚子話要說。這玩意兒吧,看起來簡單,用起來坑多,但是真正搞明白了又覺得挺香的。
前幾天有個朋友問我,說他們公司要搭建一個文件共享系統,問我推薦什么方案。我第一反應就是NFS,畢竟這貨在Linux環境下用了這么多年,雖然毛病不少,但勝在穩定可靠。結果這哥們兒一臉懵逼地看著我:“NFS是啥?”
好吧,看來有必要寫篇文章好好聊聊NFS了。我從2020年開始接觸這東西,到現在也算是愛恨交加了。今天就把我這些年踩過的坑和積累的經驗分享給大家。
NFS到底是個什么鬼
NFS全稱Network File System,網絡文件系統。簡單來說,就是讓你可以像訪問本地文件一樣訪問遠程服務器上的文件。聽起來很牛逼對吧?實際上原理也不復雜。
NFS的工作原理其實就是客戶端和服務端的通信。服務端把某個目錄"導出"(export),客戶端就可以把這個遠程目錄"掛載"(mount)到本地的某個掛載點上。掛載完成后,你在客戶端操作這個目錄,實際上就是在操作服務端的文件。
不過這里有個坑,NFS默認使用的是UDP協議,在網絡不穩定的環境下容易出問題。現在一般都推薦用TCP,雖然性能稍微差一點,但穩定性好很多。
搭建NFS服務的那些事兒
服務端配置
在CentOS系統上安裝NFS還是比較簡單的:
yum install -y nfs-utils rpcbind
安裝完成后需要啟動相關服務:
systemctl start rpcbind
systemctl start nfs-server
systemctl enable rpcbind
systemctl enable nfs-server
這里要注意一個細節,rpcbind必須先啟動,因為NFS依賴RPC服務。我之前就因為這個順序問題折騰了半天。
接下來就是配置導出目錄了,編輯/etc/exports
文件:
/data/share 192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check)
/home/backup 192.168.1.100(ro,sync,root_squash)
這個配置文件的語法看起來有點奇怪,但其實很好理解。第一行表示把/data/share
目錄共享給192.168.1.0/24網段的所有主機,權限是讀寫,同步寫入,不壓縮root權限。
說到權限配置,這里面的坑可不少。no_root_squash
這個選項要慎用,它允許客戶端的root用戶在NFS服務器上也有root權限。如果你的網絡環境不夠安全,這就是個巨大的安全隱患。
配置完成后,重新加載配置:
exportfs -ra
可以用exportfs -v
查看當前的導出狀態。
客戶端掛載
客戶端的配置相對簡單一些,同樣需要安裝nfs-utils:
yum install -y nfs-utils
然后就可以掛載了:
mount -t nfs 192.168.1.10:/data/share /mnt/nfs
不過我建議在掛載時指定一些參數:
mount -t nfs -o tcp,rsize=32768,wsize=32768,hard,intr 192.168.1.10:/data/share /mnt/nfs
這些參數的含義:
- tcp:使用TCP協議
- rsize/wsize:讀寫緩沖區大小
- hard:硬掛載,網絡中斷時會一直重試
- intr:允許中斷
如果要開機自動掛載,可以在/etc/fstab
中添加:
#添加完成一定要記得mount -a,檢查下配置是否正確!!!!
192.168.1.10:/data/share /mnt/nfs nfs tcp,rsize=32768,wsize=32768,hard,intr 0 0
性能調優這個老大難問題
NFS的性能一直是個讓人頭疼的問題。我記得有一次,業務部門抱怨說文件傳輸太慢了,讓我優化一下。當時我就想,這能有多慢?結果一測試,好家伙,傳輸速度只有幾MB/s,這在千兆網絡環境下簡直不能忍。
網絡層面的優化
網絡配置對NFS性能影響很大。我發現很多人在配置時都忽略了網絡參數的調整。
在服務端,可以增加NFS守護進程的數量:
# 編輯 /etc/sysconfig/nfs
RPCNFSDCOUNT=16
默認情況下,NFS只啟動8個守護進程,在高并發場景下明顯不夠用。我一般會根據CPU核心數來設置,比如16核的服務器就設置16個進程。
另外,網絡緩沖區的大小也很關鍵:
# 在 /etc/sysctl.conf 中添加
net.core.rmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_default = 262144
net.core.wmem_max = 16777216
存儲層面的考慮
NFS的性能很大程度上取決于底層存儲。如果你的服務器用的是機械硬盤,那性能肯定好不到哪里去。我之前在一個項目中,把NFS服務器的存儲從SATA硬盤換成SSD,性能提升了好幾倍。
文件系統的選擇也很重要。ext4雖然穩定,但在大文件和高并發場景下性能一般。如果條件允許,我更推薦使用XFS文件系統,特別是在處理大文件時。
掛載參數的調整
客戶端的掛載參數對性能影響也不小。我一般會這樣配置:
mount -t nfs -o tcp,rsize=65536,wsize=65536,hard,intr,timeo=14,intr 192.168.1.10:/data/share /mnt/nfs
rsize和wsize設置得大一些可以減少網絡往返次數,但也不能設置得太大,否則可能會出現網絡包分片的問題。
安全配置不能馬虎
NFS的安全性一直是個爭議話題。說實話,NFS在設計之初就沒有太多考慮安全問題,所以在使用時需要格外小心。
網絡層面的安全
最基本的安全措施就是限制訪問網段。在/etc/exports
中,一定要明確指定允許訪問的IP地址或網段,千萬不要使用通配符。
我見過有人這樣配置:
/data/share *(rw,sync,no_root_squash)
這簡直就是在裸奔!任何能訪問到你服務器的主機都可以掛載你的NFS共享,而且還有root權限。
正確的做法應該是:
/data/share 192.168.1.100(rw,sync,root_squash)
/data/share 192.168.1.101(rw,sync,root_squash)
防火墻配置
NFS使用的端口比較多,除了固定的111端口(rpcbind)和2049端口(nfs)外,還有一些隨機端口。為了方便防火墻配置,可以固定這些端口。
在/etc/sysconfig/nfs
中添加:
RQUOTAD_PORT=875
LOCKD_TCPPORT=32803
LOCKD_UDPPORT=32769
MOUNTD_PORT=892
STATD_PORT=662
然后在防火墻中開放這些端口:
firewall-cmd --permanent --add-port=111/tcp
firewall-cmd --permanent --add-port=2049/tcp
firewall-cmd --permanent --add-port=875/tcp
firewall-cmd --permanent --add-port=32803/tcp
firewall-cmd --permanent --add-port=32769/udp
firewall-cmd --permanent --add-port=892/tcp
firewall-cmd --permanent --add-port=662/tcp
firewall-cmd --reload
用戶權限管理
NFS的用戶權限管理是個比較復雜的話題。默認情況下,NFS會根據UID和GID來判斷用戶權限,這就要求客戶端和服務端的用戶ID必須一致。
在實際使用中,我一般會創建專門的NFS用戶:
# 在服務端和客戶端都創建相同的用戶
useradd -u 1001 nfsuser
然后把共享目錄的所有者設置為這個用戶:
chown -R nfsuser:nfsuser /data/share
故障排查的血淚經驗
搞NFS這么多年,遇到的奇葩問題不計其數。有些問題看起來很簡單,但排查起來卻讓人抓狂。
掛載失敗的常見原因
最常見的問題就是掛載失敗。每次遇到這種問題,我都會按照這個順序排查:
- 檢查網絡連通性
ping 192.168.1.10
telnet 192.168.1.10 2049
- 檢查服務狀態
systemctl status rpcbind
systemctl status nfs-server
- 檢查導出狀態
exportfs -v
showmount -e 192.168.1.10
有一次我遇到一個很奇怪的問題,showmount可以看到導出的目錄,但就是掛載不上。折騰了半天才發現是SELinux的問題。
setsebool -P nfs_export_all_rw 1
setsebool -P nfs_export_all_ro 1
性能問題的排查
性能問題相對比較難排查,因為影響因素太多了。我一般會從這幾個方面入手:
網絡層面,用iperf測試網絡帶寬:
# 服務端
iperf -s# 客戶端
iperf -c 192.168.1.10
存儲層面,用dd測試磁盤性能:
dd if=/dev/zero of=/data/share/testfile bs=1M count=1024
NFS層面,用nfsstat查看統計信息:
nfsstat -c # 客戶端統
nfsstat -s # 服務端統計
有一次我就是通過nfsstat發現了問題,客戶端的retrans(重傳)次數特別高,說明網絡有問題。后來發現是交換機的某個端口有故障。
文件鎖的詭異問題
NFS的文件鎖機制真的是讓人又愛又恨。理論上很美好,實際使用中問題一大堆。
我印象最深的一次是,有個應用程序在NFS上創建了文件鎖,結果服務器突然斷電了。重啟后,這個鎖就一直釋放不掉,導致應用程序無法正常工作。
當時試了各種方法,最后只能這樣解決:
# 停止相關服務
systemctl stop nfs-server
systemctl stop rpc-statd# 清理鎖文件
rm -rf /var/lib/nfs/sm/*
rm -rf /var/lib/nfs/sm.bak/*# 重啟服務
systemctl start rpc-statd
systemctl start nfs-server
不過這種方法比較暴力,會影響所有客戶端。在生產環境中要慎用!!!!!!!!!!!
實際應用場景的經驗分享
這么多年下來,我在不同的場景中都用過NFS,每種場景都有自己的特點和坑點。
Web服務器集群的文件共享
最常見的應用就是Web服務器集群了。多臺Web服務器需要共享靜態文件,比如圖片、CSS、JS等。
在這種場景下,我一般會這樣配置:
# 服務端導出配置
/var/www/html/static 192.168.1.0/24(ro,sync,root_squash,no_subtree_check)
注意這里用的是只讀權限,因為靜態文件一般不需要在Web服務器上修改。如果需要上傳文件,我會單獨配置一個可寫的目錄。
客戶端掛載時,我會使用這樣的參數:
mount -t nfs -o tcp,ro,rsize=32768,wsize=32768,hard,intr,noatime 192.168.1.10:/var/www/html/static /var/www/html/static
noatime參數很重要,它可以避免每次讀取文件時更新訪問時間,能顯著提升性能。
數據庫備份的存儲
另一個常見場景就是數據庫備份。我們有多臺數據庫服務器,需要把備份文件統一存儲到一個地方。
這種場景下,安全性比性能更重要:
# 服務端配置
/data/backup 192.168.1.100(rw,sync,root_squash,no_subtree_check)
/data/backup 192.168.1.101(rw,sync,root_squash,no_subtree_check)
客戶端掛載時,我會設置比較保守的參數:
mount -t nfs -o tcp,rw,rsize=8192,wsize=8192,hard,intr,timeo=30 192.168.1.10:/data/backup /backup
緩沖區設置得小一些,超時時間長一些,確保數據的完整性。
開發環境的代碼共享
在開發環境中,經常需要多個開發者共享代碼。這時候NFS就很方便了,大家都可以直接在自己的機器上編輯代碼。
不過這種場景下要注意權限問題。我一般會創建一個開發組:
groupadd -g 2000 developers
然后把所有開發者都加到這個組里,共享目錄的權限設置為組可寫:
chgrp -R developers /data/code
chmod -R g+w /data/code
NFS的替代方案思考
雖然我用NFS用了這么多年,但不得不承認,它確實有不少局限性。在某些場景下,其他方案可能更合適。
SSHFS的優勢
SSHFS基于SSH協議,安全性比NFS好很多。配置也特別簡單:
sshfs user@192.168.1.10:/data/share /mnt/sshfs
我在一些對安全性要求比較高的項目中會選擇SSHFS。雖然性能比NFS差一些,但勝在安全可靠。
分布式文件系統的崛起
現在越來越多的公司開始使用分布式文件系統,比如GlusterFS、CephFS等。這些系統在可用性和擴展性方面比NFS強很多。
我之前參與過一個項目,就是把原來的NFS系統遷移到GlusterFS。雖然遷移過程比較復雜,但遷移完成后,系統的可用性確實提升了不少。
對象存儲的興起
在云計算時代,對象存儲也是個不錯的選擇。比如AWS的S3、阿里云的OSS等。雖然訪問方式和傳統文件系統不太一樣,但在某些場景下更適合。
一些實用的小技巧
這些年積累了不少NFS使用的小技巧,分享給大家:
自動掛載的配置
手動掛載NFS比較麻煩,可以配置自動掛載。安裝autofs:
yum install -y autofs
編輯/etc/auto.master
:
/mnt/auto /etc/auto.nfs --timeout=60
創建/etc/auto.nfs
:
share -tcp,rw 192.168.1.10:/data/share
這樣,當你訪問/mnt/auto/share
時,系統會自動掛載NFS。
監控腳本的編寫
NFS服務的穩定性監控很重要,我寫了個簡單的監控腳本:
#!/bin/bash
NFS_SERVER="192.168.1.10"
NFS_PATH="/data/share"
MOUNT_POINT="/mnt/nfs"if ! mountpoint -q $MOUNT_POINT; thenecho "NFS not mounted, trying to mount..."mount -t nfs $NFS_SERVER:$NFS_PATH $MOUNT_POINT
fiif ! timeout 5 ls $MOUNT_POINT > /dev/null 2>&1; thenecho "NFS access failed, remounting..."umount -f $MOUNT_POINTmount -t nfs $NFS_SERVER:$NFS_PATH $MOUNT_POINT
fi
把這個腳本加到crontab里,每分鐘執行一次,可以自動處理一些常見的NFS問題。
性能測試的方法
想要知道NFS的性能如何,可以用這個簡單的測試:
# 寫入測試
time dd if=/dev/zero of=/mnt/nfs/testfile bs=1M count=1024# 讀取測試
echo 3 > /proc/sys/vm/drop_caches # 清理緩存
time dd if=/mnt/nfs/testfile of=/dev/null bs=1M
這個測試雖然簡單,但能大致反映NFS的性能水平。
踩過的坑和經驗教訓
說了這么多技術細節,最后想分享一些我踩過的坑,希望大家能避免。
不要忽視網絡質量
有一次,業務部門反映NFS訪問特別慢,我檢查了服務器配置、存儲性能,都沒問題。最后發現是網絡設備有問題,丟包率達到了5%。在這種網絡環境下,NFS的性能肯定好不了。
所以在部署NFS之前,一定要先測試網絡質量。
備份配置文件的重要性
還有一次,我在調整NFS配置時,不小心把/etc/exports
文件搞壞了。結果所有客戶端都掛載不上了,業務直接中斷。
幸好我有備份配置文件的習慣,很快就恢復了。從那以后,我每次修改配置前都會先備份:
cp /etc/exports /etc/exports.bak.$(date +%Y%m%d)
權限問題要提前規劃
NFS的權限管理比較復雜,如果不提前規劃好,后期會很麻煩。我建議在部署之前就把用戶權限體系設計好,包括用戶ID的分配、組的設置等。
監控和告警不能少
NFS服務雖然相對穩定,但也會出現各種問題。一定要做好監控和告警,及時發現問題。
我一般會監控這些指標:
- NFS服務的運行狀態
- 掛載點的可用性
- 網絡連通性
- 磁盤空間使用率
總結
寫了這么多,感覺還有很多東西沒有涉及到。NFS這個東西,說簡單也簡單,說復雜也復雜。關鍵是要在實踐中不斷積累經驗。
我的建議是:
- 在內網環境下使用,不要暴露到公網
- 做好安全配置,不要圖省事給過大權限
- 根據實際場景調整性能參數
- 做好監控和備份,及時發現和解決問題
- 在高可用要求的場景下考慮其他方案
NFS雖然有這樣那樣的問題,但在合適的場景下,它依然是個不錯的選擇。特別是在中小型企業的內網環境中,NFS的簡單易用還是很有優勢的。
當然,技術在不斷發展,新的文件共享方案也在不斷涌現。我們要保持學習的心態,根據實際需求選擇最合適的方案。
希望這篇文章能幫到正在使用或者準備使用NFS的朋友們。如果你們在使用過程中遇到什么問題,或者有更好的經驗分享,歡迎在評論區交流討論!
記得關注微信公眾號@運維躬行錄,我會持續分享更多實用的運維經驗和技術干貨。如果這篇文章對你有幫助,別忘了點贊轉發,讓更多的朋友看到!
公眾號:運維躬行錄
個人博客:躬行筆記