EnterpriseApps/Haproxy
| HAProxy | |
|---|---|
| Появился в: | 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/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;
}
...
}