NFS:使⽤ NFS 为远程客⼾端提供共享⽂件系统

对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的,是人的逃避方式,是对大众理想的懦弱回归,是随波逐流,是对内心的恐惧 ——赫尔曼·黑塞《德米安》

写在前面


  • 分享一些 nfs 搭建的笔记
  • 考试顺便整理
  • 内容涉及 nfs 服务端客户端的搭建配置
  • 理解不足小伙伴帮忙指正

对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的,是人的逃避方式,是对大众理想的懦弱回归,是随波逐流,是对内心的恐惧 ——赫尔曼·黑塞《德米安》


NFSNetwork File System 的缩写,即 网络文件系统。最早由Sun公司开发,用来在UNIX&Linux系统间实现磁盘文件共享的一种方法。它的主要功能是通过网络让不同的主机系统之间可以共享文件或目录。发展迭代了多个版本:

NFSv1(1984年):最早的 NFS 版本由 Sun Microsystems 开发。它基于远程过程调用(RPC)和XDR(External Data Representation)协议,使客户端能够通过网络挂载远程服务器上的共享目录。NFSv1 使用不透明句柄标识文件,并使用无状态协议,其中服务器不保持有关客户端状态的信息。

NFSv2(1989年):NFSv2 在 NFSv1 的基础上进行了改进。它引入了更强大的操作,如文件和目录的读写操作,并提供了更可靠的错误处理和更高效的数据传输。NFSv2 仍然使用不透明句柄标识文件,并保持无状态的特性。

NFSv3(1995年):NFSv3 是一个重大的改进版本,引入了许多新特性和改进。它支持透明的文件句柄,提供更好的安全性、性能和可靠性。NFSv3 引入了基于文件路径的标识符(filehandle)来替代不透明句柄,并支持文件锁定、符号链接、读写一致性和服务器端写缓存等功能。

NFSv4(2000年):NFSv4 是目前最新和最全面的 NFS 版本。它经历了多个修订版本的迭代,以提供更强大的功能和性能改进。NFSv4 引入了许多重要特性,如全面的安全性(包括 Kerberos 身份验证和加密传输)、访问控制列表(ACL)、命名空间、客户端缓存控制等。它还引入了复杂的状态管理,使服务器能够跟踪客户端的状态。

NFS客户端(一般为应用服务器,例如web) 可以通过挂载 (mount) 的方式将NFS服务端共享的数据目录挂载到NFS客户端本地系统中(就是某一个挂载点下) 。从NFS客户端的机器本地看,NFS服务端共享的目录就好像是客户自己的磁盘分区或者目录一样,而实际上确是远端的NFS服务端的目录。

在企业集群架构的工作场景中,NFS网络文件系统 一般被用来存储共享视频、图片、附件等静态资源文件。一般是把网站用户上传的文件都放在NFS共享里,例如,BBS产品的图片、附件、头像,特别是中小网站公司应用频率更高。

NFS的功能所使用的端口并不是固定的,而是在服务器启动时动态分配的,那么这样的话,客户端如何获得服务器端的相关端口呢?

NFS使用了一个称为rpcbind(或portmap)的服务,它充当了一个端口映射程序

当服务器端启动NFS服务时,它会向 rpcbind服务注册其提供的NFS功能及其对应的端口号客户端在需要连接到服务器端时,首先会向rpcbind服务发送查询请求,以获取服务器端所提供的NFS功能及其相应的端口号。

rpcbind 服务会返回服务器端注册NFS功能及其端口号信息给客户端。客户端接收到这些信息后,就可以使用相应的端口号与服务器端建立连接,并进行NFS数据传输。

rpcbind服务通常会使用固定的端口号 111 提供服务,因此客户端可以通过该固定端口号与服务器端进行通信,获取NFS功能及其端口号信息。

部署NFS服务

红帽企业Linux 8,默认使用NFS版本4.2,也可以使用NFSv4NFSv3协议,但不再支持NFSv2协议NFS版本4 (NFSv4) 仅使用TCP传输。

NFS服务由nfs-utils软件包提供,RHEL8默认安装了该软件包。

安装 nfs-utils 软件包。软件包可能已安装好。

1
2
3
4
5
6
7
[root@servera ~]# yum -y install nfs-utils
Red Hat Enterprise Linux 8.1 BaseOS (dvd) 83 kB/s | 2.8 kB 00:00
Red Hat Enterprise Linux 8.1 AppStream (dvd) 484 kB/s | 3.2 kB 00:00
Package nfs-utils-1:2.3.3-26.el8.x86_64 is already installed.
Dependencies resolved.
Nothing to do.
Complete!

配置开机自启动,同时需要开放对应的防火墙服务

1
2
3
4
5
6
7
[root@servera ~]# systemctl enable --now nfs-server.service
Created symlink /etc/systemd/system/multi-user.target.wants/nfs-server.service → /usr/lib/systemd/system/nfs-server.service.
[root@servera ~]# firewall-cmd --permanent --add-service=nfs
success
[root@servera ~]# firewall-cmd --reload
success
[root@servera ~]#

通过 man -k 命令查帮助文档, nfs 的使用关键字 exports 来进行一些常用配置,可以通过 man exports 查看具体的帮助信息

1
2
3
4
5
6
[root@servera ~]# man -k exports
exports (5) - NFS server export table
[root@servera ~]# man exports
[root@servera ~]# cat /etc/exports
[root@servera ~]# ls /etc/exports.d/
[root@servera ~]#

一般配置文件的编写有两个位置,一个是 /etc/exports 文件 ,另一个是 /etc/exports.d/ 目录下

  1. 创建 /nfsshare ⽬录并对其进⾏保护,以便只有 student 用户具有写⼊权限。

其他的配置要求:

  • student ⽤用户具有读/写访问权限,并且所有其他用户仅具有读取访问权限
  • 导出 /nfsshare ⽬录,以便只有servera.lab.example.com可以在读/写模式下挂载它。
  • 确保 lab.example.com DNS 域中的所有其他系统都可以在只读模式下挂载该共享导出。
  • 创建 /etc/exports.d/exercise.exports ⽂件。注意不要在服务器名称和选项之间添加空格((rw) 和 (ro))
1
2
3
4
5
6
[root@servera ~]# mkdir /nfsshare
[root@servera ~]# chown student /nfsshare
[root@servera ~]# ls -ld /nfsshare
drwxr-xr-x. 2 student root 6 Aug 1 00:07 /nfsshare
[root@servera ~]# cat /etc/exports.d/shar.exports
/nfsshare serverb.lab.example.com(rw) *.lab.example.com(ro)

修改完共享的配置之后,需要重新 reload 配置文件

1
[root@servera ~]# systemctl reload nfs-server

使⽤ exportfs 命令,确认 NFS 服务器正在导出 /nfsshare ⽬录。

1
2
3
[root@servera ~]# exportfs
/nfsshare servera.lab.example.com
/nfsshare *.lab.example.com

添加 -v 选项以显⽰导出选项的详细信息

