Выберите продукт

Consul DNS + Nginx: service discovery на VDS и в Kubernetes

Как связать Nginx с Consul DNS, чтобы получать актуальные IP сервисов по DNS и автоматически обходить сбои. Разберём resolver в Nginx, динамический upstream с resolve, health checks в Consul, кэширование, failover и нюансы в гибриде: VDS + Kubernetes.
Consul DNS + Nginx: service discovery на VDS и в Kubernetes

Когда сервисы живут в нескольких средах — часть на VDS, часть в Kubernetes — ручное управление списками хостов в Nginx быстро превращается в боль. Consul даёт DNS-интерфейс над каталогом сервисов и их состоянием, а Nginx умеет динамически резолвить имена и обновлять адреса. В паре «Consul DNS + Nginx» мы получаем чистый и предсказуемый service discovery: единое имя сервиса, балансировку по живым инстансам и failover без ручных правок конфигов и перезапусков.

Зачем это нужно на практике

Consul решает две задачи сразу: хранит каталог сервисов (service discovery) и проверяет их здоровье (health checks). DNS-интерфейс Consul возвращает A/AAAA записи только для «здоровых» инстансов. Nginx, опираясь на DNS, делает балансировку и переживает сбои инстансов без вмешательства администратора. Это особенно полезно в гибридных топологиях, где часть бэкендов крутится в Kubernetes, а часть — на обычных VDS.

Ключевые преимущества связки:

  • простое подключение через DNS без шаблонизаторов;
  • автоматический failover — нездоровые инстансы исчезают из ответов DNS;
  • согласованность — одно имя сервиса для VDS и Kubernetes;
  • минимум перезагрузок Nginx — обновления адресов происходят «на лету»;
  • отказоустойчивость с помощью prepared queries и политик Consul.

Архитектура: Nginx + Consul DNS

Базовая схема выглядит так:

  • Nginx на периметре (часто на VDS) — reverse proxy;
  • локальный DNS-резолвер на этом же узле — кеширует и форвардит зону .consul в Consul DNS;
  • Consul-клиенты на узлах с бэкендами — регистрируют сервисы и выставляют health checks;
  • по запросу к имени вида api.service.consul Consul отдаёт A/AAAA только живых инстансов;
  • Nginx резолвит имя с заданным resolver и направляет трафик на актуальные IP.

Важно: Nginx (open source) не умеет SRV-балансировку с портами. Он работает по A/AAAA. Поэтому либо используйте единый порт для всех инстансов, либо генерируйте upstream-список через шаблонизатор (например, consul-template) — ниже разберём оба подхода.

Схема: Nginx с resolver и Consul DNS, поток запросов и балансировка

Быстрый старт на VDS: агент Consul, DNS и health checks

На узлах с приложениями ставим агент Consul в режиме клиента и описываем сервисы. Пример конфигурации агента (HCL/JSON — на ваш вкус). Ниже — JSON с локальным DNS на 127.0.0.1 и коротким TTL для сервисов:

{
  "datacenter": "dc1",
  "node_name": "edge-proxy-1",
  "data_dir": "/var/lib/consul",
  "bind_addr": "0.0.0.0",
  "client_addr": "127.0.0.1",
  "retry_join": ["10.0.0.10", "10.0.0.11"],
  "ports": {
    "dns": 8600,
    "http": 8500
  },
  "addresses": {
    "dns": "127.0.0.1"
  },
  "dns_config": {
    "service_ttl": {"*": "5s"},
    "enable_truncate": true
  }
}

Пример регистрации сервиса с HTTP-проверкой:

{
  "service": {
    "name": "api",
    "port": 8080,
    "tags": ["v1", "blue"],
    "checks": [
      {
        "http": "http://127.0.0.1:8080/health",
        "interval": "5s",
        "timeout": "2s"
      }
    ]
  }
}

Проверки могут быть HTTP, TCP, gRPC, командные (скрипт). Консенсус прост: Consul должен видеть инстанс «passing», иначе адрес не попадёт в DNS-ответ.

Локальный DNS-резолвер для зоны .consul

Nginx нуждается в быстрых и стабильных ответах DNS. Надёжная практика — поднять на узле кеширующий резолвер (dnsmasq или unbound), который отправляет зону .consul в Consul, а прочие домены — к системным рекурсорам. Это снижает нагрузку на Consul и защищает от временных сетевых проблем.

dnsmasq (фрагмент):

no-resolv
cache-size=10000
server=/consul/127.0.0.1#8600

unbound (фрагмент):

server:
  cache-min-ttl: 5
  cache-max-ttl: 60
  qname-minimisation: yes

forward-zone:
  name: "consul."
  forward-addr: 127.0.0.1@8600

После настройки убедитесь, что на узле корректно резолвятся имена сервисов:

dig @127.0.0.1 -p 53 api.service.consul A +short

Nginx: динамический upstream через DNS

Есть два рабочих паттерна.

1) Upstream с именем хоста и флагом resolve

Подходит, когда у всех инстансов одинаковый порт. Nginx сам будет обновлять пул IP по DNS и балансировать между ними.

resolver 127.0.0.1 valid=5s ipv6=off;
resolver_timeout 2s;

upstream api_dynamic {
    zone api_dynamic 64k;
    least_conn;
    server api.service.consul:8080 resolve;
    keepalive 64;
}

server {
    listen 80;
    server_name example.local;

    location /api/ {
        proxy_pass http://api_dynamic;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_connect_timeout 2s;
        proxy_read_timeout 30s;
        proxy_next_upstream error timeout http_502 http_503 http_504;
    }
}

Ключевые моменты: resolver указывает локальный кеш, valid=5s ограничивает минимальный TTL, resolve включает динамическое обновление адресов, zone делает пул общим для воркеров и позволяет корректно применять обновления.

2) Переменная в proxy_pass (перезапрос DNS на каждый запрос)

Если нужен максимально свежий DNS на каждый запрос (и нагрузка позволяет), используйте переменную. Nginx будет обращаться к резолверу чаще — закладывайтесь на кеш.

resolver 127.0.0.1 valid=5s ipv6=off;
resolver_timeout 2s;

server {
    listen 80;
    server_name example.local;

    location /api/ {
        set $api_endpoint "api.service.consul:8080";
        proxy_pass http://$api_endpoint;
        proxy_connect_timeout 2s;
        proxy_read_timeout 30s;
        proxy_next_upstream error timeout http_502 http_503 http_504;
    }
}

Без resolve или переменных Nginx резолвит имя только при старте/перезагрузке. Это частая причина «залипших» адресов в конфиге.

Балансировка и failover

Nginx распределяет трафик по адресу из ответа DNS. Если адресов несколько — он перебирает их и исключает неотвечающие узлы (пасcивное наблюдение). Сочетая это с тем, что Consul DNS отдаёт только «passing» инстансы, получаем простой и эффективный failover.

Рекомендации:

  • включайте least_conn или round_robin по задаче;
  • тонко настраивайте таймауты и proxy_next_upstream для быстрых переключений;
  • при большом числе запросов используйте upstream с resolve и zone, а не переменные, чтобы снизить давление на DNS.

TTL, кэш и отказ Consul

valid=5s в resolver — компромисс между свежестью и нагрузкой. В Consul можно задать service_ttl — это TTL, который увидит резолвер. При кратковременном отказе Consul Nginx продолжит использовать кеш до истечения valid. Если Consul недоступен дольше, а кеш истёк — возможны ошибки резолвинга. Защитные меры:

  • поднимайте локальный кеширующий резолвер;
  • используйте valid=30s или больше на критичных путях;
  • настройте мониторинг доступности DNS и Consul;
  • предусмотрите аварийный стейт — статический upstream с ручным переключением на время инцидента.
FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Kubernetes + Consul: гибридный каталог сервисов

Если бэкенды живут в Kubernetes и на VDS одновременно, есть два распространённых подхода:

  1. Синхронизировать сервисы Kubernetes в каталог Consul (оператор/агент синхронизации). Тогда все бэкенды доступны через единообразные имена *.service.consul.
  2. Регистрировать в Consul только те сервисы из Kubernetes, которые должны быть доступны извне (например, через Service типа LoadBalancer или NodePort), и использовать их имена в Nginx.

Плюс синхронизации — единая точка правды, минус — ещё один компонент. Минимально жизнеспособный вариант — регистрировать в Consul только «edge»-сервисы, которые реально нужны периметру.

Prepared queries и междатацентровый failover

Consul Prepared Queries позволяют реализовать политику выбора ближайшего инстанса и отработку отказа в другой зоне/ДЦ, сохраняя одно имя. Пример подготовленного запроса в JSON:

{
  "Name": "web",
  "Service": {
    "Service": "web",
    "OnlyPassing": true,
    "Failover": { "NearestN": 1 }
  }
}

Такой запрос будет доступен по имени вида web.query.consul. В Nginx достаточно заменить имя сервиса — политика выбора инстанса сместится на сторону Consul. Если вы строите отказоустойчивую СУБД, посмотрите также руководство по HA PostgreSQL с Patroni и DCS.

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

Health checks: что, где и как проверять

В связке «Consul DNS + Nginx» активные проверки делает Consul, Nginx — пассивные. Это нормально: Consul точнее знает, какие порты/эндпоинты проверять, а Nginx реагирует на сетевые ошибки и коды 502/504.

Какие проверки использовать:

  • HTTP/HTTPS с короткими таймаутами и простым ответом (/health или /ready);
  • TCP для неболтливых протоколов;
  • gRPC health (если сервис на gRPC);
  • скриптовые — для комплексных кейсов.

Пример TCP-проверки в определении сервиса:

{
  "service": {
    "name": "tcp-app",
    "port": 7000,
    "checks": [
      { "tcp": "127.0.0.1:7000", "interval": "5s", "timeout": "1s" }
    ]
  }
}

Безопасность: ACL, сети и firewall

Несколько практических правил:

  • ограничьте DNS Consul адресом 127.0.0.1 на узле с Nginx, не публикуйте его наружу;
  • закройте межузловые порты Consul на границе, оставьте только то, что требуется кластеру;
  • включите ACL Consul и используйте токены с минимальными правами для сервис-регистрации;
  • в Nginx отключите IPv6 в resolver, если его нет в инфраструктуре (ipv6=off), чтобы не ждать таймаутов;
  • версионируйте конфиги и храните шаблоны регистраций сервисов в репозитории;
  • для внешних точек входа не забывайте про TLS — оформляйте и обновляйте SSL-сертификаты; для wildcard-доменов пригодится автоматизация DNS-01.

Наблюдаемость и отладка

Быстрый чек-лист диагностики:

  • dig @127.0.0.1 api.service.consul A +short — адреса есть?
  • dig @127.0.0.1 -p 8600 api.service.consul SRV +short — порты и веса с точки зрения Consul (информативно);
  • nginx -T — убедиться, что resolver и resolve не потерялись;
  • метрики Consul: число passing/critical чеков по сервису;
  • логи Nginx на 502/504 и время резолвинга (error_log на info/debug при необходимости).

Гибрид: Kubernetes и VDS за Nginx с каталогом сервисов Consul

Паттерны и анти-паттерны

  • Паттерн: upstream с resolve и локальным кеширующим DNS. Минимум запросов, быстрая реакция на изменения.
  • Паттерн: prepared queries для межДЦ-failover без переписывания конфигов Nginx.
  • Анти-паттерн: ожидать, что Nginx прочитает SRV-порты. Открытая версия не умеет. Если у инстансов разные порты — используйте консул-шаблоны для генерации списка server ip:port или унифицируйте порт.
  • Анти-паттерн: указывать в resolver внешние DNS вместо локального кеша. Это повышает латентность и риски отказа.
  • Анти-паттерн: слишком короткий valid при большом RPS — получите бурю DNS-запросов. Держите 5–30 секунд и мониторьте.
  • Анти-паттерн: «забыть» resolve или переменную в proxy_pass — адреса устареют до следующего reload.

Чек-лист внедрения

  1. Установите Consul-агенты на узлах с бэкендами. Включите service_ttl и проверьте статус health checks.
  2. Поднимите на узле с Nginx локальный кеширующий резолвер и форвардинг зоны .consul в Consul DNS.
  3. Проверьте dig для имён вида <svc>.service.consul. Убедитесь, что нездоровые инстансы не попадают в A-ответы.
  4. Настройте Nginx: resolver, upstream ... resolve или переменные в proxy_pass. Включите разумные таймауты и proxy_next_upstream.
  5. Опционально: внедрите prepared queries для кросс-ДЦ failover.
  6. Покройте мониторингом Consul DNS и ошибки 5xx на роутерах Nginx, добавьте алерты на рост timeout и upstream failures.

Итоги

Связка Consul DNS и Nginx даёт управляемый и прозрачный service discovery: Nginx не хранит список инстансов, а только имя; Consul заботится о здоровье и политике выбора. Для гибридных инфраструктур VDS + Kubernetes это простой путь к отказоустойчивости: меньше ручных переключений, быстрее реакции на сбои, единая точка учёта сервисов. Начните с локального кеширующего резолвера, настройте upstream ... resolve, задайте адекватные TTL — и у вас появится гибкий контур балансировки и failover без усложнения инфраструктуры.

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

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

Debian/Ubuntu: Name or service not known и Temporary failure in name resolution в SSH, sudo, cron и systemd OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: Name or service not known и Temporary failure in name resolution в SSH, sudo, cron и systemd

Ошибки Name or service not known и Temporary failure in name resolution в Debian/Ubuntu часто всплывают не только в SSH, но и в su ...
Debian/Ubuntu: APT repository does not have a Release file — как исправить ошибку OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: APT repository does not have a Release file — как исправить ошибку

Ошибка APT repository does not have a Release file в Debian и Ubuntu обычно связана с неподдерживаемым репозиторием, неверным code ...
Debian/Ubuntu: SSH зависает на Connecting to — как найти и убрать задержку входа OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: SSH зависает на Connecting to — как найти и убрать задержку входа

Если SSH в Debian или Ubuntu зависает на этапе Connecting to, долго показывает banner или тормозит уже после ввода пароля, причина ...