2020-10 upd: we reached the first fundraising goal and rented a server in Hetzner for development! Thank you for donating !
Внимание! Данные страницы описывают CBSD версии 13.0.x. Если вы используете более раннюю версию, рекомендуется сначала обновиться.
Синхронизация jail окружений через csync2 и модуль CBSD csync2
Сегодня существует множество подходов и инструментов для репликации или распространения данных на файловой системе между различными серверами. В зависимости от поставленной задачи, вы можете использовать:
для доставки конфигурационных файлов. Также можете выбрать Ceph, ClusterFS и им подобных для репликации бинарных данных или целых файловых систем; вы можете использовать HASTD или ZFS Send для блочной и дискретной репликации. Но все еще остаются кейсы, когда вместо сложных и монструозных решений, идеально подходят старые добрые легковесные утилиты для синхронизации данных, такие как csync2 или lsyncd.Конечно, они не годятся для синхронизации нескольких тысяч файлов или высоконагруженных на запись окружений. Но с ситуациями, когда вам необходимо синхронизировать контейнера с небольшим количеством файлов и редкой записью, подобные утилиты справляются идеально. К примеру, у вас есть jail контейнер, обслуживающий статические файлы для WEB сервера и вы хотите с помощью синхронизации растиражировать окружения в большом количестве. Модуль csync2 для CBSD является скриптом-оберткой для более комфортного менеджмента конфигурационного файла программы csync2, когда вам необходимо синхронизировать контейнеров на базе jail.
Как это работает: в системном CBSD каталоге каждого jail вы можете сопровождать любую конфигурацию для csync2, описывающую списки файлов и директорий контейнера для синхронизаций (или их исключения). Команда 'cbsd csync2' запускается каждую минуту из cron, склеивает эти файлы в один одноименный оригинальный конфигурационный файл /usr/local/etc/csync2.cfg и в зависимости от необходимой частоты синхронизации (может настраиваться для каждого контейнера индивидуально), запускает утилиту csync2 для того или иного контейнера.
В качестве примера, давайте создадим два синхронизируемых контейнера с именами 'repl1' и 'repl2' между двумя нодами CBSD.
1) Выполняем установку пакета csync2 и модуля 'cbsd csync2' на обеих нодах:
pkg install -y csync2 cbsd module mode=install csync2 echo 'csync2.d' >> ~cbsd/etc/modules.conf cbsd initenv
2) Скопируем пример конфигурационного файла модуля в рабочий каталог CBSD:
cp /usr/local/cbsd/modules/csync2.d/etc/csync2.conf ~cbsd/etc/
Конфигурационный файл небольшой и позволяет оперировать параметрами:
## Каталог для логирования: CSYNC2_CBSD_LOG_DIR="/var/log/cbsd-csync2" ## Глобальный csync2 ключ: CSYNC2_CBSD_KEY="/usr/local/etc/cbsd_csync2.key" ## Путь к программе csync2 в системе CSYNC2_CMD="/usr/local/sbin/csync2" ## Глобальный конфигурационный файл csync2, который в нашем случае будет автоматически генерируемым CBSD модулем csync2 CSYNC2_CFG_FILE="/usr/local/etc/csync2.cfg" ## Частота запуска операции синхронизации (не путать с частотой запуска 'cbsd csync2' модуля из crontab - см. ниже ## По-умолчанию, выполняем одну синхронизацию в 10 минут, но если вы хотите для некоторых контейнеров иметь другую частоту, используйте ## файл ~cbsd/jails-system/%jail%/etc для установки индивидуального для %jail% значения. CSYNC2_CBSD_RUN_INTERVAL="10"
3) Создадим контейнера 'repl1' и 'repl2' на обеих нодах. Имена одинаковые, но будем использовать непересекающиеся IP адреса, поскольку в нашем случае сервера расположены в одном сегменте.
node1# cbsd jcreate ip4_addr=10.0.100.144 jname=repl1 runasap=1 node1# cbsd jcreate ip4_addr=10.0.100.145 jname=repl2 runasap=1 node2# cbsd jcreate ip4_addr=10.0.100.146 jname=repl1 runasap=1 node2# cbsd jcreate ip4_addr=10.0.100.147 jname=repl2 runasap=1
4) На каждом сервере для каждого контейнера сформируем /usr/jails/jails-system/%jail%/csync2.cfg конфигурационный файл, описывающий директории контейнеров для синхронизации. Мы будем реплицирировать весь контейнер, за исключением каталога /var/run/ где хранятся PID процессов и не будем синхронизировать логи, содержимое файлов которых уникальны для каждого контейнера, поскольку мы планируем что все контейнера будут работать. На node1: для контейнера 'repl1' и при условии, что cbsd_workdir установлен в каталог /usr/jails:
cat > /usr/jails/jails-system/repl1/csync2.cfg <<EOF host node1.my.domain; host node2.my.domain; include /usr/jails/jails-data/repl1-data; include /usr/jails/jails-system/repl1/csync2.cfg; exclude /usr/jails/jails-data/repl1-data/var/spool/clientmqueue; exclude /usr/jails/jails-data/repl1-data/var/log/*; exclude /usr/jails/jails-data/repl1-data/var/log/*/*.log; exclude /usr/jails/jails-data/repl1-data/var/run/*; exclude /usr/jails/jails-data/repl1-data/tmp/*; action { pattern /usr/jails/jails-data/repl1-data/usr/local/etc/nginx/*; exec "/usr/local/bin/cbsd service jname=repl1 mode=action nginx reload"; logfile "/usr/jails/jails-system/repl1/csync2.actions.log"; do-local; } auto younger; EOF
такой же конфиг для контейнера 'repl2' с соответствующей разницей в путях директорий:
cat > /usr/jails/jails-system/repl2/csync2.cfg <<EOF host node1.my.domain; host node2.my.domain; include /usr/jails/jails-data/repl2-data; include /usr/jails/jails-system/repl2/csync2.cfg; exclude /usr/jails/jails-data/repl2-data/var/spool/clientmqueue; exclude /usr/jails/jails-data/repl2-data/var/log/*; exclude /usr/jails/jails-data/repl2-data/var/log/*/*.log; exclude /usr/jails/jails-data/repl2-data/var/run/*; exclude /usr/jails/jails-data/repl2-data/tmp/*; action { pattern /usr/jails/jails-data/repl2-data/usr/local/etc/nginx/*; exec "/usr/local/bin/cbsd service jname=repl2 mode=action nginx reload"; logfile "/usr/jails/jails-system/repl2/csync2.actions.log"; do-local; } auto younger; EOFОбратите внимание на 'node1.my.domain' и 'node2.my.domain' - это должны быть IP адреса или корректные DNS имена ваших CBSD хостов. Кроме этого, мы используем специальную директиву 'action' в качестве примера,которая будет перезагружать сервис nginx в нужном контейнере, если при синхронизации где-то были модифицированы конфигурационные файлы HTTP сервера 'nginx', который в нашем случае запущен в каждом контейнере.
5) Повторяем полностью аналогичную настройку из пункта '4' на второй ноде.
6) Сгенерируем на любой из наших хостов глобальный ключ csync2 путем запуска скрипта:
cbsd csync2
Если файл /usr/local/etc/cbsd_csync2.key отсутствует (параметр CSYNC2_CBSD_KEY), файл будет сгенерирован. Внимание! Вам необходимо распространить этот ключ на все ноды, учавствующие в синхронизации. Конечно, это удобно делать такими инструментами, как: Puppet,Chef,Salt,Ansible.
7) пометим сервис csync2 через /etc/rc.conf как активный, на всех нодах:
sysrc csync2_enable="YES"
8) Добавим в cron от пользователя 'root' запись для ежеминутного запуска 'cbsd csync2'. Это не означает, что синхронизация будет работать каждую минуту - как мы помним, частоту синхронизации мы регулируем параметром CSYNC2_CBSD_RUN_INTERVAL. Делаем на всех нодах вызов 'crontab -e' и добавляем строчку:
* * * * * /usr/bin/lockf -s -t0 /tmp/cbsd_csync2.lock /usr/bin/env NOCOLOR=1 /usr/local/bin/cbsd csync2 >> /var/log/cbsd-csync2/csync2.log 2>&1На этом настройка завершена. Вы можете запустить несколько раз скрипт вручную, чтобы убедится, что все работает корректно:
cbsd csync2 verbose=1 force=1Или наблюдайте логи в каталоге /var/log/cbsd-csync2 спустя несколько минут после инсталляции cron.