← Назад к вопросам
Network Policy в Kubernetes
3.0 Senior🔥 111 комментариев
#Kubernetes
Условие
В кластере Kubernetes есть три namespace: frontend, backend, database.
Требования к сетевой изоляции
- Поды в namespace
frontendмогут обращаться только к подам вbackendна порт 8080 - Поды в namespace
backendмогут обращаться кdatabaseна порт 5432 - Поды в namespace
databaseне могут инициировать соединения наружу - Весь остальной трафик между namespace запрещен
Задача
Напишите NetworkPolicy для каждого namespace.
Вопросы
- Какой CNI plugin поддерживает NetworkPolicy?
- Что происходит, если NetworkPolicy не определена?
- Как отладить проблемы с сетевой политикой?
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение
1. Диаграмма сетевой архитектуры
Frontend (namespace)
↓
└─→ Backend:8080 (namespace)
↓
└─→ Database:5432 (namespace)
(no outbound allowed)
Правила:
1. frontend → backend:8080 ✓
2. frontend → database ✗
3. backend → database:5432 ✓
4. backend → frontend ✗
5. database → backend ✗
6. database → frontend ✗
7. Весь остальной трафик ✗
2. NetworkPolicy для Namespace Backend
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-network-policy
namespace: backend
spec:
podSelector: {} # Применяется ко всем подам в namespace
policyTypes:
- Ingress
- Egress
# INGRESS - входящий трафик (кто может подключиться к backend)
ingress:
# Разрешаем трафик только из frontend на порт 8080
- from:
- namespaceSelector:
matchLabels:
name: frontend
ports:
- protocol: TCP
port: 8080
# Разрешаем DNS запросы (для kube-dns/coredns)
- from:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53
# EGRESS - исходящий трафик (куда могут подключиться поды backend)
egress:
# Разрешаем подключение к database на порт 5432
- to:
- namespaceSelector:
matchLabels:
name: database
ports:
- protocol: TCP
port: 5432
# Разрешаем DNS запросы
- to:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53
# Разрешаем выход наружу кластера (если нужно)
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 169.254.169.254/32 # AWS metadata endpoint
ports:
- protocol: TCP
port: 443
- protocol: TCP
port: 80
3. NetworkPolicy для Namespace Frontend
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend-network-policy
namespace: frontend
spec:
podSelector: {} # Применяется ко всем подам
policyTypes:
- Ingress
- Egress
# INGRESS - входящий трафик
ingress:
# Разрешаем входящий трафик на порт 80 (HTTP) и 443 (HTTPS) из интернета
- from:
- ipBlock:
cidr: 0.0.0.0/0
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
# Разрешаем DNS запросы
- from:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53
# EGRESS - исходящий трафик
egress:
# Разрешаем подключение только к backend:8080
- to:
- namespaceSelector:
matchLabels:
name: backend
ports:
- protocol: TCP
port: 8080
# Разрешаем DNS запросы
- to:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53
# Разрешаем выход в интернет (для CDN, API, и т.д.)
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 169.254.169.254/32
- 10.0.0.0/8 # Запрещаем обращение в другие подсети кластера
ports:
- protocol: TCP
port: 443
- protocol: TCP
port: 80
4. NetworkPolicy для Namespace Database
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: database-network-policy
namespace: database
spec:
podSelector: {} # Применяется ко всем подам
policyTypes:
- Ingress
- Egress
# INGRESS - входящий трафик
ingress:
# Разрешаем подключение только из backend на порт 5432
- from:
- namespaceSelector:
matchLabels:
name: backend
ports:
- protocol: TCP
port: 5432
# Разрешаем трафик из database namespace (для replica sets, sharding)
- from:
- namespaceSelector:
matchLabels:
name: database
ports:
- protocol: TCP
port: 5432
- protocol: TCP
port: 5433
# Разрешаем DNS запросы
- from:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53
# EGRESS - исходящий трафик (ОЧЕНЬ ОГРАНИЧЕН)
egress:
# Разрешаем только DNS запросы
- to:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53
# Разрешаем трафик внутри database namespace (для репликации)
- to:
- namespaceSelector:
matchLabels:
name: database
ports:
- protocol: TCP
port: 5432
- protocol: TCP
port: 5433
# ОПЦИОНАЛЬНО: разрешаем backup/replication на специальный сервер
# Раскомментируйте если нужно
# - to:
# - podSelector:
# matchLabels:
# app: backup-server
# ports:
# - protocol: TCP
# port: 9102
5. Namespace Labels (предварительные настройки)
# Перед применением NetworkPolicy нужно добавить labels к namespaces
# Label для frontend namespace
kubectl label namespace frontend name=frontend
# Label для backend namespace
kubectl label namespace backend name=backend
# Label для database namespace
kubectl label namespace database name=database
# Label для kube-system (обычно уже есть)
kubectl label namespace kube-system name=kube-system
# Проверка labels
kubectl get namespaces --show-labels
6. Применение NetworkPolicy
# Применяем политики
kubectl apply -f frontend-network-policy.yaml
kubectl apply -f backend-network-policy.yaml
kubectl apply -f database-network-policy.yaml
# Проверка примененных политик
kubectl get networkpolicy -A
# Просмотр конкретной политики
kubectl describe networkpolicy backend-network-policy -n backend
# Удаление политики (если нужно отменить)
kubectl delete networkpolicy backend-network-policy -n backend
7. Альтернативная версия с Pod Selectors
# Если вы хотите контролировать трафик между конкретными подами
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-from-frontend
namespace: backend
spec:
podSelector:
matchLabels:
tier: api # Применяется только к подам с меткой tier=api
policyTypes:
- Ingress
ingress:
# Разрешаем только из frontend подов с label tier=web
- from:
- namespaceSelector:
matchLabels:
name: frontend
podSelector:
matchLabels:
tier: web
ports:
- protocol: TCP
port: 8080
8. Какой CNI plugin поддерживает NetworkPolicy?
Поддерживающие CNI plugins
✅ Поддерживают NetworkPolicy:
- Calico — самый популярный и мощный
- Cilium — ebpf-based, высокопроизводительный
- Weave — простой, встроенная поддержка
- Kube-router — высокопроизводительный
- Azure CNI (для Azure)
- GKE встроено (Google Kubernetes Engine)
- AWS VPC CNI (с определенными ограничениями)
❌ НЕ поддерживают NetworkPolicy:
- Flannel — не поддерживает
- kubenet — не поддерживает
Проверка установленного CNI
# Посмотреть какой CNI используется
kubectl get pods -n kube-system | grep -E "calico|cilium|weave|kube-router"
# Проверить конфигурацию kubelet
ps aux | grep kubelet | grep "--cni-bin-dir"
# Проверить CNI plugin на ноде
ls /opt/cni/bin/
Установка Calico (если не установлен)
# Установка Calico
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.0/manifests/tigera-operator.yaml
kubectl apply -f - <<EOF
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
name: default
spec:
calicoNetwork:
ipPools:
- blockSize: 26
cidr: 192.168.0.0/16
encapsulation: VXLan
natOutgoing: Enabled
nodeSelector: all()
EOF
# Проверка установки
kubectl get tigerastatus
9. Что происходит, если NetworkPolicy не определена?
Поведение без NetworkPolicy
# Без NetworkPolicy:
# - По умолчанию ВСЕ подсети имеют доступ ко ВСЕМ подам
# - Нет ограничений на исходящий трафик
# - Это опасно для production!
# Пример: Без политик
frontend pod → backend pod # ✓ Разрешено
frontend pod → database pod # ✓ Разрешено
backend pod → frontend pod # ✓ Разрешено (!!)
database pod → frontend pod # ✓ Разрешено (!!)
Поведение С NetworkPolicy
# С NetworkPolicy:
# - ЗАПРЕЩЕН весь трафик по умолчанию
# - Разрешен ТОЛЬКО указанный трафик
# - Это "белый список" вместо "черного списка"
# Пример: С политиками (как выше)
frontend pod → backend pod # ✓ Разрешено (ingress rule)
frontend pod → database pod # ✗ Запрещено
backend pod → frontend pod # ✗ Запрещено (нет ingress)
database pod → frontend pod # ✗ Запрещено (нет egress)
Принцип работы
# Если вы ОПРЕДЕЛЯЕТЕ policyTypes: [Ingress]
# То ВСЕ входящие соединения ЗАПРЕЩЕНЫ
# КРОМЕ явно разрешенных в ingress rules
# Если вы ОПРЕДЕЛЯЕТЕ policyTypes: [Egress]
# То ВСЕ исходящие соединения ЗАПРЕЩЕНЫ
# КРОМЕ явно разрешенных в egress rules
# Если вы НЕ определяете NetworkPolicy
# То все соединения РАЗРЕШЕНЫ (небезопасно!)
10. Отладка проблем с NetworkPolicy
Шаг 1: Проверить применена ли политика
# Проверить существование политик
kubectl get networkpolicy -n backend
# Просмотр деталей
kubectl describe networkpolicy backend-network-policy -n backend
# Просмотр в JSON формате
kubectl get networkpolicy backend-network-policy -n backend -o yaml
Шаг 2: Проверить CNI plugin
# Убедиться что CNI поддерживает NetworkPolicy
kubectl get pods -n kube-system | grep calico
# Если Calico нет - установить
kubectl apply -f calico-install.yaml
# Проверить что Calico работает
kubectl get pods -n calico-system
Шаг 3: Проверить labels на namespaces
# Убедиться что namespace имеет нужный label
kubectl get namespace frontend --show-labels
# Если label отсутствует - добавить
kubectl label namespace frontend name=frontend
Шаг 4: Проверить connectivity вручную
# Создать тестовые поды
kubectl run test-frontend --image=busybox --rm -it -n frontend -- sh
kubectl run test-backend --image=busybox --rm -it -n backend -- sh
kubectl run test-db --image=busybox --rm -it -n database -- sh
# Внутри пода frontend пытаемся подключиться к backend
wget http://test-backend.backend:8080
# Должно работать ✓
# Пытаемся подключиться к database
wget http://test-db.database:5432
# Должно НЕ работать ✗ (timeout или refused)
# Используем curl для тестирования
curl -v http://backend-svc.backend:8080/health
Шаг 5: Проверить DNS
# Убедиться что DNS работает
kubectl run -it --rm debug --image=nicolaka/netshoot -n backend -- sh
# Внутри контейнера
nslookup test-frontend.frontend
nslookup test-backend.backend
Шаг 6: Проверить Calico Rules
# Просмотр calico правил на ноде
kubectl exec -it $(kubectl get pod -n calico-system -l k8s-app=calico-node -o jsonpath='{.items[0].metadata.name}') -n calico-system -- calicoctl get networkpolicy
# Просмотр подробных правил
kubectl exec -it $(kubectl get pod -n calico-system -l k8s-app=calico-node -o jsonpath='{.items[0].metadata.name}') -n calico-system -- calicoctl get networkpolicy -o yaml
Шаг 7: Мониторинг с помощью tcpdump
# На ноде где работает под
sudo tcpdump -i any -n 'port 8080'
# Или внутри пода (если есть сетевой namespace)
kubectl exec -it <pod_name> -n backend -- tcpdump -i any -n 'port 8080'
Шаг 8: Проверить iptables rules (если используется iptables mode)
# На ноде
sudo iptables -L -n -v | grep backend
# Или через Calico
kubectl exec -it <calico-node-pod> -n calico-system -- iptables -L -n
Практический пример отладки
#!/bin/bash
# Скрипт для диагностики NetworkPolicy
echo "1. Проверка NetworkPolicy"
kubectl get networkpolicy -A
echo ""
echo "2. Проверка labels"
kubectl get namespaces --show-labels
echo ""
echo "3. Проверка CNI"
kubectl get pods -n kube-system | grep calico
echo ""
echo "4. Проверка connectivity"
POD_FRONTEND=$(kubectl get pod -n frontend -l app=web -o jsonpath='{.items[0].metadata.name}')
echo "Пытаемся подключиться из frontend к backend:8080"
kubectl exec -it $POD_FRONTEND -n frontend -- curl -v http://backend-svc.backend:8080
echo ""
echo "5. Если не работает, проверить логи"
kubectl logs -n calico-system -l k8s-app=calico-node --tail=50
11. Лучшие практики
# 1. Определяйте политики с "белым списком"
# Всегда запрещайте по умолчанию, разрешайте только нужное
# 2. Используйте labels для организации
kubectl label pod myapp -n backend tier=api version=v1
# 3. Тестируйте политики перед production
# Используйте staging namespace
# 4. Документируйте правила
# Добавьте комментарии и описания
# 5. Мониторьте трафик
# Используйте инструменты вроде Cilium Hubble
# 6. Регулярно аудитируйте политики
# Проверяйте что они еще необходимы