redmine

Initial commit

Showing 1 changed file with 1038 additions and 0 deletions
++ Введение
В данной статье будет рассмотрен способ организации Linux HA кластера на базе широкопотребного аппаратного обеспечения. Для удобства дальнейшей эффективной эксплуатации и консолидации будет предложено использовать LXC.
Для большинства задач необходимо корректно реплицировать два типа данных:
** БД
** Файлы
Однако, как показала практика, для синхронизации конфигурационных файлов хост-узлов удобно использовать отдельный инструмент от синхронизации всех остальных файлов. Итого в рамках данной статьи предлагается использовать следующий набор ПО:
** lxc+ipw для изоляции окружений
** percona+galera для репликации БД
** clsync+rsync для репликации файлов
** csync2 для репликации конфигураций
++ HOWTO
++ Аппаратное обеспечение
Допустим, у вас в наличии имеется 3 сервера. 2 из них будем использовать для HA-кластера, а 3-ий для системы резервного копирования.
Итого получается примерно следующая схема:
srv-0 <----> srv-1
| |
+-> backup <-+
В рамках данного примера назовём:
srv-0 — anubis
srv-1 — seth
++ Установка хост-систем
В качестве ОС для хост-систем сгодится любая популярная ОС на базе современных ядер Linux и GNU окружения. Однако в моём случае, данная схема была опробована только на Debian и Gentoo.
Не рекомендую использовать LVM, ибо ничего кроме overhead-ов в данной ситуации вы от этого не получите, IMHO. В качестве ФС, нами были опробованы BtrFS, XFS, Ceph и ext4, и лучше всего прижился ext4, хоть и в нём не хватает возможности устанавливать квоты по директориям, а не по uid-ам. BtrFS был плох тем, что при любой отладке связанной как-то с ФС мы в первую очередь винили его, что отнимало немало времени :). Однако мы планируем миграцию назад на BtrFS, когда он будет признан достаточно стабильным в свободном сообществе. А XFS был плох своей производительностью для наших use case-ов.
Мы использовали /opt для директорий реплицируемых скриптов, а /srv/lxc для контейнеров.
++ Репликация конфигураций хост-систем
Допустим, что вам необходимо делать большое множество vlan-ов для эффективной изоляции различных сервисов. В таких зачастую случаях возникают определённые неприятности, например:
** Долго загружается ОС, особенно Gentoo с "rc_parallel=yes" и hangup-ами (загружаться может часами).
** Огромные конфигурационные файлы, что постоянно вызывает ошибки по "человеческому фактору".
** Иногда нельзя синхронизировать конфигурационные файлы, так как необходимо использовать разные IP-адреса.
Данные проблемы можно решить используя [[https://gitlab.ut.mephi.ru/ut/ipw ipw]], вместо стандартных init.d-скриптов настройки сети.
Все приведённые далее команды необходимо выполнять на обоих рабочих узлах.
Пример глобальной (синхронизируемой) конфигурации ipw:
cat > /etc/ipw.conf <<EOF
# vim: set filetype=sh:
ACCESS_IFACES=(eth2:zabbix eth3:mirrorport)
D1Q_IFACES=(bond0)
bond0_SLAVES=(eth0 eth1)
bond0_MODE=802.3ad
bond0_VLAN_N_BRIDGES=(
5:control
6:storage
7.1:dbrep-test
8.1:web-test
8.2:web-mail
8.3:web-billing
9:vpn
:dbcl-test
128
$(seq 2048 2176)
)
source /etc/ipw.conf.local
LXC_DIR='/srv/lxc'
EOF
Данная конфигурационный файл предполагает следующую сетевую конфигурацию:
- Интерфейсы eth0 и eth1 будут объединены в bonding-интерфейс bond0 под алгоритму 802.3ad.
- Интерфейс eth2 будет присоединенён в мост "zabbix", а eth3 будет присоединён в мост "mirrorport".
- Поверх интерфейса bond0 будет созданы dot1q-интерфейсы bond0.5, bond0.6, bond0.7, bond0.7.1, bond0.8, bond0.8.1, bond0.8.2, bond0.8.3, bond0.9.
- Будет выставлен MTU 1496 интерфейсам bond0.7.1, bond0.8.1, bond0.8.2, bond0.8.3.
- Интерфейс bond0.5 будет присоединенён в мост "control", а интерфейсы bond0.6, bond0.7.1, bond0.8.1, bond0.8.2, bond0.8.3, bond0.9 в мосты "storage", "dbrep-test", "web-test", "web-mail", "web-billing" и "vpn" соответственно.
- Будет создан мост "dbcl-test"
- Будет создан мост "vlan128", а также будет создан интерфейс bond0.128 и занесён в мост "vlan128".
- Будут созданы мосты с vlan2048 по vlan2176, а также будут созданы интерфейсы с bond0.2048 по bond0.2176 и занесены в мосты vlan2048 — vlan2176 соответственно.
Пример локальной (несинхронизируемой) конфигурации ipw:
cat > /etc/ipw.conf.local <<EOF
control_IP=(
'addr add 10.0.5.2/24'
'route add default via 10.0.5.1'
)
EOF
Данный конфигурационный файл предполагает запуск двух команд:
ip addr add 10.0.5.2/24 dev control
ip addr route add default via 10.0.5.1 dev control
В рамках предложенной конфигурации csync2, файл /etc/ipw.conf будет синхронизироваться между узлами кластера, а /etc/ipw.conf.local не будет.
Устанавливаем сам ipw.
git -C /usr/local clone https://gitlab.ut.mephi.ru/ut/ipw
ln -s ../ipw/ipw /usr/local/bin/ipw
# Debian
ln -s ../../usr/local/ipw/debian/ipw /etc/init.d/ipw
update-rc.d ipw defaults
# Gentoo
ln -s ../../usr/local/ipw/gentoo/ipw /etc/init.d/ipw
ln -s ../ipw.conf /etc/conf.d/ipw
rc-update add ipw default
Для синхронизации конфигурационных файлов самым простым и удобным решением мне показалось использовать csync2. Примеры его конфигурации широко [[http://habrahabr.ru/post/120702/ распространены в Интернете]].
Пример конфигурационного файла:
group egypt {
host anubis seth;
key /etc/csync2/egypt.key;
include /root/.bashrc /etc/rc.local /etc/rc.conf /etc/local.d/* /etc/backup.* /etc/portage/*/* /etc/make.conf /etc/bash/* /etc/profile /etc/profile.env /etc/profile.d/* /etc/environment /etc/env.d/* /etc/clsync/* /etc/clsync/rules/* /etc/clsync/synchandler/*/* /etc/clsync/hooks/*/* /etc/init.d/lxc /etc/csync2/* /etc/sudoers /etc/sudoers.d/* /etc/hosts /etc/modules /usr/local/bin/* /var/spool/cron/crontabs/* /etc/cron.*/* /etc/sysctl.conf /etc/passwd /etc/group /etc/shadow /root/.ssh/*id /root/.ssh/authorized_keys /etc/ntp.conf /etc/ssh/ssh_config /etc/ssh/sshd_config /etc/rsync* /etc/conf.d/modules /etc/ipw.conf /etc/init.d/ipw /var/lib/layman/make.conf;
auto younger;
action {
pattern /etc/rsyncd.*;
exec "/etc/init.d/rsyncd restart";
logfile "/var/log/csync2_action.log";
do-local;
}
action {
pattern /etc/ssh/sshd_config;
exec "/etc/init.d/sshd restart";
logfile "/var/log/csync2_action.log";
do-local;
}
action {
pattern /etc/sysctl.conf;
exec "sysctl -f";
logfile "/var/log/csync2_action.log";
do-local;
}
action {
pattern /var/spool/cron/crontabs/* /etc/cron.*/*;
exec "/etc/init.d/vixie-cron restart";
logfile "/var/log/csync2_action.log";
do-local;
}
action {
pattern /etc/ntp.conf;
exec "/etc/init.d/ntpd restart";
logfile "/var/log/csync2_action.log";
do-local;
}
}
++ Окружение для работы с LXC
Для удобной работы с LXC в HA-кластерах наподобие предлагаемого в данной статье, вы можете использовать набор скриптов из репозитория [[https://github.com/mephi-ut/lxc-ha mephi-ut/lxc-ha на GitHub.com]]:
git -C /opt clone https://gitlab.ut.mephi.ru/ut/ipw
echo "PATH=/opt/lxc-ha/lxc/bin:$PATH" >> ~/.bashrc
exec bash
После этого необходимо обеспечить корректную работу данных скриптов:
** Если вы используете Debian:
mkdir /etc/csync2; ln -s ../csync2.conf /etc/csync2/csync2.conf
** Для дедупликации конфигураций осуществляется завязка на конфигурационный файл lxctl, который находится по пути «/etc/lxctl/lxctl.yaml». Если такой файл у вас отсутствует, то необходимо его создать и настроить. Пример настройки:
cat > /etc/lxctl/lxctl.yaml << EOF
---
lvm:
VG: vg00
paths:
YAML_CONFIG_PATH: '/etc/lxctl'
LXC_CONF_DIR: '/srv/lxc'
ROOT_MOUNT_PATH: '/usr/lib64/lxctl/rootfs'
TEMPLATE_PATH: '/usr/lib64/lxctl/templates'
LXC_LOG_PATH: '/var/log/lxc.log'
LXC_LOG_LEVEL: 'DEBUG'
check:
skip_kernel_config_check: 1
rsync:
RSYNC_OPTS: -aH --delete --numeric-ids --exclude 'proc/*' --exclude 'sys/*' -e ssh
root:
ROOT_SIZE: 50G
ROOT_TYPE: lvm
fs:
FS: ext4
FS_OPTS: -b 4096
FS_MOUNT_OPTS: defaults,barrier=0
os:
OS_TEMPLATE: debian-amd64
set:
SEARCHDOMAIN: ru
IFNAME: 'ip'
list:
COLUMNS: 'name,disk_free_mb,status,ip,hostname'
** Настройка ssh/sshd. Вы уже к этому моменту настроили csync2, что должно слегка упростить задачу:
ssh-keygen -t ecdsa -b 521
cp ~/.ssh/id_ecdsa.pub ~/.ssh/authorized_keys
echo 'getroot:x:0:0::/root:/bin/bash' >> /etc/passwd
cat > /etc/ssh/sshd_config << EOF
# vim: set filetype=sshconfig:
ListenAddress 0.0.0.0
PasswordAuthentication no
UsePAM yes
PrintLastLog no
Subsystem sftp /usr/lib64/misc/sftp-server
UseDNS no
PermitRootLogin no
PasswordAuthentication yes
RSAAuthentication no
PubkeyAuthentication yes
RhostsRSAAuthentication no
HostbasedAuthentication no
AllowGroups sshusers
Match Group sysusers Address 10.0.5.0/24
MaxAuthTries 1
PasswordAuthentication no
PermitRootLogin yes
Match Group sysusers Address 127.0.0.0/8
MaxAuthTries 1
PasswordAuthentication no
PermitRootLogin yes
EOF
cat > /etc/ssh/ssh_config << EOF
TCPKeepAlive yes
ControlMaster auto
Host *
ControlPath ~/.ssh/master-%r@%h:%p
ConnectTimeout 1
EOF
groupadd sysusers
groupadd sshusers
gpasswd -a sysusers getroot
gpasswd -a sshusers getroot
gpasswd -a sshusers yourloginhere
В теории, csync2 должен автоматически отсинхронизировать файлы id_ecdsa и authorized_keys, что должно разрешить ssh без авторизации командой:
ssh getroot@IP_адрес_соседнего_узла
** Прописываем узлы в hosts:
echo 'anubis 10.0.5.2' >> /etc/hosts
echo 'seth 10.0.5.3' >> /etc/hosts
** Создаём скрипт backuphost:
echo 'echo backup' > /usr/local/bin/backuphost
chmod +x /usr/local/bin/backuphost
** Установка screen:
# Debian:
apt-get install screen
# Gentoo:
emerge screen
** Установка и настройка keepalived:
# Debian:
apt-get install keepalived
# Gentoo:
apt-get install keepalived
# Anubis:
cat > /etc/keepalived/keepalived.conf <<EOF
global_defs {
router_id anubis.example.org
}
vrrp_sync_group ANUBIS {
group {
ANUBIS
}
}
vrrp_instance ANUBIS {
state MASTER
interface tech
lvs_sync_daemon_interface tech
virtual_router_id 224
priority 200
authentication {
auth_type PASS
auth_pass somekeywordegqQw4K3Aj2x17kS4BIHw8SaoRcEb3k72O0sTY
}
virtual_ipaddress {
10.0.5.224/24 dev tech
}
virtual_routes {
}
notify_master /opt/lxc-ha/keepalived/bin/primary-master.sh
notify_backup /opt/lxc-ha/keepalived/bin/primary-slave.sh
}
vrrp_sync_group SETH {
group {
SETH
}
}
vrrp_instance SETH {
state SLAVE
interface tech
lvs_sync_daemon_interface tech
virtual_router_id 225
priority 100
authentication {
auth_type PASS
auth_pass somekeywordegqQw4K3Aj2x17kS4BIHw8SaoRcEb3k72O0sTY
}
virtual_ipaddress {
10.0.5.225/24 dev tech
}
virtual_routes {
}
notify_master /opt/lxc-ha/keepalived/bin/secondary-master.sh
notify_backup /opt/lxc-ha/keepalived/bin/secondary-slave.sh
}
EOF
# Seth:
cat > /etc/keepalived/keepalived.conf <<EOF
global_defs {
router_id poseidon.ut.mephi.ru
}
vrrp_sync_group ANUBIS {
group {
ANUBIS
}
}
vrrp_instance ANIBUS {
state SLAVE
interface control
lvs_sync_daemon_interface control
virtual_router_id 224
priority 100
authentication {
auth_type PASS
auth_pass somekeywordegqQw4K3Aj2x17kS4BIHw8SaoRcEb3k72O0sTY
}
virtual_ipaddress {
10.0.5.224/24 dev control
}
virtual_routes {
}
notify_master /opt/lxc-ha/keepalived/bin/secondary-master.sh
notify_backup /opt/lxc-ha/keepalived/bin/secondary-slave.sh
}
vrrp_sync_group SETH {
group {
SETH
}
}
vrrp_instance SETH {
state MASTER
interface control
lvs_sync_daemon_interface control
virtual_router_id 225
priority 200
authentication {
auth_type PASS
auth_pass somekeywordegqQw4K3Aj2x17kS4BIHw8SaoRcEb3k72O0sTY
}
virtual_ipaddress {
10.0.5.225/24 dev control
}
virtual_routes {
}
notify_master /opt/lxc-ha/keepalived/bin/primary-master.sh
notify_backup /opt/lxc-ha/keepalived/bin/primary-slave.sh
}
EOF
# Gentoo, both:
rc-update add keepalived default
** Добавляем lxc-runned-notify и lxc-setnameofhost в cron:
crontab -e # добавляем строки:
PATH=/opt/lxc-ha/lxc/bin:/usr/lib/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin
* * * * * /opt/lxc/bin/lxc-setnameofhost
* * * * * /opt/lxc/bin/lxc-runned-notify 2>/dev/null
** Определяем какое значение будет использоваться для 4-го октета MAC-адреса
echo 00 > /etc/hostmac
** Если Gentoo, то исправляем значение "lxc_path" в /usr/sbin/lxc-create (или делаем обёртку или делаем symlink) на
lxc_path=/srv/lxc
Грубо говоря, на этом можно закончить настройку самих хост-систем. Далее необходимо реализовать репликацию файлов и БД контейнеров.
++ Репликация файлов контейнеров
Для репликации файлов предлагается использовать [[https://github.com/xaionaro/clsync clsync]]:
# Debian:
apt-get install clsync
# Gentoo:
layman -a bircoph
emerge --sync
emerge =app-admin/clsync-0.3
# Both:
mkdir -p /etc/clsync/hooks/lxc /etc/clsync/rules /etc/clsync/synchandler/lxc
cat > /etc/clsync/clsync.conf << EOF
[lxc-rsyncshell]
watch-dir = /srv/lxc/%label%
background = 1
mode = rsyncshell
debug = 1
syslog = 1
full-initialsync = 1
rules-file = /etc/clsync/rules/lxc
retries = 3
ignore-exitcode = 23,24
[lxc-brother]
config-block-inherits = lxc-rsyncshell
delay-sync = 15
delay-collect = 15
sync-handler = /etc/clsync/synchandler/lxc/brother.sh
lists-dir = /dev/shm/clsync-%label%-brother
exit-hook = /etc/clsync/hooks/lxc/exit-brother.sh
pid-file = /var/run/clsync-%label%-brother.pid
status-file = /srv/lxc/%label%/clsync-brother.status
dump-dir = /tmp/clsyncdump-%label%-brother
threading = safe
[lxc-brother-atomic-sync]
config-block-inherits = lxc-brother
threading = off
background = 0
exit-on-no-events = 1
max-iterations = 10
[lxc-brother-initialsync]
config-block-inherits = lxc-brother
threading = off
background = 0
only-initialsync = 1
[lxc-backup]
config-block-inherits = lxc-rsyncshell
sync-handler = /etc/clsync/synchandler/lxc/backup.sh
delay-sync = 1800
delay-collect = 1800
delay-collect-bigfile = 43200
lists-dir = /dev/shm/clsync-%label%-backup
exit-hook = /etc/clsync/hooks/lxc/exit-backup.sh
pid-file = /var/run/clsync-%label%-backup.pid
status-file = /srv/lxc/%label%/clsync-backup.status
dump-dir = /tmp/clsyncdump-%label%-backup
[lxc-backup-copy]
config-block-inherits = lxc-brother
sync-handler = /etc/clsync/synchandler/lxc/copytobackup.sh
threading = off
background = 0
only-initialsync = 1
EOF
cat > /etc/clsync/hooks/lxc/exit-brother.sh << EOF
#!/bin/bash
LABEL="$1"
brotherssh rm -f /srv/lxc/"$LABEL"/clsync-brother.status
EOF
cat > /etc/clsync/hooks/lxc/exit-backup.sh << EOF
#!/bin/bash
LABEL="$1"
brotherssh rm -f /srv/lxc/"$LABEL"/clsync-backup.status
EOF
cat > /etc/clsync/rules/lxc << EOF
-f/var/log/.*
-d/var/lib/mysql
-f/bin\.000
-f/rootfs-readonly
-f/dmesg
EOF
cat > /etc/clsync/synchandler/lxc/backup.sh << EOF
#!/bin/bash
ACTION="$1"
LABEL="$2"
ARG0="$3"
ARG1="$4"
FROM="/srv/lxc/${LABEL}"
CLUSTERNAME=$(clustername)
BACKUPHOST=$(backuphost)
BACKUPMNT="/mnt/backup"
BACKUPDECR="/decrement/${LABEL}"
BACKUPMIRROR="rsync://$CLUSTERNAME@$BACKUPHOST/$HOSTNAME/mirror/${LABEL}"
if [ "$CLSYNC_STATUS" = "initsync" ]; then
STATICEXCLUDE=''
else
STATICEXCLUDE='--exclude-from=/etc/clsync/synchandler/lxc/rsync.exclude'
fi
function rsynclist() {
LISTFILE="$1"
EXCLISTFILE="$2"
excludefrom=''
if [ "$EXCLISTFILE" != "" ]; then
excludefrom="--exclude-from=${EXCLISTFILE}"
fi
if ping -w 1 -qc 5 -i 0.1 $BACKUPHOST > /dev/null; then
exec rsync --password-file="/etc/backup.pass" -aH --timeout=3600 --inplace --delete-before $STATICEXCLUDE "$excludefrom" --include-from="${LISTFILE}" --exclude='*' --backup --backup-dir="$BACKUPDECR"/ "$FROM"/ "$BACKUPMIRROR"/ 2>/tmp/clsync-rsync-"$LABEL"-backup.err
else
sleep $[ 3600 + $RANDOM % 1800 ]
return 128
fi
}
case "$ACTION" in
rsynclist)
rsynclist "$ARG0" "$ARG1"
;;
esac
exit 0
EOF
cat > /etc/clsync/synchandler/lxc/copytobackup.sh << EOF
#!/bin/bash
ACTION="$1"
LABEL="$2"
ARG0="$3"
ARG1="$4"
FROM="/srv/lxc/${LABEL}"
CLUSTERNAME=$(clustername)
BACKUPHOST=$(backuphost)
BACKUPMNT="/mnt/backup"
BACKUPMIRROR="rsync://$CLUSTERNAME@$BACKUPHOST/lxc/${LABEL}"
if [ "$CLSYNC_STATUS" = "initsync" ]; then
STATICEXCLUDE=''
else
STATICEXCLUDE='--exclude-from=/etc/clsync/synchandler/lxc/rsync.exclude'
fi
function rsynclist() {
LISTFILE="$1"
EXCLISTFILE="$2"
excludefrom=''
if [ "$EXCLISTFILE" != "" ]; then
excludefrom="--exclude-from=${EXCLISTFILE}"
fi
if ping -w 1 -qc 5 -i 0.1 $BACKUPHOST > /dev/null; then
exec rsync --password-file="/etc/backup.pass" -aH --timeout=3600 --inplace --delete-before $STATICEXCLUDE "$excludefrom" --include-from="${LISTFILE}" --exclude='*' "$FROM"/ "$BACKUPMIRROR"/ 2>/tmp/clsync-rsync-"$LABEL"-backup.err
else
sleep $[ 3600 + $RANDOM % 1800 ]
return 128
fi
}
case "$ACTION" in
rsynclist)
rsynclist "$ARG0" "$ARG1"
;;
esac
exit 0
EOF
cat > /etc/clsync/synchandler/lxc/brother.sh << EOF
#!/bin/bash -x
ACTION="$1"
LABEL="$2"
ARG0="$3"
ARG1="$4"
BROTHERMNT="/mnt/mirror"
BROTHERNAME=$(brothername)
CLUSTERNAME=$(clustername)
FROM="/srv/lxc/${LABEL}"
TO="rsync://${CLUSTERNAME}@${BROTHERNAME}/lxc/${LABEL}"
if [ "$CLSYNC_STATUS" = "initsync" ]; then
STATICEXCLUDE=''
else
STATICEXCLUDE='--exclude-from=/etc/clsync/synchandler/lxc/rsync.exclude'
fi
function rsynclist() {
LISTFILE="$1"
EXCLISTFILE="$2"
excludefrom=''
if [ "$EXCLISTFILE" != "" ]; then
excludefrom="--exclude-from=${EXCLISTFILE}"
fi
if ping -w 1 -qc 5 -i 0.1 $BROTHERNAME > /dev/null; then
exec rsync --password-file="/etc/rsyncd.pass" -aH --timeout=3600 --inplace --delete-before $STATICEXCLUDE "$excludefrom" --include-from="${LISTFILE}" --exclude='*' "$FROM"/ "$TO"/ 2>/tmp/clsync-rsync-"$LABEL"-brother.err
else
sleep $[ 3600 + $RANDOM % 1800 ]
exit 128
fi
}
case "$ACTION" in
rsynclist)
rsynclist "$ARG0" "$ARG1"
;;
esac
exit 0
EOF
cat >/etc/clsync/synchandler/lxc/rsync.exclude << EOF
sess_*
nanocacmail/*/*.nexus
home/mrtg/*.html
home/mrtg/*.log
home/mrtg/*.old
home/mrtg/*.png
vim/spell/*
tmp/*
sys/*
proc/*
run/*
var/tmp/*
var/lock/*
var/run/*
radwtmp
bitrix/cache/*
access.log*
error.log*
*cache/***
rootfs-readonly
dmesg
EOF
Добавим в cron запуск lxc-clsync-startstop, чтобы перезапускать репликацию (если она отвалилась) на случай разных проблем (например, если второй узел выпадал из сети):
crontab -e # добавляем строку: * * * * * /opt/lxc/bin/lxc-clsync-startstop
В предложенной конфигурации clsync использует rsync, поэтому настраиваем rsyncd (на рабочих узлах):
cat > /etc/rsyncd.conf << EOF
# /etc/rsyncd.conf
# This line is required by the /etc/init.d/rsyncd script
pid file = /var/run/rsyncd.pid
max connections = 128
log file = /var/log/rsync.log
timeout = 300
[lxc]
path = /srv/lxc
use chroot = yes
max connections = 128
read only = no
list = yes
uid = root
gid = root
auth users = egypt
secrets file = /etc/rsyncd.secrets
strict modes = no
hosts allow = 10.0.5.0/24
ignore errors = no
ignore nonreadable = yes
transfer logging = yes
timeout = 300
refuse options = checksum dry-run
dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz *.xz
EOF
touch /etc/rsyncd.{secrets,pass} /etc/backup.pass
chmod 600 /etc/rsyncd.{secrets,pass} /etc/backup/pass
cat > /etc/rsyncd.secrets << EOF
egypt:passwordhereQRWyisbVNWh1Q
EOF
cat > /etc/rsyncd.pass << EOF
passwordhereQRWyisbVNWh1Q
EOF
cat > /etc/backup.pass << EOF
passwordherevgX9rj8cAm3Es
EOF
На сервере резервного копирования:
cat > /etc/rsyncd.conf << EOF
motd file = /etc/rsyncd.motd
log file = /var/log/rsyncd.log
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
[lxc]
path = /srv/lxc
uid = root
gid = root
read only = no
list = yes
auth users = egypt
secrets file = /etc/rsyncd.secrets
[anubis]
path = /srv/storage/hosts/anubis
uid = root
gid = root
read only = no
list = yes
auth users = egypt
secrets file = /etc/rsyncd.secrets
[seth]
path = /srv/storage/hosts/seth
uid = root
gid = root
read only = no
list = yes
auth users = egypt
secrets file = /etc/rsyncd.secrets
EOF
cat > /etc/rsyncd.secrets << EOF
egypt:passwordherevgX9rj8cAm3Es
EOF
На всех трёх узлах:
# Gentoo:
rc-update add rsyncd default
/etc/init.d/rsyncd start
# Debian:
echo 'RSYNC_ENABLE=true' >> /etc/default/rsync
/etc/init.d/rsync start
Теперь необходимо протестировать как производится the репликация. Для начала необходимо создать тестовый контейнер, например:
lxc-create -t debian -n replicationtest
Если всё сделано верно, то контейнер должен отреплицироваться на соседний узел. На узле, где запущен the контейнер имеет смысл ввести команду «lxc-list»:
lxc-list
В результате вы увидите что-то вроде:
g[16:47:48] [root@anubis ~]# lxc-list
RUNNING
replicationtest [ R ][ R ] sdc1 665G
FROZEN
STOPPED
Первая «R» внутри «[ R ]» означает, что контейнер находится в синхронном состоянии на соседнем узле, а вторая «[ R ]» — что узел находится в синхронном состоянии на сервере резервного копирования.
Сами квадратные скобки «[» и «]» означают, что репликация осуществуется с _данного узла_.
Если посмотреть на «lxc-list» со стороны соседнего узла, то можно увидеть:
g[17:01:01] [root@seth ~]# lxc-list
RUNNING
FROZEN
STOPPED
remote replicationtest R R sdc1 665G
Как можно заметить, скобок «[» и «]» на данной стороне не наблюдается. Однако можно увидеть слово «remote» перед именем контейнера, что означает, что контейнер уже запущен на соседнем узле.
Кроме того, можно ввести команду:
lxc-auto replicationtest
Тогда в «lxc-list» перед именем контейнера появится ключевое слово «auto», что означает в свою очередь, что данный контейнер будет запускаться автоматически при запуске узла. Предполагается, что «lxc-auto» будет использоваться только для нерезервируемых узлов (например узлы СУБД, которые используют другие средства репликации).
++ Репликация БД
Достаточно долгие эксперименты с master-slave- и master-master-репликациями привели нас к выводу, что придётся использовать galera. И опять же долгие эксперименты с galera привели нас к связке percona+galera.
Создаём контейнер с Debian
lxc-create -t debian -n percona_test
Редактируем конфиг (хотя лучше этот процесс автоматизовать под ваши use case-ы), например:
cat > /srv/lxc/percona_test/config << EOF
## Container
lxc.utsname = percona_test
lxc.rootfs = /srv/lxc/percona_test/rootfs
lxc.arch = x86_64
lxc.console = /srv/lxc/percona_test/console.log
lxc.tty = 6
lxc.pts = 128
## Capabilities