1
2
3
4
[root@servera ~]# exportfs -v
/nfsshare servera.lab.example.com(sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,root_squash,no_all_squash)
/nfsshare *.lab.example.com(sync,wdelay,hide,no_subtree_check,sec=sys,ro,secure,root_squash,no_all_squash)
[root@servera ~]#
  • sync:表示同步写入,NFS服务器会在数据写入到磁盘之前等待确认,确保数据的持久性。这可以提供更高的数据一致性,但可能会对性能产生一定影响。
  • wdelay:表示写入延迟,NFS服务器可能会在写入数据时进行延迟,以缓冲多个写入请求并进行批量处理。这可以提高写入性能,但可能会增加数据的丢失风险。
  • hide:表示隐藏共享,NFS服务器会隐藏共享的文件或目录,使其对客户端不可见。这可以用于限制特定目录的访问权限。
  • no_subtree_check:表示禁用子树检查,NFS服务器不会检查客户端是否具有访问整个共享树的权限。这可以提高性能,但可能会降低安全性。
  • sec=sys:表示使用系统身份验证,NFS服务器使用本地系统的身份验证机制进行客户端身份验证。
  • rw:表示读写权限,客户端具有对NFS共享的读写权限。
  • secure:表示使用安全连接,NFS服务器和客户端之间的通信将通过安全的加密连接进行。
  • root_squash:表示Root映射,NFS服务器会将来自客户端的Root用户的访问权限限制为一个非特权用户,以增加安全性。
  • no_all_squash:表示禁用全部映射,NFS服务器会保留来自客户端的所有用户和组的身份,而不进行任何映射。

查看服务状态

1
[root@servera ~]# systemctl status  rpcbind.service

客户端配置使用

创建 /share 挂载点,并且挂载 servera 根目录 到 /mnt 下面

1
2
3
4
5
 创建 /share 挂载点。
[root@serverb ~]# mkdir /share
[root@serverb /]# mount servera:/ /mnt
[root@serverb /]# ls /mnt/
nfsshare

确认连通性OK,然后卸载之后,重新挂载访问

1
2
3
4
[root@serverb /]# umount /mnt
[root@serverb /]# mount -t nfs servera:/nfsshare /share
[root@serverb share]# cd /share/;touch temp
touch: cannot touch 'temp': Permission denied

创建文件失败,提示没有权限,这是因为我们在服务端只给了 student 的权限,所以这里会这样,而root 用户也没有权限,是因为默认开启了 root_squash ,root 被映射为一个非特权用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@serverb share]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 880M 0 880M 0% /dev
tmpfs 915M 0 915M 0% /dev/shm
tmpfs 915M 17M 899M 2% /run
tmpfs 915M 0 915M 0% /sys/fs/cgroup
/dev/vda1 10G 2.2G 7.9G 22% /
tmpfs 183M 0 183M 0% /run/user/1000
servera:/nfsshare 10G 2.3G 7.8G 23% /share
[root@serverb share]#
[root@serverb share]# su student
[student@serverb share]$ touch temp
[student@serverb share]$ ls
temp

切换到 student 用户,文件创建成功,可以通过 mount 来查看映射信息

1
2
3
4
[student@serverb share]$
[student@serverb share]$ mount | grep sha
servera:/nfsshare on /share type nfs4 (rw,relatime,vers=4.2,rsize=262144,wsize=262144,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=172.25.250.11,local_lock=none,addr=172.25.250.10)
[student@serverb share]$

如果希望开机自动挂载,编辑 /etc/fstab ⽂件,再为 NFS 导出添加⼀⾏,配置完成,需要使用 mount -a 来重新加载配置

1
servera.lab.example.com:/nfsshare /share nfs defaults 0 0

挂载⽂件系统,然后验证挂载是否成功

1
2
3
4
5
[root@serverb ~]# mount /share
[root@serverb share]# df /share/
Filesystem 1K-blocks Used Available Use% Mounted on
servera:/nfsshare 10474496 2319360 8155136 23% /share

确认 student 用户可以在⽬录中创建⽂件。

1
2
3
[root@serverb ~]# su - student -c "echo Hello World > /share/test.txt"
[root@serverb ~]# ls /share
test.txt

确认 serverb 上的 root 用户⽆法写⼊到导出。

1
2
[root@serverb ~]# echo Hello World > /share/root_test.txt
-bash: /share/root_test.txt: Permission denied

实战

serverd 上,创建要使⽤ NFS 导出的⽬录 /srv/operators。它应归用户 root 和 operators 所有。

  • 组 operators 应具有读/写访问权限,并且所有其他用户都不应具有访问权限
  • ⽬录应具有 setgid 权限集,因此在该⽬录中创建的⽂件将⾃动归该组所有

服务端配置:

1
2
3
4
5
6
[root@serverd ~]# mkdir /srv/operators
[root@serverd ~]# chgrp operators /srv/operators
[root@serverd ~]# chmod 2770 /srv/operators
[root@serverd ~]# ls -ld /srv/operators
drwxrws---. 2 root operators 6 Jul 6 22:19 /srv/operators
[root@serverd ~]#
  • 2:设置目录的setgid权限。这意味着在该目录下创建的文件将自动继承该目录的所属组
  • 7:表示设置目录的所有者权限为 rwx(读、写、执行)。
  • 7:表示设置目录的所属组权限为 rwx(读、写、执行)。
  • 0:表示设置目录的其他用户权限为无权限,即没有读、写、执行的权限。

serverd 上,根据以下要求使⽤ NFS 导出 /srv/operators ⽬录:

  • 只有 servera.lab.example.com 可以访问该共享
  • servera 具有对共享的读/写访问权限
  • 由于⽂件权限和root squash 设置,servera 上的 root 用户不能读取或写⼊该共享

安装工具包,配置编写导出文件,客户端主机名为 servera,访问权限为 rw.

1
2
3
4
[root@serverd ~]# yum install nfs-utils
[root@serverd exports.d]# cat share.exports
/srv/operators servera.lab.example.com(rw)
[root@serverd exports.d]#

配置开启自启动

1
2
3
4
5
6
7
[root@serverd exports.d]# systemctl enable nfs-server.service --now
Created symlink /etc/systemd/system/multi-user.target.wants/nfs-server.service → /usr/lib/systemd/system/nfs-server.service.
[root@serverd exports.d]# firewall-cmd --permanent --add-service=nfs
success
[root@serverd exports.d]# firewall-cmd --reload
success
[root@serverd exports.d]#

检索配置情况

1
2
3
[root@serverd exports.d]# exportfs -v
/srv/operators servera.lab.example.com(sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,root_squash,no_all_squash)
[root@serverd exports.d]#
1
2
3
4
[root@serverd exports.d]# logout
Connection to serverd closed.
[root@servera ~]# mkdir /operators_data
[root@servera ~]# vim /etc/fstab
1
serverd:/srv/operators nfs   defaults 0 0
1
2
3
4
5
6
[root@servera ~]# mount /operators_data
[root@servera ~]# df -h /operators_data
Filesystem Size Used Avail Use% Mounted on
serverd.lab.example.com:/srv/operators 10G 2.2G 7.9G 22% /operators_data
[root@servera ~]#

1
2
3
4
5
[root@servera ~]# cd /operators_data/
-bash: cd: /operators_data/: Permission denied
[root@servera ~]# su - operator1
[operator1@servera ~]$ cd /operators_data/
[operator1@servera operators_data]$

配置 NFS 服务(服务端报错排故)

servera配置NFS服务,要求如下:

  • 以只读的方式共享目录/public同时只能被example.com域中的系统访问
  • 以读写的方式共享目录/protected能被example.com域中的系统访问
  • 目录/protected应该包含名为project拥有人为student的子目录
  • 用户student能以读写方式访问/protected/project

servera 上面配置 nfs 导出。创建对应的目录,同时修改 project 的所有人为 student

[root@servera]

1
2
3
#-p, --parents
mkdir -p /public /protected/project
chown student /protected/project

查看帮助文档,exports 配置文件编写

1
2
3
# mandb && man -k nfs | grep 5
# man exports
# vim /etc/exports

需要注意读写权限

1
2
/public				*.example.com(ro)
/protected *.example.com(rw)

配置服务开机自启动,开启队对应的防火墙

1
2
3
4
5
# systemctl list-unit-files | grep nfs
# systemctl enable --now nfs-server

# firewall-cmd --permanent --add-service=nfs
# firewall-cmd --reload

到这一步,服务端已经配置完成,可以通过 exportfs -v 查看配置信息

客户端操作

[root@serverb]

showmount -e servera,用于显示远程主机(servera)上共享的文件系统。

客户端报错

1
2
# showmount -e servera
clnt_create: `RPC`: Unable to receive

报错信息提示我们没办法获取,RPC 的响应,前面我们讲过,nfs 客户端和服务端建立连接,使用 RPC 协议的 rpcbind 服务传递端口映射,所以我们需要放行 rpcbind 服务

所以需要在 servera 上面 做简单配置,开发对应的防火墙,通过 rpcinfo 命令可以查看当前机器的 rpcbind 服务,这里我们需要放行 111 端口

[root@servera]

1
2
3
4
5
6
# rpc<Tab><Tab>
# rpcinfo
program version netid address service owner
100000 4 tcp6 ::.0.111 `portmapper` superuser
100005 3 tcp6 ::.78.80 `mountd` superuser
...输出省略...
1
2
3
grep port.*mapper /etc/services
sunrpc 111/tcp `portmapper` `rpcbind` # RPC 4.0 portmapper TCP
sunrpc 111/udp `portmapper` `rpcbind` # RPC 4.0 portmapper UDP

当然也可以通过服务的方式,防火墙开放 rpc-bind 服务相关端口

1
2
# firewall-cmd --permanent --add-service=rpc-bind
# firewall-cmd --reload

[root@serverb ~]

开放之后回到客户机,任然提示报错

1
2
# showmount -e servera
rpc `mount` export: RPC: Unable to receive; errno = No route to host

这是因为我们同时需要开放 mountd 服务,回到服务端,添加 mountd 防火墙规则

mountd 是 NFS(Network File System)服务器上的一个守护进程,它在 NFS 的挂载过程中起着关键的作用,

  • 处理挂载请求:当客户端尝试挂载 NFS 共享时,它会向服务器上的 mountd 发送挂载请求。mountd 负责接收和处理这些请求,验证客户端的权限,并确保客户端有权访问所请求的共享目录。
  • 导出共享目录:mountd 通过导出(export)共享目录的方式,将其可用于其他主机挂载。在服务器上配置的共享目录需要在 mountd 的管理下,以便客户端能够访问和挂载这些共享。
  • 管理挂载点:mountd 跟踪服务器上已经挂载的共享,并提供有关挂载点的信息。这包括已经挂载的共享目录路径、客户端的 IP 地址等。
  • 挂载选项处理:mountd 处理挂载选项,如权限控制、访问控制列表(ACL)、并发访问控制等。它根据客户端请求中的选项参数,按照事先配置的规则进行处理,以确保挂载操作按照预期进行。
    [root@servera]
1
2
# firewall-cmd --permanent --add-service=mountd
# firewall-cmd --reload

[root@serverb ~]

1
2
3
4
# showmount -e servera
Export list for servera:
/protected *.example.com
/public *.example.com

挂载一个 NFS 共享

serverb上挂载一个来自servera的NFS共享,并符合下列要求:

  • /public挂载在下面的目录上/mnt/nfsmount
  • /protected挂载在下面的目录上/mnt/nfssecure
  • 用户student能够在/mnt/nfssecure/project上创建文件
  • 这些文件系统在系统启动时自动挂载

[root@serverb]

1
2
3
4
# showmount -e servera
Export list for servera:
/protected *.example.com
/public *.example.com
1
2
3
4
# mkdir /mnt/nfs{mount,secure}

# man fstab
# vim /etc/fstab

fstab 中编写挂载配置,这里需要注意读写权限要和上面的匹配

1
2
3
...输出省略...
servera:/public /mnt/nfsmount nfs ro 0 0
servera:/protected /mnt/nfssecure nfs rw 0 0

刷新配置

1
# mount –a

确认挂载信息,做读写测试

