Thank you for reading this post, don't forget to subscribe!
Отказоустойчивость файлового хранилища достигается посредством HAProxy, который переключает трафик между доступными хостами и Lsyncd, который выполняет репликацию данных между нодами. В данной реализации HAProxy каждые 10 секунд проверяет доступность серверов, перечисленных в директивах backend be_nfs_*. В случае если основной сервер окажется недоступным, то трафик переключается на резервный, при этом репликация файлов между всеми нодами NFS сервера работает постоянно.
имеем следующие сервера:
nfs-haproxy-151 - 192.168.1.151 тут будет стоять haproxy keepalived(192.168.1.150)
nfs-haproxy-152 - 192.168.1.152 тут будет стоять haproxy keepalived(192.168.1.150)
nfs-153 - 192.168.1.153 тут будет стоять nfs server
nfs-154 - 192.168.1.154 тут будет стоять nfs server
[root@nfs-haproxy-151 ~]# yum install keepalived -y
[root@nfs-haproxy-152 ~]# yum install keepalived -y
[root@nfs-haproxy-151 ~]# cat /etc/keepalived/keepalived.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
global_defs { notification_email { mid@test.ru } notification_email_from Andrey@test.ru smtp_server localhost smtp_connect_timeout 30 router_id centos1 } vrrp_instance VI_1 { state MASTER interface enp0s3 virtual_router_id 51 priority 100 advert_int 4 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.150 dev enp0s3 label enp0s3:vip } } |
[root@hfs-haproxy-152 ~]# cat /etc/keepalived/keepalived.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
global_defs { notification_email { mid@test.ru } notification_email_from Andrey@test.ru smtp_server localhost smtp_connect_timeout 30 router_id centos1 } vrrp_instance VI_1 { state BACKUP interface enp0s3 virtual_router_id 51 priority 99 advert_int 4 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.150 dev enp0s3 label enp0s3:vip } } |
[root@nfs-haproxy-151 ~]# echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf
[root@nfs-haproxy-151 ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
[root@nfs-haproxy-151 ~]# sysctl -p
[root@nfs-haproxy-152 ~]# echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf
[root@nfs-haproxy-152 ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
[root@nfs-haproxy-152 ~]# sysctl -p
[root@nfs-haproxy-151 ~]# systemctl enable keepalived && systemctl start keepalived
[root@nfs-haproxy-152 ~]# systemctl enable keepalived && systemctl start keepalived
теперь ставим haproxy
[root@nfs-haproxy-151 ~]# yum install haproxy -y
[root@hfs-haproxy-152 ~]# yum install haproxy -y
конфиг хапрокси одинаковый на 2х тачках:
[root@nfs-haproxy-151 ~]# cat /etc/haproxy/haproxy.cfg
[root@nfs-haproxy-152 ~]# cat /etc/haproxy/haproxy.cfg
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
#--------------------------------------------------------------------- # Example configuration for a possible web application. See the # full configuration options online. # # http://haproxy.1wt.eu/download/1.4/doc/configuration.txt # #--------------------------------------------------------------------- #--------------------------------------------------------------------- # Global settings #--------------------------------------------------------------------- global # to have these messages end up in /var/log/haproxy.log you will # need to: # # 1) configure syslog to accept network log events. This is done # by adding the '-r' option to the SYSLOGD_OPTIONS in # /etc/sysconfig/syslog # # 2) configure local2 events to go to the /var/log/haproxy.log # file. A line like the following can be added to # /etc/sysconfig/syslog # # local2.* /var/log/haproxy.log # log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon # turn on stats unix socket stats socket /var/lib/haproxy/stats #--------------------------------------------------------------------- # common defaults that all the 'listen' and 'backend' sections will # use if not designated in their block #--------------------------------------------------------------------- defaults mode tcp log global option tcplog option dontlognull option http-server-close option redispatch retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 20s timeout server 20s timeout http-keep-alive 10s timeout check 10s maxconn 3000 #--------------------------------------------------------------------- # main frontend which proxys to the backends #--------------------------------------------------------------------- frontend main_static *:5000 acl url_static path_beg -i /static /images /javascript /stylesheets acl url_static path_end -i .jpg .gif .png .css .js use_backend static if url_static default_backend app #--------------------------------------------------------------------- # static backend for serving up images, stylesheets and such #--------------------------------------------------------------------- backend static balance roundrobin server static 127.0.0.1:4331 check #--------------------------------------------------------------------- # round robin balancing between the various backends #--------------------------------------------------------------------- backend app balance roundrobin server app1 127.0.0.1:5001 check server app2 127.0.0.1:5002 check server app3 127.0.0.1:5003 check server app4 127.0.0.1:5004 check frontend main bind 192.168.1.150:2049 bind 192.168.1.150:111 bind 192.168.1.150:20048 mode tcp option tcplog acl nfs_2049 dst_port 2049 acl nfs_111 dst_port 111 acl nfs_20048 dst_port 20048 use_backend be_nfs_2049 if nfs_2049 use_backend be_nfs_111 if nfs_111 use_backend be_nfs_20048 if nfs_20048 backend be_nfs_2049 mode tcp server nfs1 192.168.1.153:2049 check server nfs2 192.168.1.154:2049 check backup backend be_nfs_111 mode tcp server nfs1 192.168.1.153:111 check port 2049 server nfs2 192.168.1.154:111 backup check port 2049 backend be_nfs_20048 mode tcp server nfs1 192.168.1.153:20048 check port 2049 server nfs2 192.168.1.154:20048 backup check port 2049 |
[root@nfs-haproxy-151 ~]# systemctl enable haproxy && systemctl start haproxy
[root@nfs-haproxy-152 ~]# systemctl enable haproxy && systemctl start haproxy
перейдём к настройке nfs
ставим nfs:
[root@nfs-153 ~]# yum -y install nfs-utils
[root@nfs-154 ~]# yum -y install nfs-utils
добавляем раздел для nfs:
pvcreate /dev/sdb
vgextend centos /dev/sdb
mkdir /nfs
lvcreate -n nfs -l 100%FREE centos
mkfs.ext4 /dev/mapper/centos-nfs
mount /dev/mapper/centos-nfs /nfs
cat /etc/fstab | grep nfs
/dev/mapper/centos-nfs /nfs ext4 defaults 1 2
[root@nfs-153 ~]# mkdir /nfs/data
[root@nfs-153 ~]# mkdir /nfs/tmp
[root@nfs-154 ~]# mkdir /nfs/data
[root@nfs-154 ~]# mkdir /nfs/tmp
[root@nfs-153 ~]# chown -R nfsnobody:nfsnobody /nfs/
[root@nfs-154 ~]# chown -R nfsnobody:nfsnobody /nfs/
[root@nfs-153 ~]# echo "/nfs/data *(rw,sync,all_squash,insecure,fsid=0)" >> /etc/exports
[root@nfs-154 ~]# echo "/nfs/data *(rw,sync,all_squash,insecure,fsid=0)" >> /etc/exports
«*»можно заменить на указание подсети, содержащей серверы приложений (в виде x.y.z.w/n).
[root@nfs-153 ~]# exportfs -a
[root@nfs-154 ~]# exportfs -a
[root@nfs-153 ~]# systemctl enable nfs-server && systemctl start nfs-server
[root@nfs-154 ~]# systemctl enable nfs-server && systemctl start nfs-server
перейдём к настройке lsync
Lsyncd просматривает дерево локальных директорий с помощью интерфейса модуля мониторинга Inotify. Он агрегирует и комбинирует события за несколько секунд и затем запускает процесс (или несколько процессов) синхронизации изменений. По умолчанию для этих целей используется rsync. Таким образом, Lyncd – легковесное решение для зеркалирования данных, сравнительно легкое в установке, не требующее специфичных файловых систем или блочных устройств, а также не влияющее на производительность файловой системы.
[root@nfs-153 ~]# yum -y install lsyncd
[root@nfs-154 ~]# yum -y install lsyncd
создайте директорию для конфигурационного файла и логов:
[root@nfs-153 ~]# mkdir -p /etc/lsyncd
[root@nfs-153 ~]# mkdir -p /var/log/lsyncd
[root@nfs-154 ~]# mkdir -p /etc/lsyncd
[root@nfs-154 ~]# mkdir -p /var/log/lsyncd
создайте пользователя, назначьте пароль, назначьте права на каталог для пользователя и сгенерируйте для него SSH-ключи - этот шаг выполните на всех нодах выполняющих роль NFS-сервера:
[root@nfs-153 ~]# mkdir -p /var/log/lsyncd
[root@nfs-153 ~]# adduser nfssync
[root@nfs-153 ~]# setfacl -R -m u:nfssync:rwx /nfs/
[root@nfs-153 ~]# setfacl -R -d -m u:nfssync:rwx /nfs/
[root@nfs-153 ~]# setfacl -R -m u:nfssync:rwx /nfs/
[root@nfs-153 ~]# passwd nfssync #ввести и подтвердить пароль, пароль можно использовать произвольный
[root@nfs-153 ~]# su - nfssync -c "ssh-keygen -t rsa"
#далее на всех пунктах нажать Enter
[root@nfs-154 ~]# mkdir -p /var/log/lsyncd
[root@nfs-154 ~]# adduser nfssync
[root@nfs-154 ~]# setfacl -R -m u:nfssync:rwx /nfs/
[root@nfs-154 ~]# setfacl -R -d -m u:nfssync:rwx /nfs/
[root@nfs-154 ~]# setfacl -R -m u:nfssync:rwx /nfs/
[root@nfs-154 ~]# passwd nfssync
[root@nfs-154 ~]# su - nfssync -c "ssh-keygen -t rsa"
скопируйте ключи на все ноды, со всех хостов выполняющих роль NFS-сервера:
[root@nfs-153 ~]# su - nfssync
[nfssync@nfs-153 ~]$ ssh-copy-id nfssync@192.168.1.154
[root@nfs-154 ~]# su - nfssync
[nfssync@nfs-154 ~]$ ssh-copy-id nfssync@192.168.1.153
Примечание
– Необходимо будет ввести пароль пользователя nfssync на ноде к которой будет осуществляться подключение.
создайте и отредактируйте файл
/etc/lsyncd.conf
следующим образом на всех нодах. В случае если нод более 2х, добавьте блок sync {} для последующих серверов:
[root@nfs-153 ~]# cat /etc/lsyncd.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
settings { logfile = "/var/log/lsyncd/lsyncd.log", statusFile = "/var/log/lsyncd/lsyncd.status", statusInterval = 1, nodaemon = true, insist = true } sync { default.rsyncssh, source = "/nfs/data/", host = "nfssync@192.168.1.154", targetdir = "/nfs/data", rsync = { rsh = "/usr/bin/ssh -l nfssync -i /home/nfssync/.ssh/id_rsa -o StrictHostKeyChecking=no", _extra = { "--temp-dir=/nfs/tmp/"}, perms = true, archive = true, compress = true, acls = true, owner = true }, delay = 1, delete = 'running', } |
[root@nfs-154 ~]# cat /etc/lsyncd.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
settings { logfile = "/var/log/lsyncd/lsyncd.log", statusFile = "/var/log/lsyncd/lsyncd.status", statusInterval = 1, nodaemon = true, insist = true } sync { default.rsyncssh, source = "/nfs/data/", host = "nfssync@192.168.1.153", targetdir = "/nfs/data", rsync = { rsh = "/usr/bin/ssh -l nfssync -i /home/nfssync/.ssh/id_rsa -o StrictHostKeyChecking=no", _extra = { "--temp-dir=/nfs/tmp/"}, perms = true, archive = true, compress = true, acls = true, owner = true }, delay = 1, delete = 'running', } |
[root@nfs-153 ~]# systemctl enable lsyncd && systemctl start lsyncd
[root@nfs-154 ~]# systemctl enable lsyncd && systemctl start lsyncd
теперь подключим шару через наш кластер.
ставим клиента и подключаем шару:
[root@ansible ~]# yum install nfs-utils -y
[root@ansible ~]# mkdir /nfs
[root@ansible ~]# mount 192.168.1.150:/nfs/data /nfs
проверяем:
[root@ansible ~]# touch /nfs/file1
[root@nfs-153 ~]# ll /nfs/data/
total 0
-rw-rw-r--+ 1 nfsnobody nfsnobody 0 Jan 17 22:04 file1
[root@nfs-154 ~]# ll /nfs/data/
total 0
-rw-rw-r--+ 1 nfssync nfssync 0 Jan 17 22:04 file1
теперь проведём ряд тестов при падении узлов:
- первым положим 192.168.1.153 (в haproxy он является основным)
[root@nfs-153 ~]# poweroff
создаём второй файл на клиенте:
[root@ansible ~]# touch /nfs/file-from-client2
и смотрим что файл создался на шаре:
[root@nfs-154 ~]# ll /nfs/data/
total 0
-rw-rw-r--+ 1 nfssync nfssync 0 Jan 17 22:04 file1
-rw-rw-r--+ 1 nfsnobody nfsnobody 0 Jan 17 22:06 file-from-client2
как видим он создался с владельцем и группой nfsnobody а не nfssync как при реплицировании.
теперь включим основной сервер nfs и глянем что произойдёт.
как ниже видим, второй файл засинковался:
[root@nfs-153 ~]# ll /nfs/data/
total 0
-rw-rw-r--+ 1 nfsnobody nfsnobody 0 Jan 17 22:04 file1
-rw-rw-r--+ 1 nfssync nfssync 0 Jan 17 22:06 file-from-client2
отсюда вывод можно спокойно ложить один из nfs серверов, после его включения на него будут подкинуты файлы.
2. теперь проверим что будет если положить сервак с хапрокси на котором виртуальный айпишник.
[root@nfs-haproxy-151 ~]# poweroff
проверяем что айпишник переехал:
[root@hfs-haproxy-152 ~]# ip a | grep vip
inet 192.168.1.150/32 scope global enp0s3:vip
смотрим на клиенте подмонтированную директорию:
[root@ansible ~]# ll /nfs/
total 0
-rw-rw-r--+ 1 nfsnobody nfsnobody 0 Jan 17 22:04 file1
-rw-rw-r--+ 1 1004 1004 0 Jan 17 22:06 file-from-client2
всё ок, создаём новый файл:
[root@ansible ~]# touch /nfs/22
ииии всё ок, файл создан:
[root@ansible ~]# ll /nfs/
total 0
-rw-rw-r--+ 1 nfsnobody nfsnobody 0 Jan 17 22:13 22
-rw-rw-r--+ 1 nfsnobody nfsnobody 0 Jan 17 22:04 file1
-rw-rw-r--+ 1 1004 1004 0 Jan 17 22:06 file-from-client2
3. теперь положим nfs сервер 153 (итого виртуальный айпишник переехал, основной nfs сервак положен) создаём кучу файлов и парочку больших
[root@ansible ~]# for i in {1..1000}; do touch /nfs/$i; done
[root@ansible ~]# dd if=/dev/urandom of=/nfs/1GB.file bs=1048576 count=1024
[root@ansible ~]# dd if=/dev/urandom of=/nfs/1.1GB.file bs=1048576 count=1024
после включения 192.168.1.153 сервака, файлы временно перемещаются в директорию /nfs/tmp/
[root@nfs-153 ~]# ll /nfs/tmp/
total 937988
-rw-------+ 1 nfssync nfssync 960495616 Jan 17 22:29 1.1GB.file.mLvZXq
и только после того как файл полностью скопируется во временную директорию он перемещается в основную.