Пример горизонтального масштабирования для распределения запросов между несколькими серверами для повышения отказоустойчивости.
Рассмотрим решение по балансировке нескольких веб-серверов при помощи сервиса HAProxy.
Технические требования
- Сервер под балансировщик с двумя сетевыми интерфейсами (Рекомендация. Внешний адрес для связи с внешним миром и локальный для общения между узлами кластера);
- Два и более серверов под распределение запросов/трафика;
В примере будет использоваться дистрибутив Linux CentOS 7.
Установка и настройка backend-серверов
В качестве backend-серверов я буду использовать несколько веб-серверов с NGINX и настроенным SSL.
Прежде всего установим NGINX
yum install nginx
Выполним настройку веб-сервера
server {
listen 80;
server_name devservers.network;
rewrite ^(.*)$ https://devservers.network$1 permanent;
}
server {
server_name devservers.network;
access_log /srv/www/devservers.network/logs/access.log;
error_log /srv/www/devservers.network/logs/error.log;
root /srv/www/devservers.network/public_html;
ssl on;
ssl_session_timeout 24h;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
listen 443 ssl http2 proxy_protocol;
set_real_ip_from 10.0.1.10/32;
real_ip_header proxy_protocol;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
location / {
try_files $uri $uri/ /index.html;
}
location ~ .(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
try_files $uri =404;
}
}
Конфигурацию SSL можно выполнить и на самом балансировщике, а бэкенд сервера оставить работать на 80 порту, но в моем случае я буду использовать режим SSL Pass-Through
. Не забываем поместить SSL-сертификаты в директорию /etc/nginx/ssl
.
Для того, чтобы принимать реальные IP-адреса клиентов на веб-сервере от HAProxy необходимо добавить proxy_protocol
в параметр listen, а также указать реальный адрес откуда разрешить принимать запросы:
set_real_ip_from 10.0.1.10/32;
real_ip_header proxy_protocol;
Создадим приветственную страницу на обоих веб-серверах touch /srv/www/devservers.network/public_html
со следующим содержимым, изменив только номер сервера для его дальнейшего определения:
<!DOCTYPE html>
<html>
<head>
<title>Server #1</title>
</head>
<body>
<h1>This is server #1</h1>
</body>
</html>
Добавляем NGINX в автозагрузку и запускаем сервис.
systemctl enable nginx
systemctl start nginx
И не забываем выполнить настройку Firewalld
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
Установка и настройка балансировщика
В качестве сервера балансировки я буду использовать VDS сервер с ресурсами 1 vCPU и 1Gb RAM. При правильной настройке, данных мощностей хватит для обслуживания 10-15к одновременных сессий, чего вполне достаточно для среднестатистического интернет-ресурса.
Установим HAProxy
Пакет HAProxy доступен в базовой репозитории CentOS.
yum install haproxy
Настройка HAProxy
HAProxy обладает очень гибкими настройками и конфигурация может содержать большое количество директив и условий. Конфигурационный файл состоит из нескольких секций. Директивы frontend, backend, listen должны иметь своё имя, к примеру defaults — может, но не обязательно, а такие как global — не должны.
Выполняем конфигурацию HAProxy в файле /etc/haproxy/haproxy.cfg
. Рекомендую использовать свой конфигурационный файл, а представленный по умолчанию оставить как резерв.
Секция global
global
log /dev/log local0
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
stats timeout 30s
maxconn 4000
user haproxy
group haproxy
daemon
Рассмотрим настройки в директиве global
:
- log — вести лог в
/dev/log
сохраняя в local0; - chroot — настройки безопасности, позволяющие работать HAProxy только в указанной директории;
- maxconn — максимальное количество соединений на один процесс;
- daemon — запуск процесса как демона.
Секция defaults
В секции defaults описываются параметры по умолчанию для всех других секций, следующих за данной. В файле конфигурации может быть несколько секций defaults, в этом случае параметры, описанные в данной секции, будут переопределены в следующей, и будут применяться к секциям, идущим за ней.
В нашем примере указаны следующие параметры:
defaults
log global
mode http
retries 3
option httplog
option redispatch
maxconn 2000
contimeout 2000
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
- log — указывает в какой лог вести запись (global в данном случае означает, что используются параметры, заданные в секции global);
- mode — устанавливает протокол взаимодействия, принимает одно из значений:
tcp
,http
,health
; - retries — количество попыток соединения с сервером в случае отказа;
- option httplog — формат лога, в случае использования HAProxy для проксирования HTTP-запросов (рекомендуется включить данную настройку);
- option redispatch — разрешает программе разорвать и переназначить сессию в случае отказа сервера;
- contimeout — максимальное время ожидания успешного соединения с сервером.
В примере я использую параметры timeout
, которые позволяют более гибко настроить поведение балансировщика. Подробно с доступными параметрами можно ознакомиться в документации к HAProxy
Секция frontend
Укажем HAProxy какие запросы он должен обрабатывать, для этого задаем секцию frontend с именем https-in
:
frontend https-in
log /dev/log local0
mode tcp
option tcplog
bind *:443
default_backend backend-https-servers
Параметр bind со значением *:443
говорит о том, что HAProxy должен принимать все запросы на 443-й порт. Ещё раз напомню, что в данном примере я использую режим SSL Pass-Through
, поэтому настройка SSL на самом HAProxy не выполняется.
Параметр default_backend указывает, какие сервера будут обрабатывать эти запросы. В данном случае — backend-https-servers, именно так необходимо назвать секцию backend.
Секция backend
В этой секции мы задаем алгоритм балансировки (параметр balance) и список серверов-обработчиков (server). В качестве алгоритма балансировки указываем roundrobin.
HAProxy имеет несколько алгоритмов балансировки:
roundrobin
— каждый сервер получает запросы пропорционально своему весу, при этом веса серверов могут меняться на лету;static-rr
— то же, что и roundrobin, только изменение весов на лету не даст никакого эффекта;leastconn
— выбирает сервер с наименьшим количеством активных соединений;first
— выбирает первый сервер с доступными слотами для соединения source — на основе хэша IP-адреса отправителя запроса и весов серверов назначается сервер для соединения;uri
— сервер выбирается на основе адреса (без параметров) страницы;url_param
— сервер выбирается на основе GET-параметров запроса;hdr
— сервер выбирается на основе заголовков запроса;rdp-cookie
— сервер выбирается на основе cookie (если они не установлены, то применяется обычный roundrobin);
При перечислении серверов используется следующий формат: ключевое слово server, имя сервера, IP-адрес, дополнительные параметры (в данном случае — проверка статуса хоста и Proxy Protocol, которые позволяет перенаправлять реальные IP-адреса клиента с HAProxy на веб-сервер).
backend backend-https-servers
mode tcp
balance roundrobin
option ssl-hello-chk
server nginx01 10.0.1.3:443 check send-proxy
server nginx02 10.0.1.4:443 check send-proxy
Просмотр статистики HAProxy
Для включения расширенной статистики HAProxy необходимо в конфигурационный файл добавить секцию:
listen stats
bind :10001
stats enable
stats uri /haproxy_stats
stats auth admin:password
bind :10001
— HAProxy будет ожидать запросы к порту 10001;stats enable
— включить отчёты со статистикой;stats uri
— установка адреса страницы с отчётом;stats auth
— логин и пароль для авторизации на странице со статистикой;
В секции listen
указываем HAProxy, что он должен показывать статистику на странице /haproxy_stats
на порту 10001 после ввода логина admin
и пароля password
.
Проверяем.
Переходим по адресу HAProxy (IP-адрес или хостнйем) и просто обновляем страницу. В зависимости от выбранного балансировщиком сервера будем получать ответ This is server #1
либо This is server #2
.
Проверяем статистику. Переходим по адресу SITE_NAME:10001/haproxy_stats
На этом всё. Выше рассмотрен самый простой метод балансировки. Более сложная настройка требует грамотно составленного ТЗ и технических данных проекта. HAProxy очень удобный и гибкий в настройке инструмент с помощью которого можно выполнить балансировку и других сервисов, к примеру почтовый сервер, Memcached, Redis и пр.