NetworkPolicy: кто с кем может общаться
Как правилами по меткам закрыть Pod от лишнего трафика и где прячется ошибка с одним дефисом.
Что такое NetworkPolicy
NetworkPolicy - объект Kubernetes, который задаёт правила сетевого трафика между Pod. Pod - наименьшая единица, которую запускает Kubernetes; внутри Pod работает один или несколько контейнеров. NetworkPolicy работает как файрвол, но выбирает Pod по их меткам (labels), а не по IP-адресам.
Сам объект NetworkPolicy ничего не блокирует. Правила применяет CNI-плагин (Container Network Interface, компонент кластера, отвечающий за сеть Pod). Calico, Cilium и Kube-router умеют NetworkPolicy, а вот у простых плагинов вроде flannel такой поддержки нет: там правила создаются в API и молча игнорируются. Проверять эффект политики нужно именно на том кластере, где она будет работать.
По умолчанию разрешено всё
Если в namespace нет ни одной NetworkPolicy, трафик открыт. Любой Pod ходит куда угодно. namespace - область внутри кластера, которая отделяет одни объекты от других.
Как только на Pod вешают NetworkPolicy, для него включается правило: запрещено всё, что явно не разрешено. После этого в политике перечисляют, какой трафик пропускать.
Анатомия манифеста
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: web-only-from-allowed
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
role: allowed
ports:
- protocol: TCP
port: 8080
podSelector - к каким Pod применяются правила. Здесь это Pod с меткой
app: web. Пустой {} означает все Pod в namespace.
policyTypes - какой трафик регулирует политика. Ingress - входящий
трафик, Egress - исходящий. Можно указать один тип или оба.
ingress.from - откуда разрешён входящий трафик. Источник задают через
podSelector (Pod с такими метками), namespaceSelector (Pod из
namespace с такими метками) или ipBlock (диапазон IP).
ports - какие порты открыты. Без этого блока открыты все порты.
AND и OR в селекторах
Внутри одного элемента списка from селекторы связаны через AND. Pod с
такой меткой И в namespace с такой меткой. Разные элементы списка
связаны через OR.
AND - один элемент, два селектора (Pod с меткой role: allowed И в
namespace с меткой team: a):
ingress:
- from:
- podSelector:
matchLabels:
role: allowed
namespaceSelector:
matchLabels:
team: a
OR - два элемента (Pod с меткой role: allowed ИЛИ любой Pod из
namespace с меткой team: a):
ingress:
- from:
- podSelector:
matchLabels:
role: allowed
- namespaceSelector:
matchLabels:
team: a
Разница - один дефис. Это самая частая ошибка в NetworkPolicy.
Запись в from | Логика | Кто пройдёт |
|---|---|---|
| два селектора в одном элементе списка | AND | Pod с меткой role: allowed из namespace team: a |
| два отдельных элемента списка | OR | Pod с меткой role: allowed или любой Pod из team: a |
Проверка эффекта
Самый надёжный способ проверить политику - попробовать подключиться с
двух сторон. Для примера рядом с Pod web держат два клиента:
client-allowed с меткой role: allowed и client-blocked с меткой
role: blocked.
# Из разрешённого клиента
kubectl exec client-allowed -- nc -zv -w 2 web 8080
# connection succeeded
# Из заблокированного
kubectl exec client-blocked -- nc -zv -w 2 web 8080
# timeout
Разрешённый клиент подключится, заблокированный зависнет до таймаута и упадёт. Обратите внимание на порт: политика открывает 8080, поэтому и проверяют 8080, а не 80.
Разобраться, что именно применилось, помогают три команды:
# Список политик в namespace
kubectl get networkpolicy
# Как политика разложена на селекторы и порты
kubectl describe networkpolicy web-only-from-allowed
# Метки Pod, чтобы понимать, что ловит matchLabels
kubectl get pods --show-labels
Домашка
Теорию закрепляет задание на своём кластере: 2 шага с проверкой. Кластер поднимается по треку Kubernetes локально, задания лежат в репозитории k8s-practice.
./run.sh start k8s-network-policy # развернуть стартовое состояние
./run.sh verify k8s-network-policy # проверить текущий шаг
Коротко
- NetworkPolicy выбирает Pod по меткам, а не по IP, и живёт внутри одного namespace.
- Пока политик нет, трафик открыт. Первая же политика переводит выбранные Pod в режим «запрещено всё, кроме перечисленного».
- Правила применяет CNI-плагин. Без поддержки на стороне плагина объект создаётся, но ничего не фильтрует.
- Селекторы внутри одного элемента
fromработают как AND, разные элементы списка - как OR. Разница в одном дефисе. - Без блока
portsоткрыты все порты выбранных Pod.
Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс