HAProxy (установка и настройка)
04.03.2017

HAProxy (High Availability Proxy) - инструмент, который хорошо подойдет для нагрузочного веб-проекта как балансировщик нагрузки (load balancer).

Балансировать нагрузку можно на транспортном уровне (слой 4 в OSI моделе). Можно на прикладном уровне (слой 7). Далее мы будем говорить про балансировку только на прикладном уровне (он еще называется HTTP-уровень). Почему? Во-первых, вся мощь HAProxy (и его синтаксиса) направлена на прикладной уровень. Во-вторых, есть более специализированные инструменты под балансировку на транспортном уровне, и которые лучше с ней справляются.

Также предполагается, что HAProxy терминейтит SSL-сессию и общается с backend-кластером по HTTP протоколу (кластер находится в закрытом сегменте сети). Начнем с установки (пишу для Убунту 16.04, под другие дистрибутивы тут):

# yes | add-apt-repository ppa:vbernat/haproxy-1.7
# apt-get update
# apt-get install -y haproxy

Конфиг (/etc/haproxy/haproxy.cfg):

global
    # SSL настройки
    ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
    ssl-default-bind-options no-sslv3
    tune.ssl.default-dh-param 2048
    # Максимальное кол-во соединений
    maxconn 2048
    # В логи писать только alert'ы
    log /dev/log local0 info alert
    log /dev/log local1 notice alert
defaults
    # Работаем на 7 уровне
    mode http
    # Различные таймауты (тут можно поиграться со значениями)
    timeout client 30s
    timeout server 30s
    timeout connect 3s
    # В запросы к backend'у вставлять X-Forwarded-For с клиентским IP
    option forwardfor
    # Закрывать соединение сразу после получения ответа
    option http-server-close
frontend http
    bind *:80
    acl is_www hdr_beg(host) -i www.
    acl is_dev hdr_beg(host) -i dev.
    # Перенаправлять клиентов с www на без www
    http-request redirect prefix http://%[hdr(host),regsub(^www\.,,i)] if is_www
    # Перенаправлять клиентов с http на https (не применять к dev'ам)
    redirect scheme https if !{ ssl_fc } !is_dev
    # Пропустить запрос на dev-окружение
    use_backend be1 if is_dev
frontend https
    # Только SNI, все старые устройства отсекаются
    bind *:443 ssl strict-sni crt site.com.pem
    acl is_www hdr_beg(host) -i www.
    # Перенаправлять клиентов с www на без www
    http-request redirect prefix https://%[hdr(host),regsub(^www\.,,i)] if is_www
    acl host_site hdr(host) -i site.com
    use_backend be1 if host_site
backend be1
    # Алгоритм выбора балансировщика (leastconn - backend с меньшим кол-вом соединений)
    balance leastconn
    option httpclose
    # Ноды backend'а
    server node1 backend1:80
    server node2 backend2:80

Обратите внимание, в конфиге предусмотрено, чтобы пропускать на backend запросы к dev-окружению (очень часто сертификаты для dev'ов не делают). Также хорошей практикой считается прописывать редиректы с www и на https. После ключевого слова strict-sni идет список сертификатов (crt <pem-сертификат> crt <pem-сертификат>). PEM-cертификат - это объединенные в один файл с расширением pem сертификат и ключ:

# cat site.com.crt site.com.key > site.com.pem
# mv site.com.pem /etc/haproxy/

После изменения конфига делаем reload.

# /etc/init.d/haproxy reload

Готовый конфиг я выложил на Гитхабе. Хорошего вам настроения!