8(800) 222 32 56
Панель управления
DevOps

Cilium FQDN egress для LLM API: DNS cache, IP churn и диагностика

Cilium FQDN egress для LLM API: DNS cache, IP churn и диагностика
Подберите идеальное решение для ваших задач:
в России, США и Нидерландах обеспечат максимальную скорость. Воспользуйтесь всеми преимуществами надежного оборудования. Базовая помощь и техническое обслуживание входят в пакет услуг.
LLM gateway внезапно теряет доступ к внешнему API, хотя DNS отвечает и домен есть в CiliumNetworkPolicy. Через минуту запрос проходит, после смены IP снова зависает, а временный allow по CIDR только прячет причину. Разберём цепочку DNS → FQDN cache → effective policy → Hubble flow → результат приложения и соберём canary, который отличает stale DNS от ошибки datapath.

Готовы перейти на современную серверную инфраструктуру?

В King Servers мы предлагаем серверы как на AMD EPYC, так и на Intel Xeon, с гибкими конфигурациями под любые задачи — от виртуализации и веб-хостинга до S3-хранилищ и кластеров хранения данных.

  • S3-совместимое хранилище для резервных копий
  • Панель управления, API, масштабируемость
  • Поддержку 24/7 и помощь в выборе конфигурации

Создайте аккаунт

Быстрая регистрация для доступа к инфраструктуре

Почему FQDN egress ломается не там, где кажется

Типичный инцидент выглядит обманчиво просто: pod с inference-gateway вчера обращался к внешнему API по доменному имени, а сегодня часть запросов висит до таймаута. DNS из shell отвечает, сертификат валиден, соседний namespace работает. Команда расширяет CIDR, перезапускает CoreDNS или временно снимает policy, и связь возвращается. Причина при этом остаётся неизвестной, а следующий IP-rotation повторяет сбой.

В Cilium правило toFQDNs не является статическим allowlist домена. Агенту нужно увидеть DNS-ответ от конкретного endpoint, связать имя с адресами, обновить FQDN cache и materialize разрешение в effective policy. После этого новый TCP/TLS flow должен попасть под эту policy. Здесь минимум четыре разных состояния: ответ resolver, содержимое cache, политика endpoint и результат приложения. Зелёный индикатор на одном слое не делает зелёной всю цепочку.

Представьте сервис, который обращается к API провайдера через имя api.vendor.example. Провайдер меняет A-запись, JVM продолжает использовать старый адрес, а Cilium уже удалил его после TTL. Новый connection к старому IP будет отброшен, хотя имя в YAML написано верно. Обратный сценарий тоже возможен: приложение получило свежий IP, но DNS-запрос прошёл не через наблюдаемый proxy, поэтому адрес не появился в policy.

Поэтому default для расследования такой: не увеличивать TTL и не расширять egress «на всякий случай». Сначала докажите, где расходятся desired state, effective network state и application outcome. Этот подход отделяет ошибку selector от DNS lifecycle и не превращает временное восстановление в постоянную дыру.

Путь DNS-запроса от pod через CoreDNS и Cilium DNS proxy к LLM API

Как toFQDNs превращает имя в разрешённый сетевой путь

Стандартный Kubernetes NetworkPolicy работает с pod selectors, namespaces, ports и CIDR. Он не задаёт переносимое правило «разрешить любой адрес, на который сейчас указывает это DNS-имя». CiliumNetworkPolicy добавляет FQDN-aware egress: matchName подходит для точного имени, matchPattern — для контролируемого шаблона. Но обе формы зависят от DNS visibility.

Рабочая цепочка начинается с DNS allow rule к вашему resolver. Запрос обычно идёт к CoreDNS на UDP/53, но production-клиент может использовать TCP при усечённом ответе, NodeLocal DNSCache или отдельный корпоративный resolver. Если policy разрешает только привычный kube-dns label, а workload фактически обращается к local listener, toFQDNs не получает исходное событие. Проверьте реальный destination, а не архитектурную схему в wiki.

После ответа Cilium хранит данные на нескольких уровнях. В документации описаны per-endpoint DNS cache, global cache и zombie mapping для адресов, чей TTL истёк, но существующие соединения ещё учитываются connection tracking. Это важно: «адрес исчез из свежего ответа» и «адрес немедленно запрещён для любого пакета» — не одно и то же. Новые соединения и уже установленные flows живут по разным правилам.

Наконец, FQDN selector должен превратиться в identities и попасть в effective policy нужного endpoint. Если labels не выбирают workload, pod работает с hostNetwork или запущен до корректной установки Cilium, вы исследуете не тот enforcement point. Официальная инструкция Cilium по troubleshooting прямо советует сначала убедиться, что pod управляется Cilium, а уже затем разбирать policy.

На каком слое искать разрыв

Проверьте, что запрос pod действительно прошёл через наблюдаемый Cilium DNS proxy и вернул ожидаемые A/AAAA.
Сопоставьте IP из ответа с per-endpoint FQDN cache и его TTL, не полагаясь на системный resolver узла.
Убедитесь, что выбран правильный endpoint и новая identity попала в effective policy.
Подтвердите новый TLS-запрос из самого приложения: один успешный curl в debug pod ещё не доказывает исправление.
Схема цепочки POD, DNS, FQDN cache, policy и внешний API

Снимите baseline до изменения policy

Хороший runbook начинается не с YAML, а с карточки инцидента. Запишите namespace, pod UID, node, service account, labels и Cilium endpoint ID. Затем из того же container network namespace получите A и AAAA, TTL, адрес resolver и время запроса. Не заменяйте этот шаг запросом с ноутбука: корпоративный DNS, split horizon и search domains легко дадут другой ответ.

Следом сохраните два Hubble-среза: DNS traffic на 53 и попытку соединения к API на 443. Для каждого нужны source identity, destination IP, verdict и drop reason. Третий снимок — effective policy endpoint. Desired CiliumNetworkPolicy из Kubernetes API показывает намерение, но не гарантирует, что selector выбрал именно этот pod и правило уже применено на его node.

Определите application outcome до эксперимента. Для streaming LLM API это может быть успешный TLS handshake, получение HTTP headers, первый SSE event и штатное завершение stream. Не смешивайте эти точки: быстрый connect без ответа модели доказывает только transport. В соседнем материале о HTTP/2 GOAWAY и graceful drain показано, почему connection event и судьба отдельного request не равны.

Нужен и отрицательный контроль. Оставьте один pod или namespace на прежней policy либо запросите заведомо неразрешённое имя. Если после изменения начинают проходить и целевой, и запрещённый destination, это не успех, а потеря границы. Отрицательный контроль особенно полезен при объединении нескольких additive policies: порядок правил не важен, разрешения складываются, и неожиданно широкий allow может прийти из другого объекта.

bashcollect-fqdn-baseline.sh
kubectl -n ai get pod inference-gateway-0 -o wide --show-labels
kubectl -n kube-system exec ds/cilium -- cilium-dbg endpoint list
kubectl -n ai exec inference-gateway-0 -- getent ahosts api.vendor.example
hubble observe -P --since 5m --namespace ai --pod inference-gateway-0
kubectl -n kube-system exec ds/cilium -- cilium-dbg fqdn cache list
Минимальный baseline без изменения кластера

Готов ли baseline к эксперименту

eBPF policy gate пропускает актуальный IP и блокирует устаревший маршрут

Соберите минимальную CiliumNetworkPolicy без широкого allow

Минимальная policy должна отвечать на два разных вопроса: куда workload разрешено отправлять DNS-запросы и к какому FQDN разрешено подключаться. Это две egress rules, а не одна магическая запись. В DNS rule выбирайте фактический resolver и разрешайте DNS L7 rule только для нужных имён либо осознанно для более широкого набора. В FQDN rule задайте TCP/443, если провайдер действительно использует HTTPS.

