Назад | Перейти на главную страницу

Nginx: особое поведение для ошибок восходящего потока «Хост не найден»?

Когда nginx proxy_pass возвращает 502, может быть множество причин. Я хочу иметь возможность определять, когда был возвращен 502, потому что вышестоящий хост не был найден (то есть не удалось разрешить).

я знаю proxy_intercept_errors, но в моем случае это не помогает.

Что у меня есть

У меня есть сервер шлюза nginx, работающий на модуле Kubernetes. Он настроен для маршрутизации запросов к соответствующим сервисам Kubernetes в соответствии с первой частью имени хоста (слово перед первой точкой, например service-name.example.com следует направить к службе, называемой service-name).

Вот упрощенный раздел конфигурации, отвечающий за эту логику:

server {
  listen 80;
  resolver 172.16.2.3; // Pod IP address
  server_name "~^(?<svc>[\w-]+)\.";

  location / {
    # Each Kubernetes service has an internal domain name matching the following pattern
    proxy_pass "http://$svc.default.svc.cluster.local";
    proxy_set_header Host $host;
    # Proxy `X-Forwarded` headers sent by ELB: http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/x-forwarded-headers.html
    proxy_set_header X-Forwarded-For $http_x_forwarded_for;
    proxy_set_header X-Forwarded-Port $http_x_forwarded_port;
    proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
  }
}

Проблема

Независимо от того, почему апстрим недоступен (если он отказывается от соединений, выходит из строя или просто не существует), nginx возвращает 502. Фактическую причину можно увидеть только в журнале ошибок nginx.

Поскольку шлюз общедоступен через AWS ELB, к нему часто обращаются по IP или просто по случайным именам, что создает помехи в мониторах, настроенных для реагирования на пики ошибок 5XX.

Что я хочу сделать

Настройте nginx так, чтобы он возвращал менее агрессивную ошибку (скажем, 404) в случае, если имя хоста службы не может быть разрешено преобразователем Kubernetes.

Например, я отправляю такой запрос:

curl -H "Host: non-existent-service.example.com" http://gateway.example.com

Я хочу, чтобы nginx мог обнаруживать тот факт, что имя хоста, соответствующее службе, не может быть внутренне разрешено, а затем возвращать 404 вместо 502.

В настоящее время журналы выглядят следующим образом:

ОБНОВИТЬ

Следует упомянуть об этом в первую очередь. Первым делом нужно было попробовать "универсальный" серверный блок по умолчанию. Оказалось, что этот блок никогда не достигается, потому что практически любое имя хоста соответствует регулярному выражению.

Просто снова включите виртуальный хост по умолчанию и игнорируйте все, что попадает в него (поскольку такие запросы напрямую запрашивают IP-адрес или являются вредоносными).

Например, как показано в nginx 1.12.x nginx.conf:

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }