Балансировка нагрузки с помощью 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 - устанавливает протокол взаимодействия, принимает одно из значений:
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 и пр.