Допустим, у нас есть один физический довольно мощный сервер. Конкретные характеристики приводить не буду, представим, что это современный сервер со средними или чуть выше средних параметрами. Ты хочешь его использовать в качестве веб-сервера для своего сайта, но в то же время нужно обеспечить его отказоустойчивость, а физический сервер всего один.

Классическая схема отказоустойчивости реализуется при наличии хотя бы двух физических серверов. Один — основной, второй — резервный. Понятно, что если что-то происходит с основным, то в дело вступает резервный. В нашем случае, поскольку нет второго физического сервера, мы будем использовать два виртуальных. Расчет довольно прост: если произойдет какой-то программный глюк на основном виртуальном сервере, то будет работать резервный.

Недостаток такого вида отказоустойчивости в том, что если что-то случится с железом, то тебе уже ничто не поможет. Но, как говорится, это лучше, чем ничего. К тому же приведенные в статье инструкции ты сможешь использовать для настройки полноценной отказоустойчивости, когда у тебя появится второй физический сервер.

 

Выбор решения виртуализации

Какое решение будем использовать для виртуализации? Первое, что приходит на ум, — это старый добрый OpenVZ. Добрый-то он добрый, но уж очень старый, я бы даже сказал — древний, а его ядро вообще родом из мезозойской эры. Другими словами, если у тебя современный дистр, то, установив OpenVZ, ты сделаешь эдакий downgrade. Но выход есть: наследник OpenVZ — Virtuozzo.

Преимущество Virtuozzo в том, что устанавливается он на голое железо и представляет собой отдельный дистрибутив Linux (Virtuozzo Linux), который уже оптимизирован для задач виртуализации и хостинга. Все, что нужно, — взять и установить его на машину, которая будет сервером виртуализации.

Недостаток в том, что Virtuozzo — решение коммерческое и придется немного потратиться. Дополнительную информацию ты сможешь найти на официальной страничке продукта.

 

Получение trial-версии

Прежде чем покупать Virtuozzo, ты можешь его попробовать, чтобы окончательно решить, понравится он тебе или нет. Заходи на их сайт и жми кнопку Try Virtuozzo 7 Now. Далее нужно заполнить несложную форму и нажать кнопку Submit. После этого ты попадешь на страничку, на которой можно скачать ISO-шник и документацию. Линк на ISO-шник и документацию также будет продублирован на твой email, если ты захочешь скачать Virtuozzo и/или документацию позже.

Форма активации твоей trial-версии
Форма активации твоей trial-версии

Триальная лицензия дается во время установки Virtuozzo 7 на хост, поэтому важно наличие интернет-соединения. Trial-версия работает 30 дней — думаю, этого вполне достаточно, чтобы принять решение о покупке.

 

Создание виртуальных серверов

Нам нужно создать два контейнера (естественно, после установки Virtuozzo Linux на физический компьютер), а затем установить в них все самое необходимое. Сначала создадим сами контейнеры:

# prlctl create first --vmtype ct --ostemplate centos-6-x86_64
# prlctl create second --vmtype ct --ostemplate centos-6-x86_64
Рис. 1. Создание контейнеров
Рис. 1. Создание контейнеров

Как ты уже догадался, это будут контейнеры для первого и второго серверов. После создания контейнеров нужно их настроить:

# prlctl set <контейнер> --cpus 1
# prlctl set <контейнер> --memsize 1G --swappages 512M
# prlctl set first --hostname first.example.com
# prlctl set first --ipadd 192.168.52.101
# prlctl set second --hostname second.example.com
# prlctl set second --ipadd 192.168.52.102
Рис. 2. Настройка контейнеров
Рис. 2. Настройка контейнеров

Здесь нужно ввести актуальные параметры. Я выделил каждому виртуальному серверу по одному процессору и гигабайту оперативки, своп — 512 Мбайт (на всякий случай). Можно было бы выделить и 512 Мбайт оперативки — большинство сайтов работают на виртуальном хостинге с худшими характеристиками. Также доменные имена и IP-адреса нужно указать собственные, у меня демонстрационные.

Запускаем виртуальный сервер:

# prlctl start <контейнер>

Устанавливаем пароль root для обоих контейнеров:

# prlctl exec <контейнер> passwd

Подключаемся к серверу по SSH:

# ssh <IP-адрес>

По сути, на данный момент у тебя уже есть два полноценных сервера, которые осталось только настроить.

