Найти в Дзене
Linux | Network | DevOps

Цикл статей: как работает DNS в Linux. Часть 2

В первой части мы разобрали, как в Linux работает процесс разрешения имен — от вызова getaddrinfo() до получения IP-адреса. Однако если бы каждый вызов требовал нового DNS-запроса, это было бы неэффективно и сильно нагружало как систему, так и сеть. Поэтому используется кэширование. Кэширование DNS может быть везде — в glibc, в systemd-resolved, в браузерах и даже в приложениях на Go. Кэш помогает увеличить скорость работы, но создает дополнительные сложности при отладке. Например: вы меняете DNS-запись, но сервер продолжает ходить по старому IP-адресу. Или, Dig показывает правильный адрес, а curl всё равно подключается к устаревшему. В этой статье разберем различные уровни кэшей самой системы, приложений и языков программирования, контейнеров, прокси. А также их мониторинг и
сброс. DNS-кэш —
это не единое хранилище, а многоуровневая система механизмов
кэширования на разных уровнях системы. Каждый DNS-запрос — это долгий
сетевой вызов, поэтому многие компоненты стараются сохранять
Оглавление

В первой части мы разобрали, как в Linux работает процесс разрешения имен — от вызова getaddrinfo() до получения IP-адреса. Однако если бы каждый вызов требовал нового DNS-запроса, это было бы неэффективно и сильно нагружало как систему, так и сеть. Поэтому используется кэширование.

Кэширование DNS может быть везде — в glibc, в systemd-resolved, в браузерах и даже в приложениях на Go. Кэш помогает увеличить скорость работы, но создает дополнительные сложности при отладке. Например: вы меняете DNS-запись, но сервер продолжает ходить по старому IP-адресу. Или, Dig показывает правильный адрес, а curl всё равно подключается к устаревшему.

В этой статье разберем различные уровни кэшей самой системы, приложений и языков программирования, контейнеров, прокси. А также их мониторинг и
сброс.

Что такое DNS-кэш и зачем он нужен

DNS-кэш
это не единое хранилище, а многоуровневая система механизмов
кэширования на разных уровнях системы. Каждый DNS-запрос — это долгий
сетевой вызов, поэтому многие компоненты стараются сохранять результаты
локально.

TTL (Time To Live) — время жизни записи
в кэше. Оно указывается в DNS-ответе и определяет, как долго можно
использовать сохранённый IP-адрес. Задается обычно в секундах. После
истечения TTL необходимо обновить данные.

Таким образом, кэширование позволяет:
- повысить скорость обработки повторных DNS запросов
- снизить нагрузку на серверную и сетевую инфраструктуру
- обеспечить отказоустойчивость при временной потере соединения
- уменьшить задержки в работе приложений

Но у кэширования есть и
обратная сторона: устаревшие данные могут стать причиной недоступности
сервисов при изменении инфраструктуры.

Где именно кэшируется DNS в Linux. Уровни работы с кэшем

Ядро

Ядро
Linux может опосредованно “кэшировать” DNS-трафик через подсистему
netfilter/conntrack, если используется stateful-фильтрация. Несмотря на
то, что UDP — протокол без установления соединения, ядро отслеживает
состояние пакетов, относящихся к одному блоку запрос-ответ (например,
запрос от [src_ip:src_port] к [8.8.8.8:53] и ожидаемый ответ от
[8.8.8.8:53] к [src_ip:src_port]) и временно хранит информацию — по
умолчанию около 30 секунд. Это необходимо для NAT и правил вроде
iptables -m conntrack --ctstate ESTABLISHED,RELATED.

Проверить текущие записи можно командой:

conntrack -L -p udp --dport 53

В
списке отобразятся активные DNS-сессии, которые считаются допустимыми
до истечения таймаута. Повторные DNS-запросы к тем же адресам в пределах
срока жизни этих записей могут быть обработаны в рамках существующей
записи состояния. Это не полноценное кэширование DNS-ответов, но
conntrack может влиять на поведение сетевого уровня, особенно при
диагностике проблем с NAT или firewall.

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

conntrack -D -p udp --dport 53

Системный уровень

1. systemd-resolved

Современные дистрибутивы с systemd часто используют systemd-resolved в качестве основного DNS-клиента, который:

  • имеет собственный кэш DNS-запросов, включая положительные и (опционально) отрицательные ответы;
  • поддерживает split DNS (разные DNS-серверы для разных доменов), конфигурируется через systemd-networkd или NetworkManager;
  • поддерживает DNS-over-TLS (DoT), включая fallback-серверы и DNSSEC;
  • предоставляет
    API по D-Bus (org.freedesktop.resolve1), позволяет получать статус,
    менять настройки и управлять кэшем через resolvectl.

2. nscd (Name Service Cache Daemon)

Если запущен nscd, он кэширует результаты NSS-вызовов, включая DNS. Его настройки находятся в /etc/nscd.conf

enable-cache hosts yes
positive-time-to-live hosts 600
negative-time-to-live hosts 20

Важный
момент: nscd устарел и не рекомендуется к использованию в новых
системах. В Debian-based дистрибутивах чаще всего его заменяет
systemd-resolved, но в RHEL-based дистрибутивах он ещё встречается.

3. Популярные локальные кэширующие резолверы

dnsmasq — популярный выбор для локального кэширования:

Настройка кэша

cache-size=1000 (cache-size управляет размером кэша. По умолчанию он небольшой (150), и для заметного эффекта его увеличивают до 1000–5000)
neg-ttl=60

unbound — более мощный DNS-рекурсор.

Управление кэшем гибкое:

Размер кэша задаётся параметром msg-cache-size (отвечает за ответы) и rrset-cache-size (за записи ресурсов):

msg-cache-size: 50m
rrset-cache-size: 100m

TTL кэшированных ответов можно ограничить директивами cache-min-ttl и cache-max-ttl

cache-min-ttl: 30    # минимальный TTL для любых ответов
cache-max-ttl: 86400 # максимальный TTL (24 часа)

bind
- распространенный DNS-сервер с поддержкой рекурсивного разрешения и
кэширования. Управление кэшем и его мониторинг осуществляется через
команду rndc (Remote Name Daemon Control).

В конфигурационном файле named.conf можно задавать TTL для кэша и контролировать поведение:

options {
    max-cache-ttl 86400;     // максимальное время жизни кэша (в секундах)
    max-ncache-ttl 3600;     // максимальное время жизни негативных ответов (NXDOMAIN)
};

Уровень приложений и языков программирования

glibc

Хотя
официально считается, что glibc не реализует полноценный DNS-кэш (в
отличие от демонов вроде systemd-resolved, dnsmasq или nscd), в её
реализации резолвера есть несколько механизмов, которые действуют как
очень простое и ограниченное кэширование или оптимизация запросов.

Во-первых,
используется NSS (Name Service Switch), который может быть
сконфигурирован для работы с nscd, systemd-resolved или другими
кэширующими компонентами. Например, с помощью следующей директивы в
файле nsswitch.conf:

hosts: files resolved myhostname

Где
вместо resolved также может быть и nscd. Хотя nscd — отдельный демон,
он поставляется вместе с glibc в большинстве дистрибутивов и тесно
интегрирован с ней.

Когда nscd запущен и настроен (часто включен
по умолчанию для passwd, group, hosts), библиотеки glibc (getaddrinfo,
gethostbyname) будут обращаться к нему первыми. Nscd кэширует ответы до
истечения их TTL. Кэширование в этом случае происходит вне самой
библиотеки glibc, но glibc использует этот кэш прозрачно для приложения.

В
реализации DNS-резолвера внутри glibc (в файле resolv/res_query.c и
др.) содержатся оптимизации, такие как повторное использование сокета и
игнорирование TTL при повторных запросах внутри одного вызова, которые
можно рассматривать в качестве некого микро-кэша в контексте одного
вызова функции разрешения. Эти оптимизации не сохраняют результаты между
разными вызовами getaddrinfo или между разными процессами и действуют
только в рамках одного системного вызова функции.

Модули NSS
(особенно files) кэшируют данные из статических файлов. Например,
nss-files (работающий в том числе с /etc/hosts) по сути "кэширует"
содержимое этих файлов в памяти процесса после их первого чтения (до
перезагрузки процесса или вызова, инвалидирующего кэш NSS). Это не
DNS-кэширование в чистом виде, но влияет на процесс разрешения имен, в
котором участвует DNS.

Также можно упомянуть, что устаревшая
функция gethostbyname имела примитивный внутренний кэш (фиксированный
малый размер, неразделяемый между процессами, игнорирующий TTL). Эта
информация может оказаться полезной при работе с legacy.

Java

Java поддерживает встроенный DNS-кэш с гибкими настройками времени жизни записей.

Особенности работы

Без использования Security Manager (начиная с Java 11 - это поведение по умолчанию):
  - положительные ответы кэшируются на 30 секунд (максимум, даже если DNS-сервер указал больший TTL);
  - отрицательные ответы (NXDOMAIN) — 10 секунд.

С использованием Security Manager:
  - положительные ответы кэшируются бесконечно (риск устаревших записей);
  - отрицательные ответы не кэшируются.

Управление

Настройки указываются в свойствах JVM. TTL в секундах для успешных запросов:

networkaddress.cache.ttl=60

TTL для неудачных запросов (NXDOMAIN):

networkaddress.cache.negative.ttl=10

Варианты значений:

0 — отключить кэширование;

-1 — кэшировать бессрочно (только для положительных ответов).

Способы настройки

1. Аргументы JVM:

java -Dnetworkaddress.cache.ttl=60 -jar app.jar

2. В коде (глобально для JVM):

Security.setProperty("networkaddress.cache.ttl", "60");

Go

Go использует две модели резолвинга:

- через cgo — вызывает системный getaddrinfo() (включая NSS). Работает через системные настройки (/etc/nsswitch.conf, /etc/resolv.conf);

- Pure Go resolver — реализует собственный DNS клиент, минуя системные библиотеки.

Выбор резолвера:

GODEBUG=netdns=go    # встроенный резолвер с кэшем
GODEBUG=netdns=cgo   # через системный getaddrinfo()

При
использовании Pure Go резолвера Go реализует in-memory DNS-кэш внутри
процесса. Этот кэш хранит успешные (A, AAAA, CNAME) и отрицательные
(NXDOMAIN) ответы, соблюдая их TTL. Кэш имеет фиксированный размер
(реализует эвристику LRU), хранится в памяти процесса и разделяется
между горутинами внутри этого процесса, но не разделяется между разными
процессами или экземплярами приложений.

Python

По
умолчанию модуль socket и большинство стандартных библиотек (включая
requests, urllib3) используют системный вызов getaddrinfo() и не имеют
встроенного кэша DNS.

•    requests → использует urllib3,
который делегирует разрешение DNS системной библиотеке
(socket.getaddrinfo()), без кэширования.

•    aiohttp по
умолчанию работает через getaddrinfo(), но может быть настроен на
использование aiodns (асинхронный DNS через libcares), где возможно
встроенное кэширование.

•    dnspython — отдельный DNS-клиент, выполняющий DNS-запросы напрямую. С версии 2.0 поддерживает явное включение кэша:

import dns.resolver
resolver = dns.resolver.Resolver()
resolver.cache = dns.resolver.Cache()

Таким
образом, поведение зависит от конкретной библиотеки. Стандартный socket
и большинство оберток над ним, включая requests, кэширование не
реализуют и полагаются на системный резолвер.

Контейнеры и оркестрация

Docker

Контейнеры используют DNS-сервер хоста (при использовании сетевого режима host) или встроенный резолвер.

В
Docker по умолчанию - это адрес 127.0.0.11 - встроенный DNS в dockerd,
который использует libnetwork. Кэш может находиться как в хосте, так и в
самом контейнере.

Podman

В Podman, в зависимости от версии, могут использоваться разные схемы.

Если используется сетевой бэкенд CNI
(устаревший, но поддерживаемый, который использовался по умолчанию в
Podman ≤ 3.x), задействуется плагин dnsname, отвечающий за работу DNS в
виртуальной сети Podman.

Кэширование DNS происходит на уровне
контейнера. Если контейнер использует systemd-resolved, dnsmasq или
другой локальный кэширующий резолвер, то кэш работает там. Сам dnsname
не кэширует ответы.

Если используется сетевой бэкенд Netavark (бэкенд по умолчанию в Podman ≥ 4.0.), то Netavark запускает aardvark-dns — легковесный DNS-сервер, который:
- поддерживает A-записи (имена → IP) и PTR-записи (обратный DNS);
-
поддерживает внешний DNS: контейнеры используют aardvark-dns как
резолвер, перенаправляющий внешние запросы (например, ya.ru) в системные
DNS-серверы, но при этом не сохраняет ответы.

Как и в случае с CNI, кэширование возможно только на стороне: системного резолвера или локального кэша внутри контейнера.

Kubernetes

Обычно
за DNS в Kubernetes отвечает CoreDNS. Важно понимать, что его поведение
по умолчанию различается для внутренних и внешних запросов:

Внутренние
записи Kubernetes, например my-svc.my-namespace.svc.cluster.local,
обрабатываются плагином kubernetes. Они всегда кэшируются в памяти
CoreDNS на время, указанное в поле TTL записи (обычно 5 секунд для
headless-сервисов и 30 сек для остальных). Это кэширование включено
всегда и не требует дополнительных плагинов.

Внешние запросы,
например google.com, обрабатываются плагином forward, который отправляет
запросы резолверам из /etc/resolv.conf CoreDNS. Без плагина cache в
конфигурации ответы на внешние запросы не кэшируются! Каждый запрос от
подов будет идти на upstream-резолвер, создавая нагрузку и увеличивая
задержку.

Чтобы включить кэширование, нужно добавить плагин cache в Corefile:

.:53 {
errors
health
# Кэшируем ВСЕ ответы (включая внешние) на 30 секунд:
cache 30 .
forward . 8.8.8.8 1.1.1.1 # Важно: cache ДОЛЖЕН стоять перед forward!
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
reload
}

Прокси-серверы на примере Nginx и HAProxy

Nginx и HAProxy имеют разные подходы к DNS-кэшированию, что важно учитывать при проксировании к динамическим бэкендам.

Nginx
по умолчанию кэширует DNS-записи на время их TTL и не перезапрашивает
их до истечения срока — это создает проблемы в контейнерных средах, где
IP-адреса сервисов меняются при перезапуске.

Решение: использовать переменную в proxy_pass (set $backend "http://service.local"; proxy_pass $backend;) и директиву resolver 8.8.8.8 valid=30s для принудительного обновления каждые 30 секунд.

HAProxy более гибок в настройке DNS-резолвинга через секцию resolvers с параметрами hold valid 10s и resolve-prefer ipv4.

Ключевая особенность — возможность автоматического обновления IP-адресов бэкендов без перезагрузки конфигурации через default-server check resolvers dns_resolvers. Однако HAProxy агрессивно кэширует разрешенные адреса и может “застревать” на одном IP из multiple A-записей.
Это может быть нежелательно в ситуациях, когда важна равномерная
загрузка, или при динамическом изменении IP-адресов. Для контроля этого
поведения в блоке resolvers следует правильно настроить ключевые
параметры.

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

resolvers mynameservers
nameserver ns1 192.168.2.10:53
nameserver ns2 192.168.3.10:53
...
hold valid 10s # время актуальности DNS-записи (рекомендуется 10-30s)
hold obsolete 0s # время хранения нерабочих IP (всегда 0s!) - настройка по умолчанию для версий выше 2.0+
resolve_retries 3 # количество попыток разрешения (2-3 оптимально)
timeout retry 1s # интервал между попытками (1-2s)
timeout resolve 2s # общий таймаут разрешения (2-3s)

Пара советов по мониторингу. Отслеживайте в логах записи вида DNS resolution failed (HAProxy) и upstream timed out (Nginx) — это индикаторы проблем с DNS-кэшем. Для Nginx также можно добавить error_log /var/log/nginx/dns_debug.log debug; в контекст resolver.

И небольшое примечание:
не все уровни позволяют принудительно сбросить кэш. Например,
библиотека musl (в Alpine Linux) использует минималистичный встроенный
резолвер без отдельного кэша, но с фиксированным таймаутом и retry. В
нем DNS-кэш отсутствует, а каждый вызов делает новый DNS-запрос.

Специальные случаи кэширования

Negative Caching (кэширование NXDOMAIN)

Даже
отсутствие ответа от DNS-сервера (например, если домен не существует)
может кэшироваться. Это называется негативным кэшированием и описано в
RFC 2308. Время хранения NXDOMAIN обычно определяется TTL из SOA-записи
зоны или настройками резолвера:

- Unbound: по умолчанию использует SOA.MINIMUM или val-ttl-negative (по умолчанию до 15 минут);
- Dnsmasq: хранит негативные ответы 10 секунд;
- Systemd-resolved: не кэширует NXDOMAIN вообще (время жизни = 0);
- Bind кеширует NXDOMAIN, используя TTL из SOA (поле Minimum TTL) и настройку max-negative-cache-ttl.

Это
поведение критично при отладке: если домен недавно добавили, но он всё
ещё возвращает NXDOMAIN — возможно, причина в негативном кеше.

Важно:
негативный кеш может сохраняться даже после появления записи в DNS. В
некоторых случаях сброс возможен только перезапуском резолвера или его
кеша — это стоит учитывать при отладке.

Stale DNS (устаревшие ответы)

Некоторые
DNS-резолверы поддерживают режим “serve expired” (RFC 8767) — возврат
устаревших (stale) ответов из кеша, если свежий ответ от
upstream-серверов недоступен.

Такое поведение полезно для
повышения устойчивости: при кратковременных сетевых сбоях система
продолжает работать, используя последние известные данные.

Когда это может случиться:
- upstream-сервер недоступен или не отвечает вовремя;
- текущий ответ устарел (TTL истёк), но в кеше осталась старая копия;
- режим “serve-expired” включён явно (например, в unbound, dnsmasq, BIND).

Недостаток такого поведения — потенциальный риск работы с недействительными или уже изменившимися записями.

Диагностика: как проверить, откуда приходит DNS-ответ

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

1. Запрос через системный резолвер (libc):

getent hosts example.com

Этот
способ использует конфигурацию nsswitch.conf и может задействовать
systemd-resolved, dnsmasq или другие локальные DNS-сервисы, если они
настроены.

2. Запрос напрямую к локальному systemd-resolved (loopback):

dig @127.0.0.53 example.com

Позволяет
обратиться напрямую к systemd-resolved, минуя nsswitch.conf и libc. Это
поможет проверить, есть ли ответ в его собственном кэше. Для этой же
цели можно использовать команду:

resolvectl query example.com

3. Запрос напрямую к внешнему DNS-серверу (например, Google DNS):

dig @8.8.8.8 example.com

Гарантированно минует все локальные уровни кэширования. Такой запрос можно использовать для сравнения с локальными ответами.

4. Просмотр TTL в ответе:

dig +nocmd +noall +answer example.com

Показывает только секцию ответа (ANSWER) с указанием оставшегося TTL. Полезно для оценки свежести кэша.

Если ответы на один и тот же домен отличаются в зависимости от используемой команды — например, getent, dig @127.0.0.53 или dig @8.8.8.8
— это может указывать на наличие кэша на каком-то уровне. Отличия в
IP-адресах или в значениях TTL особенно показательны: они помогают
понять, на каком этапе возвращаются устаревшие или закешированные
данные. Такие сравнения позволяют локализовать источник кэширования и
уточнить, какой компонент системы дает неожиданный ответ.

Отслеживание сетевого трафика

Для анализа DNS-запросов можно использовать такую команду:

tcpdump -i any udp port 53 -n -X -w dns_dump.pcap

-n — отключает преобразование IP в имена (уменьшает шум).

-X — показывает пакеты в hex и ASCII (удобнее для DNS, чем -A).

-w — сохраняет дамп в файл (можно открыть в Wireshark).

Пример вывода:

13:37:45.123 IP 10.0.0.1.4321 > 8.8.8.8.53: 12345+ A? google.com. (28)
13:37:45.456 IP 8.8.8.8.53 > 10.0.0.1.4321: 12345 1/0/0 A 142.250.185.174 (44)

A? google.com — запрос типа "A" для домена google.com.

A 142.250.185.174 — ответ с IP-адресом.

12345 — ID запроса (полезно для сопоставления вопросов и ответов).

Также
можно использовать утилиту dig, которая инициирует запрос и сразу
перехватывает его, предоставляя много сопутствующей информации:

dig example.com & tcpdump -i any udp port 53 -n

Использование tcpdump позволяет отличить кэш от реального сетевого запроса: если трафика нет, скорее всего, ответ был из кэша.

Трассировка системных вызовов

С помощью этой команды можно выполнить трассировку системных вызовов и отслеживать обращения к DNS.

strace -e trace=network curl example.com

Фрагмент вывода:

sendto(3, "\264\372\1\0\0\1\0\0\0\0\0\0\7example\3com\0\0\1\0\1", 33, 0,
       {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("192.168.1.1")}, 16) = 33
recvfrom(3, "\264\372\201\200\0\1\0\1\0\0\0\0\7example\3com\0\0\1\0\1"..., 512, 0, ..., ...) = 49

Здесь
sendto() отправляет DNS-запрос на порт 53, а recvfrom() получает ответ
от DNS-сервера. Это позволяет убедиться, что разрешение действительно
идёт через сеть, а не из кэша.

Варианты решений для типичных ситуаций

Для полноты картины приведу несколько типовых ситуаций с основными вариантами решения.

“Сайт открылся у всех, кроме меня”

Причина: устаревший кэш в браузере или системном резолвере.
Решение: сравнить IP из ping с ожидаемым, сбросить кэш.

“Поменяли A-запись, но трафик идет на старый сервер”

Причина: не был заранее снижен TTL.
Решение: устанавливать короткий TTL (60 сек) за 24-48 часов до смены.

“curl работает, а браузер — нет”

Причина: браузер использует собственный DNS-кэш.
Решение: сбросить кэш браузера.

Chrome:
- chrome://net-internals/#dns — просмотр и сброс кэша
- chrome://flags — "Built-in DNS client" — управляет встроенным кэшем

Firefox:
- about:networking#dns — список записей
- network.dnsCacheExpiration — TTL кэша (по умолчанию 60 сек)

“Nginx перестал ходить после смены DNS”

Причина: кэш в nginx (параметр valid в resolver).
Решение: уменьшить valid=1s или перезапустить nginx.

“Библиотека использует старый адрес даже после flush”

Причина: язык/библиотека ведёт собственный кэш.
Решение: настроить TTL в коде или перезапустить приложение.

Чек-лист по полной очистке кэша

Для удобства собрал все в одну таблицу:

-2

Как правильно управлять кэшем

Немного практических советов по работе с кэшами.

В разработке

1.
Использовать короткие TTL для тестовых доменов (60-120 секунд). Для
негативных ответов (NXDOMAIN) устанавливайте ещё меньший TTL (5-30 сек) в
конфигурации резолверов (например, cache_neg_ttl в dnsmasq), чтобы
быстро тестировать исправления.
2. Знать, как сбросить кэш на каждом используемом уровне.
3. Тестировать изменения DNS в изолированной среде.

В production

1. Планировать изменения DNS: снижать TTL заранее.
2. Мониторить кэширование: логировать stale answers и NXDOMAIN.
3. Использовать централизованные резолверы с контролируемым кэшированием.
4. Настроить правильные TTL:
- Для часто меняющихся сервисов: 60-300 секунд.
- Для статичных данных: 3600+ секунд.

Эффективное
управление DNS в продакшене требует непрерывного контроля кэша.
Ключевые метрики: hit rate (эффективность кэша), stale answers
(устаревшие ответы), NXDOMAIN rate (ошибки резолвинга) и latency
(задержка).

Мониторинг системных резолверов

Для анализа
работы DNS-кэша и диагностики проблем важно уметь получать статистику
резолверов. В таблице ниже собраны ключевые команды для популярных
системных DNS-сервисов — от systemd-resolved до BIND.

-3

Мониторинг в среде Kubernetes

Эффективная работа DNS критична
для производительности кластера Kubernetes. CoreDNS, как стандартный
резолвер, генерирует метрики, которые помогают выявлять:

  • эффективность кэширования (снижает ли нагрузку на upstream);
  • ошибки разрешения имен (например, всплески NXDOMAIN);
  • аномальные задержки (проблемы с сетью или перегрузку).

Собирая эти данные через Prometheus, вы можете настроить алертинг и предотвратить сбои до их влияния на приложения.

Примеры метрик

- Эффективность кэша:

sum(rate(coredns_cache_hits_total{type="success"}[5m])) / sum(rate(coredns_cache_requests_total[5m]))

- Отслеживание ошибок:

rate(coredns_dns_responses_total{rcode="NXDOMAIN"}[5m])

- Задержки запросов:

histogram_quantile(0.99, rate(coredns_dns_request_duration_seconds_bucket[5m]))

Примеры алертов

- Рост ошибок NXDOMAIN:

rate(coredns_dns_responses_total{rcode="NXDOMAIN"}[5m]) > 10

- Деградация скорости ответа:

histogram_quantile(0.99, rate(coredns_dns_request_duration_seconds_bucket[5m])) > 1

- Снижение эффективности:

rate(coredns_cache_misses_total[15m]) / rate(coredns_cache_requests_total[15m]) > 0.5

Проактивные практики

  • Автоматизируйте алерты на аномальный рост NXDOMAIN-ответов.
  • Контролируйте сроки жизни DNS-записей (TTL), чтобы избежать использования устаревших данных.
  • Визуализируйте hit/miss ratio для контроля эффективности кэширования.

Заключение

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

В следующей части разберём, как взаимодействуют различные резолверы (glibc, systemd-resolved, dnsmasq, NetworkManager), что происходит, когда /etc/resolv.conf указывает на 127.0.0.53, и как понять, кто реально управляет вашим DNS в системе.