Поговорим о горизонтальном масштабировании. Допустим, ваш проект вырос до размеров, когда один сервер не справляется с нагрузкой, а возможностей для вертикального роста ресурсов уже нет. В этом случае дальнейшее развитие инфраструктуры проекта обычно происходит за счет увеличения числа однотипных серверов с распределением нагрузки между ними. Такой подход не только позволяет решить проблему с ресурсами, но и добавляет надежности проекту — при выходе из строя одного или нескольких компонентов его работоспособность в целом не будет нарушена. Большую роль в этой схеме играет балансировщик — система, которая занимается распределением запросов/трафика. На этапе ее проектирования важно предусмотреть следующие ключевые требования: Фактически, это описание кластера, узлами которого являются серверы-балансеры. В этой статье мы хотим поделиться рецептом подобного кластера, простого и неприхотливого к ресурсам, концепцию которого успешно применяем в собственной инфраструктуре для балансировки запросов к серверам нашей панели управления, внутреннему DNS серверу, кластеру Galera и разнообразными микросервисам. — Серверы, входящие в состав кластера, будем называть узлами или балансерами.
— Конечными серверами будем называть хосты, на которые проксируется трафик через кластер.
— Виртуальным IP будем называть адрес, “плавающий” между всеми узлами, и на который должны указывать имена сервисов в DNS. — Для настройки кластера потребуется как минимум два сервера (или вирт.машины) с двумя сетевыми интерфейсами на каждом.
— Первый интерфейс будет использоваться для связи с внешним миром. Здесь будут настроены реальный и виртуальный IP адреса.
— Второй интерфейс будет использоваться под служебный трафик, для общения узлов друг с другом. Здесь будет настроен адрес из приватной (“серой”) сети 172.16.0.0/24.
Вторые интерфейсы каждого из узлов должны находиться в одном сегменте сети. VRRP, Virtual Router Redundancy Protocol — в контексте этой статьи, реализация "плавающего" между узлами кластера виртуального IP адреса. В один момент времени такой адрес может быть поднят на каком-то одном узле, именуемом MASTER. Второй узел называется BACKUP. Оба узла постоянно обмениваются специальными heartbeat сообщениями. Получение или неполучение таких сообщений в рамках заданных промежутков дает основания для переназначения виртуального IP на “живой” сервер. Более подробно о протоколе можно прочитать здесь. LVS, Linux Virtual Server — механизм балансировки на транспортном/сеансовом уровне, встроенный в ядро Linux в виде модуля IPVS. Хорошее описание возможностей LVS можно найти здесь и здесь.
Суть работы сводится к указанию того, что есть определенная пара “IP + порт” и она является виртуальным сервером. Для этой пары назначаются адреса реальных серверов, ответственных за обработку запросов, задается алгоритм балансировки, а также режим перенаправления запросов. В нашей системе мы будем использовать Nginx как промежуточное звено между LVS и конечными серверами, на которые нужно проксировать трафик. Nginx будет присутствовать на каждом узле. Для настроек VRRP и взаимодействия с IPVS будем использовать демон Keepalived, написанный в рамках проекта Linux Virtual Server. Система будет представлять собой связку из двух независимых друг от друга равнозначных узлов-балансеров, объединенных в кластер средствами технологии LVS и протокола VRRP. Точкой входа для трафика будет являться виртуальный IP адрес, поднятый либо на одном, либо на втором узле. Поступающие запросы LVS перенаправляет к одному из запущенных экземпляров Nginx — локальному или на соседнем узле. Такой подход позволяет равномерно размазывать запросы между всеми узлами кластера, т.е. более оптимально использовать ресурсы каждого балансера. Работа Nginx заключается в проксировании запросов на конечные сервера. Начиная с версии 1.9.13 доступны функции проксирования на уровне транспортных протоколов tcp и udp. Каждый vhost/stream будет настроен принимать запросы как через служебный интерфейс с соседнего балансера так и поступающие на виртуальный IP. Причем даже в том случае, если виртуальный IP адрес физически не поднят на данном балансере (Keepalived назначил серверу роль BACKUP). Таким образом, схема хождения трафика в зависимости от состояния балансера (MASTER или BACKUP) выглядит так: MASTER: BACKUP: В качестве операционной системы будем использовать Debian Jessie с подключенными backports репозиториями. Установим на каждый узел-балансер пакеты с необходимым для работы кластера ПО и сделаем несколько общесистемных настроек: На интерфейсе eth1 настроим адреса из серой сети 172.16.0.0/24: Виртуальный IP адрес прописывать на интерфейсе eth0 не нужно. Это сделает Keepalived. В файл /etc/sysctl.d/local.conf добавим следующие директивы: Первая включает возможность слушать IP, которые не подняты локально (это нужно для работы Nginx). Вторая включает автоматическую защиту от DDoS на уровне балансировщика IPVS (при нехватке памяти под таблицу сессий начнётся автоматическое вычищение некоторых записей). Третья увеличивает размер conntrack таблицы. В /etc/modules включаем загрузку модуля IPVS при старте системы: Параметр conn_tab_bits определяет размер таблицы с соединениями. Его значение является степенью двойки. Максимально допустимое значение — 20. Кстати, если модуль не будет загружен до старта Keepalived, последний начинает сегфолтиться. Теперь перезагрузим оба узла-балансера. Так мы убедимся, что при старте вся конфигурация корректно поднимется. Общие настройки выполнены. Дальнейшие действия будем выполнять в контексте двух задач: Вводные данные: Начнем с конфигурации Nginx. Добавим описание секции stream в /etc/nginx/nginx.conf: И создадим соответствующий каталог: Настройки для веб-серверов добавим в файл /etc/nginx/sites-enabled/web_servers.conf  Настройки для DNS-серверов добавим в файл /etc/nginx/stream-enabled/dns_servers.conf  Далее остается сконфигурировать Keepalived (VRRP + LVS). Это немного сложнее, поскольку нам потребуется написать специальный скрипт, который будет запускаться при переходе узла-балансера между состояниями MASTER/BACKUP. Все настройки Keepalived должны находиться в одном файле — /etc/keepalived/keepalived.conf. Поэтому все нижеследующие блоки с конфигурациями VRRP и LVS нужно последовательно сохранить в этом файле. Настройки VRRP: Скрипт, который упоминался выше — /usr/local/bin/nat-switch. Он запускается каждый раз, когда у текущего VRRP инстанса меняется состояние. Его задача заключается в том, чтобы балансер, находящийся в состоянии BACKUP, умел корректно обработать пакеты, адресованные на виртуальный IP. Для решения этой ситуации используются возможности DNAT. А именно, правило вида: При переходе в состояние MASTER, скрипт удаляет это правило. Здесь можно найти вариант скрипта nat-switch, написанный для данного примера. Настройки LVS для группы веб-серверов: Настройки LVS для группы DNS-серверов: В завершении перезагрузим конфигурацию Nginx и Keepalived: Посмотрим как балансировщик распределяет запросы к конечным серверам. Для этого на каждом из веб-серверов создадим index.php с каким-нибудь простым содержимым: И сделаем несколько запросов по http к виртуальному IP 192.168.0.100 : Результат: Если в процессе выполнения этого цикла посмотреть на статистику работы LVS (на MASTER узле), то мы можем увидеть следующую картину: Результат: Здесь видно как происходит распределение запросов между узлами кластера: есть два активных соединения, которые обрабатываются в данный момент и 6 уже обработанных соединений. Статистику по все соединениям, проходящим через LVS, можно посмотреть так: Результат: Здесь, соответственно, видим то же самое: 2 активных и 6 неактивный соединений. Предложенная нами конфигурация может послужить отправным пунктом для проектирования частного решения под конкретный проект со своими требованиями и особенностями. Если у вас возникли вопросы по статье или что-то показалось спорным — пожалуйста, оставляйте свои комментарии, будем рады обсудить. хостинг провайдер