Ниже — скелет, а не готовый универсальный манифест. Labels CoreDNS отличаются между дистрибутивами; NodeLocal DNSCache может потребовать entity или CIDR-модель, совместимую с вашей установкой. Точное имя предпочтительнее шаблона. Шаблон *.example.com не означает «example.com и все уровни поддоменов» во всех ожидаемых трактовках, поэтому проверяйте спецификацию и фактический match.

Не добавляйте IPBlock параллельно «для надёжности»: он маскирует ошибку DNS path и превращает динамический allowlist в ручной список. Если API публикует CDN-адреса, диапазон может быть большим и общим с чужими сервисами. Разрешение по CIDR снимает пользу domain-based boundary, а обслуживание такого списка становится вашим on-call debt.

После apply проверьте статус policy и endpoint, затем повторите ровно тот же запрос. В статье о PROXY protocol v2 для LLM API мы разделяли физического peer, заявленную metadata и effective identity; здесь логика похожа: имя в объекте, IP в cache и identity в datapath — самостоятельные факты.

yamlcilium-fqdn-egress.yaml
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: inference-api-egress
  namespace: ai
spec:
  endpointSelector:
    matchLabels:
      app: inference-gateway
  egress:
    - toEndpoints:
        - matchLabels:
            k8s:io.kubernetes.pod.namespace: kube-system
            k8s:k8s-app: kube-dns
      toPorts:
        - ports:
            - port: "53"
              protocol: ANY
          rules:
            dns:
              - matchName: api.vendor.example
    - toFQDNs:
        - matchName: api.vendor.example
      toPorts:
        - ports:
            - port: "443"
              protocol: TCP
Пример точного FQDN allow с отдельным DNS rule

Что означает ваш симптом

Hubble показывает разрешённый DNS flow и заблокированный TLS egress

Разберите TTL, FQDN cache и IP churn

Самый неприятный класс сбоев появляется не сразу после rollout, а через TTL. Cilium по умолчанию учитывает TTL DNS-ответа. Приложение при этом может кешировать адрес дольше, использовать собственный resolver или держать connection pool часами. Если после истечения TTL оно открывает новый connection к старому IP без нового DNS lookup, policy закономерно блокирует flow. Это не случайный drop: network state больше не подтверждает связь имени с адресом.

Сравните четыре времени: TTL в ответе, момент записи в per-endpoint cache, срок DNS-кеша runtime и возраст connection. Например, Java, Go, Envoy и sidecar могут иметь разные resolver semantics. Не переносите вывод из dig в поведение процесса без проверки. Внешний curl создаёт новый lookup и connection, поэтому часто «лечит» тест, который приложение продолжает проваливать.

Параметр минимального TTL Cilium может смягчить короткие TTL, но это компромисс, а не первая помощь. Слишком большой минимум задерживает отзыв адреса и расширяет окно, когда новый connection идёт к устаревшему backend. Прежде чем менять его, воспроизведите drop после TTL, подтвердите отсутствие повторного lookup и проверьте, что провайдер действительно допускает более долгую жизнь адреса.

AAAA — отдельная ветка. Workload может получить IPv4 и IPv6, а policy или инфраструктура поддерживает только один path. Happy Eyeballs скроет часть проблем, пока порядок адресов или latency не поменяются. Записывайте оба набора и Hubble flows по каждой семье. Похожая дисциплина описана в статье о DNS failover для LLM API, но здесь owner состояния — FQDN policy cache конкретного endpoint, а не только resolver и клиентское соединение.

Команда ниже полезна для корреляции, но формат вывода зависит от версии Cilium. На дату подготовки stable-документация показывает ветку 1.20.2; перед автоматизацией сверяйте CLI вашей установленной версии. Наличие IP в cache означает, что toFQDNs может построить identity, но не доказывает выбор endpoint или успешный application request.

