Learning Platform
Глоссарий Troubleshooting
Урок 11.02 · 28 мин
Продвинутый
NetworkPolicypodSelectornamespaceSelectoripBlockAND vs OR

Ingress и egress rules: как читать

После того как вы разобрались с podSelector и policyTypes, дальше всё держится на одном умении — правильно читать список правил. Здесь нет сложной семантики, но есть две конструкции, которые выглядят почти одинаково и означают противоположное. Их путают на CKAD чаще всего.


NAT: как роутер прячет внутренние IP за одним внешним

Структура одного rule

И ingress, и egress блоки — это списки rules. Каждый rule состоит из двух частей:

ingress:
- from:        # с какого направления разрешено
  - <peer>
  - <peer>
  ports:       # на какие порты разрешено
  - port: 8080
    protocol: TCP

egress:
- to:          # куда разрешено
  - <peer>
  - <peer>
  ports:       # на какие destination ports
  - port: 5432
    protocol: TCP

Каждый rule — это конъюнкция (AND) внутри себя:

разрешён трафик, который идёт от одного из перечисленных peers И на один из перечисленных ports

Между разными rules в списке — disjunction (OR):

трафик разрешён, если он matches rule #1 ИЛИ rule #2 ИЛИ …

Это удобно, потому что разрешения можно дробить: «от web на :80» и «от monitoring на :9100» — два отдельных rules, каждый со своим набором портов.


Peers: podSelector, namespaceSelector, ipBlock

«Peer» — это описание стороны, с которой (для ingress) или к которой (для egress) разрешён трафик. Три типа peers:

Типы peers в NetworkPolicy
podSelectorLabel selector для Pods в ТОМ ЖЕ namespace, что и NetworkPolicy. Если внутри peer объекта НЕТ namespaceSelector, поиск ограничен namespace policy. Это базовый peer для in-namespace правил.
namespaceSelectorLabel selector для namespaces. Matches ВСЕ Pods во всех namespaces, у которых labels namespace matches. Если без podSelector — это полный namespace.
ipBlockCIDR блок IP. Используется для внешнего трафика (egress в Internet) или для специфичных IP cluster nodes. Внутри cluster обычно бесполезен — Pod IP эфемерны.

podSelector

Внутри from или to, без namespaceSelector рядом, podSelector matches Pods в namespace policy (там, где NetworkPolicy создана):

ingress:
- from:
  - podSelector:
      matchLabels:
        app: web

«Разрешён ingress от Pods с label app=web в этом же namespace». Pods с тем же label в другом namespace не подходят.

namespaceSelector

ingress:
- from:
  - namespaceSelector:
      matchLabels:
        team: backend

«Разрешён ingress от всех Pods в любом namespace, который имеет label team=backend». Если в кластере несколько namespaces с этим label — все они matchятся.

Очень полезная вещь: с Kubernetes 1.22+ kubelet автоматически добавляет к каждому namespace label kubernetes.io/metadata.name: <namespace-name>. Это позволяет матчить namespace по имени без необходимости вручную лейблить его:

- namespaceSelector:
    matchLabels:
      kubernetes.io/metadata.name: monitoring

ipBlock

egress:
- to:
  - ipBlock:
      cidr: 0.0.0.0/0
      except:
      - 10.0.0.0/8
      - 169.254.169.254/32

«Разрешён egress в любой IPv4-адрес, КРОМЕ 10.0.0.0/8 и метаданных AWS». Используется для разрешения Internet с одновременным запретом внутренних сетей.

NOTE

ipBlock matches на IP назначения трафика. Это значит, что egress в ClusterIP Service срабатывает на IP бэкенд-Pod, а не на ClusterIP. Это потому что kube-proxy подменяет ClusterIP на PodIP через DNAT раньше, чем policy enforcement видит пакет. Учитывайте это при написании egress правил.


AND vs OR: главная ловушка

Внутри from (или to) можно перечислить несколько peers. И вот здесь — самая частая ошибка CKAD.