Рис. 3. Запуск виртуального сервера, изменение пароля root и подключение по SSH
Рис. 3. Запуск виртуального сервера, изменение пароля root и подключение по SSH
 

Настройка сети

Прежде чем приступить к настройке серверов, нужно настроить сетку, иначе в виртуальном сервере yum работать не будет и софт ты все равно не установишь. На данный момент мы установили только доменные имена и IP-адреса виртуальных узлов. Но этого мало. Нужно настроить NAT, разрешить доступ к виртуальным серверам извне и настроить DNS.

Начнем с настройки NAT. В Virtuozzo Linux пакет iptables-services установлен по умолчанию, а IPv4-форвардинг включен (в файле cat /proc/sys/net/ipv4/ip_forward есть единичка), поэтому никакие подготовительные действия не понадобятся: сразу приступаем к настройке правил iptables. Для NAT определенного контейнера используется команда

# iptables -t nat -A POSTROUTING -s src_net -o if -j SNAT --to ip_address

Здесь вместо src_net нужно указать IP-адрес подсетки контейнера, вместо if — интерфейс, а вместо ip_address — внешний IP-адрес твоего аппаратного узла. Но можно сделать проще и ввести команду

# iptables -t nat -A POSTROUTING -o ens33 -j MASQUERADE

 

Ошибка?

Если система будет ругаться на отсутствие таблицы NAT, не обращай внимания. Видимо, есть какой-то конфликт между версией iptables и ядра, разбираться не стал, но самое интересное, что правила работают :).

В этом случае все IP-адреса будут транслироваться SNAT. Именно эту команду я и ввел на рис. 4.

Рис. 4. Включение NAT. Установка сервера DNS для первого сервера
Рис. 4. Включение NAT. Установка сервера DNS для первого сервера

На радостях запускаем контейнер и... обнаруживаем, что пропинговать-то узел по IP мы можем, а вот DNS настроить забыли. Ничего, все это решается командой

# prlctl set <контейнер> --nameserver 8.8.8.8

Пока используем OpenDNS, ведь свой мы еще не настроили. Теперь нужно убедиться, что мы можем пропинговать узел по его имени:

# ping mail.ru
Рис. 5. Сетка на виртуальном сервере поднята и работает
Рис. 5. Сетка на виртуальном сервере поднята и работает

Вот, теперь все в порядке и можно приступить к установке софта. Только не забудь настроить доступ к виртуальным серверам извне, иначе никто не сможет к ним достучаться:

# iptables -t nat -A PREROUTING -p tcp -d ip_address --dport port_num \
  -i ens33 -j DNAT --to-destination ve_address:dst_port_num

Здесь ve_address — это IP-адрес контейнера, dst_port — TCP-порт, ip_address — внешний (публичный) IP-адрес твоего узла, а port_num — TCP-порт аппаратного узла, который будет использоваться для интернет-соединений к приватным контейнерам. Обрати внимание, что данное правило сделает сервис, который раньше висел на порту с заданным номером (port_num), недоступным. Также обрати внимание, что трансляция SNAT, которую мы делали раньше, тоже необходима.

Если ты хочешь, чтобы порт 80 был доступен на аппаратном узле, а доступ к виртуальным серверам реализован через порт 8080, используй такие правила:

# iptables -t nat -A PREROUTING -p tcp -d ip_address --dport 8080 \
  -i eth0 -j DNAT --to-destination ve_address:80
# iptables -t nat -A POSTROUTING -s ve_address -o eth0 -j SNAT --to ip_address

Тогда «достучаться» до виртуальных серверов можно будет так: http://ip_address:8080/.

Осталось только сохранить правила iptables:

# service iptables save
# service iptables restart

Теперь у наших виртуальных серверов есть доступ к интернету, они могут пропинговать друг друга и к ним можно обратиться извне (рис. 6, 7). По сути, они мало чем отличаются от обычных интернет-серверов.

Рис. 6. Пинг с сервера second (адрес *102) сервера first (адрес *101)
Рис. 6. Пинг с сервера second (адрес *102) сервера first (адрес *101)
Рис. 7. Заходим извне (прямое обращение по IP-адресу) на сервер first (адрес *101)
Рис. 7. Заходим извне (прямое обращение по IP-адресу) на сервер first (адрес *101)
 

Настройка DNS

