Home » Как настроить балансировку нагрузки в Nginx с SSL терминацией
Как настроить балансировку нагрузки в Nginx с SSL терминацией

Как настроить балансировку нагрузки в 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 или для серьёзных проектов взять выделенный сервер.


В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.

Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.

Leave a reply

Your email address will not be published. Required fields are marked