Настройка высокой доступности с помощью keepalived и плавающих IP-адресов в Ubuntu 14.04

Высокая доступность – это тип проектирования системы, который позволяет приложению автоматически перезапускать или перенаправлять работу в другую совместимую систему в случае сбоя ведущего сервера. Что касается серверов, существует несколько различных технологий, необходимых для создания высокодоступной системы. В инфраструктуре должен быть компонент, который может перенаправить работу, и механизм для мониторинга ошибок и сбоев.

Демон keepalived может использоваться для мониторинга сервисов или систем и автоматического перехода на резервный ресурс в режиме ожидания в случае возникновения проблем. В этом мануале вы узнаете, как использовать keepalived для создания высокодоступного веб-сервиса. В настройке используется плавающий IP-адрес, который можно перемещать между двумя поддерживаемыми веб-серверами. Если ведущий сервер прекращает работу, плавающий IP-адрес будет автоматически переназначен второму серверу, что позволит возобновить работу приложения.

Читайте также: Использование плавающих IP-адресов

Требования

  • Два сервера Ubuntu 14.04, настроенных по этому мануалу.
  • Серверы должны находиться в одном ЦОД и иметь частную сеть.
  • API-токен.
  • Плавающий IP-адрес.

1: Установка и настройка Nginx

Хотя keepalived часто используется для мониторинга и балансировки нагрузки (что упрощает инфраструктуру), в этом мануале вместо него в качестве простого веб-сервера используется Nginx.

Обновите индекс пакетов на каждом из ваших серверов. Затем можно установить Nginx:

sudo apt-get update
sudo apt-get install nginx

В большинстве случаев настройка высокой доступности создается для обслуживания одного и того же контента. Однако в этом мануале Nginx будет обслуживать разный контент: это нужно для того, чтобы видеть, какой из двух серверов обслуживает запросы в тот или иной момент. Для этого нужно изменить страницу index.html по умолчанию на каждом из хостов. Откройте файл:

sudo nano /usr/share/nginx/html/index.html

На первом сервере замените контент файла этой строкой:

<h1>Primary</h1>

На втором сервере файл будет содержать такую строку:

<h1>Secondary</h1>

Сохраните и закройте файлы.

Сервер 1 будет теперь первичным, а сервер 2 – вторичным.

2: Сборка и установка keepalived

Затем нужно установить демон keepalived на все серверы инфраструктуры. В репозиториях Ubuntu по умолчанию есть версия keepalived, но она устарела и содержит несколько ошибок, которые влияют на работу конфигурации. Потому лучше собрать keepalived из исходного кода.

Прежде чем начать, нужно установить все зависимости, требуемые для сборки. Метапакет build-essential предоставит инструменты компиляции, а пакет libssl-dev содержит библиотеки SSL, на которых основан демон keepalived:

sudo apt-get install build-essential libssl-dev

После установки зависимостей можно скачать тарбол демона. Посетите эту страницу и найдите последнюю доступную версию keepalived. Кликните правой кнопкой и скопируйте адрес ссылки. Вернитесь на сервер, перейдите в домашний каталог и загрузите пакет:

cd ~
wget http://www.keepalived.org/software/keepalived-1.2.19.tar.gz

Распакуйте архив и перейдите в полученный каталог:

tar xzvf keepalived*
cd keepalived*

Соберите и установите демон:

./configure
make
sudo make install

3: Создание сценария Upstart для keepalived

Установка keepalived перенесла все бинарные и сопутствующие файлы в систему. Однако среди них нехватает сценария Upstart для системы Ubuntu 14.04.

Вы можете создать очень простой сценарий Upstart, который будет обрабатывать сервис keepalived. Откройте файл под названием keepalived.conf в /etc/init:

sudo nano /etc/init/keepalived.conf

Для начала добавьте краткое описание сервиса keepalived. Можно использовать описание демона из его справки. Затем укажите уровни запуска, на которых нужно запустить и остановить сервис; в данном случае для запуска используются уровни 2-5, а для остановки – все остальные уровни (например, при перезагрузке, отключении питания или в однопользовательском режиме).

