GlusterFS: Configuration and Setup w/ NFS-Ganesha for an HA NFS Cluster (Quick Start Guide)
This is a much shorter version of our troubleshooting article on NFS Ganesh we created earlier. This is meant as a quick start guide for those who just want to get this server up and running very quickly. The point of High Availabilty is that the best implement HA solutions never allow any outage to be noticed by the client. It's not the client's job to put up with the fallout of a failure, it's the sysadmins job to ensure they never have too. In this configuration, however, we will use a 3 node Gluster Cluster. In short, we'll be using the following techs to setup an HA configuration:
- GlusterFS
- NFS Ganesha
- CentOS 7
- HAPROXY
- keepalived
- firewalld
- selinux
Here's a summary configuration for this whole work. If you run into this particularly nasty error, visit the solution page here:
HOST | SETTING | DESCRIPTION |
---|---|---|
nfs01 / nfs02 / nfs03 |
Create and reserve some IP's for your hosts. We are using the FreeIPA project to provide DNS and Kerberos functionality here: 192.168.0.80 nfs-c01 (nfs01, nfs02, nfs03) VIP DNS Entry
192.168.0.131 nfs01 |
Add the hosts to your DNS server for a clean setup. Alternately add them to /etc/hosts (ugly) |
nfs01 / nfs02 / nfs03 |
PACKAGES You can use the packages directly. Since version 2.6.X, Ganesha supports binding only on specific interfaces and has been introduced in the latest RPM packages. yum install nfs-ganesha.x86_64 nfs-ganesha-gluster.x86_64 nfs-ganesha-proxy.x86_64 nfs-ganesha-utils.x86_64 nfs-ganesha-vfs.x86_64 nfs-ganesha-xfs.x86_64 nfs-ganesha-mount-9P.x86_64 COMPILING We used this method because we needed a feature that allows binding the service only on specific ports, at the time only available from the latest source releases. wget https://github.com/nfs-ganesha/nfs-ganesha/archive/V2.6-.0.tar.gz
[root@nfs01 ~]# ganesha.nfsd -v DETAILED INSTRUCTIONS: https://github.com/nfs-ganesha/nfs-ganesha/wiki/Compiling
https://github.com/nfs-ganesha/nfs-ganesha/wiki/GLUSTER PACKAGES:
yum install glusterfs-api-devel.x86_64 COMMANDS
git clone https://github.com/nfs-ganesha/nfs-ganesha.git |
Compile and build nfsganesha 2.60+ from source. (At this time RPM packages did not work) Install the listed packages before compiling as well. |
nfs01 / nfs02 / nfs03 | Add a disk to the VM such as /dev/sdb . |
Add secondary disk for the shared GlusterFS |
nfs01 / nfs02 / nfs03 |
Create the FS on the new disk and mount it and setup Gluster:
mkfs.xfs /dev/sdb Gluster currently ships in version 4.1. This won't work with Ganesha. Use either the repo or continue installing the latest version of Gluster:
# cat CentOS-Gluster-3.13.repo
[centos-gluster313]
[centos-gluster313-test] Alternately to the above, use the following to install the latest repo: yum install centos-release-gluster Install and enable the rest:
yum -y install glusterfs glusterfs-fuse glusterfs-server glusterfs-api glusterfs-cli On node01 ONLY if creating brand new: gluster volume create gv01 replica 2 nfs01:/bricks/0/gv01 nfs02:/bricks/0/gv01
gluster volume info gv01 Replace bricks:
Unreachable brick: Reachable brick:
gluster volume remove-brick gv01 replica X nfs01:/bricks/0/gv01 start Add subsequent bricks:
(from existing cluster member ) Mount the storage locally:
systemctl disable autofs Example below. Add to /etc/fstab as well:
[root@nfs01 ~]# mount -t glusterfs nfs01:/gv01 /n Ex: nfs01:/gv01 /n glusterfs defaults 0 0 Ensure the following options are set on the gluster volume:
[root@nfs01 glusterfs]# gluster volume set gv01 cluster.quorum-type auto Here is an example Gluster volume configuration we used (This config is replicated when adding new bricks):
cluster.server-quorum-type: server
|
Configure the GlusterFS filesystem using |
nfs01 / nfs02 / nfs03 |
PACKAGES: /etc/haproxy/haproxy.cfg:
global
defaults
listen stats Set logging settings for HAProxy:
# cat /etc/rsyslog.d/haproxy.conf Configure rsyslogd (/etc/rsyslog.conf):
local0.* /var/log/haproxy.log
|
Install and Configure HAPROXY. A great source that helped with this part. |
nfs01 / nfs02 / nfs03 |
# echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf # echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf # sysctl -p net.ipv4.ip_nonlocal_bind = 1 net.ipv4.ip_forward = 1 # |
Turn on kernel parameters. These allow keepalived below to function properly. |
nfs01 / nfs02 / nfs03 |
PACKAGES: yum install keepalived # ( Used 1.3.5-1.el7.x86_64 in this case ) NFS01:
vrrp_script chk_haproxy {
vrrp_instance nfs-c01 {
authentication {
virtual_ipaddress {
track_script { NFS02:
vrrp_script chk_haproxy {
vrrp_instance nfs-c01 {
authentication {
virtual_ipaddress {
track_script { NFS03:
vrrp_script chk_haproxy {
vrrp_instance nfs-c01 {
authentication {
virtual_ipaddress {
track_script { Configure extended logging and corresponding log rotation for keepalived:
[root@nfs03 log]# cat /etc/sysconfig/keepalived
[root@nfs03 log]# cat /etc/logrotate.d/keepalived [root@nfs03 log]# Logrotate the log file: [root@nfs03 log]# logrotate /etc/logrotate.d/keepalived -v |
Configure keepalived. A great source that helped with this as well. |
nfs01 / nfs02 / nfs03 |
This step can be made quicker by copying the xml definitions from one host to the other if you already have one defined:
/etc/firewalld/zones/dmz.xml Contents of above:
# cat dmz.xml
# cat public.xml
Individual setup: # cat public.bash firewall-cmd –zone=public –permanent –add-port=2049/tcp firewall-cmd –zone=public –permanent –add-port=111/tcp firewall-cmd –zone=public –permanent –add-port=111/udp firewall-cmd –zone=public –permanent –add-port=24007-24008/tcp firewall-cmd –zone=public –permanent –add-port=49152/tcp firewall-cmd –zone=public –permanent –add-port=38465-38469/tcp firewall-cmd –zone=public –permanent –add-port=4501/tcp firewall-cmd –zone=public –permanent –add-port=4501/udp firewall-cmd –zone=public –permanent –add-port=24007-24008/tcp firewall-cmd –zone=public –permanent –add-port=24007-24008/udp firewall-cmd –zone=public –permanent –add-port=49152-49156/tcp firewall-cmd –zone=public –permanent –add-port=49152-49156/udp firewall-cmd –reload # cat dmz.bash firewall-cmd –zone=dmz –permanent –add-port=2049/tcp firewall-cmd –zone=dmz –permanent –add-port=111/tcp firewall-cmd –zone=dmz –permanent –add-port=111/udp firewall-cmd –zone=dmz –permanent –add-port=24007-24008/tcp firewall-cmd –zone=dmz –permanent –add-port=24007-24008/udp firewall-cmd –zone=dmz –permanent –add-port=49152-49156/tcp firewall-cmd –zone=dmz –permanent –add-port=49152-49156/udp firewall-cmd –zone=dmz –permanent –add-port=49152/tcp firewall-cmd –zone=dmz –permanent –add-port=38465-38469/tcp firewall-cmd –zone=dmz –permanent –add-port=4501/tcp firewall-cmd –zone=dmz –permanent –add-port=4501/udp firewall-cmd –zone=dmz –permanent –add-port=20048/tcp firewall-cmd –zone=dmz –permanent –add-port=20048/udp firewall-cmd –reload # # On Both
firewall-cmd –permanent –direct –add-rule ipv4 filter INPUT 0 -m pkttype –pkt-type multicast -j ACCEPT FINAL FILE:
# vi /etc/firewalld/zones/public.xml HANDY STUFF:
firewall-cmd –zone=dmz –list-all |
Configure firewalld. DO NOT disable firewalld . |
nfs01 / nfs02 / nfs03 |
Run any of the following command, or a combination of, on deny entries in /var/log/audit/audit.log that may appear as you stop, start or install above services:
METHOD 1:
METHOD 2: USEFULL THINGS:
ausearch –interpret |
Configure selinux. Don't disable it. This actually makes your host safer and is actually easy to work with using just these commands. |
nfs01 / nfs02 / nfs03 |
NODE 1:
[root@nfs01 ~]# cat /etc/ganesha/ganesha.conf
#
# logging directives–be careful
Facility {
NFSv4 {
NFS_KRB5 {
%include "/etc/ganesha/export.conf"
[root@nfs01 ~]# cat /etc/ganesha/export.conf
EXPORT {
FSAL {
Access_type = RW; # Access permissions
NODE 2:
# cat /etc/ganesha/ganesha.conf
# logging directives–be careful
Facility {
NFSv4 {
NFS_KRB5 {
%include "/etc/ganesha/export.conf"
FSAL {
Access_type = RW; # Access permissions
NODE 3:
[root@nfs03 ~]# cat /etc/ganesha/ganesha.conf
Facility {
NFSv4 {
NFS_Core_Param {
%include "/etc/ganesha/export.conf"
FSAL {
Access_type = RW; # Access permissions
STARTUP:
systemctl start nfs-ganesha |
Configure NFS Ganesha |
nfs01 / nfs02 / nfs03 |
[root@nfs01 ~]# cat /etc/fstab|grep -Ei "brick|gv01"
[root@nfs01 ~]# mount|grep -Ei "brick|gv01"
[root@nfs01 ~]# ps -ef|grep -Ei "haproxy|keepalived|ganesha"; netstat -pnlt|grep -Ei "haproxy|ganesha|keepalived"
|
Ensure mounts are done and everything is started up. |
nfs01 / nfs02 / nfs03 |
yumdownloader nfs-ganesha.x86_64 Copy above to the same folders under / instead of ./ :
systemctl enable nfs-ganesha.service |
Since you compiled from source you don't have nice startup scripts. To get your nice startup scripts from an existing ganesha RPM do the following. Then use systemctl to stop and start nfs-ganesha as you would any other service. |
ANY |
Enable dumps:
gluster volume set gv01 server.statedump-path /var/log/glusterfs/ |
Enable state dumps for issue isolation. |
Enable Samba / SMB for Windows File Sharing ( Optional ) |
Packages:
samba-common-4.7.1-6.el7.noarch
# cat /etc/samba/smb.conf|grep NFS -A 12 Start the service after enabling it:
systemctl enable smb Samba permissions to access NFS directories, fusefs and allow export. Likewise for fusefs filesystems:
# setsebool -P samba_share_fusefs on Likewise, for NFS shares, you'll need the following to allow sharing out of NFS shares:
# setsebool -P samba_share_nfs on And some firewalls ports to go along with it:
firewall-cmd –zone=public –permanent –add-port=445/tcp |
We can also enable SMB / Samba file sharing on the individual cluster hosts and allow visibility to the Gluster FS / NFS – Ganesha from Windows. |
nfs01 / nfs02 / nfs03 |
Referencing this post, we will import a few principals from the master IPA server. (For the KDC steps, see the reference post.): On the IPA server, issue the following to permission retrieveal of principals on clients: [root@idmipa01 ~]# ipa service-add nfs/nfs03.nix.mds.xyz
[root@idmipa01 ~]# ipa service-allow-retrieve-keytab nfs/nfs-c01.nix.mds.xyz@NIX.MDS.XYZ –groups=admins
[root@idmipa01 ~]# ipa service-allow-retrieve-keytab nfs/nfs01.nix.mds.xyz@NIX.MDS.XYZ –groups=admins
[root@idmipa01 ~]# ipa service-allow-retrieve-keytab nfs/nfs03.nix.mds.xyz –hosts=nfs01.nix.mds.xyz On the target client issue the following:
[root@nfs01 ~]# kinit admin # Or the user you permissioned above.
|
Pull in principals from your IPA / KDC Server. |
nfs01 / nfs02 / nfs03 |
Check the HAProxy GUI to see the full status report: http://nfs-c01:9000/haproxy-stats |
Verify the cluster. |
nfs01 / nfs02 / nfs03 |
Configure log rotation for the ganesha log files. They can get big.
[root@nfs03 ganesha]# cat /etc/logrotate.d/ganesha
/var/log/ganesha/ganesha-rgw.log { [root@nfs03 ganesha]# Manually rotate the log file: [root@nfs03 ganesha]# logrotate /etc/logrotate.d/ganesha -v Distribute the log rotate file to the other nodes. |
Log Rotation Setup |
Now let's do some checks on our NFS HA. Mount the share using the VIP from a client then create a test file:
[root@ipaclient01 /]# mount -t nfs4 nfs-c01:/n /n
[root@ipaclient01 n]# echo -ne "Hacked It. Gluster, NFS Ganesha, HAPROXY, keepalived scalable NFS server." > some-people-find-this-awesome.txt
[root@ipaclient01 n]# mount|grep nfs4
nfs-c01:/n on /n type nfs4 (rw,relatime,vers=4.0,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=192.168.0.236,local_lock=none,addr=192.168.0.80)
[root@ipaclient01 n]#
Then check each brick to see if the file was replicated:
[root@nfs01 n]# cat /bricks/0/gv01/some-people-find-this-awesome.txt
Hacked It. Gluster, NFS Ganesha, HAPROXY, keepalived scalable NFS server.
[root@nfs01 n]# mount|grep -Ei gv01
nfs01:/gv01 on /n type fuse.glusterfs (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=131072)
[root@nfs01 n]#
[root@nfs02 n]# cat /bricks/0/gv01/some-people-find-this-awesome.txt
Hacked It. Gluster, NFS Ganesha, HAPROXY, keepalived scalable NFS server.
[root@nfs02 n]# mount|grep -Ei gv01
nfs02:/gv01 on /n type fuse.glusterfs (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=131072)
[root@nfs02 n]#
Good! Now let's hard shutdown one node, nfs01, the primary node. Expected behaviour is that we need to see failover to nfs02 and then when we bring back the nfs01 server, we need to see the file is replicated. While we do this, the client ipaclient01 is not supposed to loose any connection to the NFS mount via the VIP. Here are the results:
[root@nfs02 n]# ps -ef|grep -Ei "haproxy|ganesha|keepalived"
root 12245 1 0 Feb19 ? 00:00:03 /usr/sbin/keepalived -D
root 12246 12245 0 Feb19 ? 00:00:03 /usr/sbin/keepalived -D
root 12247 12245 0 Feb19 ? 00:00:41 /usr/sbin/keepalived -D
root 12409 1 16 Feb20 ? 00:13:05 /usr/bin/ganesha.nfsd -L /var/log/ganesha/ganesha.log -f /etc/ganesha/ganesha.conf -N NIV_EVENT
root 17892 1 0 00:37 ? 00:00:00 /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
haproxy 17893 17892 0 00:37 ? 00:00:00 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
haproxy 17894 17893 0 00:37 ? 00:00:00 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
root 17918 21084 0 00:38 pts/0 00:00:00 grep –color=auto -Ei haproxy|ganesha|keepalived
[root@nfs02 n]# ps -ef|grep -Ei "haproxy|ganesha|keepalived"; netstat -pnlt|grep -Ei ganesha; netstat -pnlt|grep -Ei haproxy; netstat -pnlt|grep -Ei keepalived
root 12245 1 0 Feb19 ? 00:00:03 /usr/sbin/keepalived -D
root 12246 12245 0 Feb19 ? 00:00:03 /usr/sbin/keepalived -D
root 12247 12245 0 Feb19 ? 00:00:41 /usr/sbin/keepalived -D
root 12409 1 16 Feb20 ? 00:13:09 /usr/bin/ganesha.nfsd -L /var/log/ganesha/ganesha.log -f /etc/ganesha/ganesha.conf -N NIV_EVENT
root 17892 1 0 00:37 ? 00:00:00 /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
haproxy 17893 17892 0 00:37 ? 00:00:00 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
haproxy 17894 17893 0 00:37 ? 00:00:00 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
root 17947 21084 0 00:38 pts/0 00:00:00 grep –color=auto -Ei haproxy|ganesha|keepalived
tcp6 0 0 192.168.0.119:20048 :::* LISTEN 12409/ganesha.nfsd
tcp6 0 0 :::564 :::* LISTEN 12409/ganesha.nfsd
tcp6 0 0 192.168.0.119:4501 :::* LISTEN 12409/ganesha.nfsd
tcp6 0 0 192.168.0.119:2049 :::* LISTEN 12409/ganesha.nfsd
tcp6 0 0 192.168.0.119:38468 :::* LISTEN 12409/ganesha.nfsd
tcp 0 0 192.168.0.80:2049 0.0.0.0:* LISTEN 17894/haproxy
[root@nfs02 n]#
[root@nfs02 n]#
[root@nfs02 n]#
[root@nfs02 n]# ssh nfs-c01
Password:
Last login: Wed Feb 21 00:37:28 2018 from nfs-c01.nix.mine.dom
[root@nfs02 ~]# logout
Connection to nfs-c01 closed.
[root@nfs02 n]#
From client we can still see all the files (seemless with no interruption to the NFS service). As a bonus, while we started this first test, we noticed that HAPROXY was offline on nfs02. While trying to list the client files, it appeared hung but still responded then listed files right after we started HAPROXY on nfs02:
[root@ipaclient01 n]# ls -altri some-people-find-this-awesome.txt
11782527620043058273 -rw-r–r–. 1 nobody nobody 74 Feb 21 00:26 some-people-find-this-awesome.txt
[root@ipaclient01 n]# df -h .
Filesystem Size Used Avail Use% Mounted on
nfs-c01:/n 128G 43M 128G 1% /n
[root@ipaclient01 n]# ssh nfs-c01
Password:
Last login: Wed Feb 21 00:41:06 2018 from nfs-c01.nix.mine.dom
[root@nfs02 ~]#
Checking the gluster volume on nfs02:
[root@nfs02 n]# gluster volume status
Status of volume: gv01
Gluster process TCP Port RDMA Port Online Pid
——————————————————————————
Brick nfs02:/bricks/0/gv01 49152 0 Y 16103
Self-heal Daemon on localhost N/A N/A Y 16094
Task Status of Volume gv01
——————————————————————————
There are no active volume tasks
[root@nfs02 n]#
Now let's bring back the first node and fail the second after nfs01 is up again. As soon as we bring nfs01 back up, the VIP fails over to nfs01 without any hickup or manual invervention on the client end:
[root@ipaclient01 n]# ls -altri
total 11
128 dr-xr-xr-x. 21 root root 4096 Feb 18 22:24 ..
11782527620043058273 -rw-r–r–. 1 nobody nobody 74 Feb 21 00:26 some-people-find-this-awesome.txt
1 drwxr-xr-x. 3 nobody nobody 4096 Feb 21 00:26 .
[root@ipaclient01 n]#
[root@ipaclient01 n]#
[root@ipaclient01 n]#
[root@ipaclient01 n]# ssh nfs-c01
Password:
Last login: Wed Feb 21 00:59:56 2018
[root@nfs01 ~]#
So now let's fail the second node. NFS still works:
[root@ipaclient01 ~]# ssh nfs-c01
Password:
Last login: Wed Feb 21 01:31:50 2018
[root@nfs01 ~]# logout
Connection to nfs-c01 closed.
[root@ipaclient01 ~]# cd /n
[root@ipaclient01 n]# ls -altri some-people-find-this-awesome.txt
11782527620043058273 -rw-r–r–. 1 nobody nobody 74 Feb 21 00:26 some-people-find-this-awesome.txt
[root@ipaclient01 n]# df -h .
Filesystem Size Used Avail Use% Mounted on
nfs-c01:/n 128G 43M 128G 1% /n
[root@ipaclient01 n]#
So we bring the second node back up. And that concludes the configuration! All works like a charm!
You can also check out our guest post for the same on loadbalancer.org!
Good Luck!
Cheers,
Tom K.
[…] you run into Auditd / Permission issues, use the following page for reference to resolve them. It may take a few […]