Вопрос или проблема
Я разворачиваю 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 без использования резолвера, сохраняя при этом возможность поддержки различных окружений и маршрутизации к различным микросервисам.
Применение
Чтобы решить вашу задачу, можно рассмотреть следующие подходы:
-
Структуризация 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; }
-
Использование статических хост-названий:
Вместо использования переменных для динамической генерации 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; }
-
Максимальное использование несложных выражений:
Если возможно ограничиться более простыми выражениями, которые не потребуют дополнительных разрешений на стороне DNS, это позволит значительно упростить и ускорить процесс обработки. -
Разделение конфигурации на файлы:
Использование практики управления конфигурацией через разделение на смысловые и технические блоки может быть полезным для упрощения визуального восприятия и уменьшения ошибок управления. -
Контейнеризация и шаблонизация:
Поскольку ваша система развернута на OpenShift, вы можете принять стратегию шаблонизации конфигураций. Это может быть сделано с помощью инструментов, таких как Helm для Kubernetes, или используя встроенные возможности OpenShift для конфигурирования развертываний с помощью шаблонов и конфигурационных карт (ConfigMaps).
Применение этих подходов позволит минимизировать использование резолвера, обеспечив при этом мощное и гибкое управление маршрутизацией в зависимости от окружения. Вы можете достичь оптимальной конфигурации за счет стратегического применения правил маршрутизации и использование преимуществ инфраструктуры контейнеров без излишнего усложнения процесса управления конфигурацией.