NetworkPolicy закрыла исходящий трафик: как сохранить DNS и нужные подключения

Команда ограничила исходящий трафик API, после чего запросы к базе стали падать с ошибкой разрешения имени. Причина может быть двойной: закрыт доступ к DNS и отдельно закрыто соединение с самой базой. Разрешение только порта PostgreSQL не поможет приложению, которое сначала должно получить IP по имени. Построим политику вокруг этих двух действий.

Определяем, к каким Pod применяется запрет

kubectl -n demo get networkpolicy -o yaml
kubectl -n demo get pods --show-labels
kubectl -n kube-system get pods --show-labels

Сначала найдите политики, выбирающие проблемный Pod. NetworkPolicy действует через labels, а не имя Deployment. Для egress выбранный Pod становится изолированным, если хотя бы одна применимая политика содержит тип Egress. Разрешения всех применимых политик объединяются: более строгая новая политика не отменяет уже существующее широкое разрешение. Поэтому читать только последний созданный YAML недостаточно.

Убедитесь, что CNI действительно поддерживает NetworkPolicy. Kubernetes принимает объект политики и без реализации, которая применяет правила к пакетам. Успешный apply подтверждает сохранение конфигурации, а не блокировку трафика. Для проверки нужны соединения из выбранного Pod и контрольный запрещённый адрес.

Разрешаем DNS и одну базу

Пример предназначен для обычного DNS через Pod CoreDNS с меткой k8s-app: kube-dns в kube-system. База находится в namespace data и имеет app: postgres. Проверьте эти метки в своём кластере до применения. Оба selector внутри одного элемента to соединяются условием «и»:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-egress
  namespace: demo
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes: [Egress]
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: data
          podSelector:
            matchLabels:
              app: postgres
      ports:
        - protocol: TCP
          port: 5432

Если namespaceSelector и podSelector записать двумя отдельными элементами списка to, получится объединение двух групп адресатов: Pod нужного namespace плюс Pod с нужной меткой в namespace самой NetworkPolicy (здесь demo). Это шире задуманного пересечения. Отступы YAML в этом месте меняют сетевую границу, поэтому проверяйте структуру, а не только визуальное сходство строк.

DNS разрешён по UDP и TCP: некоторые ответы и повторные попытки используют TCP. Разрешение DNS не открывает доступ к IP, который вернулся в ответе. Для внешнего API обычная NetworkPolicy не умеет выбирать адресат по доменному имени; расширенные FQDN-правила отдельных CNI имеют собственную семантику. Не заменяйте меняющийся адрес облачного сервиса случайно записанным навсегда IP без плана обновления.

Проверяем точный путь приложения

kubectl -n demo exec api-example -- cat /etc/resolv.conf
kubectl -n demo exec api-example -- nslookup postgres.data.svc.cluster.local

Команда nslookup предполагает наличие утилиты в контейнере. Затем выполните штатный запрос приложения к базе или разрешённым диагностическим клиентом проверьте TCP 5432 и SQL. Успешное DNS-разрешение и успешная аутентификация PostgreSQL — разные этапы. Если у базы есть ingress-изоляция, она тоже должна разрешать трафик API: исходящее разрешение не отменяет входящий запрет назначения.

В кластерах с NodeLocal DNSCache nameserver может указывать на локальный адрес узла, а не обычный Service CoreDNS. Поведение политики вокруг node-трафика, DNAT Service и hostNetwork зависит от реализации. Сначала прочитайте реальный resolv.conf и схему DNS, затем адаптируйте правило по рекомендациям своего CNI. Иначе корректный по схеме YAML будет разрешать не тот путь, которым идут пакеты.

В тестовом namespace проверьте разрешённый DNS, нужную базу и запрещённое постороннее соединение. Если всё разрешено, найдите широкую дополнительную политику или отсутствие enforcement. Если всё запрещено, сопоставьте фактические labels и маршрутизацию. Сохраните структуру selectors вместе с результатами этих трёх проверок: так политика описывает проверенную границу приложения.

Ещё по теме

Продолжить изучение

Хотите увереннее разворачивать приложения и разбирать сбои в кластере? Сети, конфигурация, хранилища и обновления входят в программу «Kubernetes с нуля до PRO».

Продолжить на практике

  • Kubernetes с нуля до PRO ↗

    Разворачивайте и сопровождайте приложения в Kubernetes: от первого Pod до релизов, сетей, хранилищ, масштабирования и диагностики. Итоговый проект — сервис с базой данных, мониторингом и проверенным откатом.