Установка HAProxy
Debian8
1 |
# echo "deb http://httpredir.debian.org/debian jessie-backports main" >> /etc/apt/sources.list.d/backports.list |
1 |
# apt-get update |
1 |
# apt-get install haproxy -t jessie-backports |
Debian7
1 |
# echo "deb http://cdn.debian.net/debian wheezy-backports main" >> /etc/apt/sources.list.d/backports.list |
1 |
# apt-get update |
1 |
# apt-get install haproxy -t wheezy-backports |
Ubuntu14
1 |
# apt-get install haproxy |
Либо
1 |
echo "deb http://archive.ubuntu.com/ubuntu trusty-backports main universe" >> /etc/apt/sources.list.d/backports.list |
1 |
# apt-get update |
1 |
# apt-get install haproxy -t trusty-backports |
2.Настройка логирования HAProxy
Настройка HAProxy
1 |
# cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg~ |
1 |
# nano /etc/haproxy/haproxy.cfg |
1 2 |
global log 127.0.0.1 local2 notice |
Настройка Rsyslog
1 |
# nano /etc/rsyslog.conf |
1 2 3 4 5 6 |
# provides UDP syslog reception $ModLoad imudp $UDPServerRun 514 $UDPServerAddress 127.0.0.1 #### RULES #### local2.* /var/log/haproxy.log |
1 |
# /etc/init.d/rsyslog restart |
1 |
[ ok ] Restarting rsyslog (via systemctl): rsyslog.service. |
3.Настройка HAProxy
1 |
# nano /etc/haproxy/haproxy.cfg |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
###### Описание секции global ####### global # системный лог сервера, в который нужно отправлять предупреждения и извещения log 127.0.0.1 local2 notice # Запуск HAProxy в chroot-окружении chroot /var/lib/haproxy # пользователь и группа, от которых работает процесс user haproxy group haproxy # Запуск HAProxy как сервиса daemon # количество одновременных подключений на внешнем интерфейсе(максимальное число одновременных подключений для каждого процесса) maxconn 10000 # nbproc «number» (nbproc 2) — задает количество проццессов. По умолчанию только один процесс будет создан # Default SSL material locations ca-base /etc/ssl/certs crt-base /etc/ssl/private # Default ciphers to use on SSL-enabled listening sockets. # For more information, see ciphers(1SSL). This list is from: # https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ 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 ####### Описание секции defaults ####### defaults # Включает в журналирование информацию о трафике log global # Режим работы HAProxy, в http режиме происходит анализ Layer 7 трафика mode http # Добавляет в лог HTTP запросы, состояние сеанса и таймеры option httplog # Отключает логирование пустых соединений option dontlognull # количество повторных попыток подключения к backend-серверу после сбоя подключения. retries 3 # перераспределение сессии в случае сбоев соединения c каким-либо backend-сервером option redispatch # количество одновременных подключений на внешнем интерфейсе(максимальное число одновременных подключений для каждого процесса) maxconn 10000 # автоматически закрывать соединения после завершения передачи данных option httpclose # Включение X-Forwarded-For для передачи IP-адреса клиента backend-серверу option forwardfor # максимальное время ожидания для успешного подключения к серверу timeout connect 5000 # когда клиент или сервер должны подтвердить приём данных или отправить данные в TCP-процессе. Рекомендуется установить для них одинаковое значение timeout client 50000 timeout server 50000 # Включение страницу статистики stats enable # URL, по которому доступна статистика Haproxy stats uri /haproxy # Заголовок странички статистики stats realm Haproxy\ Statistics # HTTP-базовая авторизация логин/пароль для просмотра статистики HAProxy stats auth admin:123456 # Автообновление статики каждые 30 секунд stats refresh 30s # Скрывать версию HAProxy в статистике # stats hide-version # Отображение в статистеке дополнительной информацию о параметрах # stats show-legends # stats show-node # Определение страниц ошибок errorfile 400 /etc/haproxy/errors/400.http errorfile 403 /etc/haproxy/errors/403.http errorfile 408 /etc/haproxy/errors/408.http errorfile 500 /etc/haproxy/errors/500.http errorfile 502 /etc/haproxy/errors/502.http errorfile 503 /etc/haproxy/errors/503.http errorfile 504 /etc/haproxy/errors/504.http ####### Описание секции frontend ####### # Имя Frontend-сервера frontend WEBLoadBalancer-HTTP # Режим работы фронтенда mode http # IP-адрес и порт, на котором будет слушать запроcы HApoxy bind 10.10.1.43:80 # Имя Backend-сервера, на который необходимо направлять запросы default_backend webcluster ####### Описание секции backend ####### # Имя Backend-сервера backend webcluster # Режим работы backend-сервера mode http # Алгоритм балансировки запросов # roundrobin/leastconn/static-rr/uri/source/url_param balance roundrobin option httpclose option forwardfor # Проверка состояния/доступности backend-серверов option httpchk HEAD /test.php HTTP/1.0 # например,если нужно мониторить доступность виртуального хоста # option httpchk HEAD / HTTP/1.0\r\nHost:kamaok.org.us # сервера бэкенда # синтаксис server <name> <address>[:port] [param*] # name - будет появляться в логах и предупреждениях. # check - проверку состояния сервера через проверку,определенную параметром httpchk # cookie - вставка имени сервера(name) в занчение cookie server app01 192.168.10.54:80 check server app02 192.168.10.55:80 check server app03 192.168.10.56:80 check http-request add-header X-Forwarded-Proto https if { ssl_fc } |
Вся статистика по кластеру HAproxy становится доступна по адресу
http://IP-haproxy-server/haproxy с логином и паролем,указанными в параметре stats auth
Доступность серверов приложений(WEB-серверов) HAProxy будет проверять с помощью проверки, описанной в его конф.файле
1 |
option httpchk HEAD /test.php HTTP/1.0 |
Для этого создадим на WEB-серверах в корне сайта по умолчанию файл test.php,например, с таким содержанием
1 |
# nano /var/www/html/test.php |
1 2 3 |
<?php echo "OK" ?> |
Если Web-сервер недоступен/не проходит корректно проверку, он будет автоматически выброшен из кластера HAProxy и все запросы будут распределяться между оставшимися двумя Web-серверами.
Добавление HAProxy в автозагрузку
Debian 8
1 |
# systemctl enable haproxy |
Debian 7/Ubuntu 14
1 |
# update-rc.d haproxy defaults |
Запуск HAProxy и проверка корректности запуска
1 |
# /etc/init.d/haproxy start |
Debian8
1 |
# ps ax | grep [h]aproxy |
1 2 3 |
13603 ? Ss 0:00 /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid 13605 ? S 0:00 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds 13607 ? Ss 0:00 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid –Ds |
Ubuntu14
1 |
# ps ax | grep [h]aproxy |
5083 ? Ss 0:05 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -D -p /var/run/haproxy.pid
1 |
# netstat -nlpt | grep haproxy |
1 |
tcp 0 0 10.10.1.43:80 0.0.0.0:* LISTEN 13607/haproxy |
В логах HAProxy
1 |
# tail -f /var/log/haproxy.log |
1 2 3 |
Aug 3 12:12:34 localhost haproxy[15459]: Server webcluster/app02 is UP, reason: Layer7 check passed, code: 200, info: "OK", check duration: 0ms. 1 active and 0 backup servers online. 0 sessions requeued, 0 total in queue. Aug 3 12:13:54 localhost haproxy[15459]: Server webcluster/app03 is UP, reason: Layer7 check passed, code: 200, info: "OK", check duration: 0ms. 2 active and 0 backup servers online. 0 sessions requeued, 0 total in queue. Aug 3 12:14:25 localhost haproxy[15459]: Server webcluster/app01 is UP, reason: Layer7 check passed, code: 200, info: "OK", check duration: 0ms. 3 active and 0 backup servers online. 0 sessions requeued, 0 total in queue. |
Для проверки балансировки запросов на все три Web-сервера создаем на этих серверах в в корне для сайта по умолчанию либо разные странички, либо файл,например lb.php, с таким содержимым
1 |
# nano /var/www/html/lb.php |
1 2 3 4 5 6 |
<?php header('Content-Type: text/plain'); echo "Server IP: ".$_SERVER['SERVER_ADDR']; echo "\nClient IP: ".$_SERVER['REMOTE_ADDR']; echo "\nX-Forwarded-for: ".$_SERVER['HTTP_X_FORWARDED_FOR']; ?> |
Далее тестируем распределение запросов, например,с loadbalancera (EXT_IP-10.10.1.43,INT_IP-192.168.10.1)
1 |
# curl http://10.10.1.43/lb.php |
1 2 3 |
Server IP: 192.168.10.54 Client IP: 192.168.10.1 X-Forwarded-for: 10.10.1.43 |
1 |
# curl http://10.10.1.43/lb.php |
1 2 3 |
Server IP: 192.168.10.55 Client IP: 192.168.10.1 X-Forwarded-for: 10.10.1.43 |
1 |
# curl http://10.10.1.43/lb.php |
1 2 3 |
Server IP: 192.168.10.56 Client IP: 192.168.10.1 X-Forwarded-for: 10.10.1.43 |
Т.е запросы по очереди направляются на все три сервера Web-сервера
Настройка HAProxy для поддержки sticky sesions
Приведенная выше настройка HAproxy не предусматривает поддержку sticky user’s session
Т.е нет возможности направить все запросы пользователя на один и тот же сервер приложений. Такая привязка не нужна, например, если PHP-сессии хранятся в едином хранилище(например, в общей папке примонтированной по NFS на серверах приложений, или PHP-сессии хранятся на сервере/серверах memcache/redis или в базе данных)
В случае,если нет единого общего типа хранения PHP-сессий необходимо настроить HAproxy для поддержки sticky session
Липкие сессии (sticky session) позволяют закрепить пользователя за сервером, который обслужил его первый запрос. для этого нужно отметить каждый сервер бэкенда при помощи файлов cookie.
При первом соединении с HAproxy-сервером клиент будет получать от HAproxy-сервера заголовок Set-Cookie со значением сервера, который его будет обслуживать.
При последующих подключениях этого клиента, браузер клиента сообщает HAproxy-серверу значение заголовка Cookie и уже на основании этого значения HAproxy-сервер направляет запрос клиента на сервер, который обслуживал его первый запрос т.е тем самым достигается возможность обработки всех запросов конкретного клиента одним и тем же сервером(т.е конкретный клиент прикрепляется к конкретному Web-серверу)
В данном случае HAproxy-сервер будет вставлять куку с именем SRVNAME (если только пользователь не пришел с такой кукой т.е, если это первый запрос пользователя),а значение этой куки будет app01 или app02 или app03.
# nano /etc/haproxy/haproxy.cfg
1 2 3 4 5 6 7 |
backend webcluster ............. cookie SRVNAME insert server app01 192.168.10.54:80 cookie app01 check server app02 192.168.10.55:80 cookie app02 check server app03 192.168.10.56:80 cookie app03 check .............. |
1 |
# /etc/init.d/haproxy restart |
Для тестирования sticky sessions создаем файл session.php на WEB-серверах в корне сайта по умолчанию с таким содержимым
Этот код создаёт PHP-сессию и отображает количество просмотров страниц за одну сессию.
1 |
# nano /var/www/html/session.php |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?php header('Content-Type: text/plain'); session_start(); if(!isset($_SESSION['visit'])) { echo "This is the first time you're visiting this server"; $_SESSION['visit'] = 0; } else echo "Your number of visits: ".$_SESSION['visit']; $_SESSION['visit']++; echo "\nServer IP: ".$_SERVER['SERVER_ADDR']; echo "\nClient IP: ".$_SERVER['REMOTE_ADDR']; echo "\nX-Forwarded-for: ".$_SERVER['HTTP_X_FORWARDED_FOR']."\n"; print_r($_COOKIE); ?> |
Тестируем
1 |
# curl -i http://10.10.1.43/session.php |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
HTTP/1.1 200 OK Date: Wed, 03 Aug 2016 11:20:18 GMT Server: Apache/2.4.10 (Debian) Set-Cookie: PHPSESSID=qb07n1fljtklb4c4mvulsb9ci6; path=/ Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Vary: Accept-Encoding Content-Length: 138 Connection: close Content-Type: text/plain;charset=UTF-8 Set-Cookie: SRVNAME=app01; path=/ This is the first time you're visiting this server Server IP: 192.168.10.54 Client IP: 192.168.10.1 X-Forwarded-for: 10.10.1.43 Array ( ) |
Для эмуляции работы браузера (передачи полученной от HAproxy-сервера заголовка)
1 2 |
Set-Cookie: PHPSESSID=qb07n1fljtklb4c4mvulsb9ci6; path=/ Set-Cookie: SRVNAME=app01; path=/ |
Используем команду
1 |
# curl -i http://10.10.1.43/session.php --cookie "PHPSESSID=qb07n1fljtklb4c4mvulsb9ci6;SRVNAME=app01;" |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
HTTP/1.1 200 OK Date: Wed, 03 Aug 2016 11:21:42 GMT Server: Apache/2.4.10 (Debian) Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Vary: Accept-Encoding Content-Length: 181 Connection: close Content-Type: text/plain;charset=UTF-8 Your number of visits: 1 Server IP: 192.168.10.54 Client IP: 192.168.10.1 X-Forwarded-for: 10.10.1.43 Array ( [PHPSESSID] => qb07n1fljtklb4c4mvulsb9ci6 [SRVNAME] => app01 ) |
1 |
# curl -i http://10.10.1.43/session.php --cookie "PHPSESSID=qb07n1fljtklb4c4mvulsb9ci6;SRVNAME=app01;" |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
HTTP/1.1 200 OK Date: Wed, 03 Aug 2016 11:22:13 GMT Server: Apache/2.4.10 (Debian) Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Vary: Accept-Encoding Content-Length: 181 Connection: close Content-Type: text/plain;charset=UTF-8 Your number of visits: 2 Server IP: 192.168.10.54 Client IP: 192.168.10.1 X-Forwarded-for: 10.10.1.43 Array ( [PHPSESSID] => qb07n1fljtklb4c4mvulsb9ci6 [SRVNAME] => app01 ) |
Оба этих запроса обработал все тот же сервер, который обрабатывал и самый первый запрос клиента(192.168.10.54 — app01)
Постоянное HTTP-соединение
В настройках используется директива option httpclose, которая добавляет заголовок
1 |
Connection: close |
Он закрывает соединения клиента (браузера) после получения ответа.
Чтобы включить повторное использование соединений HTTP (или HTTP keep-alive) для HAProxy, нужно заменить строку option httpclose следующим кодом:
1 2 3 |
# option httpclose option http-server-close timeout http-keep-alive 3000 |
Такая настройка полезна, поскольку она помогает снизить использование ресурсов балансировки нагрузки.
Тестирование постоянного HTTP-соединения
Можно протестировать настройку при помощи curl, оправив несколько одновременных запросов. Вывод будет примерно таким (ненужные фрагменты опущены):
1 |
# curl -v http://10.10.1.43/index.html http://10.10.1.43/index.html |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
* Trying 10.10.1.43... * Connected to 10.10.1.43 (10.10.1.43) port 80 (#0) > GET /index.html HTTP/1.1 > User-Agent: curl/7.38.0 > Host: 10.10.1.43 > Accept: */* …………………….. * Connection #0 to host 10.10.1.43 left intact * Found bundle for host 10.10.1.43: 0x7f49deece710 * Re-using existing connection! (#0) with host 10.10.1.43 * Connected to 10.10.1.43 (10.10.1.43) port 80 (#0) > GET /index.html HTTP/1.1 > User-Agent: curl/7.38.0 > Host: 10.10.1.43 > Accept: */* > ………………………………… |
Как видно из вывода есть строка,которая подтверждает повторное использование существующего соединения для отправки
1 |
Re-using existing connection! (#0) with host 10.10.1.43 |
Настройка доступа к статистике HAProxy
1 |
# nano /etc/haproxy/haproxy.cfg |
1 2 3 4 5 6 7 8 9 10 11 12 |
# включают страницу статистики панели мониторинга stats enable # URL, по которому доступна статистика Haproxy stats uri /haproxy stats realm Haproxy\ Statistics # HTTP-базовая авторизация логин/пароль для просмотра статистики HAProxy stats auth admin:123456 # Скрывать версию HAProxy в статистике # stats hide-version # Автообновление статики каждые 30 секунд stats refresh 30s # stats show-node |
http://10.10.1.43/haproxy
Настройка HAProxy на поддержку/обработку HTTPS-запросов
Две основных метода работы НAProxy c SSL
SSL-Termination
Шифрованное https –соединение клиента принимает лоадбалансер и дешифрует его и уже нешифрованное http_соединение отправляет на backend сервера(сервера приложений)
Это означает, что балансировкщик нагрузки несет ответственность за расшифровку соединение SSL — медленный и трудоемкий процесс CPU относительно приема без SSL-запросов.
Вся нагрузка по рашифровке соединений ложится на процессор лоадбалансера
SSL Pass-Through
Шифрованное https –соединение клиента принимает лоадбалансер и проксирует его в неизменном виде на сервера приложений
С помощью SSL-Pass-Through, соединение SSL завершается на каждом сервере приложений распределяя нагрузку на процессоры этих серверов. Тем не менее, теряется возможность добавлять или редактировать заголовки HTTP, так как соединение просто направляется через балансиовщик нагрузки на сервера приложений.
Это означает, что серверы приложений потеряют возможность получить X-Forwarded- * заголовки, которые могут включать в себя клиента IP-адрес, порт и используемую схему.
Создание самоподписного сертификата
1 |
# openssl req -new -x509 -days 3650 -nodes -out kamaok.org.us.crt -keyout kamaok.org.us.key |
Получение PEM-файла в формате понятном для HAproxy
1 |
# cat kamaok.org.us.crt kamaok.org.us.key > /etc/ssl/kamaok.org.us.pem |
Настройка HAProxy в режиме SSL Termination
Настройка HAProxy для того, чтобы сайты были доступны,как по http, так и по https-протоколам
1 |
# nano /etc/haproxy/haproxy.cfg |
1 2 3 4 5 6 7 8 |
global tune.ssl.default-dh-param 2048 frontend WEBLoadBalancer-HTTP …………………………… bind 10.10.1.43:443 ssl crt /etc/ssl/kamaok.org.us.pem ……………………………… |
1 |
# /etc/init.d/haproxy restart |
Если необходимо иметь доступ к сайту только по https, тогда настраиваем принудительный редирект http->https
1 |
# nano /etc/haproxy/haproxy.cfg |
1 2 3 4 |
frontend WEBLoadBalancer-HTTP …………… redirect scheme https if !{ ssl_fc } …………… |
Настройка HAProxy в режиме SSL Pass-Through
Работа балансировщика нагрузки заключается только в проксировании запросов на сервера приложений. Поскольку соединение остается зашифрованным, HAProxy не может с этим ничего сделать, кроме,как перенаправить запрос на сервер приложений
В этой установке, мы должны использовать режим TCP вместо HTTP режима в обоих frontend и backend конфигурациях
SSL-сетификаты настраиваются на WEB-серверах
Настройка SSL-сертификатов на HAProxy не требуется
Для проверки доступности серверов приложений, мы можем использовать
1 |
option ssl-hello-chk |
который проверяет соединение, а также его способность обрабатывать SSL (в частности SSLv3) соединений.
frontend LBS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
defaults # option httpclose # option http-server-close # timeout http-keep-alive 3000 # option forwardfor frontend WEBLoadBalancer-HTTP mode tcp option tcplog # bind 10.10.1.43:80 bind 10.10.1.43:443 default_backend webcluster backend webcluster # mode http mode tcp balance roundrobin # option httpclose # option forwardfor # option httpchk HEAD / HTTP/1.0\r\nHost:kamaok.org.us # http-request add-header X-Forwarded-Proto https if { ssl_fc } option ssl-hello-chk # server app01 192.168.10.54:80 check # server app02 192.168.10.55:80 check # server app03 192.168.10.56:80 check server app01 192.168.10.54:443 check server app02 192.168.10.55:443 check server app03 192.168.10.56:443 check |
1 |
# /etc/init.d/haproxy restart |
Проверяем распределение запросов
1 |
# curl -k -L https://kamaok.org.us |
1 |
kamaok.org.us-ubuntu143 |
1 |
# curl -k -L https://kamaok.org.us |
1 |
kamaok.org.us-ubuntu142 |
1 |
# curl -k -L https://kamaok.org.us |
1 |
kamaok.org.us-ubuntu144 |
Если необходимо использовать Sticky session, то в секцию backend добавляем
1 2 |
stick-table type ip size 200k expire 30m stick on src |
1 |
# /etc/init.d/haproxy restart |
Проверяем
1 |
# curl -k -L https://kamaok.org.us |
1 |
kamaok.org.us-ubuntu143 |
1 |
# curl -k -L https://kamaok.org.us |
1 |
kamaok.org.us-ubuntu143 |
1 |
# curl -k -L https://kamaok.org.us |
1 |
kamaok.org.us-ubuntu143 |
Источник:
https://serversforhackers.com/load-balancing-with-haproxy
https://serversforhackers.com/using-ssl-certificates-with-haproxy
https://www.8host.com/blog/balansirovka-nagruzki-http-s-pomoshhyu-haproxy-na-servere-ubuntu/
http://linux-notes.org/ustanovka-haproxy-na-linux-debian-ubuntu-ili-centos-redhat/
https://www.digitalocean.com/community/tutorials/how-to-use-haproxy-to-set-up-http-load-balancing-on-an-ubuntu-vps
http://www.phphighload.com/2012/08/blog-post.html
http://virtuallyhyper.com/2013/05/configure-haproxy-to-load-balance-sites-with-ssl/
https://serversforhackers.com/using-ssl-certificates-with-haproxy
https://serversforhackers.com/load-balancing-with-haproxy