Cilium Network Policies (сегментация сети)

Сегментация сети и контроль трафика в кластере с помощью Cilium Network Policies.

Введение

Cilium Network Policies — это механизм сегментации сети в Kubernetes-кластере на базе Cilium. Политики определяют, какой трафик разрешён между подами, неймспейсами, сервисами, узлами кластера и внешними адресами. Всё, что не разрешено политиками для выбранного направления, Cilium блокирует.

В платформе «Штурвал» сеть кластера обеспечивает Модуль управления сетями кластера (shturval-networking, Cilium CNI). Для управления политиками используются:

  • CiliumNetworkPolicy — неймспейсная политика Cilium;
  • CiliumClusterwideNetworkPolicy — кластерная политика Cilium;
  • Kubernetes NetworkPolicy — стандартная политика Kubernetes с меньшим набором возможностей.

Официальная документация Cilium описывает эти форматы в разделе Network Policy и общий язык политик в разделе Overview of Network Policy.


Когда использовать

Используйте Cilium Network Policies, когда нужно:

  • изолировать приложения в разных неймспейсах;
  • разрешить доступ к приложению только от Ingress Controller или конкретных подов;
  • ограничить исходящий трафик приложения к DNS, KubeAPI, внутренним сервисам или внешним доменам;
  • описать правила на уровнях L3/L4: поды, неймспейсы, CIDR, entities, сервисы, порты и протоколы;
  • добавить L7-ограничения, например HTTP-метод и путь или DNS-имя;
  • явно запретить часть трафика с помощью deny-политик.

Где настраивать

В платформе доступны два основных способа настройки:

  • Графический интерфейс — в целевом кластере откройте раздел Администрирование кластера → Сетевые политики Cilium. В нём можно создавать, просматривать и изменять кластерные и неймспейсные политики, а также отслеживать их состояние. Графический редактор не отображает Kubernetes NetworkPolicy.
  • Манифесты — политики можно применять через импорт манифеста или через kubectl, если у пользователя есть необходимые права.

Для управления исходящим трафиком через выделенный egress-IP в платформе также есть отдельная страница Egress Gateway для ресурсов CiliumEgressGatewayPolicy. Это не замена CiliumNetworkPolicy: Egress Gateway управляет маршрутизацией исходящего трафика, а Cilium Network Policies управляют разрешением или запретом потоков.

Подробнее о работе в интерфейсе см. страницу Сетевые политики Cilium.

Скриншот: статус сетевой политики

Статус сетевой политики

Скриншот: редактор кластерных сетевых политик

Редактор кластерных сетевых политик

Скриншот: редактор неймспейсных сетевых политик

Редактор неймспейсных сетевых политик


Форматы политик

Формат Область действия Возможности Когда использовать
NetworkPolicy Неймспейс Стандартные Kubernetes-правила L3/L4 для ingress и egress Если достаточно стандартного Kubernetes API
CiliumNetworkPolicy Неймспейс Расширенные правила Cilium: L3-L7, entities, FQDN, HTTP/DNS, deny-правила Для изоляции приложения или неймспейса
CiliumClusterwideNetworkPolicy Весь кластер Та же спецификация, что у CiliumNetworkPolicy, но без metadata.namespace; дополнительно может использовать nodeSelector Для общих правил уровня кластера, например DNS или доступ к системным endpoints

Обратите внимание! Начинайте с неймспейсных CiliumNetworkPolicy. Кластерные политики затрагивают весь кластер, поэтому ошибка в селекторе или deny-правиле может повлиять на несколько приложений сразу.


Как Cilium применяет политики

Поведение по умолчанию

В режиме Cilium по умолчанию pod имеет неограниченный ingress и egress, пока его не выбрала политика. После этого для выбранного направления включается модель default deny:

