Распределение выполнения запросов внутри приватной сети VPS через HAProxy

Приватную сеть можно использовать для распределения выполнения загрузки и балансировки запросов между несколькими серверами. Рассмотрим организацию такой балансировки на примере HAProxy - бесплатного ПО, предназначенного для распределения нагрузки и организации проксирования TCP-пакетов между несколькими обслуживающими серверами. 

Схема работы в рассматриваемом примере будет следующей:

  • Первый сервер (с приватным IP-адресом 10.16.0.5, назовем его haproxy) будет принимать входящие HTTP-запросы. На нем будет запущен HAProxy, который будет распределять их по исполняющим серверам;
  • Второй сервер (с приватным IP-адресом 10.16.0.7, назовем его nginx2) будет отдавать JPEG- и PNG-файлы - на нем будет запущен nginx, который будет получать запросы от HAProxy;
  • Третий сервер (с приватным IP-адресом 10.16.0.6, назовем его nginx1) будет отдавать весь остальной контент - также через nginx.

Подготовка

Все три сервера будут работать на Ubuntu 20.04. На каждом из них получим и установим обновления системы:

apt update && apt upgrade -y

Установим nginx на серверах nginx1 и nginx2:

apt install nginx -y

На сервер nginx2 в папку /var/www/html положим картинку с осьминогом:

root@nginx2:/var/www/html# ll
total 320
drwxr-xr-x 2 root root 4096 Oct 19 06:33 ./
drwxr-xr-x 3 root root 4096 Oct 19 06:30 ../
-rw-r--r-- 1 root root 612 Oct 19 06:30 index.nginx-debian.html
-rw-r--r-- 1 root root 312162 Apr 26 14:48 octo.png

На сервере nginx1 создадим файл index.html с небольшой HTML-страницей и картинкой, которую мы будем брать с другого сервера:

root@nginx1:~# cat /var/www/html/index.html
<html>
<head>
<title>Beget HAProxy Test</title>
</head>
<body>
<h1>Beget HAProxy Test</h1>
<img src="octo.png">
</body>
</html>

Если мы сейчас попробуем обратиться напрямую к серверу nginx1 - то увидим, что изображение не загрузится, ведь его физически нет на сервере:

Установка HAProxy

Перейдем к установке и настройке HAProxy. Установим его из репозитория на сервер haproxy:

apt install haproxy -y

Откроем конфигурационный файл HAProxy (/etc/haproxy/haproxy.cfg) любым текстовым редактором. Те настройки, которые уже объявлены в конфигураторе, мы изменять не будем.

Для начала укажем, что HAProxy будет принимать все входящие подключения на 80 порт:

frontend website
       bind :80

В качестве бэкенд-серверов у нас будут два сервера с nginx - укажем их отдельно:

backend static
       server static1 10.16.0.7:80
 
backend main
       server main1 10.16.0.6:80

Сервера объявлены - теперь настроим правила балансировки. Расширим блок с объявлением frontend-сервера в конфигурационном файле - укажем, что если имя файла заканчивается на .jpg или .png, запрос должен уйти на сервер для статики, все остальное пусть обрабатывает основной сервер:

frontend website
       bind :80
       use_backend static if { path_end .jpg .png }
       default_backend main

Весь конфигурационный файл будет выглядеть так:

root@haproxy:~# cat /etc/haproxy/haproxy.cfg  
global
       log /dev/log    local0
       log /dev/log    local1 notice
       chroot /var/lib/haproxy
       stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
       stats timeout 30s
       user haproxy
       group haproxy
       daemon
 
       # Default SSL material locations
       ca-base /etc/ssl/certs
       crt-base /etc/ssl/private
 
       # See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
       ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-A
ES256-GCM-SHA384
       ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
       ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
 
defaults
       log     global
       mode    http
       option  httplog
       option  dontlognull
       timeout connect 5000
       timeout client  50000
       timeout server  50000
       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 website
       bind :80
       use_backend static if { path_end .jpg .png }
       default_backend main
 
backend static
       server static1 10.16.0.7:80
 
backend main
       server main1 10.16.0.6:80

Сохраним конфиг и перезапустим HAProxy:

systemctl restart haproxy

Откроем браузер и попробуем обратиться к серверу haproxy - мы увидим страницу с изображением, а значит, все работает!

Если посмотреть логи запросов к nginx на конечных серверах - можно увидеть, что все запросы идут с приватного IP сервера, где поднят HAProxy. При этом на сервер для изображений пришли только запросы к .png:

root@nginx2:~# cat /var/log/nginx/access.log
10.16.0.5 - - [19/Oct/2021:06:56:09 +0000] "GET /octo.png HTTP/1.1" 200 312162 "http://45.147.177.163/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36"
10.16.0.5 - - [19/Oct/2021:06:56:23 +0000] "GET /octo.png HTTP/1.1" 200 312162 "http://45.147.177.163/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36"

Остальные запросы, как и было необходимо, ушли на другой сервер:

root@nginx1:~# cat /var/log/nginx/access.log  
10.16.0.5 - - [19/Oct/2021:06:56:05 +0000] "GET / HTTP/1.1" 200 123 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36"
10.16.0.5 - - [19/Oct/2021:06:56:09 +0000] "GET /favicon.ico HTTP/1.1" 404 197 "http://45.147.177.163/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36"
10.16.0.5 - - [19/Oct/2021:06:56:23 +0000] "GET / HTTP/1.1" 200 123 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36"

С помощью HAProxy можно делать и более сложные цепочки правил распределения запросов, настраивать лимиты по количеству подключений, управлять таймаутами и многое другое. Более подробно о настройке HAProxy можно прочесть в официальной документации.

0
119