Официальный разбор FQDN cache также описывает zombie mappings: истёкшие записи могут удерживаться, пока connection tracking считает адрес используемым. Поэтому простой подсчёт строк cache без временной шкалы даёт ложную уверенность.

Схема диагностики DNS, cache, policy, flow и application outcome

Докажите решение через Hubble и effective policy

Hubble отвечает на вопрос «что произошло с flow на управляемом Cilium endpoint». Начните с DNS. Вы должны увидеть запрос и ответ между workload и resolver; при включённой DNS visibility доступны имя и response details. Затем отфильтруйте destination IP из ответа и TCP/443. Если DNS FORWARDED, а TLS DROPPED, проблема находится после resolution: cache, identity propagation, selector или port rule.

Если flow отсутствует, не делайте вывод «Cilium ничего не блокирует». Hubble Relay может не быть подключён к node, временное окно слишком узко, pod не управляется Cilium или traffic идёт через host network. Официальная инструкция Hubble предлагает сначала проверить status и connected nodes. Только после этого отсутствие события становится полезным фактом.

Effective policy следует читать для endpoint ID проблемного pod. Сопоставьте labels, policy revision и разрешённые identities. Kubernetes policies additive: другой allow может сделать эксперимент зелёным, а deny-модель Cilium — изменить итог в зависимости от выбранного формата и версии. Не ограничивайтесь сообщением «policy imported». Оно означает, что объект принят, но не описывает результат конкретного endpoint.

Application gate завершает доказательство. Для LLM streaming сохраните HTTP status, time to headers, time to first event, число завершённых streams и причины разрыва. Не приписывайте Cilium улучшение TTFT, если исчез только сетевой timeout. Сетевая policy управляет доступом; очередь inference, overload и backpressure остаются другими слоями. Для них уместен отдельный runbook про Envoy под перегрузкой LLM API.

bashverify-fqdn-flow.sh
hubble status -P
hubble observe -P --since 10m --namespace ai --pod inference-gateway-0 --protocol DNS
hubble observe -P --since 10m --namespace ai --pod inference-gateway-0 --port 443
kubectl -n kube-system exec ds/cilium -- cilium-dbg fqdn cache list
kubectl -n ai exec inference-gateway-0 -- curl -sS -o /dev/null -w '%{http_code}\n' https://api.vendor.example/health
Три независимых evidence gate

Как читать verdict без догадок

Пакет прошёл наблюдаемый hop. Это ещё не доказывает успешный TLS handshake или ответ LLM API.
Зафиксируйте source identity, destination IP, порт и drop reason; затем сопоставьте их с effective policy конкретного endpoint.
Проверьте, управляет ли Cilium этим pod, подключён ли Hubble Relay к нужной node и совпадает ли временное окно.
Canary rollout CiliumNetworkPolicy рядом с неизменным baseline

Rollout и rollback: меняйте одну границу за раз

Не накатывайте новую egress policy сразу на все inference pods. Создайте canary label или отдельный deployment с тем же образом, service account, resolver и переменными окружения. Единственное различие — новая policy. Baseline должен остаться активным: он показывает, изменилась ли внешняя сторона одновременно с вашим экспериментом.

Сначала выполните positive control к разрешённому FQDN, затем negative control к соседнему запрещённому имени и прямому IP. Прямой IP особенно важен: toFQDNs relies on наблюдаемый DNS lookup. Если обход без lookup проходит, проверьте другие additive policies. После этого дождитесь как минимум одного естественного TTL transition или воспроизведите контролируемую смену адреса в тестовом домене, которым владеете.

Stop condition запишите до rollout. Например: любой рост сетевых timeouts canary относительно baseline, появление drops для разрешённого destination после свежего DNS response или прохождение запрещённого destination. При срабатывании не расширяйте правило на лету. Верните canary к предыдущему selector/policy и повторите те же DNS, cache, flow и application проверки.

