inotify-to-many-nodes 5.51 KB
++ Введение

Достаточно типичной задачей в системной администрировании является поддержание определённых файлов в синхронном состоянии на большом количестве узлов.

В рамках рассмотренных ниже примеров синхронизация будет производится по схеме master-slave для файлов из директории /opt/global (на master-узле) в директорию /opt/production (на slave-узлах).

++ Установка clsync

Установить clsync можно следующим образом:

   # Debian
   apt-get install clsync
   
   # Gentoo
   layman -a bircoph
   emerge --sync
   emerge clsync
   
   # FreeBSD
   git clone https://github.com/xaionaro/clsync
   cd clsync/freebsd/usr/ports/sysutils/clsync && make install clean
   
   # Other
   pushd /tmp
   git clone https://github.com/xaionaro/clsync
   cd clsync
   autoreconf -fi
   ./configure
   make install

++ pdcp

pdcp - это утилита позволяющая производить копирование файла на множество узлов посредством ssh.

Установка (на master-узле):

   # Debian:
   apt-get install pdsh
   # Gentoo:
   emerge pdsh
   # FreeBSD
   cd /usr/ports/sysutils/pdsh && make install clean

Подготовка (обычно этот этап не требуется, так как такие кластера делаются методом клонирования системы, однако для наглядности пример команд с master-узла):

   ssh-keygen -t ecdsa -b 521
   # Копирование ключей на все узлы
   for HOST in $(seq 16 31); do
       IP=192.168.0."$host"
       echo "$IP	n${HOST}.example.org n${HOST}" >> /etc/hosts
       echo "$HOST" >> /etc/machines
       ssh-copy-id "$IP"
   done

Запуск на master-узле:

   clsync -M direct -S $(which pdcp) -W /opt/global -b -Y syslog -- -a %FILE-LIST%

Готово, можно попробовать:

   date >> /opt/global/test.log

++ uftp

uftp - это утилита позволяющая организовывать передачу файлов посредством multicast, что может быть удобным при передаче больших объёмов информации на очень большое количество узлов.

Установка зависимостей (на всех узлах)

   # Debian:
   apt-get install libssl-dev

Установка (на всех узлах):

   wget 'http://sourceforge.net/projects/uftp-multicast/files/source-tar/uftp-4.3.tar'
   tar -xvf uftp-4.3.tar
   cd uftp
   make install

Подготовка (на всех узлах):

   mkdir -p /opt/global /opt/production
   # Linux
   echo net.ipv4.igmp_max_memberships=256 >> /etc/sysctl.conf
   sysctl -f

Запуск на slave-узлах:

   uftpd -M 248.225.233.1 -D /opt/production
   # если у вас настроено использование pdsh, то тогда:
   #     pdsh -a echo uftpd -M 248.225.233.1 -D /opt/production \> /etc/rc.local  # или в другое место, в зависимости от вашей системы
   #     pdsh -a uftpd -M 248.225.233.1 -D /opt/production

Доподготовка master-узла:

   cat > /root/uftp-handler.c << EOF
   #include <stdlib.h>
   #include <unistd.h>
   #include <string.h>
   #include <sys/types.h>
   #include <sys/wait.h>
   
   #include <clsync/clsync.h>
   #include <clsync/configuration.h>
   #include <clsync/malloc.h>
   #include <clsync/error.h>
   
   struct ctx *ctx_p;
   
   int clsyncapi_init(struct ctx *_ctx_p, struct indexes *_indexes_p) {
       ctx_p = _ctx_p;
       return 0;
   }
   
   int clsyncapi_sync(int n, api_eventinfo_t *ei) {
        size_t argv_size;
        char **argv;
   
        debug(3, "n == %i", n);
   
        if(n == 0)
                return 0;
   
        argv_size = n+5; // "uftp" + "-M" + ip-address + n*path + NULL
        argv = xmalloc(argv_size * sizeof(char *));
        argv[0] = "/usr/local/bin/uftp";
        argv[1] = "-M";
        argv[2] = "248.225.233.1";
   
        int i = 3;
        int j = 0;
        while (i < n) {
                if(ei[j].path_len)
                        argv[i++] = (char*)ei[j].path;
                j++;
        }
   
        argv[i++] = NULL;
   
        int pid = clsyncapi_fork(ctx_p);
        switch(pid) {
                case -1:
                        critical("got error while clsyncapi_fork()");
                case  0:
                        execv(argv[0], argv);
                        critical("got error while execv()");
        }
   
        int status;
        if(waitpid(pid, &status, 0) != pid)
                critical("got error while waitpid()");
   
        int exitcode = WEXITSTATUS(status);
        free(argv);
        return exitcode;
   }
   EOF

   gcc -march=native -O2 -funswitch-loops -fpredictive-commoning -fgcse-after-reload -ftree-vectorize -ftree-loop-linear -ftree-loop-im -fweb -frename-registers -fomit-frame-pointer -fexcess-precision=fast -pipe --std=gnu11 -Wall -fPIC -shared -Wl,-O1,--as-needed /root/uftp-handler.c -o /root/uftp-handler.so


Запуск на master-узле:

   clsync --mode=so --sync-handler=/root/uftp-handler.so --watch-dir=/opt/global --background=1 --output=syslog

Готово, можно попробовать:

   date >> /opt/global/test.log