HAProxy. Установка и настройка

Материал из megapuper
Перейти к: навигация, поиск

Установку будем проводить на Debian 11. Если текущая версия устраивает, то просто apt install haproxy. Если требуется последняя, то подключаем репозиторий.


Добавляем ключ репозитория

curl https://haproxy.debian.net/bernat.debian.org.gpg | gpg --dearmor > /usr/share/keyrings/haproxy.debian.net.gpg


Добавляем сам репозиторий

echo deb "[signed-by=/usr/share/keyrings/haproxy.debian.net.gpg]" http://haproxy.debian.net bullseye-backports-2.6 main > /etc/apt/sources.list.d/haproxy.list
apt update


Ставим HAProxy

apt-get install haproxy=2.6.\*


Конфигурирование HAProxy выполняется в файле /etc/haproxy/haproxy.cfg. Все основные настройки находятся в 4-х секциях:

  • global. Глобальные настройки, распространяемые на все публикации.
  • defaults. Настройки, применяемые по умолчанию, если они не указаны явно в публикации.
  • frontend. Правила обработки запросов, приходящих на сервер и передачи этих запросов серверам backend. Может быть несколько.
  • backend. Настройка конечных серверов, которые обрабатывают запросы и возвращают результаты. Может быть несколько.

Также есть возможность создать дополнительные секции, например userlist.


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

global
       log /dev/log    local0
       log /dev/log    local1 notice
       log 127.0.0.1   local2
       chroot /var/lib/haproxy
       stats timeout 30s
       user haproxy
       group haproxy
       daemon

defaults
       log     global
       mode    http
       option  httplog
       option  dontlognull
       timeout connect 5000
       timeout client  50000
       timeout server  50000

frontend http_front
       bind *:80
       mode http
       log global
       bind  *:1937 #for stats page
       stats enable
       stats uri /stats
       stats hide-version
       stats realm Haproxy\ Statistics
       stats auth username:password

       log-format %ci\ %ft\ %b/%s\ %ST\ %B\ %CC\ \%CS\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %bq\ %hr\ %hs\ %{+Q}r
 
       monitor-uri /monitoruri

       default_backend homepage_back

backend homepage_back
       balance roundrobin
       server 192.168.150.54:80 check
       server 192.168.150.55:80 check

Конфиг определяет балансировщик нагрузки транспортного уровня (layer 4) с внешним именем http_front, прослушивающий порт 80, который затем направляет трафик к бэкенду по умолчанию с именем homepage_back, состоящий из двух веб-серверов. Трафик на них распределяется по очереди. По /stats подключается страница статистики, защищённая паролем.


Настройка балансировки нагрузки на прикладном уровне(layer 7)

Полезно, когда части веб-приложения расположены на разных хостах. Например, основная страница на одном хосте, а блог на другом. Это может быть достигнуто путем регулирования передачи соединения, например, по URL.

frontend http_front
       bind *:80
       stats uri /stats
       acl url_blog path_beg /blog
       use_backend blog_back if url_blog
       default_backend homepage_back

backend homepage_back
      balance roundrobin
      server 192.168.150.54:80 check
      server 192.168.150.55:80 check

backend blog_back
      server 192.168.150.56:80 check

Фронтенд объявляет правило ACL с именем url_blog, которое применяется ко всем соединениям с путями, начинающимися с /blog. Use_backend определяет, что соединения, соответствующие условию url_blog, должны обслуживаться бэкендом с именем blog_back, а все остальные запросы обрабатываются бэкендом по умолчанию.


frontend http_front
    bind 192.168.150.55:80
    acl url_stat path_end -i .css .js

    use_backend static if url_stat
    default_backend webserver

В данном случае слушаем веб-запросы и если они идут на файлы с расширениями .css или .js, передаем запрос на бэкэнд static. Все остальные запросы передаем на бэкэнд webserver.


