- Home »

Как настроить балансировку нагрузки в Nginx с SSL терминацией
Если у вас есть несколько backend-серверов и нужно равномерно распределить между ними нагрузку, плюс при этом не хочется заморачиваться с настройкой SSL на каждом сервере — то эта статья для вас. Мы разберём, как поднять Nginx в роли load balancer’а с SSL терминацией, чтобы клиенты подключались по HTTPS к балансировщику, а он уже по HTTP форвардил запросы на бэкенды. Это позволит централизованно управлять сертификатами и снизить нагрузку на сами приложения.
Как это работает?
Схема довольно простая: клиент подключается к Nginx по HTTPS, тот расшифровывает SSL-трафик, выбирает один из backend-серверов по алгоритму балансировки и отправляет запрос уже по обычному HTTP. Ответ идёт обратно — с бэкенда на Nginx, оттуда шифруется и отправляется клиенту.
Основные компоненты:
- Upstream блок — описывает группу backend-серверов
- SSL терминация — Nginx обрабатывает HTTPS и передаёт HTTP на бэкенды
- Алгоритмы балансировки — round-robin, least_conn, ip_hash и другие
- Health checks — проверка доступности серверов
Установка и базовая настройка
Для начала убедитесь, что у вас установлен Nginx с модулем SSL (в большинстве дистрибутивов он есть по умолчанию):
sudo apt update
sudo apt install nginx
nginx -V 2>&1 | grep -o with-http_ssl_module
Если модуль есть, увидите “with-http_ssl_module”. Теперь создадим базовую конфигурацию:
sudo nano /etc/nginx/sites-available/loadbalancer
Базовый конфиг будет выглядеть так:
upstream backend {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/ssl/certs/example.com.pem;
ssl_certificate_key /etc/ssl/private/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Активируем конфигурацию:
sudo ln -s /etc/nginx/sites-available/loadbalancer /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Алгоритмы балансировки
Nginx поддерживает несколько алгоритмов балансировки. Вот основные с примерами:
Алгоритм | Описание | Когда использовать |
---|---|---|
round-robin (по умолчанию) | Последовательно перебирает серверы | Равномерная нагрузка, одинаковые серверы |
least_conn | Выбирает сервер с наименьшим количеством подключений | Разные по мощности серверы |
ip_hash | Привязывает клиента к серверу по IP | Нужна sticky session |
weighted | Распределяет нагрузку по весам | Серверы разной производительности |
Примеры конфигураций:
# Least connections
upstream backend {
least_conn;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
# IP hash для sticky sessions
upstream backend {
ip_hash;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
# Weighted балансировка
upstream backend {
server 192.168.1.10:8080 weight=3;
server 192.168.1.11:8080 weight=2;
server 192.168.1.12:8080 weight=1;
}
Настройка SSL сертификатов
Для продакшена лучше использовать Let’s Encrypt. Установим certbot:
sudo apt install snapd
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
Получаем сертификат:
sudo certbot --nginx -d example.com
Certbot автоматически обновит конфигурацию Nginx. Для автоматического обновления добавьте в crontab:
sudo crontab -e
# Добавьте строку:
0 12 * * * /usr/bin/certbot renew --quiet
Health checks и мониторинг
Nginx автоматически исключает недоступные серверы, но можно настроить более тонкую проверку:
upstream backend {
server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.12:8080 backup;
}
Параметры:
max_fails=3
— количество неудачных попытокfail_timeout=30s
— время, на которое сервер исключаетсяbackup
— резервный сервер, используется когда основные недоступны
Для мониторинга можно настроить специальный endpoint:
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
Оптимизация производительности
Несколько важных настроек для высокой нагрузки:
# В секции server
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g
inactive=60m use_temp_path=off;
server {
# ... SSL конфигурация
# Кэширование статики
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
proxy_pass http://backend;
proxy_cache my_cache;
proxy_cache_valid 200 1h;
proxy_cache_use_stale error timeout invalid_header updating;
add_header X-Cache-Status $upstream_cache_status;
}
# Gzip сжатие
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript;
# Буферизация
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
# Таймауты
proxy_connect_timeout 5s;
proxy_send_timeout 10s;
proxy_read_timeout 10s;
}
Продвинутые возможности
Nginx Plus (коммерческая версия) предоставляет дополнительные функции, но и в бесплатной версии можно многое:
Сессионная привязка через cookie
upstream backend {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
map $cookie_backend $backend_pool {
~^server1 192.168.1.10:8080;
~^server2 192.168.1.11:8080;
default backend;
}
server {
# ... SSL конфигурация
location / {
proxy_pass http://$backend_pool;
# Остальные proxy_set_header
}
}
Геобалансировка
geo $backend_pool {
default backend_us;
~^85\.21\.78 backend_eu;
~^46\.229\.168 backend_eu;
}
upstream backend_us {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
}
upstream backend_eu {
server 10.0.2.10:8080;
server 10.0.2.11:8080;
}
Интеграция с Docker и CI/CD
Для автоматизации развёртывания можно использовать шаблоны конфигураций:
# docker-compose.yml
version: '3'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/ssl
depends_on:
- app1
- app2
app1:
image: myapp:latest
ports:
- "8080"
app2:
image: myapp:latest
ports:
- "8080"
Скрипт для автоматического обновления upstream при деплое:
#!/bin/bash
# update_upstream.sh
NGINX_CONF="/etc/nginx/sites-available/loadbalancer"
TEMP_CONF="/tmp/nginx_upstream.conf"
# Получаем список активных контейнеров
CONTAINERS=$(docker ps --format "table {{.Names}}\t{{.Ports}}" | grep myapp | awk '{print $1}')
# Генерируем новый upstream блок
echo "upstream backend {" > $TEMP_CONF
for container in $CONTAINERS; do
IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $container)
echo " server $IP:8080;" >> $TEMP_CONF
done
echo "}" >> $TEMP_CONF
# Обновляем конфигурацию
sudo cp $TEMP_CONF $NGINX_CONF
sudo nginx -t && sudo systemctl reload nginx
Сравнение с альтернативами
Решение | Плюсы | Минусы |
---|---|---|
Nginx | Простота, высокая производительность, малое потребление памяти | Ограниченные возможности в free версии |
HAProxy | Продвинутые health checks, детальная статистика | Сложнее в настройке, только L4/L7 |
Traefik | Автоматическое обнаружение сервисов, интеграция с Docker | Больше потребление ресурсов |
Cloudflare | CDN, DDoS защита, удобная панель | Внешний сервис, возможные задержки |
Отладка и troubleshooting
Основные проблемы и их решение:
502 Bad Gateway
# Проверяем доступность бэкендов
curl -I http://192.168.1.10:8080/
# Смотрим логи Nginx
sudo tail -f /var/log/nginx/error.log
# Проверяем SELinux (если используется)
sudo setsebool -P httpd_can_network_connect 1
SSL проблемы
# Проверяем сертификат
openssl x509 -in /etc/ssl/certs/example.com.pem -text -noout
# Тестируем SSL
openssl s_client -connect example.com:443 -servername example.com
Мониторинг производительности
# Установка nginx-prometheus-exporter
wget https://github.com/nginxinc/nginx-prometheus-exporter/releases/download/v0.8.0/nginx-prometheus-exporter-0.8.0-linux-amd64.tar.gz
tar xzf nginx-prometheus-exporter-0.8.0-linux-amd64.tar.gz
sudo mv nginx-prometheus-exporter /usr/local/bin/
Автоматизация и скрипты
Скрипт для массового обновления серверов в upstream:
#!/bin/bash
# mass_update_backend.sh
UPSTREAM_FILE="/etc/nginx/conf.d/upstream.conf"
BACKUP_DIR="/etc/nginx/backups"
DATE=$(date +%Y%m%d_%H%M%S)
# Создаём backup
mkdir -p $BACKUP_DIR
cp $UPSTREAM_FILE $BACKUP_DIR/upstream_$DATE.conf
# Читаем новый список серверов из файла
while IFS= read -r server; do
if [[ $server =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+$ ]]; then
echo " server $server;" >> /tmp/new_upstream.conf
fi
done < servers.txt
# Заменяем upstream блок
sed -i '/upstream backend {/,/}/c\
upstream backend {\
'"$(cat /tmp/new_upstream.conf)"'\
}' $UPSTREAM_FILE
# Проверяем и перезагружаем
if sudo nginx -t; then
sudo systemctl reload nginx
echo "Upstream updated successfully"
else
echo "Configuration error, restoring backup"
cp $BACKUP_DIR/upstream_$DATE.conf $UPSTREAM_FILE
fi
Полезные ссылки
Заключение
Nginx с SSL терминацией и балансировкой нагрузки — отличное решение для большинства задач. Он прост в настройке, производителен и надёжен. Основные преимущества:
- Централизованное управление SSL сертификатами
- Снижение нагрузки на backend серверы
- Гибкие алгоритмы балансировки
- Встроенные health checks
- Возможность кэширования и сжатия
Используйте это решение когда нужно быстро поднять load balancer без лишних заморочек. Для более сложных сценариев с микросервисами можно рассмотреть Traefik или Istio, но для классических web-приложений Nginx будет оптимальным выбором.
Кстати, если вам нужен сервер для экспериментов, можете арендовать VPS или для серьёзных проектов взять выделенный сервер.
В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.
Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.