Rollback считается успешным, когда восстановилось не только число запросов, но и прежняя граница доступа. Удаление policy может сделать все egress разрешённым и визуально «починить» приложение. Это не возврат к безопасному baseline. Сохраните YAML, policy revision и Hubble evidence до и после отката; иначе расследование останется рассказом без контрфакта.

Проверка перед rollout

Выделенный edge, resolver и Kubernetes-кластер с контролируемым egress path

Когда выделенная инфраструктура помогает, а когда нет

Выделенный VPS, dedicated edge или отдельный Kubernetes node pool полезны, когда вам нужен контроль над resolver, Cilium version, network path, firewall policy, Hubble retention и change window. На shared-платформе часть этих границ принадлежит провайдеру: вы видите application timeout, но не можете сопоставить его с datapath verdict. Собственный edge делает evidence chain воспроизводимой и уменьшает число неизвестных владельцев.

Это не означает, что новое железо исправит FQDN policy. Оно не починит stale DNS cache внутри приложения, ошибочный endpointSelector, connection reuse старого IP или отсутствие DNS visibility. Disqualifier простой: если canary на тех же node и network path проходит после исправления selector или resolver, capacity upgrade не является лечением.

Для небольшого сервиса разумный default — не усложнять. Оставьте обычный egress через контролируемый gateway, если команда не готова сопровождать Cilium CRD, Hubble и DNS lifecycle. FQDN-aware policy оправдана, когда внешний API меняет адреса, CIDR allowlist непрактичен, а domain boundary действительно нужна для compliance или ограничения blast radius.

Когда нагрузка и требования растут, сравнивайте варианты по ownership. Managed egress снимает часть on-call debt, dedicated gateway даёт версии и change windows, а отдельный Kubernetes pool добавляет полный datapath control. Коммерческий смысл KingServers здесь не в обещании меньшей latency, а в возможности закрепить предсказуемый network baseline для canary и расследований. Архитектурный контекст для такого выбора есть в руководстве про Private AI API на своих серверах.

Нужен ли отдельный egress-контур

Итог: доменное имя — начало доказательства, а не готовое разрешение

Cilium FQDN egress полезен именно там, где IP внешнего LLM API меняются, а широкие CIDR неприемлемы. Но надёжность появляется не от строки matchName. Её даёт цепочка доказательств: DNS-запрос прошёл через наблюдаемый resolver, свежий IP оказался в cache, identity попала в effective policy нужного endpoint, Hubble показал ожидаемый verdict, а приложение завершило реальный запрос.

Начните с baseline и отрицательного контроля. Затем примените минимальную policy к canary, дождитесь TTL transition и проверьте rollback теми же командами. Если ошибка остаётся, не расширяйте allowlist наугад: локализуйте owner между runtime DNS cache, Cilium endpoint и внешним API.

Практический следующий шаг прост: возьмите один некритичный deployment, сохраните DNS/cache/policy/flow evidence и проведите controlled rollout по чек-листу из статьи. Когда для этого не хватает контроля над resolver, datapath или change window, выделенный egress-контур становится обоснованным инфраструктурным решением — с ясной причиной и проверяемым результатом.

GPU throttling в LLM inference: мониторинг через DCGM и Prometheus
AI

GPU throttling в LLM inference: мониторинг через DCGM и Prometheus

Практический мониторинг GPU throttling в LLM inference: DCGM Exporter, Prometheus, метрики power/thermal violation, PromQL, алерты и production-runbook.

Кто такой DevOps инженер и как им стать?
DevOps

Кто такой DevOps инженер и как им стать?

Devops инженер является тем самым звеном, которое эффективно связывает между собой различные отделы IT-компаний для обеспечения высокой производительности при реализации проектов.

Envoy под перегрузкой LLM API: circuit breakers, backpressure и overload manager
DevOps

Envoy под перегрузкой LLM API: circuit breakers, backpressure и overload manager

Production-runbook для Envoy перед LLM API: как локализовать перегрузку, настроить circuit breakers, overload manager, backpressure, canary и rollback.