Перейти к содержанию
Бэкенд и системы

10 вопросов по теме «DevOps: Сети в эксплуатации» на собеседовании

В этом материале — 10 вопросов из русской колоды RecallDeck по теме «DevOps: Сети в эксплуатации». Сначала сформулируйте короткий ответ сами, затем откройте подробный разбор и проверьте примеры, ограничения и отказные случаи.

9 мин чтения10 подробных ответовПроверено 24 августа 2026
Главная мысль

Стройте ответ вокруг владения состоянием, лимитов, отказа и восстановления. Определение становится инженерным ответом только в конкретном production-сценарии.

Вопросы и ответы

10 подробных ответов

01

Проследите полный путь DNS-резолвинга: от getaddrinfo в приложении до авторитативного сервера. Где по пути кэши и как отлаживать каждый хоп?

Короткий ответ: Приложение вызывает getaddrinfo → libc смотрит nsswitch.conf (сначала /etc/hosts) → локальный stub-резолвер (systemd-resolved со своим кэшем) → рекурсивный резолвер (ISP/CoreDNS), кэширующий по TTL → root → TLD → авторитативный сервер зоны.

Подробно:

  1. nsswitch.conf и /etc/hosts — до всякого DNS: строка hosts: files dns означает, что /etc/hosts выигрывает у сети.
  2. Stub-резолвер — systemd-resolved (127.0.0.53) держит свой кэш; сбрасывается resolvectl flush-caches.
  3. Рекурсивный резолвер — кэширует ответы по TTL и, что часто забывают, NXDOMAIN тоже (negative caching, TTL берётся из SOA).
  4. Рекурсия — root → TLD (.com) → авторитативный сервер зоны.

Отладка по хопам: dig example.com (системный резолвер), dig @8.8.8.8 (конкретный резолвер), dig +trace (полная рекурсия от root, мимо всех кэшей), getent hosts (путь как у приложения, через nsswitch).

app → getaddrinfo → nsswitch.conf → /etc/hosts
                                  → stub (systemd-resolved, кэш)
                                  → рекурсивный резолвер (кэш по TTL)
                                  → root → TLD → авторитативный

⚠️ Частая ошибка: отлаживать одним dig'ом и пропустить nsswitch и /etc/hosts (dig ходит в DNS напрямую, мимо них) — и negative caching: «запись удалил, а NXDOMAIN ещё доживает свой TTL».

02

curl по IP работает, а по hostname падает — но не каждый раз. Как диагностировать?

Короткий ответ: «Иногда» — сигнатура DNS: один битый адрес в наборе A-записей, закэшированный отрицательный ответ, split-horizon (разные резолверы отдают разное) или экспансия search-доменов в Kubernetes (ndots). Метод: опросить dig'ом каждый резолвер в цепочке и сравнить ответы и TTL.

Подробно:

  1. Битый адрес в наборе — DNS отдаёт несколько A-записей round-robin; если один бэкенд мёртв, падает каждый N-й запрос.
  2. Negative caching — резолвер закэшировал NXDOMAIN/SERVFAIL и отдаёт его до конца TTL, хотя запись уже существует.
  3. Split-horizon — внутренний и внешний резолверы видят разные зоны; какой достался машине — вопрос resolv.conf.
  4. ndots в Kubernetes — имя с числом точек меньше 5 сначала прогоняется через search-домены (svc.cluster.local и т.д.): лишние запросы, тайм-ауты, изредка неожиданные совпадения имён.
dig +short api.example.com                # системный резолвер
dig +short api.example.com @10.0.0.2      # каждый резолвер из resolv.conf
dig +trace api.example.com                # что отдаёт авторитативный
dig api.example.com                       # сравнить ANSWER-набор и TTL

⚠️ Частая ошибка: решить «IP работает — значит, сеть в порядке» и уйти отлаживать приложение. Перемежающийся сбой по имени — это round-robin по битому набору или гонка кэшей, а не баг в коде.

03

Опишите TLS-хендшейк. Зачем нужен SNI и как несколько сертификатов уживаются на одном IP?

