Балансировка нагрузки с помощью HAProxy

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




Рассмотрим решение по балансировке нескольких веб-серверов при помощи сервиса 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 — устанавливает протокол взаимодействия, принимает одно из значений: tcphttphealth;
  • 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 очень удобный и гибкий в настройке инструмент с помощью которого можно выполнить балансировку и других сервисов, к примеру почтовый сервер, MemcachedRedis и пр.



2022-04-14T17:49:53
Software