Ситуация Поведение
Pod не выбран ни одной политикой Ingress и egress разрешены
Pod выбран политикой с секцией ingress Для ingress разрешён только трафик, который совпал с allow-правилами
Pod выбран политикой с секцией egress Для egress разрешён только трафик, который совпал с allow-правилами
Pod выбран политиками с ingress и egress Оба направления ограничены независимо

Политики Cilium работают по allowlist-модели: правило разрешает совпавший трафик, а несовпавший трафик отбрасывается в соответствии с режимом enforcement. Если несколько allow-правил применяются к одному pod, разрешается объединение всех совпавших правил.

Режимы enforcement

Cilium поддерживает три режима применения политик:

  • default — стандартный режим: endpoints не ограничены, пока их не выбрала политика;
  • always — политики включены для всех endpoints, даже если их не выбрали правила;
  • never — политики не применяются, даже если правила существуют.

В платформенной документации и примерах ниже предполагается стандартное поведение Cilium: без политик трафик разрешён, после выбора pod политикой разрешены только явно описанные потоки.

Allow и deny

Обычные секции ingress и egress разрешают трафик. Секции ingressDeny и egressDeny явно запрещают трафик и имеют приоритет над allow-правилами. Это значит, что deny-правило заблокирует совпавший поток даже тогда, когда другая политика его разрешает.

Ограничения deny-политик Cilium:

  • deny не поддерживает L7-запреты, например запрет конкретного HTTP URL;
  • deny не поддерживает toFQDNs, то есть запрет конкретного доменного имени через FQDN-правило.

Структура CiliumNetworkPolicy

Минимальная политика содержит apiVersion, kind, metadata и spec. В spec задаются селектор endpoints и правила ingress/egress:

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: example-policy
  namespace: app
spec:
  description: "Allow ingress from frontend to backend"
  endpointSelector:
    matchLabels:
      app: backend
  ingress:
    - fromEndpoints:
        - matchLabels:
            app: frontend

Ключевые поля:

Поле Назначение
metadata.name Имя политики в Kubernetes
metadata.namespace Неймспейс, к которому относится CiliumNetworkPolicy; у CiliumClusterwideNetworkPolicy поле не задаётся
spec.description Человекочитаемое описание назначения политики; Cilium не интерпретирует это поле
spec.endpointSelector Выбирает pods, к которым применяется политика
spec.nodeSelector Выбирает nodes; доступно только для CiliumClusterwideNetworkPolicy
spec.ingress Allow-правила для входящего трафика к выбранным endpoints
spec.egress Allow-правила для исходящего трафика от выбранных endpoints
spec.ingressDeny Deny-правила для входящего трафика
spec.egressDeny Deny-правила для исходящего трафика

Селекторы и неймспейсы

endpointSelector

endpointSelector выбирает pods, на которые распространяется политика. Селектор основан на Kubernetes LabelSelector.

Примеры:

# Все pods в неймспейсе политики
endpointSelector: {}
# Только pods с app.kubernetes.io/name=backend
endpointSelector:
  matchLabels:
    app.kubernetes.io/name: backend

Для CiliumNetworkPolicy селектор endpointSelector всегда применяется только внутри неймспейса, где создана политика. Указывать неймспейс в endpointSelector нельзя: это нарушило бы namespace isolation в Kubernetes.

fromEndpoints и toEndpoints

fromEndpoints выбирает источники ingress-трафика, а toEndpoints — назначения egress-трафика. В этих селекторах можно использовать label неймспейса pod:

fromEndpoints:
  - matchLabels:
      io.kubernetes.pod.namespace: frontend
      app.kubernetes.io/name: web

Если нужно разрешить трафик между неймспейсами, явно указывайте namespace label в fromEndpoints или toEndpoints. Без этого пустой селектор обычно означает endpoints в области действия политики, а не весь кластер.

Namespace labels

Cilium поддерживает выбор endpoints по лейблам неймспейса через labels вида io.cilium.k8s.namespace.labels.<label-name>. Это удобно, если нужно разрешить трафик не в конкретный неймспейс, а во все неймспейсы с заданной ролью, например env=prod или team=payments.


Уровни фильтрации

L3: источники и назначения

L3-правила определяют, какие endpoints или внешние адреса могут взаимодействовать. Cilium поддерживает несколько способов описания L3:

Способ Поля Для чего использовать
Endpoints fromEndpoints, toEndpoints Трафик между Cilium-managed pods по labels
Services toServices Egress к Kubernetes Service без ручного перечисления IP
Entities fromEntities, toEntities Специальные категории Cilium: world, cluster, host, remote-node, kube-apiserver и другие
Nodes fromNodes, toNodes, nodeSelector Трафик с учётом узлов кластера
CIDR fromCIDR, toCIDR, toCIDRSet Внешние сети со стабильными IP или подсетями
DNS/FQDN toFQDNs Внешние сервисы по DNS-имени

Обратите внимание! CIDR-правила зависят от стабильности IP-адресов. Для внешних сервисов с меняющимися IP чаще используйте toFQDNs вместе с правилом доступа к DNS.

L4: порты и протоколы

L4-правила ограничивают трафик по портам и протоколам через поле toPorts. Если L4-правило не задано, совпавший L3-трафик разрешается на всех портах и протоколах. Если L4-правило задано, разрешаются только указанные порты и протоколы.

Пример egress только на TCP-порт 443:

egress:
  - toFQDNs:
      - matchName: api.example.com
    toPorts:
      - ports:
          - port: "443"
            protocol: TCP

Cilium также поддерживает диапазоны портов через endPort. Для TLS-трафика можно ограничивать SNI через serverNames, если включено L7 proxy enforcement.

L7: HTTP, DNS и Kafka

L7-правила задаются внутри L4-правил. Cilium поддерживает:

  • HTTP — метод, путь, Host и заголовки;
  • DNS — matchName и matchPattern;
  • Kafka — правила Kafka находятся в beta/deprecated-статусе в документации Cilium и не рекомендуются для новых сценариев без отдельной проверки совместимости.

При нарушении L7-правила Cilium обычно возвращает ответ уровня приложения, например HTTP 403 или DNS REFUSED, а не просто отбрасывает пакет.

Пример HTTP-правила:

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-public-api
  namespace: app
spec:
  description: "Allow GET /public from frontend to backend"
  endpointSelector:
    matchLabels:
      app: backend
  ingress:
    - fromEndpoints:
        - matchLabels:
            app: frontend
      toPorts:
        - ports:
            - port: "80"
              protocol: TCP
          rules:
            http:
              - method: "GET"
                path: "/public$"

DNS и FQDN-политики

toFQDNs разрешает egress к внешним ресурсам по DNS-имени. Cilium получает IP-адреса для FQDN-правил из DNS-ответов, которые видит DNS proxy, и учитывает TTL DNS-записей.

Для FQDN-политик обычно нужны два egress-правила:

  1. Разрешить DNS-запросы к кластерному DNS.
  2. Разрешить подключение к домену через toFQDNs.

Пример: разрешить приложению ходить только к api.github.com:

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-api-github
  namespace: app
spec:
  description: "Allow egress to api.github.com and DNS"
  endpointSelector:
    matchLabels:
      app: mediabot
  egress:
    - toEndpoints:
        - matchLabels:
            io.kubernetes.pod.namespace: kube-system
            k8s-app: kube-dns
      toPorts:
        - ports:
            - port: "53"
              protocol: ANY
          rules:
            dns:
              - matchPattern: "*"
    - toFQDNs:
        - matchName: api.github.com
      toPorts:
        - ports:
            - port: "443"
              protocol: TCP

Особенности matchName и matchPattern:

  • matchName: api.github.com совпадает только с точным именем;
  • matchPattern: "*.github.com" совпадает с поддоменами, например support.github.com, но не с github.com;
  • matchPattern: "*" разрешает DNS-запросы к любым именам и добавляет IP из ответов в DNS cache Cilium.