Короткий ответ: Клиент шлёт ClientHello (версии, шифры и hostname в SNI) → сервер отвечает сертификатом и параметрами обмена ключами → стороны выводят сессионные ключи, дальше трафик шифруется симметрично. SNI нужен потому, что TLS происходит ДО HTTP: Host-заголовок ещё не отправлен, и серверу нечем выбрать сертификат.

Подробно:

  1. ClientHello — версии TLS, список шифров, SNI открытым текстом; в TLS 1.3 сразу и key share.
  2. ServerHello + сертификат — сервер выбирает шифр и сертификат под пришедший SNI.
  3. Обмен ключами — (EC)DHE даёт forward secrecy; из общего секрета выводятся сессионные ключи.
  4. Почему именно SNI — hostname обязан ехать в хендшейке: Host-заголовок HTTP придёт уже внутри зашифрованного канала. Так десятки виртуальных хостов с разными сертификатами живут на одном IP:443.
Где терминировать TLS Плюсы Минусы
На балансировщике дёшево, центральное управление сертификатами внутри периметра трафик открытым текстом
На поде / mTLS шифрование end-to-end, взаимная аутентификация CPU, раздача и ротация сертификатов

⚠️ Частая ошибка: просроченный сертификат — классика аварий. «Продлим руками» — неправильный ответ: ACME/cert-manager для автообновления плюс алерт за 2–3 недели до истечения.

04

L4- vs L7-балансировка: что видит и что умеет каждый уровень?

Короткий ответ: L4-балансировщик видит только IP и порт — раскидывает TCP/UDP-потоки, быстрый и дешёвый, но для него протокол непрозрачен. L7 разбирает HTTP: маршрутизация по пути и заголовкам, ретраи, терминация TLS, sticky-сессии — ценой CPU на парсинг.

Подробно:

L4 L7
Видит IP:порт, SYN метод, путь, заголовки, куки
Маршрутизация round-robin/хэш по потокам /api → один пул, /static → другой
Ретраи и таймауты нет — не знает, где кончается запрос per-request ретраи, circuit breaking
TLS пропускает насквозь (passthrough) терминация, X-Forwarded-For
Цена почти нулевая, миллионы pps парсинг HTTP: CPU и латентность

Примеры: L4 — IPVS, AWS NLB; L7 — nginx, Envoy, AWS ALB. Частый каскад: L4 снаружи → L7 внутри.

⚠️ Частая ошибка: ждать от L4 ретраев и маршрутизации по пути — он не видит HTTP и в принципе не знает, где закончился один запрос и начался следующий.

05

В логах «nf_conntrack: table full, dropping packet». Что такое conntrack и как это чинить?

Короткий ответ: conntrack — таблица состояний соединений в netfilter; на ней держатся NAT и stateful-файрвол. Каждый NAT-нутый поток занимает запись; таблица переполнилась — новые пакеты молча дропаются. Лечение: поднять лимит, убрать лишние NAT-хопы, укротить DNS-трафик.

Подробно:

  1. Зачем таблица — чтобы обратный пакет прошёл ту же трансляцию, ядро помнит каждый поток: адреса, порты, состояние, тайм-аут.
  2. UDP тоже считается — каждый DNS-запрос создаёт запись, живущую ~30 с после ответа. Микросервисы без DNS-кэша плодят тысячи записей — классический продовый инцидент в Kubernetes.
  3. Диагностика — сравнить счётчик с лимитом и посмотреть, кто ест таблицу:
sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
conntrack -L -p udp --dport 53 | wc -l            # сколько съел DNS
sysctl -w net.netfilter.nf_conntrack_max=1048576  # тактическое лечение
  1. Стратегически — меньше NAT-хопов, локальный DNS-кэш (NodeLocal DNSCache), eBPF-датаплейн (Cilium) вместо kube-proxy/iptables — потоки идут мимо conntrack.

⚠️ Частая ошибка: выкрутить лимит и закрыть тикет. Лимит — симптоматическое: причина обычно в DNS-шторме или лишнем NAT, и с ростом трафика она вернётся.