OR между peers в списке
from:Список из двух элементов peer. Каждый элемент — отдельный peer. Между ними OR.
peer #1: namespaceSelectorПервый peer — namespace selector. Сам по себе matches все Pods в matching namespaces.
peer #2: podSelectorВторой peer — pod selector. Сам по себе matches Pods в namespace policy с label.
OR
effectiveЛюбой Pod, который или в нужном namespace, или с нужным label в текущем ns — matchится.
# OR: matches Pods в namespace с label team=backend
# ИЛИ Pods в этом же ns с label app=web
ingress:
- from:
  - namespaceSelector:
      matchLabels:
        team: backend
  - podSelector:
      matchLabels:
        app: web
AND внутри одного peer
from:Список из ОДНОГО элемента peer.
peer #1: оба поляОДИН peer объект, у которого внутри И namespaceSelector, И podSelector. Между полями peer объекта — AND.
AND
effectivePod должен быть В namespace с нужным label И иметь нужный pod label. Гораздо более restrictive.
# AND: matches только Pods, которые И в namespace team=backend
# И имеют label app=web
ingress:
- from:
  - namespaceSelector:
      matchLabels:
        team: backend
    podSelector:
      matchLabels:
        app: web
DANGER

Различие — наличие или отсутствие дефиса перед podSelector. С дефисом — это новый элемент списка, OR. Без дефиса — поле того же peer-объекта, AND. На CKAD используйте kubectl describe networkpolicy NAME и читайте раздел Allowing ingress traffic — там видно, как K8s интерпретировал ваш YAML.

Чтобы запомнить: представьте, что один peer — это «одно описание точки», и AND внутри сужает множество matched Pods. Список peers — несколько описаний, и любое подходит.


ports внутри rule

ports — список разрешённых портов и протоколов. По умолчанию protocol: TCP.

ingress:
- from:
  - podSelector:
      matchLabels:
        app: web
  ports:
  - port: 80
    protocol: TCP
  - port: 53
    protocol: UDP
  - port: dns
    protocol: UDP

port может быть числом или именем порта из containerPort.name target Pod-а — это удобно для портов с именами (http, metrics).

С 1.25+ stable поддерживается endPort для диапазонов:

ports:
- port: 32000
  endPort: 32767
  protocol: TCP

Если ports отсутствует — разрешены все порты для matching peers. Если ports есть, но пустой — это синтаксическая ошибка (валидатор API server отбросит).


Empty selector behavior: четыре формы

Это место, где синтаксис YAML и семантика расходятся. Запомните таблицу:

Эквиваленты пустоты в NetworkPolicy
podSelector: {}Пустой объект селектора. Семантика matchLabels: matches ВСЕ Pods. Применяется к ns policy.
namespaceSelector: {}Пустой объект селектора namespace. Matches ВСЕ namespaces. В сочетании с podSelector — все Pods во всех ns. Без него внутри peer — только все Pods в текущем ns.
from: []Пустой список peers. Семантически — нет ни одного разрешённого источника. ДЕНАЙ. Используется крайне редко, обычно как явное `nothing allowed`.
отсутствует fromПоле from не указано совсем (только ports или вообще ничего). Это allow от любого источника. С точки зрения CKAD — самый интересный паттерн `allow all to port :80`.
# Pod isolated, ingress полностью запрещён (no rules)
spec:
  podSelector: {}
  policyTypes: [Ingress]

# Pod isolated, ingress от ВСЕХ Pods во всех ns
spec:
  podSelector: {}
  policyTypes: [Ingress]
  ingress:
  - from:
    - namespaceSelector: {}

# Pod isolated, ingress от ВСЕХ Pods и ВСЕХ внешних IP на :80
spec:
  podSelector: {}
  policyTypes: [Ingress]
  ingress:
  - ports:
    - port: 80

