Как настроить nginx для запуска, если upstream хост недоступен при использовании upstream блоков.

Вопрос или проблема

Мы используем 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, чтобы он не зависел от статического разрешения имени хоста.

Шаги по настройке

  1. Отключите статическое разрешение имени хоста в блоке upstream.

    Мы не будем указывать конкретных серверов в блоке upstream. Вместо этого мы будем использовать переменную.

  2. Используйте директиву resolver для динамического разрешения имен.

    Убедитесь, что у вас есть настроенный DNS-сервер, который сможет разрешать ваши upstream-сервера.

  3. Настройте ваши блоки 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-серверов.

Оцените материал
Добавить комментарий

Капча загружается...