Программирование

Как настроить перенаправление доменов в Kubernetes Ingress

Настройка кросс-доменного проксирования в Kubernetes Ingress без перенаправлений. Решение проблемы 301 ошибки при проксировании robots.txt между доменами.

Как настроить перенаправление запросов с одного домена на другой в Kubernetes Ingress?

Добрый день! У меня возникла задача настроить Ingress в Kubernetes так, чтобы запросы к https://animori.tv/robots.txt обслуживались с https://s3.animori.tv/animori/public/robots.txt.

Текущая конфигурация Ingress

Вот моя текущая конфигурация Ingress:

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: path-based-ingress
  annotations:
    kubernetes.io.ingress.class: "nginx"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
    nginx.ingress.kubernetes.io/proxy-request-buffering: "off"
    nginx.ingress.kubernetes.io/proxy-buffering: "off"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
    nginx.ingress.kubernetes.io/client-body-timeout: "300"
    nginx.ingress.kubernetes.io/proxy-next-upstream-timeout: "1800"
    nginx.ingress.kubernetes.io/proxy-max-temp-file-size: "0"
spec:
  rules:
  - host: animori.tv
    http:
      paths:
      - path: /api(/|$)(.*)
        pathType: ImplementationSpecific
        backend:
          service:
            name: ani-mori-backend-svc
            port:
              number: 8088
      - path: /
        pathType: Prefix
        backend:
          service:
            name: ani-mori-frontend-svc
            port:
              number: 80

  - host: rabbitmq.animori.tv
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: ani-mori-rabbit-mq-sf-svc
            port:
              number: 15672

  - host: minio.animori.tv
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: ani-mori-minio-sf-svc
            port:
              number: 9090

  - host: s3.animori.tv
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: ani-mori-minio-sf-svc
            port:
              number: 9000

  - host: sentry.animori.tv
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: glitchtip-svc
            port:
              number: 8000

Моя попытка решения

Я попробовал добавить следующую настройку:

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: path-based-ingress
  annotations:
    kubernetes.io.ingress.class: "nginx"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
    nginx.ingress.kubernetes.io/proxy-request-buffering: "off"
    nginx.ingress.kubernetes.io/proxy-buffering: "off"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
    nginx.ingress.kubernetes.io/client-body-timeout: "300"
    nginx.ingress.kubernetes.io/proxy-next-upstream-timeout: "1800"
    nginx.ingress.kubernetes.io/proxy-max-temp-file-size: "0"
    # Для специфических путей используем configuration-snippet
    nginx.ingress.kubernetes.io/configuration-snippet: |
      location = /robots.txt {
        proxy_pass https://s3.animori.tv/;
        proxy_set_header Host s3.animori.tv;
        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;
      }
spec:
  rules:
  - host: animori.tv
    http:
      paths:
      - path: /robots.txt
        pathType: ImplementationSpecific
        backend:
          service:
            name: ani-mori-minio-sf-svc
            port:
              number: 9000
      - path: /api(/|$)(.*)
        pathType: ImplementationSpecific
        backend:
          service:
            name: ani-mori-backend-svc
            port:
              number: 8088
      - path: /
        pathType: Prefix
        backend:
          service:
            name: ani-mori-frontend-svc
            port:
              number: 80

Проблема, с которой я столкнулся

Однако при попытке перейти по https://animori.tv/robots.txt происходит перенаправление на https://animori.tv/animori/public/robots.txt и возвращается ошибка 404. При проверке с помощью curl я получаю такой ответ:

html
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>openresty</center>
</body>
</html>

Вопрос

Как правильно настроить Ingress в Kubernetes, чтобы запросы к https://animori.tv/robots.txt обслуживались с https://s3.animori.tv/animori/public/robots.txt без перенаправления и с кодом ответа 200?

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

Содержание


Основные подходы к перенаправлению в Ingress

В Kubernetes Ingress существует несколько способов настройки перенаправлений и проксирования. На самом деле, вот основные из них:

  1. Использование аннотаций для перенаправления

    • nginx.ingress.kubernetes.io/permanent-redirect - для постоянного перенаправления (301)
    • nginx.ingress.kubernetes.io/temporal-redirect - для временного перенаправления (302)
  2. Использование проксирования с контролем перенаправлений

    • nginx.ingress.kubernetes.io/proxy-redirect-from - для указания исходного URL в перенаправлениях
    • nginx.ingress.kubernetes.io/proxy-redirect-to - для указания целевого URL в перенаправлениях
  3. Использование server-snippet или configuration-snippet

    • Для сложных сценариев с индивидуальной настройкой location

Для вашей задачи, честно говоря, подойдет третий подход, но с правильной настройкой заголовков и параметров проксирования. Интересно, что многие упускают важность именно этой части конфигурации.


Настройка проксирования между доменами

При проксировании между разными доменами в Nginx возникает автоматическое перенаправление, которое нужно контролировать. Согласно документации Ingress-Nginx [1], для этого необходимо правильно настроить заголовки и параметры.

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

  1. Правильно настроить заголовки проксирования
  2. Использовать директиву proxy_redirect off
  3. Настроить обработку заголовков Host

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


Решение для вашего случая