1
2
3
4
5
6
# df -h | grep nfs
servera:/public 10G 2.1G 7.9G 22% /mnt/nfsmount
servera:/protected 10G 2.1G 7.9G 22% /mnt/nfssecure

# ls /mnt/nfsmount
# su - student -c "touch /mnt/nfssecure/project/s.txt"

NFS 调优

NFS服务器端配置调优:

  • 增加NFS服务器的线程数和并发连接数,以处理更多的客户端请求。可以通过增大rpc.mountd和rpc.nfsd的线程数配置参数来实现。

    1
    2
    3
    # NFS Server Configuration
    RPCNFSDCOUNT=16 # 设置 rpc.nfsd 的线程数为 16
    RPCMOUNTDOPTS="-N 8" # 设置 rpc.mountd 的线程数为 8
  • 调整 NFS 服务器的读写缓存大小,以适应不同的工作负载。可以通过调整 rsize 和 wsize 参数来设置读写缓存的大小。

1
2
3
4
5
# NFS Client Configuration
rsize=8192 # 设置读取缓存大小为 8 KB
wsize=8192 # 设置写入缓存大小为 8 KB
nfsiodthreads=8 # 设置 nfsiod 线程数为 8
actimeo=300 # 设置客户端缓存的有效期为 300 秒
  • 启用服务器端的写缓存,以提高写入性能。可以通过设置async或sync参数来配置写入策略。
  • 配置服务器端的文件句柄缓存(File Handle Cache),以加速文件句柄的查找和访问。可以通过调整acdirmin和acdirmax参数来设置文件句柄缓存的大小。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # NFS Server Configuration
    RPCNFSDCOUNT=16 # 设置 rpc.nfsd 的线程数为 16
    RPCMOUNTDOPTS="-N 8" # 设置 rpc.mountd 的线程数为 8

    # 启用服务器端的写缓存
    RPCNFSDARGS="-N 16 -H 256" # 设置 rpc.nfsd 的线程数为 16,并设置文件句柄缓存的大小为 256

    # 配置文件句柄缓存的大小
    MOUNTD_NFS_ARGS="-F -n 8 -N 16 -H 256" # 设置 rpc.mountd 的线程数为 8,文件句柄缓存的大小为 256

NFS客户端配置调优:

  • 调整NFS客户端的读写缓存大小,以适应不同的工作负载。可以通过调整rsize和wsize参数来设置读写缓存的大小。
  • 增加NFS客户端的并发连接数,以提高并发性能。可以通过增大nfsiod线程数配置参数来实现。
  • 启用客户端的读写缓存,以减少与服务器的交互次数。可以通过设置actimeo参数来配置缓存的有效期。
  • 调整NFS客户端的超时设置,以适应网络延迟和可靠性需求。可以通过调整timeo和retrans参数来设置超时和重传次数。

网络配置调优:

  • 使用高速网络接口卡(NIC)和千兆以太网(Gigabit Ethernet)或更高的网络带宽,以提高NFS的传输性能。
  • 配置合适的网络拓扑和路由,以减少网络延迟和瓶颈。可以使用专用网络或VLAN来隔离NFS流量。
  • 调整NFS版本和传输协议,以适应网络环境。例如,使用NFSv4和TCP协议可以提供更好的性能和可靠性。

安全性和身份验证调优:

  • 配置合适的身份验证和授权机制,以确保只有合法用户能够访问NFS共享。可以使用Kerberos身份验证来提供更安全的访问控制。
  • 启用NFSv4的安全特性,如访问控制列表(ACL)和加密传输,以保护数据的安全性和完整性。

博文部分内容参考

© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知


<RH358 授课课堂笔记>


© 2018-至今 liruilonger@gmail.com, All rights reserved. 保持署名-非商用-相同方式共享(CC BY-NC-SA 4.0)

发布于

2023-07-05

更新于

2024-11-22

许可协议

评论
Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×