NFS
NFS(Network File System,网络文件系统),它可以通过网络让不同操作系统,不同机器共享彼此的文件。
NFS 分为服务端和客户端。服务端提供共享的文件目录,客户端将该目录挂载到本地目录,从客户端上看,相当于是将磁盘分区挂载到目录,非常便利。
NFS 工作原理
NFS 工作原理如上图所示。其中,RPC 服务是 Remote Process Call 远程过程调用服务,它的出现主要是为了解决 NFS 端口无法固定的问题。由于文件系统非常复杂,NFS 中不同程序对应不同的功能,每个程序开启相应的功能会随机启用额外的端口。但是对于客户端来说,随机取用的端口,客户端无法获取到,所以就需要 RPC 服务作为“中介”,NFS 服务每次启用的端口信息,都会到 RPC 中注册(所以启动 NFS 服务之前要先确保 RPC 服务已经启动了)。同时,RPC 会提供一个固定的外部端口 111 供外部机器访问。这样客户端有 NFS 请求,服务端会通过 RPC 服务将 NFS 的端口信息告知客户端,从而实现客户端和服务端 NFS 的连接和数据传输。
NFS 的工作流程:
1. NFS 服务器端会启动 RPC 服务(portmap),并开启 111 端口。
2. NFS 服务器端再启动 NFS 服务,服务启动后向 RPC 服务注册端口信息。
3. 客户端启动 RPC 服务,向服务端的 RPC 服务请求服务端的 NFS 端口信息。
4. 服务端的 RPC 服务将端口信息发给客户端的 RPC 服务。
5. 客户端通过获取到的端口信息建议和服务端 NFS 的连接和数据的传输。
NFS 部署
NFS 程序
NFS 程序主要有 RPC 主程序 rpcbind 和 NFS 主程序 nfs-utils。
rpcbind: 如前所述,负责 port mapping 的工作。
nfs-utils: NFS 主程序,包含 rpc.nfsd / rpc.mount / rpc.locked / rpc.statd 等几个 damones 。
[root@test home]# ps -ef | egrep "rpc|nfs" root 487 2 0 Mar21 ? 00:00:00 [rpciod] rpc 65293 1 0 Mar21 ? 00:00:00 /sbin/rpcbind -w rpcuser 76183 1 0 Mar21 ? 00:00:00 /usr/sbin/rpc.statd --no-notify root 152992 567813 0 18:43 pts/0 00:00:00 grep -E --color=auto rpc|nfs root 757265 1 0 17:08 ? 00:00:00 /usr/sbin/rpc.idmapd root 757267 1 0 17:08 ? 00:00:00 /usr/sbin/rpc.mountd root 757272 2 0 17:08 ? 00:00:00 [nfsd4_callbacks] root 757278 2 0 17:08 ? 00:00:00 [nfsd] root 757279 2 0 17:08 ? 00:00:00 [nfsd] root 757280 2 0 17:08 ? 00:00:00 [nfsd] root 757281 2 0 17:08 ? 00:00:00 [nfsd] root 757282 2 0 17:08 ? 00:00:00 [nfsd] root 757283 2 0 17:08 ? 00:00:00 [nfsd] root 757284 2 0 17:08 ? 00:00:00 [nfsd] root 757285 2 0 17:08 ? 00:00:00 [nfsd]
每个 damones 负责的功能如下:
rpc.nfsd:管理客户端是否能使用服务端文件系统。包括判断用户登录 ID 等。
rpc.mountd:管理 NFS 文件系统。当客户端通过 rpc.nfsd 登入主机之后,rpc.mountd 通过读取 NFS 配置文件 /etc/exports 对客户端进行权限认证。当权限认证通过后,客户端即可以访问服务端文件系统。
rpc.locked:管理文件锁定问题。当多个用户读写同一份文件时可能会对文件造成一些问题,rpc.locked 即对文件进行保护,从而避免出现这样的问题,它是可选的。
rpc.statd:管理文件一致性问题。当多个用户同时使用文件造成文件损坏时,rpc.statd 可以检测并且尝试恢复该文件。
NFS 配置文件
NFS 的主要配置文件是 /etc/exports 文件。它的格式是
#共享目录 [客户端地址1(权限)] [客户端地址2(权限)] ...
其中,共享目录是服务端要共享给客户端的目录。客户端地址是可以建立 NFS 连接的客户端地址,可以是 ip ,可以是 cidr ,也可以是主机名 (前提是在 /etc/hosts 或者通过 DNS 可以查询到)。权限是客户端用户访问服务端文件系统所具有的权限,它包含以下几个参数:
参数命令
|
参数作用
|
rw
|
可读写
|
ro
|
只读权限
|
sync
|
请求或写入数据时,数据会同步写入到服务端硬盘,再返回
|
no_root_squas
|
对于客户端用户 root 不压缩。即客户端 root 可以以 root 身份来访问文件
|
root_squash
|
对客户端用户 root 压缩,将 root 身份压缩为 nobody
|
all_squash
|
对客户端所用用户压缩,默认将用户身份压缩为用户 nobody 和用户组 nobody。
可指定压缩用户的身份,但是需要客户端和服务端都有该用户,否则无法访问
|
anonuid
|
匿名的 uid,说明客户端以什么用户来访问服务端文件系统
|
anongid
|
匿名的 gid,说明客户端以什么用户组来访问服务端文件系统
|
举例:
/home/test 10.57.0.0/24(rw,sync,all_squash,anonuid=4300,anongid=4300),指
在 cidr 10.57.0.0/24 内的客户端主机,能够以 uid/gid 4300 的用户身份通过读写方式访问服务端 /home/test 目录。
NFS 还有两个文件是 /var/lib/nfs/etab 和 /var/lib/nfs/rmtab 。 etab 文件记录了 NFS 共享的文件目录的完整权限设定值。 rmtab 文件记录了共享目录被挂载情况。
NFS 命令
rpcinfo: 输出 RPC 记录的信息。
exportfs: 维护 NFS 文件系统表。通过 exportfs 命令可重新分享 /etc/exports 文件的目录,该命令用在服务端。
showmount:查看 NFS server 共享的目录资源,该命令主要用在客户端。
NFS 配置实例
配置 NFS 使得 cidr 10.57.0.0/24 内的客户端主机,能够以 uid/gid 4300 的用户身份通过读写方式访问服务端 /home/test 目录。
配置步骤如下:
1. 服务端,客户端安装 rpcbind 和 nfs-utils。
2. 启动 rpcbind 服务,启动 nfs 服务。
3. 服务端配置 /etc/exports 文件:/home/test 10.57.0.0/24(rw,sync,all_squash,anonuid=4300,anongid=4300)
4. 服务端关闭 iptables。关闭 iptables 是因为 NFS 随机开启的端口信息并不会写入到 iptables 中,所以需要手动写入(关于 iptables 可看这里),这里暴力一点直接将 iptables 关掉。SELiunx 有开的,可以将 SELiunx 关闭。
5. 客户端挂载服务端共享目录。
6. 新建文件测试是否配置是否生效。
1. 服务端,客户端安装 rpcbind 和 nfs-utils:
[root@test home]# rpm -qa | egrep "rpc|nfs" libnfsidmap-0.25-15.el7.x86_64 rpcbind-0.2.0-38.el7.x86_64 libtirpc-0.2.4-0.8.el7.x86_64 nfs-utils-1.3.0-0.33.el7.x86_64 xmlrpc-c-1.32.5-1905.svn2451.el7.x86_64 xmlrpc-c-client-1.32.5-1905.svn2451.el7.x86_64
已经安装好了,没安装的可通过 yum install rpcbind nfs-utils 命令安装。
2. 启动 rpcbind 服务,启动 nfs 服务:
[root@test home]# systemctl start rpcbind [root@test home]# systemctl start nfs [root@test test]# rpcinfo -p localhost program vers proto port service 100000 4 tcp 111 portmapper 100000 3 tcp 111 portmapper 100000 2 tcp 111 portmapper 100000 4 udp 111 portmapper 100000 3 udp 111 portmapper 100000 2 udp 111 portmapper 100024 1 udp 55860 status 100024 1 tcp 49019 status 100005 1 udp 20048 mountd 100005 1 tcp 20048 mountd 100005 2 udp 20048 mountd 100005 2 tcp 20048 mountd 100005 3 udp 20048 mountd 100005 3 tcp 20048 mountd 100003 3 tcp 2049 nfs 100003 4 tcp 2049 nfs 100227 3 tcp 2049 nfs_acl 100003 3 udp 2049 nfs 100003 4 udp 2049 nfs 100227 3 udp 2049 nfs_acl 100021 1 udp 36125 nlockmgr 100021 3 udp 36125 nlockmgr 100021 4 udp 36125 nlockmgr 100021 1 tcp 42363 nlockmgr 100021 3 tcp 42363 nlockmgr 100021 4 tcp 42363 nlockmgr
3. 服务端配置 /etc/exports 文件:
服务端:
[root@test test]# cat /etc/passwd | grep 4300 [root@test test]# cat /etc/group | grep 4300 [root@test test]# groupadd -g 4300 lianhuasheng [root@test test]# useradd -u 4300 -g 4300 lianhuasheng [root@test test]# cat /etc/passwd | grep lianhuasheng lianhuasheng:x:4300:4300::/home/lianhuasheng:/bin/bash [root@test home]# cat /etc/exports | grep 4300 /home/test 10.57.0.0/24(rw,sync,all_squash,anonuid=4300,anongid=4300) [root@test home]# systemctl restart nfs
客户端:
[root@test test]# cat /etc/passwd | grep 4300 [root@test test]# cat /etc/group | grep 4300 [root@test test]# groupadd -g 4300 lianhuasheng [root@test test]# useradd -u 4300 -g 4300 lianhuasheng [root@test test]# cat /etc/passwd | grep lianhuasheng lianhuasheng:x:4300:4300::/home/lianhuasheng:/bin/bash
如参数一节所述,服务端和客户端都需要配置相同的 uid 和 gid。同时,在重新写 exports 文件后,需要重启 nfs 服务使配置生效。
4. 关闭 iptables:
[root@test test]# systemctl stop iptables
5. 客户端挂载服务端共享目录:
[root@test lianhuasheng]# showmount -e 10.57.0.1 Export list for 10.57.0.1: /home/test 10.57.0.0/24 [root@test test]# mount -t nfs 10.57.0.1:/home/test /home/test/lianhuasheng/ [root@test home]# df -hT | grep lianhuasheng 10.57.0.1:/home/test nfs4 895G 849G 46G 95% /home/test/lianhuasheng
6. 新建文件测试是否配置是否生效:
客户端:
[root@test lianhuasheng]# touch nfs.log [root@test lianhuasheng]# ll total 0 -rw-r--r--. 1 lianhuasheng lianhuasheng 0 Mar 22 17:10 nfs.log
服务端:
[root@test test]# ll -h total 0 -rw-r--r--. 1 lianhuasheng lianhuasheng 0 Mar 22 17:10 nfs.log
客户端以 root 身份创建文件 nfs.log,文件所属用户和用户组被修改为 4300 对应的用户 lianhuasheng。服务端查看该文件所属用户和用户组为 lianhuasheng。
NFS Troubleshooting
1. 挂载出现 error:clnt_create: RPC: Port mapper failure - Unable to receive: errno 113 (No route to host)
出现这种 error 是由于客户端无法访问到服务端。可通过两种方式解决:
-
暴力一点直接将 iptables 服务关闭。
-
固定 NFS 端口,将端口信息写入 iptables 中,重启 iptables 服务。
参考连接见这里:
2. umount 文件时出现 error:umount:/mnt:target is busy
出现这个 error 时当前磁盘正在使用。可通过 lsof 命令 show 出使用该挂载目录的 PID:
[root@test lianhuasheng]# lsof /home/test/lianhuasheng/ COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME lsof 407987 root cwd DIR 0,549 21 1325440613 /home/test/lianhuasheng (10.57.0.1:/home/test) lsof 407988 root cwd DIR 0,549 21 1325440613 /home/test/lianhuasheng (10.57.0.1:/home/test) bash 682732 root cwd DIR 0,549 21 1325440613 /home/test/lianhuasheng (10.57.0.1:/home/test)
然后将此 PID kill 掉,重新 umount。
(完)