06

Как iptables обрабатывает пакет: какие таблицы и цепочки, и где происходит DNAT?

Короткий ответ: Пакет идёт по цепочкам в фиксированном порядке: PREROUTING (таблица nat — здесь DNAT) → решение маршрутизации → INPUT или FORWARD (filter) → POSTROUTING (nat — здесь SNAT/masquerade). Обратные пакеты правила заново не проходят: conntrack применяет обратную трансляцию автоматически.

Подробно:

  1. DNAT до маршрутизации — адрес назначения надо переписать до того, как ядро решит, куда пакет: себе (INPUT) или транзитом (FORWARD).
  2. filter в INPUT/FORWARD — здесь живут обычные правила файрвола.
  3. SNAT/masquerade на выходе — в POSTROUTING, когда исходящий интерфейс уже известен.
  4. conntrack — правило DNAT срабатывает только на первом пакете потока; остальные пакеты и обратный трафик транслируются по записи conntrack.
пакет ─► PREROUTING (nat: DNAT) ─► routing decision
                                      │ локальный?
                                      ├─ да ─► INPUT (filter) ─► процесс
                                      └─ нет ─► FORWARD (filter)
                                               └─► POSTROUTING (nat: SNAT) ─► наружу

Публикация порта контейнера (-p 8080:80) — это ровно DNAT-правило в PREROUTING плюс masquerade для обратного пути.

⚠️ Частая ошибка: искать DNAT в таблице filter — и удивляться, что tcpdump за точкой трансляции показывает уже переписанные адреса: NAT случился раньше, чем вы смотрите.

07

Через VPN мелкие запросы проходят, а большие аплоады виснут. Как диагностировать?

Короткий ответ: Классический MTU-блэкхол: туннель съедает часть кадра (оверлей уменьшает эффективный MTU; VXLAN — минус 50 байт), а Path MTU Discovery не работает, потому что файрвол режет ICMP «fragmentation needed». Мелкие пакеты пролезают, большие молча теряются.

Подробно:

  1. Механика — приложение шлёт пакеты под MTU 1500, туннель добавляет заголовки, пакет не влезает; с флагом DF его отбрасывают и должны сообщить ICMP type 3 code 4 — но ICMP заблокирован, и отправитель ничего не узнаёт.
  2. Сигнатура — TCP-хендшейк и мелкие ответы ок (маленькие сегменты), передача данных виснет. Ровно «curl работает, upload висит».
  3. Тест — бинарный поиск размера с запретом фрагментации:
ping -M do -s 1472 host   # 1472 + 28 = 1500: проходит?
ping -M do -s 1422 host   # сужаем, ищем реальный path MTU
  1. Лечение — MSS clamping на границе туннеля (--clamp-mss-to-pmtu), либо снизить MTU интерфейса, либо разрешить нужный ICMP на файрволе.

⚠️ Частая ошибка: не связать «зависит от размера» с MTU и уйти отлаживать приложение. Размерозависимый сбой через туннель — это MTU, пока не доказано обратное.

08

На сервере тысячи сокетов в TIME_WAIT — это проблема?

Короткий ответ: Само по себе — нет: TIME_WAIT — штатное состояние стороны, закрывшей соединение первой (ждёт 2×MSL, обычно 60 с, чтобы опоздавшие сегменты не попали в новое соединение). Болит только на стороне КЛИЕНТА с высоким churn'ом соединений: заканчиваются эфемерные порты.

Подробно:

  1. Зачем состояние — защита от «заблудших» сегментов старого соединения и надёжное завершение: последний ACK может потеряться.
  2. Когда болит — клиент (прокси, сервис с соединением на каждый запрос) плодит десятки тысяч TIME_WAIT и исчерпывает ~28k эфемерных портов на кортеж (dst IP, dst port) — новые connect'ы падают с EADDRNOTAVAIL.
  3. Правильное лечение — keep-alive и connection pooling: не открывать соединение на каждый запрос.
  4. Ручкиtcp_tw_reuse безопасен для исходящих (переиспользование по TCP timestamps); расширить ip_local_port_range.
ss -s                                    # сводка: сколько timewait
ss -tan state time-wait | awk '{print $4}' | sort | uniq -c | sort -rn | head

⚠️ Частая ошибка: рекомендовать tcp_tw_recycle — он ломал клиентов за NAT (timestamps от разных машин перемешиваются) и удалён из ядра начиная с 4.12.

09

Health-check балансировщика зелёный, а пользователи ловят 502/504. Как такое возможно?

Короткий ответ: Health-check проверяет не то, чем живёт трафик: путь /healthz отвечает, а /api умирает на зависимости. Вторая классика — рассинхрон idle-таймаутов keep-alive: балансировщик держит соединение дольше приложения, переиспользует уже закрытый сокет и получает 502.

Подробно:

  1. Проверка ≠ боевой путь — check без зависимостей зелёный, а реальный запрос падает на БД или внешнем API. Нужен readiness, дёргающий реальные зависимости (аккуратно: не устроить каскад).
  2. Гонка keep-alive — приложение закрывает idle-соединение через 5 с, балансировщик считает его живым 60 с: следующий запрос уезжает в закрытый сокет → 502. Правило: idle-таймаут приложения больше таймаута балансировщика.
  3. 502 vs 504 — разные болезни: 502 — бэкенд ответил «неправильно», 504 — не ответил вовсе.
Код Что значит Типовая причина
502 некорректный ответ бэкенда гонка keep-alive, креш процесса, RST
504 не дождались ответа за таймаут зависший воркер, таймаут БД, перегрузка

⚠️ Частая ошибка: верить зелёному health-check'у. Он отвечает на вопрос «жив ли процесс», а не «обслуживает ли он реальные запросы».

10

HTTP/1.1 vs HTTP/2 vs HTTP/3: какую проблему решает каждый и что такое head-of-line blocking?

Короткий ответ: Каждая версия убирает свой уровень head-of-line blocking (HOL). В HTTP/1.1 запросы на соединении идут строго по очереди; HTTP/2 мультиплексирует стримы в одном TCP, но потеря одного пакета стопорит все стримы (HOL уровня TCP); HTTP/3 (QUIC поверх UDP) даёт независимые стримы и 0-RTT.

Подробно:

HTTP/1.1 HTTP/2 HTTP/3 (QUIC)
Транспорт TCP TCP UDP
Параллелизм 1 запрос на соединение (браузер открывает ~6) мультиплексирование стримов независимые стримы
HOL на уровне HTTP: очередь запросов ушёл из HTTP, остался в TCP нет: потеря тормозит только свой стрим
Бонусы простота, отладка глазами HPACK, приоритеты 0-RTT, миграция соединения при смене сети
  1. HOL в 1.1 — медленный ответ держит всех за собой; pipelining на практике сломан.
  2. HOL TCP в h2 — TCP гарантирует порядок байтов: дыра в потоке блокирует доставку всех стримов, даже если их байты уже дошли.
  3. QUIC — надёжность на уровне стрима, хендшейк совмещён с TLS 1.3.

⚠️ Частая ошибка: «h2 решил HOL полностью». Он убрал HOL на уровне HTTP, но в сети с потерями h2 на одном TCP-соединении может проиграть даже 1.1 с шестью соединениями.

Источники

Источники и редакционная политика

Материалы RecallDeck сопоставлены с официальной документацией и открытыми публикациями компаний, когда первичный источник доступен. Мы не связаны с упомянутыми работодателями, не публикуем конфиденциальные задания и не продаём места в подборках. Формат найма может меняться — уточняйте его у рекрутера.

От чтения к воспроизведению

Отрепетируйте полный цикл интервью.

RecallDeck возвращает сложные темы по расписанию и помогает удерживать в памяти язык, SQL, архитектуру и поведенческие истории.

Начать подготовку

Продолжить подготовку

Библиотека собеседований RecallDeck

Подробные русские ответы, разборы этапов найма и планы подготовки для российского IT-рынка.

RSS