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
Чеклист отладки
hubble observe --verdict DROPPED— что блокируется- Проверить метки namespace —
namespaceSelectorиспользует метки namespace - Проверить метки подов — при неправильной метке политика не сработает
- DNS egress требует явного порта 53 на kube-dns перед любыми FQDN-правилами
- L7-правила требуют включённого Envoy proxy