inotify-to-many-nodes 7.62 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-узла:



   cat > /root/pdcp-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+4; // "pdcp" + "-a" + n*path + NULL

        argv = xmalloc(argv_size * sizeof(char *));

        argv[0] = "/usr/bin/pdcp";

        argv[1] = "-a";

   

        int i = 2;

        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/pdcp-handler.c -o /root/pdcp-handler.so





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



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



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



   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