Вход на сайт

Просмотр новости

Найдите то, что Вас интересует

BPF XDP DNS: оптимизации, которые мы заслужили (часть 1)

Дата публикации: 07-07-2026 10:28:37

Ошибки в работе компонент DNS могут приводить к инцидентам: нагрузка за секунды возрастает на порядки, а с учётом политики обработки ошибок timeout и retry на клиентах — быстро приобретает лавинообразный характер. Такое случалось в истории эксплуатации нашего внутреннего рекурсивного контура DNS. Отказы в обслуживании создавались небольшим числом внешних запросов, которые обрабатывались параллельно с внутренними. Но в результате их расследования нам удалось преодолеть фундаментальные ограничения функционирования DNS‑сервисов.Меня зовут Олег Горохов, в Yandex Infrastructure я работаю в команде управления трафиком. В этой статье поделюсь, как мы оптимизировали процессы обработки в задаче классификации и изоляции DNS‑запросов — и в итоге исключили влияние внешних запросов на внутренние благодаря перераспределению ресурсов. 2 мкс — ровно столько сейчас требуется выбранному методу для ответа на запросы в прод‑контуре. Это на три порядка быстрее, если сравнивать с традиционными ответами обычных DNS‑серверов.Реализованные оптимизации стали возможными при использовании BPF‑программ в разных сегментах, в частности, BPF socket selection reuseport. Для полноценной работы требуются контроллеры, обеспечивающие runtime‑конфигурирование, мониторинг, менеджмент, доставку и синхронизацию внешних данных — об этом тоже немного поговорим.Внутренние и внешние запросыИтак, внешние DNS‑запросы, которые обрабатываются долго и непредсказуемо, могут влиять на остальные запросы. Формально для этой задачи мы оперируем классами запросов UDP DNS:Внутренние — ответ для них существует на рекурсивном контуре (в одном из кешей) или в худшем случае терминируется на наших же авторитетах. Например, это запрос для ресолва yandex.ru или fb-4oxozf2sz22atvfg.sas.yp-c.yandex.net. Для таких запросов мы хотим гарантировать максимальную доступность сервиса. Внутренние данные в инфраструктуре находятся в репликах DNS‑серверов и для ответов на них хождение по сети не осуществляется. Тем не менее, при обработке тяжёлых внешних запросов (CPU, sockets) потребление доступных ресурсов приводит к отказу в обслуживании для всех остальных запросов. Это происходит уже на стадии приёма пакета на начальном этапе, при получении данных из сокета. Внешние — ответы для таких запросов требуют рекурсивного обхода авторитетных серверов и апстримов вне наших сетей, доступность которых не гарантируется. Например, запросы на ресолв google.com или vk.com. Источники ответов на такие запросы могут быть недоступны, могут отвечать с недетерминированной задержкой и в общем случае потребляют значительные ресурсы DNS‑сервера при их обработке. Особенностью процессинга внешних запросов с негарантированным временем ответов является исчерпание ресурсов процесса на ожидание, менеджмент состояний, потоками процесса, выполняющими обработку в сценариях недоступности DNS‑апстримов, медленных ответов. А поскольку пул объектов DNS‑сервера один и тот же и распределяется тредами как для внутренних, так и для внешних запросов, то отказ в обслуживании распространяется на все запросы. Посмотрим на графики мониторинга во время подобного инцидента с отказом в обслуживании при процессинге внешних запросов:Видно что утилизация CPU всех ядер DNS‑контейнера практически моментально стала 100%. В отчёте по инциденту указано, что даже при небольшой доле внешних запросов, порядка 1–5%, можно наблюдать отказ в обслуживании. Для решения задачи мы подтвердили воспроизводимость проблемы отказа. В нашем эксперименте поучаствовало два танка, с номинальными внутренними запросами, и с внешними, рейт которых постепенно рос таким образом, чтобы получить точку разлома.На этом графике приведён базовый эксперимент для четырёх потоков DNS‑сервера, относительно которого мы будем искать влияние внешних запросов. Видно, что точка разлома для этой конфигурации находится в районе 125K rps. Далее постепенно добавим внешние запросы, полученные из продового трафика. Для большинства этих запросов нет ответов: либо авторитеты не отвечают за выделенный timeout, либо сами недоступны.В следующем эксперименте мы добавили к базовой нагрузке из второго танка всего 6K rps — но потенциально таких, с которыми DNS‑сервер плохо справляется. Это повлияло не только на ответы на внешние недоступные для ответа запросы, но и вообще на весь DNS‑сервер целиком, на его способность отвечать.Можем видеть: DNS‑сервер справляется с такими сценариями плохо, здесь требуется классификация и изоляция обработки запросов. При отказе и невозможности ответов для внешних запросов, внутренний поток ответов страдать не должен.Подходы к решению Первоначальный план решения включал в себя исследование поведения самого DNS‑сервера (мы используем unbound) и выделение проблемных участков процессинга. Достаточно быстро стало понятно, что без значительных изменений в коде не обойтись, поэтому мой коллега [id134647|@tailer] провёл серьёзное исследование и рефакторинг особо страдающих кусков кода. Добавляя новые структуры данных и разделяя треды и объекты по классам, мы надеялись изолировать процессинг разных запросов внутри кода DNS‑сервера. Но это не удалось. Фактически вывод был неутешительным — модель обработки DNS‑пакетов в unbound не позволяет провести изоляцию различных классов запросов. Второй подход был основан на результатах первого: мы выдвинули гипотезу, что классификацию и изоляцию следует делать до процессинга пакетов DNS‑сервером. Очевидно, если после классификации запросов разные классы обрабатываются разными серверами на непересекающихся подмножествах ресурсов CPU, то задача имеет решение. Однако это означает введение дополнительных контуров и управление ими. Для начала вот список тех мест, где можно сделать такую классификацию и принять решение о судьбе пакета: приложение на стороне клиента; сокет клиентского приложения, отправляющий DNS‑пакет; промежуточный (кеширующий, рекурсивный) DNS‑сервер; балансер, обслуживающий VS рекурсивного контура; сокет DNS‑сервера; DNS‑сервер, терминирующий рекурсивный запрос. По ряду причин мы сделали выбор в пользу механики, которая позволяет выбирать LISTEN‑сокет приложения DNS‑сервера для каждого пакета, инициирующего соединение. За этот выбор будет отвечать BPF‑программа, код которой исполняется в нужном месте так, что все DNS‑пакеты, для которых нужен процесс принятия сокетом, прошли через него. Это секция sk_reuseport. Идея в том, чтобы классифицировать DNS‑пакет по его контенту и делать для него сопоставление сокетов, разбитых по группам соответствующего класса:все внешние QNAME в пакетах относить к первой группе, все внутренние — ко второй,и так далее. Разумеется, группы сокетов не должны пересекаться, а каждый тред должен иметь однозначное соответствие как с группой принадлежащих ему сокетов, так и с ядрами CPU, на которых он выполняется. В итоге для этой задачи накопилось достаточно большое количество предположений, в рамках которых она может быть решена. Кроме того, был до конца не ясен вопрос: есть ли интерференция между потоками DNS‑сервера, даже при такой изоляции DNS‑запросов на входе в процесс. Поэтому сначала давайте посмотрим, как устроена обработка пакетов, как можно реализовать их классификацию и что может нам помочь в этом, кроме BPF‑программы. Обработка DNS-пакета Рассмотрим, как схематично устроена обработка DNS‑пакетов на этапе от буфера сетевой карты до сокета приложения DNS‑сервера. Нас интересует именно этот участок, так как мы хотим изменить порядок назначения сокетов приложения пакетам, поступающих в систему.Справа от схемы я указал некоторые идеи, которые реализуют наше решение. Основным этапом является загрузка BPF‑программы и её привязка ко всем открытым LISTEN‑сокетам процесса DNS‑сервера. Так как сегмент инсталляции включает sk_reuseport, каждый пакет, инициирующий соединение, проходит через нашу программу. К счастью для нас, для UDP это как раз все пакеты, для TCP — только SYN. Предположим, что доля TCP бесконечна мала, и будем обрабатывать весь трафик DNS TCP как отдельный класс со своим пулом потоков в DNS‑сервере. UDP‑пакеты мы предполагаем парсить и классифицировать на внешние и внутренние запросы по полю QNAME.Классификация и изоляция   Итак, основная наша задача — изолировать потенциально плохой паттерн нагрузки от всех внутренних запросов. Чтобы уточнить, что такое плохой паттерн, мы ограничились внешними запросами, которые просто классифицировать по суффиксам QNAME DNS‑запросов.BPF‑программа в SEC(sk_reuseport) позволяет нам заменить традиционный алгоритм выбора сокета для пакета, инициирующего соединение, на нужный нам: для внешних запросов мы равномерно выбираем сокет из socket map, в котором сгруппированы сокеты приложения для тредов, выделенных нам для внешнего DNS‑трафика. В крайнем случае, когда внешние запросы начали пожирать ресурсы, мы готовы ими пожертвовать, при этом мы также жертвуем тредами, выделенными специально для этого. для внутренних запросов DNS UDP мы соответственно выбираем пул сокетов для тредов внутренней обработки. Мы не готовы ими жертвовать, даже если внешние запросы сойдут с ума и захотят принести нам страдание. Рассчитываем, что внешние запросы в случае проблем с их обработкой поставят в полку треды и, возможно, соответствующие CPU, но внутренние под эту деградацию не попадут для всех ошибочных ситуаций, непонятных кодов ответов, отсутствия сокетов в нужных пулах, некорректных сокетов и так далее sk_reuseport делает fallback на традиционное распределение сокетов приложения между поступающими пакетами. Это нас спасёт, когда что‑то идёт кардинально неправильно. Кроме того, пакет должен соответствовать параметрам, с которым сокет создан, (dstip, dstport, proto). Если наше сопоставление не удовлетворяет этому правилу, система снова сделает fallback. КонтроллерРеализация идей и поиск решений не всегда проходили гладко. На этом пути мы последовательно пробовали разные варианты:Код управления непосредственно в кодовой базе DNS‑сервера unbound. Налог на поддержание патчей к DNS‑серверу сделал этот вариант менее приоритетным. Контроллер на С. Контроллер управления N...

Схожие новости

#Наименование новостиТональностьИнформативностьДата публикации
1Ошибки в работе компонент DNS могут приводить к инцидентам: нагрузка ...5707-07-2026
2Поставили на поток: как растет зарубежный сетевой трафик российских операторов0724-04-2026
3От полной выгрузки к S3 и PostgreSQL: как мы доставляем гигабайты данных в память подов5706-07-2026
4Что происходит при DDoS и как отличить атаку от нагрузки0525-06-2026
5Как мы научили реляционую базу хранить оргструктуру в виде графа на 500к пользователей0823-06-2026
6Как я пробовал сэкономить на апгрейде сети в Synology DS923+, да не получилось-2327-03-2026
7«Обит»: отказоустойчивость инфраструктуры все чаще зависит от инженерной экспертизы0506-07-2026
8HyperLogLog: как найти уникальные значения в терабайте данных, не храня их0724-06-2026
9- По мере возрастания, теперь уже, критических проблем, что меня ...0728-06-2026
10Число EoP-уязвимости выросло почти в два раза0723-06-2026

Классификация: Экономика. Схожих патентов: 0. Схожих новостей: 10. Тональность: 5. Информативность: 7. Источник: vk.com.