# Pod isolated, ingress полностью запрещён даже с указанными правилами
spec:
  podSelector: {}
  policyTypes: [Ingress]
  ingress:
  - from: []        # пустой список — никто не подходит
    ports:
    - port: 80
WARNING

from: [] против отсутствующего from — самая subtle разница в API. Пустой список — ничего не разрешено, отсутствие поля — всё разрешено. Это противоречит интуиции «отсутствие — это null, который ничего не значит». Поэтому всегда явно: либо from: со списком peers, либо вообще не пишите блок from.


ipBlock против podSelector в одном peer

ipBlock нельзя объединить с podSelector или namespaceSelector в одном peer объекте. Они взаимоисключающи. API server отвергает такую комбинацию.

# Невалидно — API отвергнет
from:
- ipBlock:
    cidr: 10.0.0.0/8
  podSelector:
    matchLabels:
      app: web

Логика: ipBlock — про L3 IP-адрес, podSelector — про Pod identity. Они matchятся на разных уровнях и комбинировать их в одном AND не имеет смысла.

Если нужно «или IP-блок, или Pods» — это OR, два разных peer элемента:

from:
- ipBlock:
    cidr: 10.0.0.0/8
- podSelector:
    matchLabels:
      app: web

Killer момент: namespace policy и cross-namespace peers

Когда вы пишете podSelector внутри from без namespaceSelector, поиск идёт только в namespace policy. Если хотите матчить Pods в другом namespace — обязательно указывайте namespaceSelector. Иначе ваш «allow от Pods app=web» молча превратится в «allow от Pods app=web в моём namespace».

# Разрешает Pods app=web ТОЛЬКО в этом ns
from:
- podSelector:
    matchLabels: {app: web}

# Разрешает Pods app=web ВО ВСЕХ ns
from:
- namespaceSelector: {}
  podSelector:
    matchLabels: {app: web}

# Разрешает Pods app=web в ns с label team=frontend
from:
- namespaceSelector:
    matchLabels: {team: frontend}
  podSelector:
    matchLabels: {app: web}

Это классическая ошибка: задача звучит как «разрешить web из frontend-namespace к API в backend-namespace», люди пишут только podSelector — и удивляются, почему не работает. NetworkPolicy в namespace backend, поиск app=web идёт в backend, там таких Pods нет, никто не подходит.


Проверка знанийKnowledge check
Разница между списком из двух peers и одним peer с двумя полями (namespaceSelector + podSelector)?
ОтветAnswer
Список (через дефис) — это OR между peers. Один peer с двумя полями — AND между полями. Пример: список namespaceSelector + podSelector matches либо все Pods в matching ns, либо Pods с labels в текущем ns. Один peer с обоими полями — matches только Pods, которые ОДНОВРЕМЕННО в matching ns И имеют matching labels.
Проверка знанийKnowledge check
Что значит from: [] в ingress rule?
ОтветAnswer
Пустой список peers — никто не разрешён. Этот rule никому не открывает доступ. Часто используется ошибочно вместо отсутствующего поля from (которое наоборот разрешает всем).
Проверка знанийKnowledge check
Pod в namespace api, NetworkPolicy там же. Хотите разрешить ingress от Pods app=web из namespace frontend. Что писать в from?
ОтветAnswer
Обязательно namespaceSelector + podSelector в одном peer (AND): - namespaceSelector с matchLabels kubernetes.io/metadata.name: frontend, и podSelector с matchLabels app: web. Без namespaceSelector поиск app=web пойдёт только в namespace api, где таких Pods нет.
Проверка знанийKnowledge check
Может ли один peer объект содержать одновременно ipBlock и podSelector?
ОтветAnswer
Нет. ipBlock и podSelector/namespaceSelector взаимоисключающи в одном peer. API server отвергнет такой YAML. Если нужно матчить и IP, и Pods — это два разных peer элемента в списке (OR).

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 5. В ingress.from записано: from: - namespaceSelector: matchLabels: {team: backend} - podSelector: matchLabels: {app: web} Какие Pods matchятся?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5