Cilium NetworkPolicy: default-deny и DNS-aware правила

Published: 2026-03-27

В k3s с Cilium работает стандартный Kubernetes NetworkPolicy, но CiliumNetworkPolicy умеет больше: L7 HTTP-правила, egress по DNS-именам и кластерные политики через CiliumClusterwideNetworkPolicy.


Default deny

Начните с политики запрета всего входящего трафика в namespace. Без неё каждый под может обращаться к любому другому поду в любом namespace.

yamlapiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: dev
spec:
  podSelector: {}
  policyTypes:
    - Ingress

Применяйте её в каждом прикладном namespace. Запрещён только ingress — egress по умолчанию разрешён.

Для полной изоляции добавьте запрет egress:

yamlspec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

Затем добавьте явные правила egress для DNS и других нужных сервисов.


Разрешить ingress от APISIX

После default-deny сервисам нужны явные правила:

yamlapiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-apisix-ingress
  namespace: dev
spec:
  podSelector:
    matchLabels:
      expose: "true"
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: ingress-apisix

Сервисы, доступные снаружи, получают метку expose: "true". Остальные изолированы.


Взаимодействие между сервисами

yamlapiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: dev
spec:
  podSelector:
    matchLabels:
      app: backend
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - port: 8080

CiliumNetworkPolicy для DNS-based egress

Стандартный NetworkPolicy выбирает только по IP. CiliumNetworkPolicy поддерживает FQDN:

yamlapiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-external-apis
  namespace: dev
spec:
  endpointSelector:
    matchLabels:
      app: backend
  egress:
    - toFQDNs:
        - matchName: "api.some-external-service.com"
      toPorts:
        - ports:
            - port: "443"
              protocol: TCP
    - toEndpoints:
        - matchLabels:
            "k8s:io.kubernetes.pod.namespace": kube-system
            "k8s:k8s-app": kube-dns
      toPorts:
        - ports:
            - port: "53"
              protocol: UDP
          rules:
            dns:
              - matchPattern: "*"

Правило DNS должно явно разрешать порт 53 на kube-dns — иначе FQDN-правила не смогут резолвить имена.


L7 HTTP-правила

yamlapiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: api-http-policy
  namespace: dev
spec:
  endpointSelector:
    matchLabels:
      app: api
  ingress:
    - fromEndpoints:
        - matchLabels:
            app: frontend
      toPorts:
        - ports:
            - port: "8080"
              protocol: TCP
          rules:
            http:
              - method: GET
                path: /api/v1/.*
              - method: POST
                path: /api/v1/orders

L7-правила требуют HTTP-прокси Cilium (Envoy). На L7 Cilium может логировать совпавшие запросы в Hubble UI.


Кластерная политика для Prometheus

Вместо добавления правил в каждый namespace:

yamlapiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: allow-prometheus-scrape
spec:
  endpointSelector: {}
  ingress:
    - fromEndpoints:
        - matchLabels:
            "k8s:io.kubernetes.pod.namespace": observability
            app.kubernetes.io/name: prometheus
      toPorts:
        - ports:
            - port: "9090"
              protocol: TCP
            - port: "9100"
              protocol: TCP
            - port: "8080"
              protocol: TCP

Одна политика — и Prometheus собирает метрики во всех namespace.


Проверка через Hubble

bash# Отброшенные потоки в реальном времени
hubble observe --namespace dev --verdict DROPPED -f

# Политики для конкретного пода
hubble observe --pod dev/api-6d8b4c5f9-xk4qv -f

# Потоки на конкретный порт
hubble observe --namespace dev --port 5432 -f

Чеклист отладки

  1. hubble observe --verdict DROPPED — что блокируется
  2. Проверить метки namespace — namespaceSelector использует метки namespace
  3. Проверить метки подов — при неправильной метке политика не сработает
  4. DNS egress требует явного порта 53 на kube-dns перед любыми FQDN-правилами
  5. L7-правила требуют включённого Envoy proxy