← Назад к вопросам

Network Policy в Kubernetes

3.0 Senior🔥 111 комментариев
#Kubernetes

Условие

В кластере Kubernetes есть три namespace: frontend, backend, database.

Требования к сетевой изоляции

  1. Поды в namespace frontend могут обращаться только к подам в backend на порт 8080
  2. Поды в namespace backend могут обращаться к database на порт 5432
  3. Поды в namespace database не могут инициировать соединения наружу
  4. Весь остальной трафик между 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. Регулярно аудитируйте политики
# Проверяйте что они еще необходимы