Обратите внимание! Для DNS/L7-политик Cilium рекомендует перехватывать DNS-трафик только к доверенному кластерному DNS, например kube-dns. Если направить DNS proxy на недоверенный резолвер, он сможет влиять на IP-адреса, которые Cilium считает разрешёнными для toFQDNs.


Базовые сценарии

Разрешить доступ к KubeAPI

Для operators и controllers, которым нужен Kubernetes API, используйте entity kube-apiserver:

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-kube-apiserver
  namespace: operators
spec:
  description: "Allow egress to kube-apiserver"
  endpointSelector: {}
  egress:
    - toEntities:
        - kube-apiserver

Разрешить DNS в платформе

DNS нужен приложениям, которые обращаются к Kubernetes Service или внешним FQDN. В платформе обычно нужно разрешить egress к kube-dns и shturval-caching-dns:

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-dns
  namespace: app
spec:
  description: "Allow egress to kube-dns and shturval-caching-dns"
  endpointSelector: {}
  egress:
    - toEndpoints:
        - matchLabels:
            io.kubernetes.pod.namespace: kube-system
            k8s-app: kube-dns
      toPorts:
        - ports:
            - port: "53"
              protocol: UDP
            - port: "53"
              protocol: TCP
            - port: "9153"
              protocol: TCP
    - toEndpoints:
        - matchLabels:
            io.kubernetes.pod.namespace: kube-system
            app.kubernetes.io/name: shturval-caching-dns
      toPorts:
        - ports:
            - port: "53"
              protocol: UDP
            - port: "9253"
              protocol: TCP

Разрешить входящий трафик от Ingress Controller

Для приложения, опубликованного через Ingress, разрешите ingress от Ingress Controller:

Схема allow-ingress

Схема allow-ingress

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-ingress
  namespace: app
spec:
  description: "Allow ingress from ingress-controller"
  endpointSelector: {}
  ingress:
    - fromEndpoints:
        - matchLabels:
            app.kubernetes.io/name: shturval-ingress-controller
            io.kubernetes.pod.namespace: ingress

Разрешить egress к backend-приложению

Схема allow-egress

Схема allow-egress

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-egress-to-backend
  namespace: frontend
spec:
  description: "Allow egress to backend app only"
  endpointSelector: {}
  egress:
    - toEndpoints:
        - matchLabels:
            io.kubernetes.pod.namespace: backend
            app.kubernetes.io/name: api
      toPorts:
        - ports:
            - port: "8080"
              protocol: TCP

Если frontend обращается к backend по DNS-имени Service, добавьте отдельное правило для DNS.

Разрешить трафик внутри неймспейса

Схема allow-in-namespace

Схема allow-in-namespace

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-in-namespace
  namespace: app
spec:
  description: "Allow all traffic within namespace"
  endpointSelector: {}
  ingress:
    - fromEndpoints: [{}]
  egress:
    - toEndpoints: [{}]

Полная изоляция неймспейса

Такая политика переводит все pods в неймспейсе в default-deny для ingress и egress. Применяйте её только после того, как подготовили нужные разрешающие правила.

Схема deny-all

Схема deny-all

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: deny-all
  namespace: app
spec:
  description: "Deny all traffic in this namespace"
  endpointSelector: {}
  ingress:
    - {}
  egress:
    - {}

Явно запретить внешний ingress

Пример кластерной deny-политики: запретить ingress из entity world, но оставить остальной allow-трафик по другим правилам:

apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: external-lockdown
spec:
  description: "Deny ingress from world to all Cilium-managed endpoints"
  endpointSelector: {}
  ingressDeny:
    - fromEntities:
        - world
  ingress:
    - fromEntities:
        - all

Пошаговый пример: веб-приложение с Ingress и DNS

