Вы научитесь настраивать прокси-сервер Nginx с поддержкой SSL Let’s Encrypt для балансировки между двумя upstream-серверами. Данное руководство для ОС семейства Debian — Ubuntu Linux, Debian Linux и других, которые используют схожие пакеты и методы их установки.
Nginx часто используется не как самостоятельный Web-сервер, а как обратный прокси, который, который распределяет трафик на обрабатывающие серверы (в общей терминологии — upstream), которые уже выполняют всю работу. Эта схема часто применяется даже там, где вы ее не ожидаете, например, для взаимодействия с PHP-FPM или для передачи обработки на сервер Apache2.
Говоря о роли Nginx как об обратном прокси необходимо отметить несколько функций, которые Nginx выполняет:
- Маршрутизация трафика. В рамках этой функции Nginx решает какой трафик на какой сервер отправить, в этот процесс может входить и балансировка по доступным серверам и видоизменение запроса, добавление в него дополнительной информации.
- Обработка SSL. Прокси размещается на границе сети, позволяя внутренним серверам использовать HTTP без шифрования, а задачи шифрования трафика решаются Nginx. Соответственно, уменьшается количество необходимых мест управления сертификатами и упрощается инфраструктура.
- Аутентификация и поддержка SSO. Опциональная роль, в рамках которой Nginx решает задачи пропуска запросов на обрабатывающие серверы в зависимости от того, прошли ли их отправители аутентификацию.
Чем более сложные задачи приходится решать на уровне прокси-сервера тем более часто он называется API Gateway. Существуют продукты, которые построены на Nginx, но решают задачи, требующие продвинутой обработки, которые Nginx «из коробки» не умеет. Эти задачи решаются с помощью скриптов на Lua. Два известных проекта — Kong и OpenResty.
Демонстрационный Upstream-сервер
Для демонстрации будем использовать тривиальный HTTP-сервер, реализованный на Python:
sudo apt update sudo apt install -y python3 python3 -m http.server <PORT> --bind 127.0.0.1
Эта команда создает тривиальный HTTP-сервер, который просто выводит структуру каталога, в котором запущен. Вы можете запустить его на локальной машине, например, на 8000 порту и проверить его работу через браузер или curl:
curl http://localhost:8000/
Для целей урока на сервере, где будет настраиваться Nginx, мы так же запустим два сервера — один на порту 8081, второй на порту 8082.
Будем использовать различные каталоги, чтобы нагляднее видеть как меняется поведение. Эти серверы не будут доступны извне, но будут использоваться в качестве Upstream-серверов, между которых будет распределять трафик Nginx:
cd /tmp; python3 -m http.server 8081 --bind 127.0.0.1 & cd /usr; python3 -m http.server 8082 --bind 127.0.0.1 &
Обратите внимание на символ ‘&‘ в конце строки — это означает, что процесс будет запущен в фоновом режиме. Вы не должны закрывать терминал, в котором запустили эти процессы до окончания урока.
Проверьте работоспособность обоих серверов с помощью curl, соединившись с ними:
curl http://localhost:8081/ curl http://localhost:8082/
Настройка Let’s Encrypt
Для настройки Let’s Encrypt (далее LE) необходимо установить программное обеспечение CertBot:
sudo apt update sudo apt install -y certbot
Теперь запросим сертификат Let’s Encrypt. Вам понадобится e-mail, и имя домена:
Обратите внимание, ваш сервер должен быть доступен по доменному имени извне перед началом запуска команды получения сертификата. Не забывайте везде заменять домен ngx.cs2.netpoint-dc.com на ваш домен.
sudo certbot certonly --standalone -m user@site.com --agree-tos -d ngx.cs2.netpoint-dc.com
В примере выше имя домена — ngx.cs2.netpoint-dc.com, а e-mail: user@site.com. В момент запуска этой команды у вас не должно быть сервисов, занимающих порты 80 и 443. Если вы уже установили Nginx, остановите его с помощью service nginx stop.
После успешного завершения работы приложения вы получите сообщения следующего вида:
IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/ngx.cs2.netpoint-dc.com/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/ngx.cs2.netpoint-dc.com/privkey.pem Your cert will expire on 2019-06-27. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
В данном сообщении содержится важная информация о месте хранения данных сертификата. Мы будем использовать это в дальнейшем.
Следующий шаг — настроить автопродление сертификата. Сертификаты LE требуется продлевать каждые 90 дней. Мы просто настроим ежедневную задачу CRON, которая будет это делать. Для этого создайте файл /etc/cron.daily/le-renew со следующим содержимым:
#/bin/bash certbot renew
Пометьте его как исполняемый и проверьте, что он работает:
sudo chmod 755 /etc/cron.daily/le-renew sudo /etc/cron.daily/le-renew
Установка Nginx
В этой части урока мы установим Nginx и настроим его для балансировки трафика между двумя upstream-серверами, запущенными ранее с поддержкой сертификата LE. Установка из пакетов выполняется стандартным способом:
sudo apt update sudo apt install -y nginx
Теперь настроим конфигурацию для сайта, создав новый файл настроек для виртуального хоста — /etc/nginx/sites-available/ngx.cs2.netpoint-dc.com. Добавим в него следующее содержимое:
# переадресация с HTTP на HTTPS # server { if ($host = ngx.cs2.netpoint-dc.com) { return 301 https://$host$request_uri; } listen 80; listen [::]:80; server_name ngx.cs2.netpoint-dc.com; } # upstream-серверы для балансировки (python) # upstream dirlist { ip_hash; # липкая балансировка по IP-клиента server 127.0.0.1:8081; server 127.0.0.1:8082; } # обработка SSL и соединение с upstream-серверами # server { listen 443 ssl; listen [::]:443 ssl; server_name ngx.cs2.netpoint-dc.com; ssl_certificate /etc/letsencrypt/live/ngx.cs2.netpoint-dc.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/ngx.cs2.netpoint-dc.com/privkey.pem; access_log /var/log/nginx/website_access.log; error_log /var/log/nginx/website_error.log; # все запросы отправляем на upstream location / { proxy_pass http://dirlist/; } }
Теперь активируем созданный виртуальный хост:
sudo ln -s /etc/nginx/sites-{available,enabled}/ngx.cs2.netpoint-dc.com sudo nginx -t && sudo service nginx restart
Теперь при заходе через браузер на https://ngx.cs2.netpoint-dc.com/ вы будете видеть содержимое каталога, который отдается одним из upstream-серверов. В нашей настройке мы использовали ключевой слово ip_hash, что говорит Nginx делать липкую баансировку. Это означает, что до тех пор пока upstream-сервер, на который были распределены запросы от вашего IP работает, вы будете обслуживаться на нем.
Nginx поддерживает и другие способы, кроме ip_hash, например, least_conn, при этом Nginx будет выбирать наименее загруженный upstream-сервер.
Имитация отказа Upstream-сервера
Убедимся в том, что Nginx переключает трафик на второй upstream-сервер при падении первого. Для этого вы должны идентифицировать вывод какого каталога вы видите. В моем случае — это каталог ‘/usr’, а значит, это отдает сервер, работающий на порту 8082; отключим его.
Для этого в терминале, где вы запускали upstream-серверы python, выполните следующие команды:
$ cd; jobs [1]- Запущен python3 -m http.server 8081 --bind 127.0.0.1 & (рабочий каталог: /tmp) [2]+ Запущен python3 -m http.server 8082 --bind 127.0.0.1 & (рабочий каталог: /usr) # у меня отдается трафик с 8082, значит я буду останавливать процесс %2 # активирую %2 $ kill %2 python3 -m http.server 8082 --bind 127.0.0.1
Теперь, если вы обновите страницу в браузере, вы должны увидеть, что Nginx отдает контент с оставшегося сервера. Запустите сервер опять — в моем случае сервер на порту 8082:
cd /usr; python3 -m http.server 8082 --bind 127.0.0.1 &
Обоновите страницу в браузере. Вы можете повторить этот опыт еще несколько раз, чтобы проверить корректное переключение.
Заключение
Вы научились создавать базовый проксирующий сервер Nginx с поддержкой сертификата Let’s Encrypt, освоили настройку секции upstream Nginx, которая позволяет балансировать нагрузку между несколькими серверами, познакомились с директивой балансировщика ip_hash, предназначенной для реализации липкой балансировки.
Вам могут быть интересны следующие статьи:
- Как установить сервер WordPress с Nginx, PHP-FPM и MariaDB и сертификатом Let’s Encrypt в Debian Linux 9 (Stretch)
- Как установить сервер WordPress с Nginx, PHP-FPM и MariaDB и сертификатом Let’s Encrypt в Ubuntu Linux 18.04
- Защита, оптимизация и повышение производительности сайта с помощью CDN CloudFlare
Если вам понравилась статья, поделитесь ей.