Сетевые политики Cilium

Обзор

Сетевые политики Cilium ограничивают, какой трафик может приходить в поды (Ingress) и уходить из подов (Egress). Без политик весь трафик разрешён. После добавления хотя бы одной политики для неймспейса или пода действует принцип «запрещено всё, что не разрешено явно».

Где настраивать: Сетевые политики в разделе сетей кластера или АдминистрированиеКастомные ресурсы. Политики можно создавать через графический интерфейс или импорт манифеста.

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

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


Важно: как работают политики

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

Ситуация Результат
В неймспейсе нет сетевых политик Весь трафик разрешён (входящий и исходящий)
В неймспейсе есть хотя бы одна политика Разрешён только трафик, явно описанный в правилах. Всё остальное блокируется

Обратите внимание! Частая ошибка: Добавили политику «разрешить Ingress» и забыли разрешить DNS. Поды перестали резолвить имена — приложение «сломалось». Всегда добавляйте все нужные правила в одной политике или несколькими политиками.

Что такое endpointSelector

endpointSelector определяет, к каким подам применяется политика:

  • endpointSelector: {} — ко всем подам в неймспейсе (пустой селектор = все поды)
  • endpointSelector: { matchLabels: { app: my-app } } — только к подам с лейблом app=my-app

Политика с endpointSelector: {} и правилами ingress/egress задаёт, какой трафик разрешён для выбранных подов. Всё, что не попало в правила, блокируется.


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

Тип Применение Когда использовать
ClusterwideCiliumNetworkPolicy Ко всему кластеру Общие правила (например, доступ к DNS для всех)
CiliumNetworkPolicy К одному неймспейсу Изоляция конкретного приложения

Рекомендация для начала: Используйте неймспейсные политики (CiliumNetworkPolicy). Они проще и не затрагивают весь кластер.

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

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

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

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


Ключевые понятия

Ingress (входящий трафик)

Кто может подключаться к вашим подам:

  • Вне кластера — пользователи, внешние сервисы, Ingress Controller
  • Внутри кластера — поды из других неймспейсов
  • Внутри неймспейса — поды из того же неймспейса

Egress (исходящий трафик)

Куда ваши поды могут подключаться от:

  • Вне кластера — внешние API, интернет (по IP или FQDN)
  • Внутри кластера — Kubernetes DNS, KubeAPI, другие поды и сервисы
  • Внутри неймспейса — поды и сервисы в том же неймспейсе

matchLabels

Селектор по лейблам подов. Пример:

matchLabels:
  app.kubernetes.io/name: my-backend
  io.kubernetes.pod.namespace: my-app

Правило применяется только к подам, у которых есть все указанные лейблы. Посмотреть лейблы пода: kubectl get pod <name> -n <ns> --show-labels.


Пошаговая настройка: веб-приложение с Ingress

Типичный сценарий: приложение в неймспейсе my-app, доступно извне через Ingress.

Шаг 1. Определите, какой трафик нужен

Направление Кто/куда Зачем
Ingress От Ingress Controller Пользователи заходят через браузер
Egress К Kubernetes DNS Резолв имён (Service, внешние домены)
Egress (опционально) К KubeAPI Нужно только операторам, контроллерам

Шаг 2. Узнайте лейблы Ingress Controller

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

Обычно: app.kubernetes.io/name: shturval-ingress-controller, io.kubernetes.pod.namespace: ingress.

Шаг 3. Создайте политику

Одна политика с всеми нужными правилами:

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: my-app-policy
  namespace: my-app
spec:
  description: "Web app: Ingress from controller + DNS"
  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

Что делает эта политика:

  • endpointSelector: {} — применяется ко всем подам в my-app
  • ingress — разрешает входящий трафик только от Ingress Controller
  • egress — разрешает исходящий трафик к kube-dns и shturval-caching-dns (DNS)

Шаг 4. Проверьте

# Приложение отвечает
curl -H "Host: app.example.com" http://<INGRESS_IP>/

# Поды в Running
kubectl get pods -n my-app

Если приложение перестало работать — см. Траблшутинг.


Типичные сценарии

Сценарий 1: Frontend + Backend в одном неймспейсе

Frontend принимает трафик от Ingress, ходит в Backend по имени Service.

Нужно разрешить:

  • Ingress: от Ingress Controller
  • Egress: DNS, трафик к Backend (по лейблам или toEndpoints: [{}] внутри неймспейса)

Сценарий 2: Backend вызывает внешний API

Backend обращается к https://api.external.com.

Нужно разрешить:

  • Egress: DNS (обязательно для FQDN)
  • Egress: до CIDR или FQDN внешнего API (по IP или домену)

Сценарий 3: Backend только для внутренних подов

Backend не должен быть доступен извне, только из других подов кластера.

Нужно разрешить:

  • Ingress: от конкретных неймспейсов или подов (по лейблам)
  • Egress: DNS, при необходимости — к другим сервисам

Сценарий 4: Оператор или контроллер

Поды, которым нужен доступ к KubeAPI (например, операторы).

Нужно разрешить:

  • Egress: toEntities: [kube-apiserver]
  • Egress: DNS (если нужно)

Примеры с пояснениями

Доступ к KubeAPI-серверу

Для подов, которым нужен доступ к API Kubernetes (операторы, контроллеры):

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

toEntities: [kube-apiserver] — специальный селектор Cilium для API-сервера кластера.


Запрещающая политика (deny-all)

Блокирует весь трафик в неймспейсе. Используйте осторожно, только если нужна полная изоляция.

Скриншот: deny-all в редакторе

Запрещающая политика deny-all

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

ingress: [{}] и egress: [{}] — пустые правила означают «ничего не разрешать».


Исходящий трафик к KubeDNS и NodeLocalDNS

Обязательно для подов, которые обращаются по имени (Service, FQDN):

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-dns
  namespace: yournamespacename
spec:
  description: "For endpoints in this namespace, 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

Порт 9153 — метрики CoreDNS; 9253 — shturval-caching-dns. Без них DNS может работать нестабильно.


Исходящий трафик к определённому приложению

Разрешить подам в неймспейсе ходить только в конкретный backend:

Скриншот: allow-egress в редакторе

Исходящий трафик к приложению

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-egress
  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

Замените backend, api, 8080 на реальные неймспейс, имя приложения и порт. Не забудьте добавить правило для DNS, если backend указывается по имени Service.


Входящий трафик из Ingress-контроллера

Обязательно для приложений, доступных извне через Ingress:

Скриншот: allow-ingress в редакторе

Входящий трафик из Ingress

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

Без этого правила запросы от пользователей не дойдут до подов приложения.


Трафик внутри неймспейса

Разрешить подам в неймспейсе общаться друг с другом:

Скриншот: allow-in-namespace в редакторе

Трафик внутри неймспейса

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

fromEndpoints: [{}] и toEndpoints: [{}] — «любые поды в том же неймспейсе».


Полный пример: приложение с Ingress, DNS и внутренним API

Веб-приложение my-app в неймспейсе my-app: доступ извне через Ingress, внутри ходит в Redis по имени Service.

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: my-app-full
  namespace: my-app
spec:
  description: "Web app: Ingress + DNS + Redis in same namespace"
  endpointSelector: {}
  ingress:
    - fromEndpoints:
        - matchLabels:
            app.kubernetes.io/name: shturval-ingress-controller
            io.kubernetes.pod.namespace: ingress
  egress:
    # DNS — обязательно
    - 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
    # Redis в том же неймспейсе
    - toEndpoints:
        - matchLabels:
            app: redis
      toPorts:
        - ports:
            - port: "6379"
              protocol: TCP

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

Ошибка Что происходит Решение
Забыли разрешить DNS Поды не резолвят имена, приложение не работает Добавить egress к kube-dns и shturval-caching-dns
Забыли разрешить Ingress Пользователи не могут зайти через браузер Добавить ingress от shturval-ingress-controller
Указали только один порт DNS Резолв может работать нестабильно Добавить порты 53 (UDP/TCP), 9153, 9253
Неправильные лейблы в matchLabels Правило не срабатывает Проверить kubectl get pod ... --show-labels
Применили deny-all без разрешающих правил Всё заблокировано Сначала добавить все нужные разрешения, потом при необходимости deny-all

Проверка после настройки

  1. Поды запущены: kubectl get pods -n <namespace>
  2. Приложение отвечает: curl или браузер по URL
  3. Логи приложения: kubectl logs -n <namespace> <pod>
  4. Cilium: при проблемах — Траблшутинг

Подробнее о подходах к настройке — Справочная информация.