Якщо ви хочете контролювати потік трафіку на рівні IP-адреси чи порту для протоколів TCP, UDP та SCTP, вам варто розглянути використання NetworkPolicies Kubernetes для окремих застосунків у вашому кластері. NetworkPolicies — це конструкція, орієнтована на застосунки, яка дозволяє визначити, як Pod може взаємодіяти через мережу з різними мережевими «сутностями» (ми вживаємо тут слово «сутність», щоб не перевантажувати поширеніші терміни, як-от «точки доступу» та «Services», які мають у Kubernetes особливі значення). NetworkPolicies застосовуються до зʼєднання, на одному або обох кінцях якого є Pod, і не стосуються інших зʼєднань.
Сутності, з якими може взаємодіяти Pod, визначаються за допомогою комбінації таких трьох ідентифікаторів:
Під час визначення NetworkPolicy на основі Podʼів або просторів імен ви використовуєте селектор, щоб вказати, який трафік дозволений до Podʼів і від Podʼів, що відповідають цьому селектору.
Натомість під час створення NetworkPolicies на основі IP ми визначаємо політики на основі IP-блоків (діапазонів CIDR).
Мережеві політики реалізуються мережевим втулком. Щоб використовувати мережеві політики, вам потрібне мережеве рішення, яке підтримує NetworkPolicy. Створення ресурсу NetworkPolicy без контролера, який його реалізує, не матиме ефекту.
Існує два види ізоляції для Podʼа: ізоляція для вихідного трафіку (egress) та ізоляція для вхідного трафіку (ingress). Вони стосуються того, які зʼєднання можуть бути встановлені. «Ізоляція» тут не є абсолютною, а означає «застосовуються певні обмеження». Альтернатива, «неізольований для $direction», означає, що в зазначеному напрямку обмежень немає. Обидва види ізоляції (або її відсутності) оголошуються незалежно, і обидва мають значення для зʼєднання від одного Podʼа до іншого.
Стандартно Pod не є ізольованим для вихідного трафіку: усі вихідні зʼєднання дозволені. Pod є ізольованим для вихідного трафіку, якщо існує будь-яка NetworkPolicy, яка одночасно вибирає цей Pod і має "Egress" у своєму policyTypes; ми кажемо, що така політика застосовується до Podʼа для вихідного трафіку. Коли Pod ізольований для вихідного трафіку, єдині дозволені зʼєднання з Podʼа — це ті, що дозволені списком egress якоїсь NetworkPolicy, яка застосовується до Podʼа для вихідного трафіку. Трафік відповідей для цих дозволених зʼєднань також буде неявно дозволений. Дія цих списків egress обʼєднується адитивно.
Стандартно Pod не є ізольованим для вхідного трафіку: усі вхідні зʼєднання дозволені. Pod є ізольованим для вхідного трафіку, якщо існує будь-яка NetworkPolicy, яка одночасно вибирає цей Pod і має "Ingress" у своєму policyTypes; ми кажемо, що така політика застосовується до Podʼа для вхідного трафіку. Коли Pod ізольований для вхідного трафіку, єдині дозволені зʼєднання до Podʼа — це зʼєднання з вузла Podʼа та ті, що дозволені списком ingress якоїсь NetworkPolicy, яка застосовується до Podʼа для вхідного трафіку. Трафік відповідей для цих дозволених зʼєднань також буде неявно дозволений. Дія цих списків ingress обʼєднується адитивно.
Мережеві політики не конфліктують, вони адитивні. Якщо одна чи кілька політик застосовуються до певного Podʼа в певному напрямку, то дозволені в цьому напрямку зʼєднання цього Podʼа — це обʼєднання того, що дозволяють застосовні політики. Тому порядок обчислення не впливає на результат політики.
Щоб зʼєднання від Podʼа-джерела до Podʼа-призначення було дозволене, його мають дозволяти і політика вихідного трафіку на Podʼі-джерелі, і політика вхідного трафіку на Podʼі-призначенні. Якщо хоча б одна сторона не дозволяє зʼєднання, воно не відбудеться.
Повне визначення ресурсу дивіться в довіднику NetworkPolicy.
Приклад NetworkPolicy може виглядати так:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
Обовʼязкові поля: Як і всім іншим конфігураціям Kubernetes, NetworkPolicy потрібні поля apiVersion, kind та metadata. Загальну інформацію про роботу з файлами конфігурації дивіться в Налаштування Podʼів для використання ConfigMap та Управління обʼєктами.
spec: Специфікація NetworkPolicy містить усю інформацію, необхідну для визначення конкретної мережевої політики в заданому просторі імен.
podSelector: Кожна NetworkPolicy містить podSelector, який вибирає групу Podʼів, до яких застосовується політика. Політика з прикладу вибирає Podʼи з міткою "role=db". Порожній podSelector вибирає всі Podʼи в просторі імен.
policyTypes: Кожна NetworkPolicy містить список policyTypes, який може включати Ingress, Egress або обидва значення. Поле policyTypes вказує, чи застосовується ця політика до вхідного трафіку до вибраних Podʼів, до вихідного трафіку від вибраних Podʼів чи до обох. Якщо в NetworkPolicy не вказано жодного policyTypes, то стандартно завжди буде встановлено Ingress, а Egress буде встановлено, якщо NetworkPolicy має хоча б одне правило вихідного трафіку.
ingress: Кожна NetworkPolicy може містити список дозволених правил ingress. Кожне правило дозволяє трафік, який відповідає обом секціям: from і ports. Політика з прикладу містить одне правило, яке відповідає трафіку на одному порту від одного з трьох джерел: перше вказано через ipBlock, друге через namespaceSelector, а третє через podSelector.
egress: Кожна NetworkPolicy може містити список дозволених правил egress. Кожне правило дозволяє трафік, який відповідає обом секціям: to і ports. Політика з прикладу містить одне правило, яке відповідає трафіку на одному порту до будь-якого призначення в 10.0.0.0/24.
Отже, NetworkPolicy з прикладу:
ізолює Podʼи role=db у просторі імен default як для вхідного, так і для вихідного трафіку (якщо вони ще не були ізольовані)
(правила Ingress) дозволяє зʼєднання до всіх Podʼів у просторі імен default з міткою role=db на TCP-порт 6379 від:
default з міткою role=frontendproject=myproject172.17.0.0–172.17.0.255 та 172.17.2.0–172.17.255.255 (тобто всіх адрес 172.17.0.0/16, крім 172.17.1.0/24)(правила Egress) дозволяє зʼєднання від будь-якого Podʼа в просторі імен default з міткою role=db до CIDR 10.0.0.0/24 на TCP-порт 5978
Додаткові приклади дивіться в покроковому посібнику Оголошення мережевої політики.
to та fromІснує чотири види селекторів, які можна вказати в секції from правила ingress або в секції to правила egress:
podSelector: Вибирає певні Podʼи в тому самому просторі імен, що й NetworkPolicy, які мають бути дозволені як джерела вхідного трафіку або призначення вихідного трафіку.
namespaceSelector: Вибирає певні простори імен, усі Podʼи яких мають бути дозволені як джерела вхідного трафіку або призначення вихідного трафіку.
namespaceSelector та podSelector: Один запис to/from, який вказує і namespaceSelector, і podSelector, вибирає певні Podʼи в певних просторах імен. Будьте уважні й використовуйте правильний синтаксис YAML. Наприклад:
...
ingress:
- from:
- namespaceSelector:
matchLabels:
user: alice
podSelector:
matchLabels:
role: client
...
Ця політика містить один елемент from, який дозволяє зʼєднання від Podʼів з міткою role=client у просторах імен з міткою user=alice. Але наведена далі політика відрізняється:
...
ingress:
- from:
- namespaceSelector:
matchLabels:
user: alice
- podSelector:
matchLabels:
role: client
...
Вона містить два елементи в масиві from і дозволяє зʼєднання від Podʼів у локальному просторі імен з міткою role=client або від будь-якого Podʼа в будь-якому просторі імен з міткою user=alice.
Якщо є сумніви, скористайтеся kubectl describe, щоб побачити, як Kubernetes інтерпретував політику.
ipBlock: Вибирає певні діапазони IP CIDR, дозволені як джерела вхідного трафіку або призначення вихідного трафіку. Це мають бути IP-адреси поза кластером, оскільки IP-адреси Podʼів є ефемерними та непередбачуваними.
Механізми вхідного та вихідного трафіку кластера часто вимагають переписування IP-адреси джерела або призначення пакетів. У таких випадках не визначено, чи відбувається це до обробки NetworkPolicy, чи після неї, і поведінка може відрізнятися для різних комбінацій мережевого втулка, хмарного провайдера, реалізації Service тощо.
Для вхідного трафіку це означає, що в одних випадках ви можете фільтрувати вхідні пакети за фактичною початковою IP-адресою джерела, а в інших «IP-адреса джерела», за якою працює NetworkPolicy, може бути IP-адресою LoadBalancer, вузла Podʼа тощо.
Для вихідного трафіку це означає, що на зʼєднання від Podʼів до IP-адрес Service, які переписуються на зовнішні для кластера IP-адреси, політики на основі ipBlock можуть поширюватися, а можуть і не поширюватися.
Стандартно, якщо в просторі імен немає жодної політики, весь вхідний і вихідний трафік до Podʼів і від Podʼів у цьому просторі імен дозволений. Наведені нижче приклади дозволяють змінити стандартну поведінку в цьому просторі імен.
Ви можете створити «стандартну» політику ізоляції вхідного трафіку для простору імен, створивши NetworkPolicy, яка вибирає всі Podʼи, але не дозволяє жодного вхідного трафіку до цих Podʼів.
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
Це гарантує, що навіть Podʼи, не вибрані жодною іншою NetworkPolicy, залишатимуться ізольованими для вхідного трафіку. Ця політика не впливає на ізоляцію вихідного трафіку будь-якого Podʼа.
Якщо ви хочете дозволити всі вхідні зʼєднання до всіх Podʼів у просторі імен, ви можете створити політику, яка явно це дозволяє.
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-ingress
spec:
podSelector: {}
ingress:
- {}
policyTypes:
- Ingress
За наявності цієї політики жодна додаткова політика чи політики не можуть призвести до відмови у вхідному зʼєднанні до цих Podʼів. Ця політика не впливає на ізоляцію вихідного трафіку будь-якого Podʼа.
Ви можете створити «стандартну» політику ізоляції вихідного трафіку для простору імен, створивши NetworkPolicy, яка вибирає всі Podʼи, але не дозволяє жодного вихідного трафіку від цих Podʼів.
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
spec:
podSelector: {}
policyTypes:
- Egress
Це гарантує, що навіть Podʼам, не вибраним жодною іншою NetworkPolicy, не буде дозволено вихідний трафік. Ця політика не змінює поведінку ізоляції вхідного трафіку будь-якого Podʼа.
Якщо ви хочете дозволити всі зʼєднання від усіх Podʼів у просторі імен, ви можете створити політику, яка явно дозволяє всі вихідні зʼєднання від Podʼів у цьому просторі імен.
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-egress
spec:
podSelector: {}
egress:
- {}
policyTypes:
- Egress
За наявності цієї політики жодна додаткова політика чи політики не можуть призвести до відмови у вихідному зʼєднанні від цих Podʼів. Ця політика не впливає на ізоляцію вхідного трафіку будь-якого Podʼа.
Ви можете створити «стандартну» політику для простору імен, яка забороняє весь вхідний І вихідний трафік, створивши в цьому просторі імен наведену нижче NetworkPolicy.
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Це гарантує, що навіть Podʼам, не вибраним жодною іншою NetworkPolicy, не буде дозволено вхідний або вихідний трафік.
NetworkPolicy визначена для зʼєднань рівня 4 (TCP, UDP та, за потреби, SCTP). Для всіх інших протоколів поведінка може відрізнятися залежно від мережевого втулка.
Коли визначено мережеву політику deny all, гарантовано забороняються лише зʼєднання TCP, UDP та SCTP. Для інших протоколів, таких як ARP чи ICMP, поведінка не визначена. Те саме стосується дозвільних правил: коли певний Pod дозволений як джерело вхідного трафіку або призначення вихідного трафіку, не визначено, що відбувається (наприклад) з пакетами ICMP. Такі протоколи, як ICMP, можуть бути дозволені одними мережевими втулками та заборонені іншими.
Під час написання NetworkPolicy ви можете націлитися на діапазон портів, а не на один порт.
Це можна зробити за допомогою поля endPort, як показано в наведеному нижче прикладі:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: multi-port-egress
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 32000
endPort: 32768
Наведене вище правило дозволяє будь-якому Podʼу з міткою role=db у просторі імен default взаємодіяти з будь-якою IP-адресою в діапазоні 10.0.0.0/24 через TCP за умови, що цільовий порт перебуває в діапазоні від 32000 до 32768.
Під час використання цього поля застосовуються такі обмеження:
endPort має бути рівним полю port або більшим за нього.endPort можна визначити, лише якщо також визначено port.endPort у специфікаціях NetworkPolicy. Якщо ваш мережевий втулок не підтримує поле endPort, а ви вкажете NetworkPolicy із цим полем, політика буде застосована лише для одного поля port.У цьому сценарії ваша NetworkPolicy типу Egress націлена на кілька просторів імен за назвами їхніх міток. Щоб це працювало, потрібно додати мітки до цільових просторів імен. Наприклад:
kubectl label namespace frontend namespace=frontend
kubectl label namespace backend namespace=backend
Додайте мітки в namespaceSelector у документі NetworkPolicy. Наприклад:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: egress-namespaces
spec:
podSelector:
matchLabels:
app: myapp
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchExpressions:
- key: namespace
operator: In
values: ["frontend", "backend"]
namespaceSelector із matchLabels або matchExpressions, щоб вибрати простори імен за їхніми мітками.Панель управління Kubernetes встановлює незмінну мітку kubernetes.io/metadata.name на всі простори імен, значенням мітки є назва простору імен.
Хоча NetworkPolicy не може націлитися на простір імен за його назвою через якесь поле обʼєкта, ви можете використати стандартизовану мітку, щоб націлитися на конкретний простір імен.
Коли створюється новий обʼєкт NetworkPolicy, мережевому втулку може знадобитися певний час, щоб обробити цей новий обʼєкт. Якщо Pod, на який впливає NetworkPolicy, створено до того, як мережевий втулок завершив обробку NetworkPolicy, цей Pod може бути запущений незахищеним, а правила ізоляції будуть застосовані, коли обробку NetworkPolicy буде завершено.
Щойно NetworkPolicy оброблено мережевим втулком,
Усі новостворені Podʼи, на які впливає певна NetworkPolicy, будуть ізольовані до їхнього запуску. Реалізації NetworkPolicy повинні гарантувати, що фільтрація діє протягом усього життєвого циклу Podʼа, починаючи з першої миті запуску будь-якого контейнера в цьому Podʼі. Оскільки NetworkPolicies застосовуються на рівні Podʼа, вони однаково застосовуються до init-контейнерів, sidecar-контейнерів і звичайних контейнерів.
Дозвільні правила будуть зрештою застосовані після правил ізоляції (або можуть бути застосовані одночасно з ними). У найгіршому випадку новостворений Pod може взагалі не мати мережевого звʼязку під час першого запуску, якщо правила ізоляції вже застосовані, а дозвільні правила ще ні.
Кожна створена NetworkPolicy рано чи пізно буде оброблена мережевим втулком, але через API Kubernetes неможливо дізнатися, коли саме це станеться.
Тому Podʼи мають бути стійкими до запуску з іншим мережевим звʼязком, ніж очікувалося. Якщо вам потрібно переконатися, що Pod може досягти певних призначень до запуску, ви можете використати init-контейнер, щоб дочекатися доступності цих призначень, перш ніж kubelet запустить контейнери застосунків.
Кожна NetworkPolicy рано чи пізно буде застосована до всіх вибраних Podʼів. Оскільки мережевий втулок може реалізовувати NetworkPolicy розподілено, Podʼи можуть бачити дещо неузгоджене подання мережевих політик під час першого створення Podʼа або коли змінюються Podʼи чи політики. Наприклад, новостворений Pod, який має мати доступ і до Podʼа A на вузлі 1, і до Podʼа B на вузлі 2, може виявити, що Pod A доступний йому одразу, а Pod B — лише через кілька секунд.
hostNetworkПоведінка NetworkPolicy для Podʼів із hostNetwork не визначена, але вона має обмежуватися двома можливостями:
hostNetwork від усього іншого трафіку (зокрема, відрізняти трафік різних Podʼів із hostNetwork на тому самому вузлі) і застосовує NetworkPolicy до Podʼів із hostNetwork так само, як і до Podʼів у мережі Podʼів.hostNetwork, тому він ігнорує такі Podʼи під час зіставлення podSelector та namespaceSelector. Трафік до Podʼів і від Podʼів із hostNetwork обробляється так само, як і весь інший трафік до IP-адреси вузла та від неї. (Це найпоширеніша реалізація.)Це стосується випадків, коли
Pod із hostNetwork вибирається за допомогою spec.podSelector.
...
spec:
podSelector:
matchLabels:
role: client
...
Pod із hostNetwork вибирається за допомогою podSelector чи namespaceSelector у правилі ingress чи egress.
...
ingress:
- from:
- podSelector:
matchLabels:
role: client
...
Водночас, оскільки Podʼи з hostNetwork мають ті самі IP-адреси, що й вузли, на яких вони розміщені, їхні зʼєднання вважатимуться зʼєднаннями вузла. Наприклад, ви можете дозволити трафік від Podʼа з hostNetwork за допомогою правила ipBlock.
У Kubernetes 1.37 наведена нижче функціональність відсутня в API NetworkPolicy, але ви можете реалізувати обхідні рішення за допомогою компонентів операційної системи (таких як SELinux, OpenVSwitch, IPTables тощо), технологій рівня 7 (контролери Ingress, реалізації Service Mesh) або контролерів допуску. Якщо ви лише починаєте знайомитися з мережевою безпекою в Kubernetes, варто зазначити, що наведені нижче сценарії користувачів поки що не можна реалізувати за допомогою API NetworkPolicy.
Коли змінюється набір NetworkPolicies, що застосовуються до наявного зʼєднання, — через зміну самих NetworkPolicies або через зміну відповідних міток просторів імен чи Podʼів, вибраних політикою (і субʼєкта, і його співрозмовників (peers)), посеред наявного зʼєднання, — те, чи вплине ця зміна на це наявне зʼєднання, визначається реалізацією. Приклад: створено політику, яка призводить до заборони раніше дозволеного зʼєднання; реалізація базового мережевого втулка відповідає за визначення того, чи закриє ця нова політика наявні зʼєднання. Рекомендується не змінювати політики, Podʼи чи простори імен у спосіб, який може вплинути на наявні зʼєднання.