Далее нужно установить на физический компьютер пакет bind — это DNS-сервер. Пакет хоть и имеет версию 9, но называется просто bind. Каталог /etc/bind отсутствует (вместо него — каталог /etc/named, но он пуст), а конфиг самого сервера находится в /etc/named.conf. Это я описываю отличия настройки пакета bind в Virtuozzo Linux от привычных дистрибутивов. Во всем остальном bind настраивается так же, как в любом другом дистрибутиве Linux.

Твоя цель — создать две A-записи на www.example.com в зоне example.com:

@       IN      A       192.168.52.101
www     IN      A       192.168.52.101
www     IN      A       192.168.52.102
first   IN    A    192.168.52.101
second  IN     A    192.168.52.102

Полные конфиги не стану приводить по двум причинам. Первая — все они стандартны и только будут занимать место (да и Google не любит дублирование контента :)). Вторая — все равно у тебя будет реальная зона, у меня же она демонстрационная. Если ты повторяешь все написанное в статье в VMware/Windows (то есть «физический» сервер с Virtuozzo Linux — это виртуальная машина VMware), то можно для обеспечения отказоустойчивости добавить в C:\Windows\System32\drivers\etc\hosts строки

192.168.52.101 www.example.com
192.168.52.102 www.example.com

Это тоже две A-записи, но только в Windows. После этого введи команду ipconfig /flushdns.

В Linux проверить наш сценарий также можно без DNS-сервера — отредактировав файл /etc/hosts и добавив в него те же записи. Но на практике тебе будет нужен DNS-сервер, делегирующий твой домен. Так что управление доменом придется перетащить к себе или же к регистратору, где есть вменяемая панель управления зоной — с возможностью добавления необходимых тебе записей.

 

Проверка отказоустойчивости

Для начала расскажу, почему все это будет работать. Современные браузеры, получив несколько A-записей, пытаются зайти на сайт, используя первый IP-адрес. Если он недоступен, они используют второй и так далее. Другими словами, таких вот серверов у тебя может быть даже не два, а гораздо больше. Например, у Google их одиннадцать, а у Mail.Ru — четыре (рис. 8).

Рис. 8. Для google.com используется одиннадцать А-записей, для mail.ru — четыре
Рис. 8. Для google.com используется одиннадцать А-записей, для mail.ru — четыре

Чтобы проверить отказоустойчивость, нам нужно сделать разным контент на первом и втором серверах. Ведь сейчас открывается одна и та же страничка (Apache 2 Test Page), и мы просто-напросто не будем знать, с какого сервера получен ответ. Поэтому, чтобы не использовать дополнительные инструменты для отслеживания пакетов, проще всего зайти на второй сервер и отредактировать файл /var/www/html/index.html. Пусть его содержимое будет вот таким простым:

<h1>Second server</h1>

После этого нужно остановить первый сервер и обратиться к www.example.com. Но обо всем по порядку:

ssh 192.168.52.102
[root@second]: echo "<h1>Second server</h1>" > /var/www/html/index.html
[root@second]: exit
prlctl stop first

Первая команда обеспечивает вход на второй сервер. Вторую мы уже вводим в SSH-сеансе со вторым сервером. Она добавляет «контент» в index.html. Затем мы выходим со второго сервера и останавливаем первый.

Рис. 9. Первый сервер остановлен
Рис. 9. Первый сервер остановлен

Осталось открыть твой любимый браузер и ввести URL http://www.example.com. У тебя должна появиться страничка с надписью Second server (рис. 10). Если ты увидел тестовую страничку Apache, то что-то ты сделал не так. Копать нужно в сторону DNS (ну или ты забыл снести тестовый контент на втором сервере).

Рис. 10. Отказоустойчивость работает
Рис. 10. Отказоустойчивость работает
 

Настройка синхронизации

По сути, поставленная задача, а именно отказоустойчивость работает. Но нам нужно еще настроить синхронизацию контента, чтобы все работало как следует.

Если у тебя только HTML-контент или же движок, который хранит данные в файлах, то все очень просто. Достаточно только настроить синхронизацию каталогов двух веб-серверов (кстати, сами серверы httpd на виртуальных серверах оказались уже установленными — очень удобно). Если же контент хранится в базе данных MySQL или какой-либо другой, то нужно настраивать репликацию БД, однако это тема для отдельной статьи. Поэтому есть два выхода — или разбираться с репликацией MySQL, или писать сценарий на PHP, который будет делать импорт/экспорт БД на второй сервер. Как по мне, проще и эффективнее использовать уже существующие механизмы репликации, а не изобретать велосипед заново.

Сейчас мы рассмотрим, как синхронизировать HTML-контент. На обоих серверах нужно установить lsyncd (если не требуется двусторонняя синхронизация, то достаточно установить пакет только на первом):

