EnterpriseApps/Haproxy

Материал из ALT Linux Wiki
Stub.png
Данная страница находится в разработке.
Эта страница ещё не закончена. Информация, представленная здесь, может оказаться неполной или неверной.
HAProxy
Altenter-menu-Haproxy.png
Появился в: 2001
Оф. сайт: haproxy.org
Репозиторий ALT Linux haproxy
Лицензия: GNU GPL v2

HAProxy — серверное программное обеспечение не только для обеспечения высокой доступности и балансировки нагрузки TCP- и HTTP-приложений посредством распределения входящих запросов на несколько обслуживающих серверов, но и эффективный способ проксирования доступа извне ко внутренним службам и ресурсам.

Установка

# apt-get install haproxy && systemctl enable --now haproxy

Настройка

Файлы и каталоги
/etc/haproxy/haproxy.cfg основной файл с настройками
/etc/haproxy/conf.d (исходно пустой) каталог с настройками, вынесенными из основного конфига
/etc/logrotate.d/haproxy (для старых систем журналирования)
/etc/sysconfig/haproxy опции запуска

С виду процесс довольно прост: по сути, нужно лишь сообщить сервису, какие соединения прослушивать и куда их ретранслировать, что делается через /etc/haproxy/haproxy.cfg.

Балансировка

Добавим в конец конфига пару разделов для "прослушки" (frontend) и "проброса" (backend):

/etc/haproxy/haproxy.cfg  
frontend http_front
   bind *:80
   stats uri /haproxy?stats
   default_backend http_back
 
backend http_back
   balance roundrobin
   server server_name1 private_ip1:80 check
   server server_name2 private_ip2:80 check

Что здесь происходит:

  • при запросе к 80 порту фронтенд http_front перекидывает его бэкенду http_back на страницу статистики /haproxy?stats
  • бэкенд http_back перераспределяет запрос с балансировкой Roundrobin (чередование — см. ниже) между парой серверов с их именами и адресами.
при этом по адресу IP/haproxy?stats доступна статистика в открытом виде.

То есть, при переходе на сервер по 80 порту пользователь перенаправляется на один из серверов бекенда http_back.

Типы балансировки
RoundRobin Каждый сервер используется по очереди в соответствии со своим весом. Это самый плавный и честный алгоритм, когда время обработки серверами остается равномерно распределенным. Этот алгоритм является динамическим, что позволяет регулировать вес сервера на лету.
Leastconn Выбирается сервер с наименьшим количеством соединений. Циклический перебор выполняется между серверами с одинаковой нагрузкой. Использование этого алгоритма рекомендуется для длинных сеансов, таких как LDAP, SQL, TSE и т. д., но он не очень подходит для коротких сеансов, таких как HTTP.
First Первый сервер с доступными слотами для подключения получает соединение. Серверы выбираются от самого низкого числового идентификатора до самого высокого, который по умолчанию соответствует положению сервера в ферме. Как только сервер достигает значения maxconn, используется следующий сервер.
Source IP-адрес источника хешируется и делится на общий вес запущенных серверов, чтобы определить, какой сервер будет получать запрос. Таким образом, один и тот же IP-адрес клиента будет всегда доставаться одному и тому же серверу, в то время как серверы остаются неизменными.

Защита статистики

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

listen stats
    bind *:8181
    stats enable
    stats uri /
    stats realm Haproxy\ Statistics
    stats auth username:password

Доступ извне ко внутренним ресурсам

Если вы не провайдер с кучей реальных IP-адресов, и для доступа к вашим ресурсам общего пользования типа веб-сервера, почтаря, мониторинга, документообормота и разного прочего, размещённого внутри производственной ИТ-инфраструктуры имеется единственный IP с привязанным к нему доменом (скажем, domain.ru) — выручит как раз HAproxy.

Можно долго мучиться, прикручивая разные обходные схемы к веб-службам типа Апача или к серверам приложений вроде Энджи, но к чему эти потуги?

Простая выдержка из конфига:

/etc/haproxy/haproxy.cfg  
# Для тех, кто стучится по веб-порту:
frontend http
    bind *:80
    # Незащищённые обращения к ресурсам небезопасны, так что сразу перекидываем запрос на шифрование:
    redirect scheme https code 301 if !{ ssl_fc }

# Для тех, кто стучится сразу защищённо, а также для перекида с голого-босого веб-порта:
frontend https
    # Файл с актуальным общедоменным "ключертификатом" (годится для любого сайта 3 уровня в нашем домене):
    bind *:443 ssl crt /etc/haproxy/ssl/domain.ru.pem
    # Веб-сервер у нас один, стало быть обслуживать и domain.ru, и www.domain.ru избыточно,
    # так что просто перекинем запросы к www сразу на domain.ru:
    http-request redirect prefix https://%[hdr(host),regsub(^www\.,,i)] code 301 if { hdr_beg(host) -i www. }
    # Пробросы к конкретным службам:
    use_backend web    if { ssl_fc_sni        domain.ru }
    use_backend doc    if { ssl_fc_sni    doc.domain.ru }
    use_backend mail   if { ssl_fc_sni   mail.domain.ru }
    use_backend health if { ssl_fc_sni health.domain.ru }
    # К какому из внутренних сервисов стучаться по умолчанию (пусть это будет веб-сайт):
    default_backend web

# Соответствие службы внутреннему имени сервера:порту с ней на борту:
backend web
    server domain.ru  web:80 check

backend doc
    server doc        doc:5389 check

backend health
    server health grafana:3000 check

backend mail
    server mail    zimbra:8081 check

Подводные камни

Не всегда работают попытки проброса 443 порта извне на такой же внутри сети.

Порой проще огородить запросы общедоменным сертификатом на входе, и уже шифрованным перекинуть на веб-порт внутри. Но тут возникают коллизии.

К примеру, сервис angie, слушающий веб-порт, тут же сам норовит его обезопасить пробросом на https. Для внутренних клиентов это совершенно верное поведение — однако нечто подобное уже произошло на стороне НА-прокси, в результате чего запускается бесконечный "мёбиус" без возможности с него соскочить.

Выручает такой трюк со стороны Энджи:

server {
    listen 80 
    ...
    location = / {
        if ($remote_addr ~* "ип.адрес.ха.прокси") {
            rewrite ^ http://$server_name; # с ха-прокси отправляем на 80 порт
        }
        rewrite ^ https://$server_name;    # с остальных - на 443
        allow all;
    }
    ...
}

Обратная связь