13.1 NFS 的由来与其功能
NFS 这个藉由网络分享文件系统的服务在架设的时候是很简单的,不过,它最大的问题在于『权限』方面的概念! 因为在客户端与服务器端可能必须要具备相同的账号才能够存取某些目录或档案。 另外,NFS 的启动需要透过所谓的远程过程调用 (RPC),也就是说,我们并不是只要启动 NFS 就好了, 还需要启动 RPC 这个服务才行啊!
因此,在开始进行 NFS 的设定之前,我们得先来了解一下,什么是 NFS 呢?不然讲了一堆也没有用,对吧! ^_^! 底下就来谈一谈什么是 NFS ,且 NFS 的启动还需要什么样的协议啊!
13.1.1 什么是 NFS (Network FileSystem)
NFS 就是 Network FileSystem 的缩写,最早之前是由 Sun 这家公司所发展出来的 (注1)。 它最大的功能就是可以透过网络,让不同的机器、不同的操作系统、可以彼此分享个别的档案 (share files)。所以,你也可以简单的将他看做是一个文件服务器 (file server) 呢!这个 NFS 服务器可以让你的 PC 来将网络远程的 NFS 服务器分享的目录,挂载到本地端的机器当中, 在本地端的机器看起来,那个远程主机的目录就好像是自己的一个磁盘分区槽一样 (partition)!使用上面相当的便利!
图 13.1-1、NFS 服务器分享目录与 Client 挂载示意图
就如同上面的图示一般,当我们的 NFS 服务器设定好了分享出来的 /home/sharefile 这个目录后,其他的 NFS 客户端就可以将这个目录挂载到自己系统上面的某个挂载点 (挂载点可以自定义),例如前面图示中的 NFS client 1 与 NFS client 2 挂载的目录就不相同。我只要在 NFS client 1 系统中进入 /home/data/sharefile 内,就可以看到 NFS 服务器系统内的 /home/sharefile 目录下的所有数据了 (当然,权限要足够啊!^_^)!这个 /home/data/sharefile 就好像 NFS client 1 自己机器里面的一个 partition 喔!只要权限对了,那么你可以使用 cp, cd, mv, rm... 等等磁盘或档案相关的指令!真是他 X 的方便吶!
好的,既然 NFS 是透过网络来进行数据的传输,那么经由第二章谈到的 socket pair 的概念你会知道 NFS 应该会使用一些埠口吧?那么 NFS 使用哪个埠口来进行传输呢?基本上 NFS 这个服务的埠口开在 2049 ,但是由于文件系统非常复杂,因此 NFS 还有其他的程序去启动额外的端口,但这些额外的端口启动的号码是? 答案是....不知道! @_@ !因为预设 NFS 用来传输的埠口是随机选择小于 1024 以下的埠口来使用的。咦!那客户端怎么知道你服务器端使用那个埠口啊?此时就得要 远程过程调用 (Remote Procedure Call, RPC) 的协定来辅助啦!底下我们就来谈谈什么是 RPC?
13.1.2 什么是 RPC (Remote Procedure Call)
因为 NFS 支持的功能相当的多,而不同的功能都会使用不同的程序来启动, 每启动一个功能就会启用一些端口来传输数据,因此, NFS 的功能所对应的端口才没有固定住, 而是随机取用一些未被使用的小于 1024 的埠口来作为传输之用。但如此一来又造成客户端想要连上服务器时的困扰, 因为客户端得要知道服务器端的相关埠口才能够联机吧!
此时我们就得需要远程过程调用 (RPC) 的服务啦!RPC 最主要的功能就是在指定每个 NFS 功能所对应的 port number ,并且回报给客户端,让客户端可以连结到正确的埠口上去。 那 RPC 又是如何知道每个 NFS 的埠口呢?这是因为当服务器在启动 NFS 时会随机取用数个埠口,并主动的向 RPC 注册,因此 RPC 可以知道每个埠口对应的 NFS 功能,然后 RPC 又是固定使用 port 111 来监听客户端的需求并回报客户端正确的埠口, 所以当然可以让 NFS 的启动更为轻松愉快了!
Tips: 所以你要注意,要启动 NFS 之前,RPC 就要先启动了,否则 NFS 会无法向 RPC 注册。 另外,RPC 若重新启动时,原本注册的数据会不见,因此 RPC 重新启动后,它管理的所有服务都需要重新启动来重新向 RPC 注册。
图 13.1-2、NFS 与 RPC 服务及文件系统操作的相关性
如上图所示,当客户端有 NFS 档案存取需求时,他会如何向服务器端要求数据呢?
- 客户端会向服务器端的 RPC (port 111) 发出 NFS 档案存取功能的询问要求;
- 服务器端找到对应的已注册的 NFS daemon 埠口后,会回报给客户端;
- 客户端了解正确的埠口后,就可以直接与 NFS daemon 来联机。
由于 NFS 的各项功能都必须要向 RPC 来注册,如此一来 RPC 才能了解 NFS 这个服务的各项功能之 port number, PID, NFS 在服务器所监听的 IP 等等,而客户端才能够透过 RPC 的询问找到正确对应的埠口。 也就是说,NFS 必须要有 RPC 存在时才能成功的提供服务,因此我们称 NFS 为 RPC server 的一种。事实上,有很多这样的服务器都是向 RPC 注册的,举例来说,NIS (Network Information Service) 也是 RPC server 的一种呢。此外,由图 13.1-2 你也会知道,不论是客户端还是服务器端,要使用 NFS 时,两者都需要启动 RPC 才行喔!
更多的 NFS 相关协议信息你可以参考底下网页:
- RFC 1094, NFS 协议解释 http://www.faqs.org/rfcs/rfc1094.html
- Linux NFS-HOWTO:http://www.tldp.org/HOWTO/NFS-HOWTO/index.html
13.1.3 NFS 启动的 RPC daemons
我们现在知道 NFS 服务器在启动的时候就得要向 RPC 注册,所以 NFS 服务器也被称为 RPC server 之一。 那么 NFS 服务器主要的任务是进行文件系统的分享,文件系统的分享则与权限有关。 所以 NFS 服务器启动时至少需要两个 daemons ,一个管理客户端是否能够登入的问题, 一个管理客户端能够取得的权限。如果你还想要管理 quota 的话,那么 NFS 还得要再加载其他的 RPC 程序就是了。我们以较单纯的 NFS 服务器来说:
rpc.nfsd: 最主要的 NFS 服务器服务提供商。这个 daemon 主要的功能就是在管理客户端是否能够使用服务器文件系统挂载信息等, 其中还包含这个登入者的 ID 的判别喔!
rpc.mountd 这个 daemon 主要的功能,则是在管理 NFS 的文件系统哩!当客户端顺利的通过 rpc.nfsd 而登入服务器之后,在他可以使用 NFS 服务器提供的档案之前,还会经过档案权限 (就是那个 -rwxrwxrwx 与 owner, group 那几个权限啦) 的认证程序!他会去读 NFS 的配置文件 /etc/exports 来比对客户端的权限,当通过这一关之后客户端就可以取得使用 NFS 档案的权限啦!(注:这个也是我们用来管理 NFS 分享之目录的权限与安全设定的地方哩!)
rpc.lockd (非必要) 这个玩意儿可以用在管理档案的锁定 (lock) 用途。为何档案需要『锁定』呢? 因为既然分享的 NFS 档案可以让客户端使用,那么当多个客户端同时尝试写入某个档案时, 就可能对于该档案造成一些问题啦!这个 rpc.lockd 则可以用来克服这个问题。 但 rpc.lockd 必须要同时在客户端与服务器端都开启才行喔!此外, rpc.lockd 也常与 rpc.statd 同时启用。
rpc.statd (非必要) 可以用来检查档案的一致性,与 rpc.lockd 有关!若发生因为客户端同时使用同一档案造成档案可能有所损毁时, rpc.statd 可以用来检测并尝试回复该档案。与 rpc.lockd 同样的,这个功能必须要在服务器端与客户端都启动才会生效。
上述这几个 RPC 所需要的程序,其实都已经写入到两个基本的服务启动脚本中了,那就是 nfs 以及 nfslock 啰! 亦即是在 /etc/init.d/nfs, /etc/init.d/nfslock,与服务器较有关的写入在 nfs 服务中,而与客户端的 rpc.lockd 之类的,就设定于 nfslock 服务中。
13.1.4 NFS 的档案访问权限
不知道你有没有想过这个问题,在图 13.1-1 的环境下,假如我在 NFS client 1 上面以 dmtsai 这个使用者身份想要去存取 /home/data/sharefile/ 这个来自 NFS server 所提供的文件系统时, 请问 NFS server 所提供的文件系统会让我以什么身份去存取?是 dmtsai 还是?
为什么会这么问呢?这是因为 NFS 本身的服务并没有进行身份登入的识别, 所以说,当你在客户端以 dmtsai 的身份想要存取服务器端的文件系统时, 服务器端会以客户端的使用者 UID 与 GID 等身份来尝试读取服务器端的文件系统。这时有个有趣的问题就产生啦! 那就是如果客户端与服务器端的使用者身份并不一致怎么办? 我们以底下这个图示来说明一下好了:
图 13.1-3、NFS 的服务器端与客户端的使用者身份确认机制
当我以 dmtsai 这个一般身份使用者要去存取来自服务器端的档案时,你要先注意到的是: 文件系统的 inode 所记录的属性为 UID, GID 而非账号与群组名。 那一般 Linux 主机会主动的以自己的 /etc/passwd, /etc/group 来查询对应的使用者、组名。 所以当 dmtsai 进入到该目录后,会参照 NFS client 1 的使用者与组名。 但是由于该目录的档案主要来自 NFS server ,所以可能就会发现几个情况:
NFS server/NFS client 刚好有相同的账号与群组 则此时使用者可以直接以 dmtsai 的身份进行服务器所提供的文件系统之存取。
NFS server 的 501 这个 UID 账号对应为 vbird 若 NFS 服务器上的 /etc/passwd 里面 UID 501 的使用者名称为 vbird 时, 则客户端的 dmtsai 可以存取服务器端的 vbird 这个使用者的档案喔!只因为两者具有相同的 UID 而已。这就造成很大的问题了!因为没有人可以保证客户端的 UID 所对应的账号会与服务器端相同, 那服务器所提供的数据不就可能会被错误的使用者乱改?
NFS server 并没有 501 这个 UID 另一个极端的情况是,在服务器端并没有 501 这个 UID 的存在,则此时 dmtsai 的身份在该目录下会被压缩成匿名者, 一般 NFS 的匿名者会以 UID 为 65534 为其使用者,早期的 Linux distributions 这个 65534 的账号名称通常是 nobody ,我们的 CentOS 则取名为 nfsnobody 。但有时也会有特殊的情况,例如在服务器端分享 /tmp 的情况下, dmtsain 的身份还是会保持 501 但建立的各项数据在服务器端来看,就会属于无拥有者的资料。
如果使用者身份是 root 时 有个比较特殊的使用者,那就是每个 Linux 主机都有的 UID 为 0 的 root 。 想一想,如果客户端可以用 root 的身份去存取服务器端的文件系统时,那服务器端的数据哪有什么保护性? 所以在预设的情况下, root 的身份会被主动的压缩成为匿名者。
总之,客户端使用者能做的事情是与 UID 及其 GID 有关的,那当客户端与服务器端的 UID 及账号的对应不一致时, 可能就会造成文件系统使用上的困扰,这个就是 NFS 文件系统在使用上面的一个很重要的地方! 而在了解使用者账号与 UID 及文件系统的关系之后,要实际在客户端以 NFS 取用服务器端的文件系统时, 你还得需要具有:
- NFS 服务器有开放可写入的权限 (与 /etc/exports 设定有关);
- 实际的档案权限具有可写入 (w) 的权限。
当你满足了 (1)使用者账号,亦即 UID 的相关身份; (2)NFS 服务器允许有写入的权限; (3)文件系统确实具有 w 的权限时,你才具有该档案的可写入权限喔! 尤其是身份 (UID) 确认的环节部分,最容易搞错啦!也因为如此, 所以 NFS 通常需要与 NIS (十四章) 这一个可以确认客户端与服务器端身份一致的服务搭配使用,以避免身份的错乱啊! ^_^
Tips: 老实说,这个小节的数据比较难懂~尤其是刚刚接触到 NFS server 的朋友。因此,你可以先略过 13.1.4 这个小节。 但是,在你读完与做完本章后续所有的实作之后,记得回到这个小节来再查阅一次文章内容,相信会有进一步的认识的!