Поиск по сайту:

Как настроить высокодоступные серверы HAProxy с Keepalived и зарезервированными IP-адресами в Ubuntu 14.04


Введение

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

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

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

Предпосылки

Чтобы выполнить это руководство, вам необходимо создать четыре сервера Ubuntu 14.04 в своей учетной записи DigitalOcean. Все серверы должны быть расположены в одном центре обработки данных и должны иметь включенную частную сеть.

На каждом из этих серверов вам потребуется пользователь без полномочий root, настроенный с доступом sudo. Вы можете следовать нашему руководству по первоначальной настройке сервера Ubuntu 14.04, чтобы узнать, как настроить этих пользователей.

Поиск информации о сети сервера

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

Для выполнения этого руководства вам потребуется следующая информация о ваших серверах:

  • веб-серверы: частный IP-адрес
  • балансировщики нагрузки: частные и привязные IP-адреса

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

Самый простой способ найти частный IP-адрес вашего дроплета — использовать curl для получения частного IP-адреса из службы метаданных DigitalOcean. Эту команду следует запускать из ваших капель. В каждой капле введите:

  1. curl 169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address && echo

Правильный IP-адрес должен быть напечатан в окне терминала:

Output
10.132.20.236

Поиск якорных IP-адресов

«IP-адрес привязки» — это локальный частный IP-адрес, к которому будет привязан зарезервированный IP-адрес при подключении к серверу DigitalOcean. Это просто псевдоним для обычного адреса eth0, реализованный на уровне гипервизора.

Самый простой и наименее подверженный ошибкам способ получить это значение — прямо из службы метаданных DigitalOcean. Используя curl, вы можете обратиться к этой конечной точке на каждом из ваших серверов, набрав:

  1. curl 169.254.169.254/metadata/v1/interfaces/public/0/anchor_ipv4/address && echo

IP-адрес привязки будет напечатан в отдельной строке:

Output
10.17.1.18

Установка и настройка веб-сервера

После сбора вышеуказанных данных мы можем перейти к настройке наших сервисов.

В этой настройке программное обеспечение, выбранное для уровня веб-сервера, довольно взаимозаменяемо. В этом руководстве будет использоваться Nginx, поскольку он является универсальным и довольно простым в настройке. Если вам удобнее работать с Apache или веб-сервером (пригодным для работы) для конкретного языка, не стесняйтесь использовать его вместо этого. HAProxy будет просто передавать клиентские запросы на внутренние веб-серверы, которые могут обрабатывать запросы так же, как и прямые клиентские подключения.

Мы начнем с настройки наших внутренних веб-серверов. Оба этих сервера будут обслуживать один и тот же контент. Они будут принимать веб-соединения только через свои частные IP-адреса. Это поможет обеспечить направление трафика через один из двух серверов HAProxy, которые мы настроим позже.

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

Установка Nginx

Мы будем устанавливать Nginx на наших веб-серверах, чтобы обеспечить эту функциональность.

Начните с входа под своим пользователем sudo на две машины, которые вы хотите использовать в качестве веб-серверов. Обновите локальный индекс пакетов на каждом из ваших веб-серверов и установите Nginx, набрав:

  1. sudo apt-get update
  2. sudo apt-get install nginx

Настройте Nginx так, чтобы он разрешал только запросы от балансировщиков нагрузки.

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

Чтобы внести эти изменения, откройте файл блока сервера Nginx по умолчанию на каждом из ваших веб-серверов:

  1. sudo nano /etc/nginx/sites-available/default

Для начала мы изменим директивы listen. Измените директиву listen для прослушивания частного IP-адреса текущего веб-сервера на порту 80. Удалите лишнюю строку listen. Это должно выглядеть примерно так:

server {
    listen web_server_private_IP:80;

    . . .

После этого мы настроим две директивы allow, чтобы разрешить трафик, исходящий с частных IP-адресов наших двух балансировщиков нагрузки. За этим последует правило deny all, чтобы запретить весь остальной трафик:

server {
    listen web_server_private_IP:80;

    allow load_balancer_1_private_IP;
    allow load_balancer_2_private_IP;
    deny all;

    . . .

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

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

  1. sudo nginx -t

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

  1. sudo service nginx restart

Тестирование изменений

Чтобы проверить, правильно ли ограничены ваши веб-серверы, вы можете отправлять запросы с помощью curl из разных мест.

На самих ваших веб-серверах вы можете попробовать простой запрос локального контента, набрав:

  1. curl 127.0.0.1

Из-за ограничений, которые мы установили в наших блочных файлах сервера Nginx, этот запрос будет фактически отклонен:

Output
curl: (7) Failed to connect to 127.0.0.1 port 80: Connection refused

Это ожидаемо и отражает поведение, которое мы пытались реализовать.

Теперь из любого из балансировщиков нагрузки мы можем сделать запрос на любой из общедоступных IP-адресов нашего веб-сервера:

  1. curl web_server_public_IP

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

Output
curl: (7) Failed to connect to web_server_public_IP port 80: Connection refused

Однако если мы изменим вызов, чтобы сделать запрос с использованием частного IP-адреса веб-сервера, он должен работать правильно:

  1. curl web_server_private_IP

Должна быть возвращена страница Nginx index.html по умолчанию:

Output
<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> . . .

Проверьте это с обоих балансировщиков нагрузки на оба веб-сервера. Каждый запрос на частный IP-адрес должен быть выполнен успешно, а каждый запрос на общедоступные адреса — с ошибкой.

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

Установите и настройте HAProxy

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

Конфигурация HAProxy будет передавать запросы на оба веб-сервера. Балансировщики нагрузки будут прослушивать запросы на своем якорном IP-адресе. Как упоминалось ранее, это IP-адрес, к которому будет привязан зарезервированный IP-адрес при подключении к дроплету. Это гарантирует, что будет пересылаться только трафик, исходящий с зарезервированного IP-адреса.

Установить HAProxy

Первым шагом, который нам необходимо выполнить для наших балансировщиков нагрузки, будет установка пакета haproxy. Мы можем найти это в репозиториях Ubuntu по умолчанию. Обновите локальный индекс пакетов в ваших балансировщиках нагрузки и установите HAProxy, набрав:

  1. sudo apt-get update
  2. sudo apt-get install haproxy

Настроить HAProxy

Первый элемент, который нам нужно изменить при работе с HAProxy, — это файл /etc/default/haproxy. Откройте этот файл сейчас в вашем редакторе:

  1. sudo nano /etc/default/haproxy

Этот файл определяет, будет ли HAProxy запускаться при загрузке. Поскольку мы хотим, чтобы служба запускалась автоматически при каждом включении сервера, нам нужно изменить значение ENABLED на \1:

# Set ENABLED to 1 if you want the init script to start haproxy.
ENABLED=1
# Add extra flags here.
#EXTRAOPTS="-de -m 16"

Сохраните и закройте файл после внесения вышеуказанного редактирования.

Далее мы можем открыть основной файл конфигурации HAProxy:

  1. sudo nano /etc/haproxy/haproxy.cfg

Первый элемент, который нам нужно настроить, — это режим, в котором будет работать HAProxy. Мы хотим настроить TCP или уровень 4, балансировку нагрузки. Для этого нам нужно изменить строку mode в разделе default. Мы также должны изменить параметр, следующий сразу за журналом:

. . .

defaults
    log     global
    mode    tcp
    option  tcplog

. . .

В конце файла нам нужно определить конфигурацию нашего внешнего интерфейса. Это будет определять, как HAProxy прослушивает входящие соединения. Мы привяжем HAProxy к IP-адресу привязки балансировщика нагрузки. Это позволит прослушивать трафик, исходящий с зарезервированного IP-адреса. Для простоты мы назовем наш интерфейс \www. Мы также укажем серверную часть по умолчанию для передачи трафика (которую мы сейчас настроим):

. . .

defaults
    log     global
    mode    tcp
    option  tcplog

. . .

frontend www
    bind    load_balancer_anchor_IP:80
    default_backend nginx_pool

Далее мы можем настроить наш бэкэнд-раздел. Это укажет нисходящие местоположения, через которые HAProxy будет передавать получаемый трафик. В нашем случае это будут частные IP-адреса обоих настроенных нами веб-серверов Nginx. Мы укажем традиционную циклическую балансировку и снова установим режим «tcp»:

. . .

defaults
    log     global
    mode    tcp
    option  tcplog

. . .

frontend www
    bind load_balancer_anchor_IP:80
    default_backend nginx_pool

backend nginx_pool
    balance roundrobin
    mode tcp
    server web1 web_server_1_private_IP:80 check
    server web2 web_server_2_private_IP:80 check

Когда вы закончите вносить вышеуказанные изменения, сохраните и закройте файл.

Убедитесь, что сделанные нами изменения конфигурации представляют допустимый синтаксис HAProxy, набрав:

  1. sudo haproxy -f /etc/haproxy/haproxy.cfg -c

Если об ошибках не сообщалось, перезапустите службу, набрав:

  1. sudo service haproxy restart

Тестирование изменений

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

С серверов балансировщика нагрузки попробуйте запросить локальный хост, собственный общедоступный IP-адрес балансировщика нагрузки или собственный частный IP-адрес сервера:

  1. curl 127.0.0.1
  2. curl load_balancer_public_IP
  3. curl load_balancer_private_IP

Все они должны завершиться ошибкой с сообщениями, похожими на это:

Output
curl: (7) Failed to connect to address port 80: Connection refused

Однако если вы сделаете запрос к якорному IP-адресу балансировщика нагрузки, он должен завершиться успешно:

  1. curl load_balancer_anchor_IP

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

Output
<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> . . .

Если это поведение соответствует поведению вашей системы, то ваши балансировщики нагрузки настроены правильно.

Сборка и установка Keepalived

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

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

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

  1. sudo apt-get install build-essential libssl-dev

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

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

Используйте команду tar, чтобы расширить архив. Переместитесь в полученный каталог:

  1. tar xzvf keepalived*
  2. cd keepalived*

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

  1. ./configure
  2. make
  3. sudo make install

Теперь демон должен быть установлен в обеих системах балансировки нагрузки.

Создайте скрипт Keepalived Upstart

Установка keepalived переместила все двоичные файлы и вспомогательные файлы на место в нашей системе. Однако одна часть, которая не была включена, — это скрипт Upstart для наших систем Ubuntu 14.04.

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

  1. sudo nano /etc/init/keepalived.conf

Внутри мы можем начать с простого описания функций, которые предоставляет keepalived. Мы будем использовать описание из прилагаемой страницы man. Далее мы укажем уровни запуска, на которых служба должна запускаться и останавливаться. Мы хотим, чтобы эта служба была активна во всех нормальных условиях (уровни запуска 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

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

Создайте файл конфигурации Keepalived

Теперь, когда наши файлы Upstart готовы, мы можем перейти к настройке keepalived.

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

  1. sudo mkdir -p /etc/keepalived

Создание конфигурации основного балансировщика нагрузки

Затем на сервере балансировщика нагрузки, который вы хотите использовать в качестве основного сервера, создайте основной файл конфигурации keepalived. Демон ищет файл с именем keepalived.conf внутри каталога /etc/keepalived:

  1. sudo nano /etc/keepalived/keepalived.conf

Внутри мы начнем с определения проверки работоспособности для нашей службы HAProxy, открыв блок vrrp_script. Это позволит keepalived отслеживать наш балансировщик нагрузки на наличие сбоев, чтобы он мог сигнализировать о том, что процесс не работает, и начать меры по восстановлению.

Наша проверка будет очень простой. Каждые две секунды мы будем проверять, что процесс с именем haproxy все еще требует pid:

vrrp_script chk_haproxy {
    script "pidof haproxy"
    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


}

Далее мы назначим идентификатор для этой кластерной группы, который будет общим для обоих узлов. В этом примере мы будем использовать «33». Нам нужно установить unicast_src_ip на частный IP-адрес нашего основного балансировщика нагрузки. Мы установим unicast_peer на частный IP-адрес нашего вторичного балансировщика нагрузки. адрес:

vrrp_script chk_haproxy {
    script "pidof haproxy"
    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
    }


}

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

vrrp_script chk_haproxy {
    script "pidof haproxy"
    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
    }


}

Затем мы скажем keepalived использовать проверку, которую мы создали в верхней части файла, помеченную chk_haproxy, для определения работоспособности локальной системы. Наконец, мы установим скрипт notify_master, который выполняется всякий раз, когда этот узел становится «мастером» пары. Этот скрипт будет отвечать за запуск переназначения зарезервированного IP-адреса. Мы создадим этот скрипт на мгновение:

vrrp_script chk_haproxy {
    script "pidof haproxy"
    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_haproxy
    }

    notify_master /etc/keepalived/master.sh
}

