ZIM-НИЙ SAAALEЗимние скидки: до −50% на старт и −20% на продление
до 31.01.2026 Подробнее
Выберите продукт

Nginx upstream и DNS: как обновлять IP без stale cache и таймаутов

Когда Nginx проксирует на upstream по имени, он может «залипать» на старом IP: контейнер пересоздали, запись A поменялась, а прокси продолжает стучаться в прошлый адрес. Разбираем resolver/valid, Docker DNS, systemd-resolved, reload и диагностику таймаутов.
Nginx upstream и DNS: как обновлять IP без stale cache и таймаутов

В Nginx тема DNS для upstream всплывает не в теории, а в самый неподходящий момент: контейнер пересоздали — IP поменялся, балансировщик отдал другой адрес, сервис переехал, а Nginx продолжает ходить «в никуда». В логах появляются upstream timed out, connect() failed, а иногда конфиг вообще не стартует с ошибкой host not found in upstream.

Ниже — практическая шпаргалка: как устроен резолвинг upstream в Nginx, что именно называют «stale DNS cache» применительно к Nginx, как правильно настроить resolver и valid, как жить с Docker DNS и systemd-resolved, и что проверять при подозрениях на DNS-проблемы и таймауты upstream.

Почему Nginx «не видит» новый IP: модель резолвинга

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

Отсюда два типовых сценария:

  • Смена IP у backend по DNS (запись A/AAAA обновилась, контейнер пересоздан) — Nginx продолжает использовать старый адрес до тех пор, пока не произойдёт повторное разрешение имени (иногда только после reload).
  • Nginx не стартует с ошибкой upstream host not found — если имя не резолвится в момент загрузки конфига, Nginx может завершиться, даже если DNS «починится» через 10 секунд.

Типовые симптомы и как их отличить от «просто таймаутов»

Перед тем как крутить DNS, полезно понять, какой именно режим отказа вы наблюдаете. Ниже — наиболее частые сообщения и их смысл.

1) upstream host not found и nginx does not resolve host

Обычно это ошибка на этапе загрузки конфигурации. Nginx пытается резолвить имя из upstream или из proxy_pass, но DNS не отвечает или отвечает NXDOMAIN. Часто встречается в контейнерных средах при старте Nginx раньше, чем поднялся DNS/сеть/сервис.

2) connect() failed (111: Connection refused) / no route to host

DNS уже отдал IP, но на адресе ничего не слушает, либо маршрут не существует. Это может быть как реальная недоступность сервиса, так и «залипание» на старом IP после пересоздания контейнера/VM.

3) upstream timed out и 504

Это не всегда DNS. Но DNS-проблемы могут маскироваться под таймауты, если Nginx упорно подключается к старому адресу, который стал «чёрной дырой» (SYN уходит, ответа нет).

Если таймауты начались одновременно со сменой IP/релизом/пересозданием контейнеров и исчезают после nginx -s reload, очень вероятно, что причина именно в резолвинге upstream.

Пример конфигурации Nginx: resolver и proxy_pass через переменную для динамического DNS

Как заставить Nginx пере-резолвить upstream: resolver + переменная в proxy_pass

Самый надёжный приём: перевести целевой хост в режим «динамического» разрешения имени. В Nginx это обычно делается двумя шагами:

  1. задать DNS-серверы директивой resolver;
  2. использовать переменную в proxy_pass (иначе имя может быть резолвлено один раз при парсинге конфига).

Базовый пример: резолвить имя периодически

resolver 1.1.1.1 8.8.8.8 valid=30s;
resolver_timeout 2s;

server {
  listen 80;

  location / {
    set $backend "app.example.internal";
    proxy_pass http://$backend:8080;
    proxy_connect_timeout 2s;
    proxy_read_timeout 30s;
  }
}

Что здесь важно:

  • valid=30s — это срок, в течение которого Nginx считает результат резолвинга пригодным. По истечении срока Nginx сделает новый DNS-запрос при необходимости.
  • resolver_timeout — защита от зависания на проблемном DNS.
  • proxy_pass http://$backend:8080 — наличие переменной заставляет Nginx резолвить имя в рантайме (вместо единоразового разрешения при загрузке конфига).

Что значит valid на практике

Если вы ожидаете, что Nginx будет строго следовать TTL записи A/AAAA, вас может ждать сюрприз: в этой схеме вы управляете TTL кэша Nginx через valid. Реальная цель — подобрать компромисс между:

  • скоростью реакции на смену IP (меньше valid);
  • нагрузкой на DNS и стабильностью (больше valid).

Для сервисов в Docker/Kubernetes, где IP может меняться часто, обычно разумны значения 5–30 секунд. Для более статичных upstream — 30–300 секунд.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Почему upstream { server name; } не всегда решает задачу

Многие начинают с «красивого» блока upstream:

upstream backend {
  server app.example.internal:8080;
  keepalive 32;
}

server {
  location / {
    proxy_pass http://backend;
  }
}

Проблема в том, что без дополнительных механизмов Nginx может разрешить имя один раз и держать IP неизменным. В итоге смена DNS не приводит к смене реального адреса назначения, и вы получаете классическую историю про stale DNS cache.

Если вам критично именно «следовать DNS», чаще проще и прозрачнее идти через resolver + переменную в proxy_pass, чем надеяться на поведение резолвинга внутри upstream.

Nginx reload и DNS: когда перезагрузка действительно помогает

Запрос «nginx reload dns» популярен по простой причине: reload часто действительно «лечит» ситуацию, потому что Nginx перечитывает конфигурацию и заново резолвит статические имена.

Но у этого подхода есть минусы:

  • Если DNS «дрожит» или upstream часто меняет IP, вам придётся делать reload слишком часто.
  • В момент проблем с DNS вы рискуете получить отказ при перечитывании конфига (если имя не резолвится) и усложнить инцидент.
  • Это костыль: вы лечите симптомы, а не причину.

Рекомендация: использовать reload как аварийную меру, а для постоянного решения — включать динамический резолвинг через resolver.

Docker DNS + Nginx: почему «всё работает, пока не пересоздали контейнер»

Частый кейс: Nginx работает в контейнере (или на хосте) и проксирует на сервис по имени контейнера/сервиса. В Docker Compose имя сервиса резолвится через встроенный DNS Docker. При пересоздании контейнера IP меняется, а имя остаётся тем же.

Но Nginx может сохранить старый IP, если резолвил имя только при старте. Итог — «после деплоя 502/504 до перезапуска nginx».

Практический рецепт в контейнерных сетях:

  • в resolver указывать DNS-сервер Docker (часто это 127.0.0.11 внутри контейнера);
  • использовать переменную в proxy_pass;
  • ставить небольшой valid (например, 10s).

Пример (внутри контейнера Nginx):

resolver 127.0.0.11 valid=10s;
resolver_timeout 2s;

server {
  listen 80;
  location / {
    set $backend "api";
    proxy_pass http://$backend:8080;
  }
}

Если вы не уверены, какой DNS использует контейнер, проверьте /etc/resolv.conf внутри него.

Если параллельно вы обслуживаете сайты/приложения на внешнем периметре, держите под рукой и доменную часть: сроки продления и переносы иногда всплывают в виде «внезапного NXDOMAIN». Полезный разбор — как устроен перенос домена: EPP, DNS и типовые ошибки.

systemd-resolved и Nginx: где ломается цепочка

На современных дистрибутивах часто включён stub-resolver, и в /etc/resolv.conf</code прописан <code>127.0.0.53. Для обычных приложений это нормально, но для Nginx есть нюансы:

  • resolver в Nginx — это не чтение /etc/resolv.conf. Если вы не указали resolver, Nginx может вести себя как «статический» резолвер на старте.
  • Если вы указали resolver 127.0.0.53, важно, чтобы Nginx действительно мог обращаться к этому адресу в своём неймспейсе (особенно если Nginx в контейнере).

На хостовой установке обычно рабочий вариант: либо указывать реальные DNS вашего окружения (смотрите resolvectl dns), либо оставить 127.0.0.53 если вы уверены, что Nginx запускается на хосте и stub доступен.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Диагностика: что проверять, когда «upstream timeouts» похожи на DNS

Ниже — короткий прикладной чеклист, который помогает быстро отделить DNS от TCP и проблем приложения.

Шаг 1. Убедиться, что имя резолвится там, где работает Nginx

getent hosts app.example.internal
nslookup app.example.internal
dig +short app.example.internal A
dig +short app.example.internal AAAA

Если Nginx в контейнере — выполняйте команды внутри контейнера.

Шаг 2. Сравнить IP из DNS и фактические подключения Nginx

ss -tnp | grep nginx
ss -tn dst :8080

Смысл: увидеть, к каким адресам Nginx реально подключается. Если DNS уже показывает новый IP, а Nginx продолжает стучаться в старый — это и есть эффект stale DNS cache.

Шаг 3. Проверить логи Nginx с деталями upstream

Если у вас в access log есть $upstream_addr, $upstream_connect_time, $upstream_response_time — отлично. Если нет, на время диагностики удобно включить расширенный формат логов (или отдельный лог для проблемного location):

log_format upstream_debug '$remote_addr - $host "$request" $status '
                         'upstream=$upstream_addr '
                         'uct=$upstream_connect_time urt=$upstream_response_time '
                         'uht=$upstream_header_time rt=$request_time';

Дальше смотрим: upstream=старый_IP:порт при том, что DNS уже другой — диагноз почти готов.

Шаг 4. Понять, что именно не так: DNS, TCP или приложение

Быстрые проверки:

curl -sS -v --max-time 2 http://NEW_IP:8080/
curl -sS -v --max-time 2 http://OLD_IP:8080/

Если на новом IP сервис отвечает, а на старом нет — проблема не в приложении, а в том, что Nginx не обновил адрес назначения.

Диагностика: анализ логов Nginx с upstream_addr и таймаутами до upstream

Антипаттерны: как делают хуже

  • Ставить огромный valid «чтобы реже трогать DNS», а потом удивляться, что Nginx держит старый IP часами.
  • Лечить всё nginx -s reload и не разбираться с динамическим резолвингом. Это повышает операционные риски.
  • Смешивать несколько источников правды: в контейнере резолвить через внешний DNS, который не знает внутренних имён Docker/overlay-сети.
  • Игнорировать IPv6: DNS может отдавать AAAA, и Nginx попытается ходить по IPv6, где нет маршрута. Если у вас dual-stack «не везде», обязательно проверяйте AAAA-ответы.

Рекомендуемые рабочие схемы

Схема A: статичный backend (редко меняется)

Можно оставить классический upstream с IP или с именем, но понимать: смена адреса потребует reload. Для критичных систем лучше всё равно предусмотреть динамический резолвинг.

Схема B: backend по имени, IP меняется (контейнеры/автоскейлинг)

Используйте resolver и переменную в proxy_pass. Подберите valid 5–30 секунд. Это обычно самый предсказуемый вариант.

Схема C: несколько upstream и внешний healthcheck

Nginx (open source) не делает «настоящие» активные healthchecks для HTTP как коробочное решение, поэтому при динамическом DNS особенно важно иметь внешнюю проверку доступности сервисов и наблюдать метрики 502/504, а также времена коннекта.

Короткий итог

Если у вас всплывают кейсы уровня «nginx upstream dns», «stale dns cache», «nginx does not resolve host» или «upstream host not found», чаще всего проблема в том, что имя резолвится не так, как вы ожидаете. Практическое лечение — задать явный resolver и организовать динамический резолвинг через переменную в proxy_pass, а затем подтвердить изменения диагностикой: сравнить DNS-ответы и реальные $upstream_addr в логах.

Когда это настроено, смена IP у backend перестаёт быть «магией», а становится предсказуемым процессом с понятным временем реакции, зависящим от valid и стабильности DNS.

Поделиться статьей

Вам будет интересно

Kubernetes Terminating и finalizers: как разморозить namespace, CRD и PV OpenAI Статья написана AI (GPT 5)

Kubernetes Terminating и finalizers: как разморозить namespace, CRD и PV

Если namespace, CRD или PV застряли в Terminating, почти всегда виноваты finalizers и недоработавшие контроллеры. Разберём диагнос ...
SSHD MaxStartups и rate limit: как снизить CPU от brute force и DDoS на SSH OpenAI Статья написана AI (GPT 5)

SSHD MaxStartups и rate limit: как снизить CPU от brute force и DDoS на SSH

Когда SSH засыпают ботами, растут CPU, число полуоткрытых сессий и задержки входа. Разберём MaxStartups и LoginGraceTime в OpenSSH ...
NVMe в Linux: SMART и Health для мониторинга дисков OpenAI Статья написана AI (GPT 5)

NVMe в Linux: SMART и Health для мониторинга дисков

Пошагово разбираем, как в Linux читать SMART/health у NVMe-дисков: команды nvme-cli и smartctl, важные поля (critical_warning, med ...