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

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

Roman Bogachev VMware Specialist | Drone Pilot | Traveler

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

Рассмотрим решение по балансировке нескольких веб-серверов при помощи сервиса HAProxy.

Общая схема

Технические требования

  • Сервер под балансировщик с двумя сетевыми интерфейсами (Рекомендация. Внешний адрес для связи с внешним миром и локальный для общения между узлами кластера);
  • Два и более серверов под распределение запросов/трафика;

В примере будет использоваться дистрибутив Linux CentOS 7.

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

В качестве backend-серверов я буду использовать несколько веб-серверов с NGINX и настроенным SSL.

Прежде всего установим NGINX

1
yum install nginx
Выполним настройку веб-сервера
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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, а также указать реальный адрес откуда разрешить принимать запросы:

1
2
set_real_ip_from 10.0.1.10/32;
real_ip_header proxy_protocol;

Создадим приветственную страницу на обоих веб-серверах touch /srv/www/devservers.network/public_html со следующим содержимым, изменив только номер сервера для его дальнейшего определения:

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
<head>
<title>Server #1</title>
</head>
<body>
<h1>This is server #1</h1>
</body>
</html>

Добавляем NGINX в автозагрузку и запускаем сервис.

1
2
systemctl enable nginx
systemctl start nginx

И не забываем выполнить настройку Firewalld

1
2
firewall-cmd --permanent --add-service=https
firewall-cmd --reload

Установка и настройка балансировщика

В качестве сервера балансировки я буду использовать VDS сервер с ресурсами 1 vCPU и 1Gb RAM. При правильной настройке, данных мощностей хватит для обслуживания 10-15к одновременных сессий, чего вполне достаточно для среднестатистического интернет-ресурса.

Установим HAProxy

Пакет HAProxy доступен в базовой репозитории CentOS.

1
yum install haproxy

Настройка HAProxy

HAProxy обладает очень гибкими настройками и конфигурация может содержать большое количество директив и условий. Конфигурационный файл состоит из нескольких секций. Директивы frontend, backend, listen должны иметь своё имя, к примеру defaults - может, но не обязательно, а такие как global - не должны.

Выполняем конфигурацию HAProxy в файле /etc/haproxy/haproxy.cfg.
Рекомендую использовать свой конфигурационный файл, а представленный по умолчанию оставить как резерв.

Секция global

1
2
3
4
5
6
7
8
9
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, в этом случае параметры, описанные в данной секции, будут переопределены в следующей, и будут применяться к секциям, идущим за ней.

В нашем примере указаны следующие параметры:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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:

1
2
3
4
5
6
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 на веб-сервер).

1
2
3
4
5
6
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 необходимо в конфигурационный файл добавить секцию:

1
2
3
4
5
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 и пр.