rpm -ivh http://mirror.yandex.ru/epel/7/x86_64/e/epel-release-7-5.noarch.rpm
yum install lsyncd

Первая команда добавляет нужный репозиторий, вторая устанавливает lsyncd. Эти команды надо вводить на всех виртуальных серверах. При создании виртуальных серверов я использовал шаблоны CentOS. Если ты выбрал Debian-совместимый шаблон, то для установки lsyncd используй apt-get:

# apt-get install lsyncd

Репозиторий подключать не требуется, если ты выбрал шаблон Ubuntu или Debian начиная с версии 7. Там lsyncd уже находится в репозитории.

После установки lsyncd нужно создать каталоги для хранения логов и временных файлов (создай эти каталоги на двух серверах, если в будущем понадобится двусторонняя синхронизация):

# mkdir -p /var/log/lsyncd
# mkdir -p /var/www/temp

Теперь отредактируем основной файл конфигурации первого сервера /etc/lsyncd.conf:

settings {
  logfile    = "/var/log/lsyncd/lsyncd.log",
  statusFile = "/var/log/lsyncd/lsyncd.status",
  nodaemon   = true
}
sync {
  default.rsyncssh,
  source="/var/www/html",
  host="second.example.com",
  targetdir="/var/www/html",
  rsync = {
    archive=true,
    compress=true,
    temp_dir="/var/www/temp",
    update=true,
    links=true,
    times=true,
    protect_args=true
  },
  delay=5,
  ssh = {
    port = 22
  }
}

В host нужно указать второй сервер, в source — папку на текущем сервере (она будет одинакова на обоих серверах), в targetdir — папку на удаленном сервере. Параметр delay задает время синхронизации в секундах (значение по умолчанию — 10 с). Параметр nodaemon после отладки следует установить в true, чтобы lsyncd запускался в режиме демона.

Перед проверкой надо создать SSH-ключи, поскольку lsyncd нужно, чтобы был предоставлен доступ к каждому из серверов по ключу. На обоих серверах введи команду

# ssh-keygen

На вопросы можно отвечать, просто нажав Enter. С сервера first добавляем ключ сервера second:

# ssh-copy-id root@second.example.com

Аналогично с сервера second добавь ключ на сервер first:

# ssh-copy-id root@first.example.com

Теперь подключись с сервера first к серверу second и наоборот. Пароль запрашиваться не будет. На вопросы при подключении отвечай yes.

Вот теперь на сервере first создай тестовый файл:

# touch /var/www/html/test

Далее запусти lsyncd вручную:

# lsyncd /etc/lsyncd.conf

Проверь, что все синхронизировалось корректно. Если все прошло хорошо, то на втором сервере в /var/www/html ты увидишь созданный файл test.

Осталось изменить значение nodaemon в конфиге на false и добавить lsyncd в автозагрузку:

systemctl start lsyncd.service
systemctl enable lsyncd.service

Первая команда включает автозагрузку сервиса, а вторая запускает сам сервис.

 

Примечания

Наша схема синхронизации работает в одном направлении. При желании можно сделать и двухстороннюю синхронизацию (SSH уже настроен, осталось настроить lsyncd), но она нужна далеко не всегда.

Обычно имеется одно хранилище контента (первый сервер) и каждые 5–10 с выполняется репликация со вторым сервером. Если сервер обновляется не очень часто, можно вообще производить синхронизацию вручную, после его обновления, или же установить интервал не в пять секунд, а в 3600 (синхронизация один раз в час). В данном примере пять секунд использовались, чтобы меньше ждать при тестировании.

Собственно, на этом все! Отказоустойчивость настроена, синхронизация (хоть и частичная, без репликации БД) — тоже.

3 комментария

  1. Аватар

    username1366

    30.11.2016 в 15:31

    Не понятно кому сейчас нужен (никому) проприетарный Virtuozzo, если есть свободные Kubernetes, Docker Swarm и Mesos/Marathon

  2. Аватар

    zhag

    01.12.2016 в 16:53

    Допустим, у нaс есть один физический довольно мощный сервер.
    Вот дальше можно не читать…

  3. Аватар

    olegbukatchuk

    03.12.2016 в 15:38

    Если речь о гипервизорах, то лучше XenServer сейчас ничего нет на рынке OpenSource-решений. А в целом выше у же отписались о Docker Swarm и Kubernetes.

Оставить мнение