description "load-balancing and high-availability service"
start on runlevel [2345]
stop on runlevel [!2345]

Поскольку этот сервис является неотъемлемой частью обеспечения высокой доступности вашего приложения, его необходимо перезагружать в случае сбоя. Затем нужно добавить строку exec, которая запустит сервис, и добавить в нее опцию —dont-fork, чтобы система Upstart правильно отслеживала pid:

description "load-balancing and high-availability service"
start on runlevel [2345]
stop on runlevel [!2345]
respawn
exec /usr/local/sbin/keepalived --dont-fork

Сохраните и закройте файл.

Такой файл нужно создать на всех серверах инфраструктуры.

4: Конфигурация keepalived

Теперь можно перейти к настройке keepalived.

Сервис ищет конфигурации в каталоге /etc/keepalived. Создайте этот каталог на обоих серверах:

sudo mkdir -p /etc/keepalived

Поиск внутренних IP-адресов серверов

Прежде чем продолжить работу над конфигурацией, нужно найти IP-адреса серверов инфраструктуры. Его можно найти в метаданных:

curl http://169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address && echo
10.132.7.107

Также для этого можно использовать инструменты iproute2:

ip -4 addr show dev eth1

Значение, которое вы ищете, выделено красным:

3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 10.132.7.107/16 brd 10.132.255.255 scope global eth1
valid_lft forever preferred_lft forever

Скопируйте это значение на обоих серверах. Их нужно будет использовать в конфигурации демона.

Конфигурация первичного сервера

Перейдите на сервер 1 и создайте главный конфигурационный файл keepalived. Демон ищет файл keepalived.conf в каталоге /etc/keepalived.

sudo nano /etc/keepalived/keepalived.conf

Начните с определения проверки работоспособности сервиса Nginx, открыв блок vrrp_script. Это настроит мониторинг состояния веб-сервера, что позволяет своевременно обнаружить сбой и начать восстановление.

Эта проверка очень проста. Каждые две секунды демон будет проверять, что процесс nginx все еще требует pid:

vrrp_script chk_nginx {
script "pidof nginx"
interval 2
}

Затем откройте блок vrrp_instance. Это основной раздел конфигурации, который определяет, как keepalived будет обеспечивать высокую доступность.

Настройте keepalived для использования частного интерфейса eth1. В настройках первичного сервера в параметре state нужно указать MASTER. Это исходное значение, которое будет использовать keepalived.

Во время голосования для выбора ноды используется опция priority. Это решение основывается на том, какой сервер имеет наибольшее значение этого параметра. Укажите 200 на первичном сервере:

vrrp_script chk_nginx {
script "pidof nginx"
interval 2
}
vrrp_instance VI_1 {
interface eth1
state MASTER
priority 200
}

Далее нужно присвоить этой группе кластера ID, который будут совместно использовать обе ноды. В мануале используется ID 33. В параметре unicast_src_ip укажите внутренний IP-адрес первичного сервера, а в unicast_peer – внутренний IP-адрес вторичного сервера.

vrrp_script chk_nginx {
script "pidof nginx"
interval 2
}
vrrp_instance VI_1 {
interface eth1
state MASTER
priority 200
virtual_router_id 33
unicast_src_ip primary_private_IP
unicast_peer {
secondary_private_IP
}
}

Затем можно настроить простую аутентификацию для связи демонов друг с другом. Это всего лишь базовая мера предосторожности, которая гарантирует, что в инфраструктуре работают только авторизованные серверы. Создайте подблок authentication. Внутри укажите настройте парольную аутентификацию, установив auth_type. В параметре auth_pass установите общий секретный ключ, который будет использоваться всеми нодами. Здесь имеют значение только первые восемь символов.

vrrp_script chk_nginx {
script "pidof nginx"
interval 2
}
vrrp_instance VI_1 {
interface eth1
state MASTER
priority 200
virtual_router_id 33
unicast_src_ip primary_private_IP
unicast_peer {
secondary_private_IP
}
authentication {
auth_type PASS
auth_pass password
}
}

Затем нужно использовать подпрограмму chk_nginx, созданную в начале файла, чтобы определить состояние работоспособности локальной системы. После этого нужно создать скрипт notify_master, который будет выполняться всякий раз, когда эта нода будет ведущей. Этот скрипт будет отвечать за запуск переназначения плавающего IP-адреса.

vrrp_script chk_nginx {
script "pidof nginx"
interval 2
}
vrrp_instance VI_1 {
interface eth1
state MASTER
priority 200
virtual_router_id 33
unicast_src_ip primary_private_IP
unicast_peer {
secondary_private_IP
}
authentication {
auth_type PASS
auth_pass password
}
track_script {
chk_nginx
}
notify_master /etc/keepalived/master.sh

Сохраните и закройте файл.

Конфигурация вторичного сервера

Теперь нужно создать подобный файл на вторичном сервере. Откройте файл в /etc/keepalived/keepalived.conf:

sudo nano /etc/keepalived/keepalived.conf

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

  • state: измените значение параметра на BACKUP, чтобы нода инициализировалась в режиме резервного копирования до проведения голосования.
  • priority: здесь нужно указать меньшее значение, чем на первичном сервере, например, 100.
  • unicast_src_ip: здесь нужно указать внутренний IP-адрес вторичного сервера.
  • unicast_peer: здесь нужно указать внутренний IP-адрес первичного сервера.

Изменив эти параметры, вы получите такой конфигурационный файл вторичного сервера:

vrrp_script chk_nginx {
script "pidof nginx"
interval 2
}
vrrp_instance VI_1 {
interface eth1
state BACKUP
priority 100
virtual_router_id 33
unicast_src_ip secondary_private_IP
unicast_peer {
primary_private_IP
}
authentication {
auth_type PASS
auth_pass password
}
track_script {
chk_nginx
}
notify_master /etc/keepalived/master.sh
}

Сохраните и закройте файл.

5: Создание сценария для переназначения плавающего IP-адреса

Затем нужно создать пару сценариев, которые будут использоваться для переназначения плавающего IP-адреса на текущий сервер, когда локальный экземпляр keepalived становится мастер-сервером.

Загрузка сценария

Загрузите в каталог /usr/local/bin простой сценарий Python, который будет переназначать плавающий IP-адрес с помощью API.

cd /usr/local/bin
sudo curl -LO http://do.co/assign-ip

Этот сценарий будет переназначать плавающий IP после запуска команды:

python /usr/local/bin/assign-ip floating_ip sever_ID

Это будет работать, только если у вас есть переменная окружения TOKEN, в которой указан валидный токен API.

Создайте такой токен и плавающий IP-адрес, если вы не сделали этого ранее.

Если вы запросите свой плавающий IP в браузере, он должен вернуть страницу index.html первичного сервера:

Primary

Создание сценария

Теперь у вас есть все компоненты, необходимые для создания сценария /usr/local/bin/assign-ip.

Этот сценарий нужно создать на обоих серверах.

sudo nano /etc/keepalived/master.sh

Для начала добавьте переменную TOKEN с токеном API и переменную IP с плавающим IP-адресом.

export TOKEN='api_token'
IP='floating_ip_addr'

Затем используйте команду curl, чтобы запросить в метаданных ID текущего сервера. Это значение будет присвоено переменной ID. Также нужно уточнить, имеет ли в настоящее время этот сервер назначенный ему плавающий IP-адрес. Результаты этого запроса сохраняются в переменной HAS_FLOATING_IP

export TOKEN='api_token'
IP='floating_ip_addr'
ID=$(curl -s http://169.254.169.254/metadata/v1/id)
HAS_FLOATING_IP=$(curl -s http://169.254.169.254/metadata/v1/floating_ip/ipv4/active)

Теперь можно использовать приведенные выше переменные для вызова сценария assign-ip. Сценарий будет использоваться только в случае, если плавающий IP-адрес еще не связан с текущим сервером. Это поможет свести к минимуму вызовы API и предотвратить конфликтующие запросы API в случаях, когда отношения между серверами быстро меняются.

Чтобы обработать случаи, когда плавающий IP обслуживает какое-то событие, запустите сценарий assign-ip несколько раз. В данном случае сценарий будет запускаться 10 раз с интервалом в 3 секунды между каждым вызовом. Цикл завершится немедленно, если перемещение плавающего IP-адреса будет выполнено успешно.

export TOKEN='api_token'
IP='floating_ip_addr'
ID=$(curl -s http://169.254.169.254/metadata/v1/id)
HAS_FLOATING_IP=$(curl -s http://169.254.169.254/metadata/v1/floating_ip/ipv4/active)
if [ $HAS_FLOATING_IP = "false" ]; then
n=0
while [ $n -lt 10 ]
do
python /usr/local/bin/assign-ip $IP $ID && break
n=$((n+1))
sleep 3
done
fi

Сохраните и закройте файл.

Сделайте сценарий исполняемым:

sudo chmod +x /etc/keepalived/master.sh

6: Запуск keepalived и тестирование настройки

Теперь демон keepalived и все его сопутствующие скрипты полностью настроены. Можно запустить сервис на обеих машинах, набрав:

sudo start keepalived

Сервис запустится на каждой машине, свяжется со второй нодой и аутентифицируется с помощью общего секретного ключа. Каждый демон будет отслеживать локальный процесс Nginx и прослушивать сигналы удаленного процесса keepalived.

Если оба сервера работают корректно, при посещении плавающего адреса в браузере вы увидите страницу Nginx первичного сервера:

Primary

Протестируйте высокую доступность и функцию обработки сбоев инфраструктуры.

Обработка сбоев должна происходить при возникновении любого из следующих условий:

  1. Когда проверка состояния Nginx на первичном сервере указывает на то, что Nginx больше не работает. В этом случае демон keepalived первичного сервера перейдет в состояние «fault». Он уведомит вторичный сервер о том, что он должен взять на себя роль первичного сервера и присвоить себе плавающий IP-адрес.
  2. Когда вторичный сервер теряет свое соединение keepalived с первичным сервером. Если по какой-либо причине вторичный сервер не может связаться с первичным сервером, он перейдет в состояние master и попытается присвоить плавающий IP-адрес.

Если первичный сервер позже восстановится, он вернется в состояние master и вернет плавающий IP-адрес, потому что он инициирует новое голосование (ведь ему по-прежнему принадлежит наивысший приоритет).

Тестирование обработки ошибок Nginx

Проверить обработку ошибок в первой ситуации можно путем остановки Nginx на первичном сервере:

sudo service nginx stop

Обновите страницу в браузере, и вы увидите сообщение об ошибке:

This webpage is not available
ERR_CONNECTION_REFUSED

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

Secondary

Чтобы устранить неполадку, перезапустите сервис Nginx на первичном сервере:

sudo service nginx start

Обновив страницу через несколько секунд, вы обнаружите, что первичный сервер восстановил плавающий IP-адрес:

Primary

Тестирование обработки ошибок сервера

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

sudo reboot

Опять же, сначала вы увидите сообщение об ошибке:

This webpage is not available
ERR_CONNECTION_REFUSED

Через несколько секунд вторичный сервер обработает запросы, и на странице появится сообщение:

Secondary

Спустя пару секунд первичный сервер завершит перезагрузку и вернет себе плавающий IP-адрес.

Заключение

Теперь у вас есть простая инфраструктура высокой доступности на основе keepalived, интерфейса API и плавающего IP-адреса. Используйте эту инфраструктуру как шаблон для построения более сложного кластера.

Читайте также: Настройка высокой доступности с помощью Heartbeat и плавающих IP-адресов в Ubuntu 16.04

Tags: , ,
  • Дмитрий Иванов

    А что такое ТОКЕН API и как его создать?
    «Это будет работать, только если у вас есть переменная окружения TOKEN, в которой указан валидный токен API.

    Создайте такой токен и плавающий IP-адрес, если вы не сделали этого ранее.»