Сценарий: приложение my-app работает в неймспейсе my-app, доступно извне через Ingress Controller и использует DNS.

1. Определите нужные потоки

Направление Источник или назначение Зачем
Ingress Ingress Controller Пользователи заходят в приложение
Egress kube-dns и shturval-caching-dns Резолв Kubernetes Service и внешних имён
Egress, опционально kube-apiserver Только если приложение является operator/controller
Egress, опционально Внутренний backend или внешний FQDN Если приложение вызывает другие сервисы

2. Проверьте labels

Проверьте labels приложения:

kubectl get pods -n my-app --show-labels

Проверьте labels Ingress Controller:

kubectl get pods -n ingress -l app.kubernetes.io/name=shturval-ingress-controller --show-labels

3. Примените политику

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: my-app-policy
  namespace: my-app
spec:
  description: "Web app: ingress from controller and DNS egress"
  endpointSelector: {}
  ingress:
    - fromEndpoints:
        - matchLabels:
            app.kubernetes.io/name: shturval-ingress-controller
            io.kubernetes.pod.namespace: ingress
  egress:
    - toEndpoints:
        - matchLabels:
            io.kubernetes.pod.namespace: kube-system
            k8s-app: kube-dns
      toPorts:
        - ports:
            - port: "53"
              protocol: UDP
            - port: "53"
              protocol: TCP
            - port: "9153"
              protocol: TCP
    - toEndpoints:
        - matchLabels:
            io.kubernetes.pod.namespace: kube-system
            app.kubernetes.io/name: shturval-caching-dns
      toPorts:
        - ports:
            - port: "53"
              protocol: UDP
            - port: "9253"
              protocol: TCP

4. Проверьте работу

kubectl get ciliumnetworkpolicy -n my-app
kubectl get pods -n my-app
kubectl logs -n my-app <pod-name>

Проверьте доступ к приложению через Ingress. Если приложение перестало резолвить имена или отвечать на запросы, проверьте labels и наличие DNS-правил.


Типичные ошибки

Ошибка Что происходит Как исправить
Добавили ingress-политику и забыли DNS egress Приложение принимает входящий трафик, но не может резолвить имена Добавить egress к kube-dns и shturval-caching-dns
Не указали namespace label в fromEndpoints или toEndpoints Правило не совпадает с pod из другого неймспейса Добавить io.kubernetes.pod.namespace: <namespace>
Использовали кластерную политику вместо неймспейсной Правило затронуло больше приложений, чем ожидалось Для прикладных сценариев использовать CiliumNetworkPolicy
Смешали много policy types без схемы Итоговый allow-набор сложно понять Документировать назначение политики в description и группировать правила по приложениям
Применили deny-all до разрешающих правил Приложение потеряло входящий или исходящий доступ Сначала подготовить allow-правила, затем включать изоляцию
Использовали toFQDNs, но не разрешили DNS FQDN-правило не получает DNS-данные Добавить egress к кластерному DNS с rules.dns
Ожидали, что *.example.com разрешит example.com Домен верхнего уровня не совпал с wildcard-паттерном Добавить отдельный matchName: example.com
Указали только UDP/53 для DNS Часть DNS-запросов может не работать Разрешить UDP/53 и TCP/53, а для платформенных DNS-компонентов учесть нужные порты

Наблюдаемость и проверка

Для отладки сетевого трафика и политик можно включить Cilium Hubble. Hubble UI визуализирует сетевые потоки и помогает понять, какое правило разрешило или заблокировало соединение.

Инструкция по включению: Как включить Hubble UI.

Также используйте:

kubectl get ciliumnetworkpolicy -A
kubectl get ciliumclusterwidenetworkpolicy
kubectl describe ciliumnetworkpolicy -n <namespace> <policy-name>

При проблемах с сетевым взаимодействием см. Траблшутинг сетевого модуля.


Ссылки