NFS锁相关的问题
前言
问题的来源是对nfs的共享目录的锁控制问题,关于共享的文件系统,通常有两种需求
需求一
需要有一个共同的锁,然后客户端的软件会判断锁在哪台机器上面,然后根据这个来进行服务的管理
需求二
使用共同的文件,客户端相互之间不能有锁,否则服务无法同时启动,那么需要高可用的时候,可能存在问题
本篇就是根据实际情况,我们来看怎么处理nfs服务,怎么样能够开启锁,怎么用关闭锁,这个根据实际情况进行配置
实践
准备三台机器,一台服务器进行nfs的数据的共享,另外两台机器同时去访问这个共享目录,使用的是nfs v3
lab201 nfs服务端
lab202 nfs客户端
lab203 nfs客户端
在lab201配置nfs服务
[root@lab201 ~]# chmod 777 /nfsshare/
[root@lab201 ~]# cat /etc/exports
/nfsshare *(fsid=123,no_root_squash,async,no_subtree_check,rw)
在lab202和lab203同时使用默认参数挂载nfs服务
[root@lab202 ~]# mount -t nfs -o v3 192.168.0.201:/nfsshare /mnt
[root@lab203 ~]# mount -t nfs -o v3 192.168.0.201:/nfsshare /mnt
查看挂载参数
192.168.0.201:/nfsshare on /mnt type nfs (rw,relatime,vers=3,rsize=524288,wsize=524288,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=192.168.0.201,mountvers=3,mountport=892,mountproto=udp,local_lock=none,addr=192.168.0.201)
查看服务端的
[root@lab201 ~]# systemctl status rpc-statd
● rpc-statd.service - NFS status monitor for NFSv2/3 locking.
Loaded: loaded (/usr/lib/systemd/system/rpc-statd.service; static; vendor preset: disabled)
Active: active (running) since Fri 2021-10-08 14:52:07 CST; 2min 25s ago
Process: 8400 ExecStart=/usr/sbin/rpc.statd $STATDARGS (code=exited, status=0/SUCCESS)
Main PID: 8405 (rpc.statd)
Tasks: 1
CGroup: /system.slice/rpc-statd.service
└─8405 /usr/sbin/rpc.statd -p 662 -o 2020
Oct 08 14:52:07 lab201 systemd[1]: Starting NFS status monitor for NFSv2/3 locking....
Oct 08 14:52:07 lab201 rpc.statd[8405]: Version 1.3.0 starting
Oct 08 14:52:07 lab201 rpc.statd[8405]: Flags: TI-RPC
Oct 08 14:52:07 lab201 systemd[1]: Started NFS status monitor for NFSv2/3 locking..
这里介绍下,nfs的多个客户端同时挂载的时候是通过rpc-statd这个服务来处理多台机器的锁的情况的,默认就是通过这个服务来加锁的,也就是远程锁
如果有锁的时候是什么情况,我们看下
在lab202上面运行服务,并且对文件加锁
[root@lab202 mnt]# flock lockfile -c top
这个时候top的命令是有输出的,并且文件是加上锁了,我们在另外一台机器lab203上面执行
[root@lab203 mnt]# flock lockfile -c top
可以看到,这个命令并没有输出,处于一直卡着的状态,这个是在等待lockfile释放以后,这个命令就可以输出了,我们去中断下lab202上面刚刚的命令
下面的lab203的命令马上有输出了,这个时候就是正常的开启了远程锁的情况
既然我们知道上面的rpc-statd是管理锁的,我们把那个服务停止掉,看下什么情况
注意操作步骤如下:
- 卸载客户端
- 重启nfs服务
- 关闭rpc-statd
- 挂载客户端
必须上面的操作步骤
然后即使一台机器执行,也会报下面的,无法上锁
[root@lab202 mnt]# flock lockfile -c top
flock: lockfile: No locks available
这种情况实际上是有问题的,也就是默认的挂载把锁交给了远端nfs server,但是远端无法上锁,所以就出现提示无法上锁
我们验证服务
把mysql的数据放到上面这种配置的没有锁的目录里面
[root@lab202 mariadb]# df -h /var/lib/mysql/
Filesystem Size Used Avail Use% Mounted on
192.168.0.201:/nfsshare 80G 68G 13G 84% /var/lib/mysql
[root@lab202 mariadb]# ls /var/lib/mysql/
aria_log.00000001 ibdata1 ib_logfile1 mysql test
aria_log_control ib_logfile0 lockfile performance_schema
启动服务,可以看到卡住
[root@lab202 mysql]# systemctl start mariadb
我们查看日志
[root@lab202 mariadb]# tail -n 50 /var/log/mariadb/mariadb.log
211008 15:07:07 InnoDB: Using Linux native AIO
211008 15:07:07 InnoDB: Initializing buffer pool, size = 128.0M
211008 15:07:07 InnoDB: Completed initialization of buffer pool
InnoDB: Unable to lock ./ibdata1, error: 37
211008 15:07:13 InnoDB: Retrying to lock the first data file
InnoDB: Unable to lock ./ibdata1, error: 37
InnoDB: Unable to lock ./ibdata1, error: 37
InnoDB: Unable to lock ./ibdata1, error: 37
可以看到这个地方,即使一台机器的mysql,这个服务也是无法启动的,所以我们可以得到一个结论,mysql服务启动是需要对文件上锁的
然后我们现在远端没有提供锁,这个服务就无法启动,但是如果启动锁,那么如果要两台服务器启动,不可能同时拿到远程锁
那么这个地方的处理,应该就只有一种情况了,我们需要让每个客户端自己去处理自己的锁的情况,远端的锁,启动和不启动不影响客户端这边,并且远端的锁有的时候通过内核lockd进行的提供,并没有关闭的地方,nfs是通过客户端这边进行控制,提供了挂载参数处理这种情况
我们看下说明比较清楚
[root@lab202 ~]# man 5 nfs
lock / nolock Selects whether to use the NLM sideband protocol to lock files on the
server. If neither option is specified (or if lock is specified), NLM lock‐
ing is used for this mount point. When using the nolock option, applica‐
tions can lock files, but such locks provide exclusion only against other
applications running on the same client. Remote applications are not
affected by these locks.
NLM locking must be disabled with the nolock option when using NFS to mount
/var because /var contains files used by the NLM implementation on Linux.
Using the nolock option is also required when mounting exports on NFS
servers that do not support the NLM protocol.
可以看下内容,默认会开启nlm的锁,如果没添加挂载参数的话,如果使用了nolock,那么跨机器之间的锁是没影响的,本机器的锁由本机器来提供
/var/目录进行挂载nfs的时候,需要使用nolock,因为里面包含了一些nlm锁没有实现的功能
也就是通过nolock来挂载/var/lib/mysql服务,由本地机器提供锁相关的
再次挂载
[root@lab202 ~]# mount -t nfs -o v3,nolock 192.168.0.201:/nfsshare /var/lib/mysql/
[root@lab202 ~]# mount|grep mysql
192.168.0.201:/nfsshare on /var/lib/mysql type nfs (rw,relatime,vers=3,rsize=524288,wsize=524288,namlen=255,hard,nolock,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=192.168.0.201,mountvers=3,mountport=892,mountproto=udp,local_lock=all,addr=192.168.0.201)
再次启动mysql,可以正常启动
[root@lab202 ~]# systemctl start mariadb
我们在另外一台机器上面把mysql挂载起来,可以看到直接可以启动
目前两台机器上面都是以nolock进行的挂载,我们继续之前的flock测试
在lab202上面开两个终端
运行
flock lockfile -c top
在lab203上面开一个终端运行
flock lockfile -c top
可以看到lab202与lab203能够同时运行成功,lab202另外一个终端运行会卡住等待,这里说明本地锁是成功的,跨机器是没有锁的,也就是我们需要运行两台机器mysql的模式
我们查看上面的挂载参数的时候可以看到
默认的挂载参数里面的,local_lock=none,而加上了nolock之后,local_lock=all,自动修正为这个选项了,也就是本地锁
我们看下这块的参数解释
[root@lab202 ~]# man 5 nfs
local_lock=mechanism
Specifies whether to use local locking for any or both of the flock and the
POSIX locking mechanisms. mechanism can be one of all, flock, posix, or
none. This option is supported in kernels 2.6.37 and later.
The Linux NFS client provides a way to make locks local. This means, the
applications can lock files, but such locks provide exclusion only against
other applications running on the same client. Remote applications are not
affected by these locks.
If this option is not specified, or if none is specified, the client assumes
that the locks are not local.
If all is specified, the client assumes that both flock and POSIX locks are
local.
If flock is specified, the client assumes that only flock locks are local
and uses NLM sideband protocol to lock files when POSIX locks are used.
If posix is specified, the client assumes that POSIX locks are local and
uses NLM sideband protocol to lock files when flock locks are used.
To support legacy flock behavior similar to that of NFS clients < 2.6.12,
use 'local_lock=flock'. This option is required when exporting NFS mounts
via Samba as Samba maps Windows share mode locks as flock. Since NFS clients
> 2.6.12 implement flock by emulating POSIX locks, this will result in con‐
flicting locks.
NOTE: When used together, the 'local_lock' mount option will be overridden
by 'nolock'/'lock' mount option.
可以看到,如果指定了本地,锁就用本地锁,不指定,就默认不用本地锁,如果指定了nolock选项,会覆盖这个选项
我们试下不指定nolock,直接指定local_lock的效果
[root@lab202 ~]# mount -t nfs -o v3,local_lock=all 192.168.0.201:/nfsshare /var/lib/mysql/
[root@lab202 ~]# mount |grep mysql
192.168.0.201:/nfsshare on /var/lib/mysql type nfs (rw,relatime,vers=3,rsize=524288,wsize=524288,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=192.168.0.201,mountvers=3,mountport=892,mountproto=udp,local_lock=all,addr=192.168.0.201)
通过flock命令进行测试,可以看到与nolock的效果一致
总结
我们使用nfs的时候,如果需要用到锁
首先判断,是需要本地锁还是远程锁
如果远程锁,需要看下rpc-statd服务是否正常启动,提供远程锁服务
如果是本地锁,那么需要检查local_lock=all这个是否开启,或者nolock与local_lock=all是否同时开启
通过上面的flock命令可以快速判断锁的情况
备注
nfs v3的锁是通过nlm协议处理的,nfs v4的锁是nfs 自己处理的,本篇所说的都是nfs v3的