Содержание

Балансировка нагрузки с помощью 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:

Секция 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

В примере я использую параметры 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 имеет несколько алгоритмов балансировки:

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

В секции 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 и пр.