Настройка Nginx multiple reverse proxy для k3s+istio

от автора

Немного воды

Всем читателям, привет! Хочется поделиться своим опытом по созданию Nginx reverse proxy для интересного кейса. Не судите строго но критике и предложениям буду рад.

Начало

Поступил вызов о необходимости реализации следующего кейса:

  • Есть 1 ip и на него нацелено n доменов

  • Есть n серверов (за NAT)

  • Когда пользователь заходит на домен_1 попадает на сервер_1

  • Когда пользователь заходит на домен_2 попадает на сервер_2

  • Когда пользователь заходит на домен_n попадает на сервер_n

Казалось бы, тривиальная задача… Но не с инфраструктурой которая есть

Немного о инфраструктуре

Из за отсутствия необходимости реверсивного прокси схема инфраструктуры выглядела так как на рис.1.

рис.1

рис.1

Естественно, для реализации кейса, необходимо было встроить Nginx в эту схему. Итоговая схема представлена на рис.2

В целом такая конфигурация не предоставляет собой ничего сложного. Однако если istio настроен и присутствуют политики авторизации будут тонкости но об этом дальше.

Настройка Nginx reverse proxy

Немного вводных:

  1. ОС виртуализации Centos7

  2. Iptables настроен на полный запрет иных портов кроме 443

  3. Istio нацелен на доменное имя которое соответствует ВМ

Так как у меня ОС Centos7 конфиги http и server будут совмещены. Но важно понимать что если у вас раздельные конфиги как в Ubuntu это так же будет работать. Главное поместить нужный код в нужные места 😉

Итоговый конфиг для nginx выглядит так:

worker_processes 10;     events {     worker_connections 1024; } http {     include mime.types;     default_type application/octet-stream;     sendfile on;     keepalive_timeout 65;     #ВМ_1     server {         server_name test1.domain.ru;         listen       443 ssl;         listen [::]:443 ssl;         ssl_certificate      /home/CERT.crt;         ssl_certificate_key  /home/CERT.key;         ssl_session_cache    shared:SSL:1m;         ssl_session_timeout  5m;         ssl_protocols        TLSV1.1 TLSV1.2 TLSV1.3;         ssl_ciphers  HIGH:!aNULL:!MD5;         ssl_prefer_server_ciphers  on;         location / {             proxy_pass https://192.168.0.21;             proxy_http_version  1.1;             proxy_cache_bypass  $http_upgrade;             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;             proxy_set_header X-Real-IP $remote_addr;             proxy_set_header X-Forwarded-Host  $host;             proxy_set_header X-Forwarded-Proto $scheme;             proxy_set_header X-Forwarded-Port  $server_port;         }     #ВМ_2     server {         server_name test2.domain.ru;         listen       443 ssl;         listen [::]:443 ssl;         ssl_certificate      /home/CERT.crt;         ssl_certificate_key  /home/CERT.key;         ssl_session_cache    shared:SSL:1m;         ssl_session_timeout  5m;         ssl_protocols        TLSV1.1 TLSV1.2 TLSV1.3;         ssl_ciphers  HIGH:!aNULL:!MD5;         ssl_prefer_server_ciphers  on;         location / {             proxy_pass https://192.168.0.21;             proxy_http_version  1.1;             proxy_cache_bypass  $http_upgrade;             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;             proxy_set_header X-Real-IP $remote_addr;             proxy_set_header X-Forwarded-Host  $host;             proxy_set_header X-Forwarded-Proto $scheme;             proxy_set_header X-Forwarded-Port  $server_port;         }     }     #ВМ_n     server {         server_name testn.domain.ru;         listen       443 ssl;         listen [::]:443 ssl;         ssl_certificate      /home/CERT.crt;         ssl_certificate_key  /home/CERT.key;         ssl_session_cache    shared:SSL:1m;         ssl_session_timeout  5m;         ssl_protocols        TLSV1.1 TLSV1.2 TLSV1.3;         ssl_ciphers  HIGH:!aNULL:!MD5;         ssl_prefer_server_ciphers  on;         location / {             proxy_pass https://192.168.0.x;             proxy_http_version  1.1;             proxy_cache_bypass  $http_upgrade;             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;             proxy_set_header X-Real-IP $remote_addr;             proxy_set_header X-Forwarded-Host  $host;             proxy_set_header X-Forwarded-Proto $scheme;             proxy_set_header X-Forwarded-Port  $server_port;         }     } }

Теперь давайте немного разберем основные параметры.

Общий блок:

  • worker_processes — Колличество возможных рабочих процессов при подключении к одному IP. Как правило, на ядро запускается 1 рабочий процесс;

  • worker_processes — Колличество пользователей могут одновременно обслуживаться Nginx;

Блок http {

  • keepalive_timeout — Максимальное время поддержания keepalive-соединения, в случае, если пользователь по нему ничего не запрашивает.

Блок http { server {

  • server_name — Ожидаемое доменное имя по которому будет доступен сервер. Например testn.domain.ru

  • listen — Указывает на порт по которому будет доступен сервер. В случае с https/443 необходимо контролировать наличие подписи ssl в строке.

  • ssl_certificate/ssl_certificate_key — доменнные сертификаты

  • ssl_session_cache — Кеширование сессий. Необходимо для повторного использования ключей, чтобы не повторять хэндшейк.

  • ssl_protocols — Определение возможных TLS протоколов для работы с сервером.

Блок http { server { location / {

ВАЖНО
В случае если у вас есть фронт с url testn.domain.ru/front не получится использовать другие location кроме как корневой (/). Связано с передачей url от nginx на сервер во время proxy. istio будет отбивать такие запросы и rewrite не поможет

  • proxy_pass — Сервер на которое осуществляется проксирование домена, указанного в server_name блока server. 

  • proxy_http_version — Позволяет использовать HTTP/1.1 вместо дефолтного параметра HTTP/1.0

  • proxy_cache_bypass — В нашем случае не отдаются данные об изменении http запроса ($http_upgrade)

  • proxy_set_header — Записывает заголовки для передачи на сервер назначения proxy_pass

Подробнее можете почитать в доках nginx.

Должен отметить что по незнанию к такому конфигу я шел достаточно долго. 3 рабочих дня если быть точным.
Я долго не мог заставить дружить istio и nginx и перелопатил кучу информации. И что в итоге? Самый важный параметр всего этого конфига — это proxy_cache_bypass.

В чем же суть этого proxy_cache_bypass?
proxy_cache_bypass
 — Задает условия, при которых nginx не станет брать ответ из кэша, а сразу перенаправит запрос на бэкенд. Если хотя бы один из параметров не пустой и не равен “0”. Подробнее почитайте вот тут

В итоге у нас получается достаточно гибкая конфигурация прокси сервера которую легко аадминистрировать. Основной изменяемый/удаляемый/добавляемый блок — это блок http { server {

    #ВМ_n     server {         server_name testn.domain.ru;         listen       443 ssl;         listen [::]:443 ssl;         ssl_certificate      /home/CERT.crt;         ssl_certificate_key  /home/CERT.key;         ssl_session_cache    shared:SSL:1m;         ssl_session_timeout  5m;         ssl_protocols        TLSV1.1 TLSV1.2 TLSV1.3;         ssl_ciphers  HIGH:!aNULL:!MD5;         ssl_prefer_server_ciphers  on;         location / {             proxy_pass https://192.168.0.x;             proxy_http_version  1.1;             proxy_cache_bypass  $http_upgrade;             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;             proxy_set_header X-Real-IP $remote_addr;             proxy_set_header X-Forwarded-Host  $host;             proxy_set_header X-Forwarded-Proto $scheme;             proxy_set_header X-Forwarded-Port  $server_port;         }     }

Итоги

На мой взгляд получилась достаточно гибкая конфигурация отвечающая всем условиям кейса. Надеюсь будет полезно. Спасибо за внимание.


ссылка на оригинал статьи https://habr.com/ru/articles/765536/


Комментарии

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *