Как я могу упростить конфигурацию обратного прокси-сервера Nginx для нескольких сред без использования резолвера?

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

Я разворачиваю Nginx в поде OpenShift (OCP) в качестве обратного прокси для наших микросервисов.

Наша настройка включает четыре окружения:

Продакшн синий: myproject.mycompany.com
Продакшн зеленый: myproject-green.mycompany.com
UAT синий: myproject-uat.mycompany.com
UAT зеленый: myproject-uat-green.mycompany.com
У нас в кластере развернуто около 18 микросервисов. Например, некоторые из наших конечных точек выглядят так:

/api/messaging/

/api/dashboard/

/api/profile/

/mfe/profile/

/mfe/dashboard/

…и другие…

В настоящее время у меня есть отдельный блок location для каждой конечной точки (жестко закодированной) для каждого окружения. Я попытался сократить количество блоков location, используя регулярные выражения для соответствия /api и /mfe и динамически создавая URL-адрес proxy_pass через переменные. Этот подход полагается на карты (например, сопоставление окружения и конечной точки с бэкенд-сервисом), но заставляет меня использовать DNS резолвер для разрешения во время выполнения.

Мой вопрос:

Есть ли способ упростить конфигурацию (уменьшить количество блоков location) без необходимости указывать резолвер? В частности, я хочу избежать динамических имен хостов, требующих выполнения DNS-запросов во время выполнения, при этом поддерживая несколько окружений (Prod/UAT и Blue/Green) без дублирования конфигурации для всех 18 служб.

Буду признателен за любые предложения, обходные пути или лучшие практики для достижения этого с помощью Nginx в среде OCP!

Я пробовал использовать карты для первоначального сопоставления с окружением и создания всех URL динамическими, но это требует указания резолвера, чего я не могу сделать. Я хочу использовать регулярные выражения, чтобы избежать жесткого кодирования, а также чтобы мой nginx был более чистым и адаптируемым.

Ответ или решение

Теория

Настройка Nginx в качестве обратного прокси для нескольких окружений может быть сложной задачей, особенно когда необходимо поддерживать множество микросервисов, как в вашем случае. Главная задача здесь заключается в том, чтобы минимизировать количество конфигурационных блоков и избежать избыточного дублирования конфигурации, сохраняя при этом возможность управления несколькими окружениями (Prod/UAT) и схемами Blue/Green. Многие предпочитают использовать функции культуры, такие как сопоставление по шаблону (regex) и переменные, для упрощения конфигурации. Однако, такие подходы зачастую требуют использования DNS resolver для динамического определения имен хостов во время выполнения, что нежелательно в вашем случае.

Пример

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

Применение

Чтобы решить вашу задачу, можно рассмотреть следующие подходы:

  1. Структуризация URL на основе пути:
    Использование предопределённых правил маршрутизации, основанных на паттернах URI, и карт для соответствия микросервисам может значительно снизить сложность конфигурации. Поскольку у вас есть чёткое разграничение между типами микросервисов, многие из них начинаются с /api или /mfe, можно значительно сократить количество location-блоков, объединив их на основе этих шаблонов и других предопределённых правил. Это может быть достигнуто за счёт использования регулярных выражений для маршрутизации в зависимости от префикса URI.

    map $http_host $backend {
       ~*^myproject(-uat)?(-green)?\.mycompany\.com$ "backend_$http_host";
    }
    
    location ~ ^/(api|mfe)/ {
       set $service_uri $1;
       proxy_pass http://$backend/$service_uri;
    }
  2. Использование статических хост-названий:
    Вместо использования переменных для динамической генерации backend-адресов, можно заранее определить все возможные хосты в карте, что позволит обойти необходимость в резолвере.

    map $http_host $upstream {
       default "backend_default";
       "myproject.mycompany.com" "backend_prod_blue";
       "myproject-green.mycompany.com" "backend_prod_green";
       "myproject-uat.mycompany.com" "backend_uat_blue";
       "myproject-uat-green.mycompany.com" "backend_uat_green";
    }
    
    location ~ ^/(api|mfe)/ {
       proxy_pass http://$upstream/$1;
    }
  3. Максимальное использование несложных выражений:
    Если возможно ограничиться более простыми выражениями, которые не потребуют дополнительных разрешений на стороне DNS, это позволит значительно упростить и ускорить процесс обработки.

  4. Разделение конфигурации на файлы:
    Использование практики управления конфигурацией через разделение на смысловые и технические блоки может быть полезным для упрощения визуального восприятия и уменьшения ошибок управления.

  5. Контейнеризация и шаблонизация:
    Поскольку ваша система развернута на OpenShift, вы можете принять стратегию шаблонизации конфигураций. Это может быть сделано с помощью инструментов, таких как Helm для Kubernetes, или используя встроенные возможности OpenShift для конфигурирования развертываний с помощью шаблонов и конфигурационных карт (ConfigMaps).

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

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

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