Вопрос или проблема
Мы используем nginx в качестве обратного прокси для перенаправления запросов на наши различные серверы. В настоящее время, если какой-либо из этих upstream-серверов недоступен, nginx не запускается. Это вызывает разочарование, так как значит, что если один из наших upstream-серверов временно недоступен, то вся наша система становится недоступной.
Мы хотели бы настроить nginx таким образом, чтобы он успешно запускался, даже если один или несколько upstream-серверов недоступны.
Я наткнулся на https://sandro-keil.de/blog/let-nginx-start-if-upstream-host-is-unavailable-or-down/, который, если я правильно понимаю, говорит о том, что использование set
для настройки местоположения, которое будет proxy_pass
, как переменной перемещает разрешение имени хоста на время запроса, а не на время запуска, что решает проблему. Однако примеры в этом посте и те, которые я смог найти в другом месте, не описывают, как реализовать это “обходное решение”, используя блоки конфигурации upstream
для определения нескольких upstream-серверов, например для балансировки нагрузки. К сожалению, так как мое понимание фаз и деталей запуска и обработки запросов nginx минимально, я не уверен, как адаптировать пример “обходного решения” для случая, когда используются блоки upstream
.
Сработает ли этот подход, чтобы позволить nginx запускаться, когда upstream-сервер(ы) недоступны? Если да, то как и где мне set
и ссылаться на переменную? Если нет, как я могу это сделать?
Наша (сокращенная) конфигурация nginx:
upstream webserver {
server webserver:8080;
}
upstream websocketserver {
server websocketserver:8080;
}
server {
...
# Обратный прокси для запросов Liferay к веб-серверу(ам)
location / {
proxy_pass http://webserver;
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;
proxy_set_header X-Forwarded-Host $host;
}
# Обратный прокси для запросов Server-Push к WebSocket-серверу(ам)
location /websocket/ {
proxy_pass http://websocketserver;
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;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Prefix /websocket;
}
}
(Неудачная) попытка 1, установка переменной в блоке upstream
:
upstream webserver {
set $upstream_webserver webserver:8080;
server $upstream_webserver;
}
server {
...
# Обратный прокси для запросов Liferay к веб-серверу(ам)
location / {
proxy_pass http://webserver;
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;
proxy_set_header X-Forwarded-Host $host;
}
}
приводит к
root@039266c002d9:/# nginx -t
2024/10/11 17:29:06 [emerg] 40#40: "set" directive is not allowed here in /etc/nginx/conf.d/psif.conf:9
nginx: [emerg] "set" directive is not allowed here in /etc/nginx/conf.d/app.conf:9
nginx: configuration file /etc/nginx/nginx.conf test failed
(Неудачная) попытка 2, установка переменной в блоке server
(чтобы иметь возможность повторно использовать ее в нескольких блоках location
):
upstream webserver {
server webserver:8080;
}
server {
set $upstream_webserver webserver;
...
# Обратный прокси для запросов Liferay к веб-серверу(ам)
location / {
proxy_pass http://$upstream_webserver;
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;
proxy_set_header X-Forwarded-Host $host;
}
}
приводит к
root@039266c002d9:/# nginx -t
2024/10/11 17:31:44 [emerg] 41#41: host not found in upstream "webserver:8080" in /etc/nginx/conf.d/app.conf:7
nginx: [emerg] host not found in upstream "webserver:8080" in /etc/nginx/conf.d/app.conf:7
nginx: configuration file /etc/nginx/nginx.conf test failed
Как я могу настроить nginx, чтобы он запускался, когда upstream-сервер(ы) недоступны, используя блоки конфигурации upstream
?
Ответ или решение
Настройка Nginx для работы в ситуации, когда один из upstream-серверов недоступен, может быть не совсем очевидной, особенно при использовании блоков upstream
. Давайте разберемся, как это сделать, чтобы Nginx действительно мог запускаться, даже если некоторые из upstream-серверов временно не работают.
Проблема
При стандартной настройке Nginx, если один из серверов в блоке upstream
не доступен при старте, Nginx не запустится. Это может стать проблемой для вашей системы, поскольку даже временная недоступность одного сервера сделает его полностью недоступным. Решение заключается в том, чтобы перенести разрешение имен в момент выполнения запросов, а не во время старта.
Решение
Для достижения желаемого поведения мы можем использовать переменные Nginx и директиву resolver
. Сначала следует настроить свой блок upstream
, чтобы он не зависел от статического разрешения имени хоста.
Шаги по настройке
-
Отключите статическое разрешение имени хоста в блоке
upstream
.Мы не будем указывать конкретных серверов в блоке
upstream
. Вместо этого мы будем использовать переменную. -
Используйте директиву
resolver
для динамического разрешения имен.Убедитесь, что у вас есть настроенный DNS-сервер, который сможет разрешать ваши upstream-сервера.
-
Настройте ваши блоки
location
для динамического проксирования.
Пример конфигурации:
# Укажите DNS для разрешения имен
resolver 8.8.8.8 valid=30s; # Используйте ваш DNS-сервер
server {
listen 80;
server_name example.com;
# Объявляем переменные для upstream серверов
set $upstream_webserver "webserver:8080";
set $upstream_websocketserver "websocketserver:8080";
# Реверс-прокси для web-сервера
location / {
proxy_pass http://$upstream_webserver;
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;
proxy_set_header X-Forwarded-Host $host;
}
# Реверс-прокси для WebSocket сервера
location /websocket/ {
proxy_pass http://$upstream_websocketserver;
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;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Prefix /websocket;
}
}
Объяснение конфигурации
- Директива
resolver
: Обеспечивает Nginx возможность динамического разрешения доменных имен. Вы можете использовать любой рабочий DNS-сервер, например, 8.8.8.8 (Google DNS). - Переменные
$upstream_webserver
и$upstream_websocketserver
: Эти переменные используются в директивеproxy_pass
, что позволяет Nginx пытаться разрешить их при каждом запросе, а не только при старте. - Обработка запросов: Теперь, когда вы обращаетесь к вашим веб-приложениям, Nginx будет пытаться получить IP-адреса upstream-серверов на момент выполнения запросов, что позволяет избежать проблем при запуске, если один из серверов временно недоступен.
Заключение
Эта настройка позволяет запускать Nginx, даже если один или несколько upstream-серверов недоступны. Убедитесь, что ваш DNS-сервер может быстро и правильно разрешать ваши upstream-имена, чтобы минимизировать задержки при обработке запросов. Теперь вы сможете более устойчиво управлять вашим приложением и обеспечить его доступность даже в случае временных сбоев в работе upstream-серверов.