Для решения вашей задачи используйте следующую конфигурацию:

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: path-based-ingress
  annotations:
    kubernetes.io.ingress.class: "nginx"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
    nginx.ingress.kubernetes.io/proxy-request-buffering: "off"
    nginx.ingress.kubernetes.io/proxy-buffering: "off"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
    nginx.ingress.kubernetes.io/client-body-timeout: "300"
    nginx.ingress.kubernetes.io/proxy-next-upstream-timeout: "1800"
    nginx.ingress.kubernetes.io/proxy-max-temp-file-size: "0"
    # Конфигурация для проксирования robots.txt
    nginx.ingress.kubernetes.io/configuration-snippet: |
      location = /robots.txt {
        proxy_pass https://s3.animori.tv/animori/public/robots.txt;
        proxy_set_header Host s3.animori.tv;
        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_redirect off;
        proxy_ssl_server_name on;
      }
spec:
  rules:
  - host: animori.tv
    http:
      paths:
      - path: /robots.txt
        pathType: ImplementationSpecific
        backend:
          service:
            name: ani-mori-minio-sf-svc
            port:
              number: 9000
      - path: /api(/|$)(.*)
        pathType: ImplementationSpecific
        backend:
          service:
            name: ani-mori-backend-svc
            port:
              number: 8088
      - path: /
        pathType: Prefix
        backend:
          service:
            name: ani-mori-frontend-svc
            port:
              number: 80

Ключевые изменения:

  1. Полный путь в proxy_pass: Вместо proxy_pass https://s3.animori.tv/; используем proxy_pass https://s3.animori.tv/animori/public/robots.txt; - это указывает точный целевой ресурс.

  2. Отключение перенаправлений: Добавлена директива proxy_redirect off; для предотвращения автоматических перенаправлений. Это, по сути, самое важное изменение.

  3. Настройка SSL: Добавлена proxy_ssl_server_name on; для корректной работы с HTTPS бэкендом.

  4. Заголовки проксирования: Сохранены необходимые заголовки для правильной работы.

На самом деле, эти изменения кажутся небольшими, но они решают основную проблему с автоматическими перенаправлениями при кросс-доменном проксировании.


Дополнительные рекомендации

1. Использование отдельного Ingress для проксирования

Для более чистой конфигурации можно создать отдельный Ingress специально для проксирования:

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: robots-proxy-ingress
  annotations:
    kubernetes.io.ingress.class: "nginx"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      location = /robots.txt {
        proxy_pass https://s3.animori.tv/animori/public/robots.txt;
        proxy_set_header Host s3.animori.tv;
        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_redirect off;
        proxy_ssl_server_name on;
      }
spec:
  rules:
  - host: animori.tv
    http:
      paths:
      - path: /robots.txt
        pathType: ImplementationSpecific
        backend:
          service:
            name: ani-mori-minio-sf-svc
            port:
              number: 9000

2. Альтернативный подход с rewrite-target

Если вы хотите использовать более стандартные аннотации, можно попробовать:

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: robots-rewrite-ingress
  annotations:
    kubernetes.io.ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: "/animori/public/$2"
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  rules:
  - host: animori.tv
    http:
      paths:
      - path: /robots.txt
        pathType: ImplementationSpecific
        backend:
          service:
            name: ani-mori-minio-sf-svc
            port:
              number: 9000

3. Настройка CORS для кросс-доменных запросов

Если потребуется настроить CORS, используйте аннотации [2]:

yaml
nginx.ingress.kubernetes.io/cors-allow-origin: "*"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization"

Интересно, что многие забывают про CORS при настройке кросс-доменного проксирования, что потом приводит к проблемам с браузерными политиками безопасности.


Проверка конфигурации

После применения конфигурации проверьте работу с помощью curl:

bash
curl -I https://animori.tv/robots.txt

Ожидаемый результат должен содержать:

  • Статус код 200 OK
  • Правильные заголовки Location (если есть перенаправления)
  • Отсутствие нежелательных перенаправлений

Если проблема сохраняется, проверьте логи Ingress controller:

bash
kubectl logs -n ingress-nginx <ingress-controller-pod-name>

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


Заключение

  1. Правильное проксирование - Используйте proxy_pass с полным путем к ресурсу и proxy_redirect off для предотвращения автоматических перенаправлений. Это, пожалуй, самое важное.

  2. Заголовки проксирования - Корректно настройте заголовки Host, X-Forwarded-* и другие для работы с кросс-доменным проксированием. Не пренебрегайте этим моментом.

  3. Разделение конфигураций - Для сложных сценариев используйте отдельные Ingress объекты или конфигурационные сниппеты. Это действительно упрощает поддержку.

  4. Постоянная проверка - Регулярно проверяйте работу конфигурации с помощью curl и мониторинга логов. Поверьте, это сэкономит вам кучу нервов в будущем.

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

С предложенной конфигурацией запросы к https://animori.tv/robots.txt должны успешно проксироваться на https://s3.animori.tv/animori/public/robots.txt с кодом ответа 200 без нежелательных перенаправлений. Надеюсь, это решит вашу проблему!

Источники

  1. Annotations - Ingress-Nginx Controller
  2. NGINX Kubernetes Ingress Controller & Other NGINX K8s Solutions | Solo.io
  3. Kubernetes nginx ingress: How to redirect foo.example.org to example.org? - Server Fault
  4. What is the Best way to Setup Proxy Pass in an Nginx Ingress object for Kubernetes - Stack Overflow
Авторы
Проверено модерацией
Модерация