После того, как вы настроили указанную выше информацию, сохраните и закройте файл.

Создание конфигурации вторичного балансировщика нагрузки

Далее мы создадим сопутствующий скрипт на нашем вторичном балансировщике нагрузки. Откройте файл в /etc/keepalived/keepalived.conf на вашем вторичном сервере:

  1. sudo nano /etc/keepalived/keepalived.conf

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

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

Когда вы измените эти значения, сценарий для вторичного сервера должен выглядеть следующим образом:

vrrp_script chk_haproxy {
    script "pidof haproxy"
    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_haproxy
    }

    notify_master /etc/keepalived/master.sh
}

После того, как вы ввели сценарий и изменили соответствующие значения, сохраните и закройте файл.

Создайте сценарии перехода зарезервированного IP-адреса

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

Загрузите сценарий назначения зарезервированного IP-адреса

Сначала мы загрузим общий скрипт Python (написанный менеджером сообщества DigitalOcean), который можно использовать для переназначения зарезервированного IP-адреса дроплету с использованием API DigitalOcean. Мы должны загрузить этот файл в каталог /usr/local/bin:

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

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

  1. python /usr/local/bin/assign-ip reserved_ip droplet_ID

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

Создайте токен API DigitalOcean

Чтобы использовать приведенный выше скрипт, нам нужно будет создать токен DigitalOcean API в нашей учетной записи.

В панели управления нажмите на ссылку «API» вверху. В правой части страницы API нажмите «Создать новый токен»:

На следующей странице выберите имя для вашего токена и нажмите кнопку «Создать токен»:

На странице API будет отображаться ваш новый токен:

Скопируйте токен сейчас. В целях безопасности нет возможности снова отобразить этот токен позже. Если вы потеряете этот токен, вам придется уничтожить его и создать новый.

Настройте зарезервированный IP-адрес для вашей инфраструктуры

Далее мы создадим и назначим зарезервированный IP-адрес для использования на наших серверах.

В панели управления DigitalOcean перейдите на вкладку «Сеть» и выберите элемент навигации «Зарезервированные IP-адреса». Выберите основной балансировщик нагрузки из меню для первоначального назначения:

Новый зарезервированный IP-адрес будет создан в вашей учетной записи и назначен указанной капле:

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

Скопируйте зарезервированный IP-адрес вниз. Это значение понадобится вам в приведенном ниже сценарии.

Создайте сценарий оболочки

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

Создайте файл сейчас на обоих ваших балансировщиках нагрузки, набрав:

  1. sudo nano /etc/keepalived/master.sh

Внутри начните с назначения и экспорта переменной с именем DO_TOKEN, которая содержит только что созданный токен API. Ниже мы можем назначить переменную с именем IP, которая содержит ваш зарезервированный IP-адрес:

export DO_TOKEN='digitalocean_api_token'
IP='reserved_ip_addr'

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

export DO_TOKEN='digitalocean_api_token'
IP='reserved_ip_addr'
ID=$(curl -s http://169.254.169.254/metadata/v1/id)
HAS_RESERVED_IP=$(curl -s http://169.254.169.254/metadata/v1/reserved_ip/ipv4/active)

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

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

export DO_TOKEN='digitalocean_api_token'
IP='reserved_ip_addr'
ID=$(curl -s http://169.254.169.254/metadata/v1/id)
HAS_RESERVED_IP=$(curl -s http://169.254.169.254/metadata/v1/reserved_ip/ipv4/active)

if [ $HAS_RESERVED_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

Сохраните и закройте файл, когда закончите.

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

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

Запустите службу Keepalived и проверьте отказоустойчивость

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

  1. sudo start keepalived

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

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

Мы можем протестировать отказоустойчивость простым способом, просто отключив HAProxy на нашем основном балансировщике нагрузки:

  1. sudo service haproxy stop

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

http://reserved_IP_addr

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

Наша служба HAProxy по-прежнему отключена на нашем основном балансировщике нагрузки, поэтому это указывает на то, что наш вторичный балансировщик нагрузки взял на себя управление. Используя keepalived, вторичный сервер смог определить, что произошло прерывание службы. Затем он перешел в состояние «мастер» и потребовал зарезервированный IP-адрес с помощью API DigitalOcean.

Теперь мы можем снова запустить HAProxy на основном балансировщике нагрузки:

  1. sudo service haproxy start

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

Визуализация перехода

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

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

Следите за журналами на веб-серверах

На каждом из наших внутренних веб-серверов мы можем отследить местоположение /var/log/nginx/access.log. Это покажет каждый запрос, сделанный на сервер. Поскольку наши балансировщики нагрузки равномерно распределяют трафик, используя циклическую ротацию, каждый серверный веб-сервер должен получать около половины сделанных запросов.

К счастью, адрес клиента является самым первым полем в журнале доступа. Мы можем извлечь значение с помощью простой команды awk. Запустите следующее на обоих ваших веб-серверах Nginx:

  1. sudo tail -f /var/log/nginx/access.log | awk '{print $1;}'

Скорее всего, они будут показывать в основном один адрес:

Output
. . . primary_lb_private_IP primary_lb_private_IP secondary_lb_private_IP secondary_lb_private_IP primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP

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

Оставьте команду tail запущенной на обоих ваших веб-серверах.

Автоматизируйте запросы к зарезервированному IP-адресу

Теперь на вашем локальном компьютере мы будем запрашивать веб-контент по зарезервированному IP-адресу каждые 2 секунды. Это позволит нам легко увидеть изменение балансировщика нагрузки. В своем локальном терминале введите следующее (мы отбрасываем фактический ответ, потому что он должен быть одинаковым независимо от того, какой балансировщик нагрузки используется):

  1. while true; do curl -s -o /dev/null reserved_IP; sleep 2; done

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

Прервать службу HAProxy на основном балансировщике нагрузки

Теперь мы можем снова отключить службу HAProxy на нашем основном балансировщике нагрузки:

  1. sudo service haproxy stop

Через несколько секунд на ваших веб-серверах вы должны увидеть список IP-адресов, переходящих с частного IP-адреса основного балансировщика нагрузки на частный IP-адрес вторичного балансировщика нагрузки:

Output
. . . primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP secondary_lb_private_IP secondary_lb_private_IP secondary_lb_private_IP secondary_lb_private_IP

Все новые запросы выполняются из вашего вторичного балансировщика нагрузки.

Теперь снова запустите экземпляр HAProxy на вашем основном балансировщике нагрузки:

  1. sudo service haproxy start

Вы увидите, как клиентские запросы переходят обратно на частный IP-адрес основного балансировщика нагрузки в течение нескольких секунд:

Output
. . . primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP secondary_lb_private_IP secondary_lb_private_IP secondary_lb_private_IP secondary_lb_private_IP primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP

Основной сервер восстановил контроль над зарезервированным IP-адресом и возобновил свою работу в качестве основного балансировщика нагрузки для инфраструктуры.

Настройте Nginx для регистрации фактического IP-адреса клиента

Как вы видели, журналы доступа Nginx показывают, что все клиентские запросы поступают с частного IP-адреса текущего балансировщика нагрузки, а не с фактического IP-адреса клиента, который первоначально сделал запрос (т. е. вашего локального компьютера). Часто бывает полезно регистрировать IP-адрес исходного клиента, а не сервера балансировщика нагрузки. Этого легко добиться, внеся несколько изменений в конфигурацию Nginx на всех ваших внутренних веб-серверах.

На обоих веб-серверах откройте файл nginx.conf в редакторе:

  1. sudo nano /etc/nginx/nginx.conf

Найдите раздел «Настройки ведения журнала» (внутри блока http) и добавьте следующую строку:

log_format haproxy_log 'ProxyIP: $remote_addr - ClientIP: $http_x_forwarded_for - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent "$http_referer" ' '"$http_user_agent"';

Сохранить и выйти. Это определяет новый формат журнала, называемый haproxy_log, который добавляет значение $http_x_forwarded_for — IP-адрес клиента, сделавшего первоначальный запрос, — к записям журнала доступа по умолчанию. Мы также включаем $remote_addr, который является IP-адресом обратного прокси-балансировщика нагрузки (т. е. активного сервера балансировщика нагрузки).

Затем, чтобы использовать этот новый формат журнала, нам нужно добавить строку в наш блок сервера по умолчанию.

На обоих веб-серверах откройте конфигурацию сервера default:

  1. sudo nano /etc/nginx/sites-available/default

В блоке server (прямо под директивой listen — хорошее место) добавьте следующую строку:

        access_log /var/log/nginx/access.log haproxy_log;

Сохранить и выйти. Это говорит Nginx вести свои журналы доступа, используя формат журнала haproxy_log, который мы создали выше.

На обоих веб-серверах перезапустите Nginx, чтобы изменения вступили в силу:

  1. sudo service nginx restart

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

New Nginx access logs:
. . . ProxyIP: load_balancer_private_IP - ClientIP: local_machine_IP - - [05/Nov/2015:15:05:53 -0500] "GET / HTTP/1.1" 200 43 "-" "curl/7.43.0" . . .

Если ваши журналы выглядят хорошо, все готово!

Заключение

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

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