Алгоритмы балансировки нагрузки

  • Roundrobin: каждый сервер используется по очереди в соответствии со своим весом. Это самый плавный и честный алгоритм, когда время обработки серверами остается равномерно распределенным. Этот алгоритм является динамическим, что позволяет регулировать вес сервера на лету.
  • Leastconn: выбирается сервер с наименьшим количеством соединений. Циклический перебор выполняется между серверами с одинаковой нагрузкой. Использование этого алгоритма рекомендуется для длинных сеансов, таких как LDAP, SQL, TSE и т.д., но он не очень подходит для коротких сеансов, таких как HTTP.
  • First: первый сервер с доступными слотами для подключения получает соединение. Серверы выбираются от самого низкого числового идентификатора до самого высокого, который по умолчанию соответствует положению сервера в ферме. Как только сервер достигает значения maxconn, используется следующий сервер.
  • Source: IP-адрес источника хешируется и делится на общий вес запущенных серверов, чтобы определить, какой сервер будет получать запрос. Таким образом, один и тот же IP-адрес клиента будет всегда доставаться одному и тому же серверу, в то время как серверы остаются неизменными.
  • Static-rr — серверы используются по очереди. Нагрузка распространяется равномерно, в зависимости от указанного веса. Вес не может быть изменен на лету.
  • Uri — запросы с одним и тем же URL (до знака вопроса) будут переправляться на один и тот же сервер.
  • Url_param — запросы с одинаковыми параметрами GET (все, что после знака вопроса) будут переправляться на один и тот же сервер.


Примеры использования


  • HTTPS запросы

Frontend:

frontend https-frontend
   bind *:443 ssl crt /etc/ssl/domaincert.pem
   reqadd X-Forwarded-Proto:\ https
   default_backend https-backend

Backend:

backend https-backend
   redirect scheme https if !{ ssl_fc }
   server back1 192.168.150.54:80 check
   server back2 192.168.150.55:80 check


  • Распределение запросов по весу (weight)

Backend:

backend weight-backend
   ...
   server back1 192.168.150.54:80 weight 100
   server back2 192.168.150.55:80 weight 80

в данном примере запросы будут отправляться чаще на сервер back1


  • Поддержка sticky session

Backend:

backend sticky-backend
   ...
   server back1 192.168.150.54:80 cookie check
   server back2 192.168.150.55:80 cookie check

Поддержка sticky session позволит перенаправлять http-запросы пользователя всегда на один и тот же сервер. Это необходимо в том случае, когда не предусмотрен механизм хранения PHP-сессий в общем каталоге.


  • Защита паролем

Сделаем необходимость вводить пароль при подключении к серверу.

Получаем хеш пароля

echo -n 'password' | md5sum

В haproxy создаем список пользователей

userlist http-users
   user user1 password 5f4dcc3b5aa765d61d8327deb882cf99

Backend:

backend web-servers
   ...
   acl AuthAccept http_auth(http-users)
   http-request auth realm Site if !AuthAccept


  • Распределение запросов по серверам с помощью url_reg

С помощью url_reg можно распределить запросы по группам серверов исходя из URL страницы.

Frontend:

frontend https-frontend
   acl url_page1 url_reg -i ^/page1/[a-z0-9]{10}/(img|doc)/$
   acl url_page2 url_reg -i ^/page2/[a-zA-Z0-9]*/$
   use_backend back1 if url_page1
   use_backend back2 if url_page2
   default_backend www

в данном примере ищем страницы, которые начинаются на page1, затем слеш и 10 любых символов в нижнем регистре и/или цифр, еще один слеш и в конце либо img, либо doc - этому урлу присваиваем acl url_page1. Второй урл — page2, затем слеш и любое количество символов в нижнем регистре регистре и/или цифры — acl url_page2. Для url_page1 используем группу серверов back1, для url_page2 - back2. По умолчанию все запросы отправляем на backend www

Backend:

backend back1
   server www1 192.168.150.54:80 check
   server www2 192.168.150.53:80 check

backend back2
   server www3 192.168.150.55:80 check
   server www4 192.168.150.56:80 check

В работе url_reg и use_backend есть нюанс — Haproxy найдет все возможные acl для запросов, а перенаправит на тот use_backend, который первым встретится в конфигурации. Таким образом, если адрес страницы будет соответствовать нескольким acl, результат работы может быть непредсказуем. В этом случае, необходимо более частный acl ставить выше при описании use_backend.


Примеры форматов для логов

frontend tcp_frontend
log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq"
frontend engy_frontend
log-format %ci:%cp\ [%t]\ %ft\ %b/%s\ %Tq/%Tw/%Tc/%Tr/%Tt\ %ST\ %B\ %CC\ %CS\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %hr\ %hs\ {valid:%[ssl_c_verify],User:%{+Q}[ssl_c_s_dn(cn)]}
frontend https_frontend
log-format %ci:%cp\ [%t]\ %ft\ %b/%s\ %ST\ %B\ %CC\ %CS\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %hr\ %hs\ {valid:%[ssl_c_verify],User:%{+Q}[ssl_c_s_dn(cn)]}
frontend http_frontend
log-format %ci\ %ft\ %b/%s\ %ST\ %B\ %CC\ \%CS\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %bq\ %hr\ %hs\ %{+Q}r
frontend mail_frontend
log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq"
frontend k8s_api_frontend
log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq"