Мережеві політики
Якщо ви хочете контролювати потік трафіку на рівні IP-адреси чи порту для протоколів TCP, UDP та SCTP, то вам, можливо, варто розглянути використання NetworkPolicies Kubernetes для конкретних застосунків у вашому кластері. NetworkPolicies — це конструкт, орієнтований на застосунок, який дозволяє вам визначати, як Pod може взаємодіяти з різними мережевими "сутностями" (ми використовуємо тут слово "сутність", щоб уникнути перевантаження більш загальноприйнятими термінами, такими як "Endpoints" та "Services", які мають конкретні конотації Kubernetes) мережею. NetworkPolicies – застосовується до зʼєднання з Pod на одному або обох кінцях і не має відношення до інших зʼєднань.
Сутності, з якими може взаємодіяти Pod, ідентифікуються за допомогою комбінації наступних трьох ідентифікаторів:
- Інші дозволені Podʼи (виняток: Pod не може блокувати доступ до себе самого)
- Дозволені простори імен
- IP-блоки (виняток: трафік до та від вузла, де працює Pod, завжди дозволений, незалежно від IP-адреси Podʼа чи вузла)
При визначенні мережевої політики на основі Podʼа чи простору імен ви використовуєте селектор для визначення, який трафік дозволений до та від Podʼа(ів), які відповідають селектору.
Тим часом при створенні мережевих політик на основі IP ми визначаємо політику на основі IP-блоків (діапазони CIDR).
Передумови
Мережеві політики впроваджуються мережевим втулком. Для використання мережевих політик вам слід використовувати рішення з підтримкою NetworkPolicy. Створення ресурсу NetworkPolicy без контролера, який його реалізує, не матиме ефекту.
Два види ізоляції для Podʼів
Існують два види ізоляції для Podʼа: ізоляція для вихідного трафіку (egress) та ізоляція для вхідного трафіку (ingress). Це стосується того, які зʼєднання можуть бути встановлені. Тут "ізоляція" не є абсолютною, але означає "діють деякі обмеження". Альтернатива, "non-isolated for $direction", означає, що в зазначеному напрямку обмеження відсутні. Два види ізоляції (або ні) декларуються незалежно та є важливими для підключення від одного Podʼа до іншого.
Типово Pod не є ізольованим для вихідного трафіку (egress); всі вихідні зʼєднання дозволені. Pod ізольований для вихідного трафіку, якщо є будь-яка мережева політика, яка одночасно вибирає Pod і має "Egress" у своєму policyTypes
; ми кажемо, що така політика застосовується до Podʼа для вихідного трафіку. Коли Pod ізольований для вихідного трафіку, єдині дозволені зʼєднання з Podʼа — ті, які дозволені списком egress
деякої мережевої політики, яка застосовується до Podʼа для вихідного трафіку. Також буде неявно дозволений вихідний трафік для цих дозволених зʼєднань. Ефекти цих списків egress
обʼєднуються адитивно.
Типово Pod не є ізольованим для вхідного трафіку (ingress); всі вхідні зʼєднання дозволені. Pod ізольований для вхідного трафіку, якщо є будь-яка мережева політика, яка одночасно вибирає Pod і має "Ingress" у своєму policyTypes
; ми кажемо, що така політика застосовується до Podʼа для вхідного трафіку. Коли Pod ізольований для вхідного трафіку, єдині дозволені зʼєднання до Podʼа - ті, що з вузла Podʼа та ті, які дозволені списком ingress
деякої мережевої політики, яка застосовується до Podʼа для вхідного трафіку. Також буде неявно дозволений вхідний трафік для цих дозволених зʼєднань. Ефекти цих списків ingress
обʼєднуються адитивно.
Мережеві політики не конфліктують; вони є адитивними. Якщо будь-яка політика чи політики застосовуються до певного Podʼа для певного напрямку, то зʼєднання, які дозволяються в цьому напрямку від цього Podʼа, — це обʼєднання того, що дозволяють відповідні політики. Таким чином, порядок оцінки не впливає на результат політики.
Для того, щоб зʼєднання від джерела до призначення було дозволено, обидві політики, вихідна на джерелі та вхідна на призначенні, повинні дозволяти зʼєднання. Якщо хоча б одна сторона не дозволяє зʼєднання, воно не відбудеться.
Ресурс NetworkPolicy
Для повного визначення ресурсу дивіться посилання на 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
Примітка:
Надсилання (POST) цього до сервера API вашого кластера не матиме жодного ефекту, якщо ваше обране мережеве рішення не підтримує мережеву політику.Обовʼязкові поля: Як і з усіма іншими конфігураціями Kubernetes, для NetworkPolicy потрібні поля apiVersion
, kind
та metadata
. Для загальної інформації щодо роботи з конфігураційними файлами дивіться Налаштування Pod для використання ConfigMap та Управління обʼєктами.
spec: Специфікація мережевої політики spec містить всю інформацію, необхідну для визначення конкретної мережевої політики в заданому просторі імен.
podSelector: Кожна NetworkPolicy включає podSelector
, який вибирає групу Podʼів, до яких застосовується політика. У прикладі політики вибираються Podʼи з міткою "role=db". Порожній podSelector
вибирає всі Podʼи в просторі імен.
policyTypes: Кожна NetworkPolicy включає список policyTypes
, який може містити або Ingress
, або Egress
, або обидва. Поле policyTypes
вказує, чи політика застосовується, чи ні до трафіку ingress до вибраних Podʼів, трафіку egress від вибраних Podʼів чи обох. Якщо на NetworkPolicy не вказано жодних policyTypes
, то станадартно буде завжди встановлено Ingress
, а Egress
буде встановлено, якщо у NetworkPolicy є хоча б одне правило egress.
ingress: Кожна NetworkPolicy може включати список дозволених правил ingress
. Кожне правило дозволяє трафіку, який відповідає як from
, так і секції ports
. У прикладі політики є одне правило, яке відповідає трафіку на одному порту від одного з трьох джерел: перше вказано через ipBlock
, друге через namespaceSelector
, а третє через podSelector
.
egress: Кожна NetworkPolicy може включати список дозволених правил egress
. Кожне правило дозволяє трафіку, який відповідає як секції to
, так і ports
. У прикладі політики є одне правило, яке відповідає трафіку на одному порту до будь-якого призначення в 10.0.0.0/24
.
Отже, приклад NetworkPolicy:
ізолює Podʼи
role=db
в просторі іменdefault
для трафіку як ingress, так і egress (якщо вони ще не були ізольовані)(Правила Ingress) дозволяє підключення до всіх Podʼів в просторі імен
default
з міткоюrole=db
на TCP-порт 6379 від:- будь-якого Pod в просторі імен
default
з міткоюrole=frontend
- будь-якого Pod в просторі імені з міткою
project=myproject
- IP-адреси в діапазонах
172.17.0.0
–172.17.0.255
nf172.17.2.0
–172.17.255.255
(тобто, усе172.17.0.0/16
, за винятком172.17.1.0/24
)
- будь-якого Pod в просторі імен
(Правила Egress) дозволяє підключення з будь-якого Pod в просторі імен
default
з міткоюrole=db
до CIDR10.0.0.0/24
на TCP-порт 5978
Дивіться Оголошення мережевої політики для ознайомлення з додатковими прикладами.
Поведінка селекторів to
та from
Існує чотири види селекторів, які можна вказати в розділі from
для ingress
або to
для egress
:
podSelector: Вибирає певні Podʼи в тому ж просторі імен, що і NetworkPolicy, які мають бути допущені як джерела ingress або призначення egress.
namespaceSelector: Вибирає певні простори імен, для яких всі Podʼи повинні бути допущені як джерела ingress або призначення egress.
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 для дозволу їх як джерел ingress або призначення egress. Це повинні бути зовнішні для кластера IP, оскільки IP Podʼів є ефемерними та непередбачуваними.
Механізми ingress та egress кластера часто вимагають переписування IP джерела або IP призначення пакетів. У випадках, коли це відбувається, не визначено, чи це відбувається до, чи після обробки NetworkPolicy, і поведінка може бути різною для різних комбінацій мережевого втулка, постачальника хмарних послуг, реалізації Service
тощо.
У випадку ingress це означає, що у деяких випадках ви можете фільтрувати вхідні пакети на основі фактичної вихідної IP, тоді як в інших випадках "вихідна IP-адреса", на яку діє NetworkPolicy, може бути IP LoadBalancer
або вузла Podʼа тощо.
Щодо egress це означає, що підключення з Podʼів до IP Service
, які переписуються на зовнішні IP кластера, можуть або не можуть підпадати під політику на основі ipBlock
.
Стандартні політики
Типово, якщо в просторі імен відсутні будь-які політики, то трафік ingress та egress дозволено до та від Podʼів в цьому просторі імен. Наступні приклади дозволяють змінити стандартну поведінку в цьому просторі імені.
Стандартна заборона всього вхідного трафіку
Ви можете створити політику стандартної ізоляції вхідного трафіку для простору імен, створивши NetworkPolicy, яка вибирає всі Podʼи, але не дозволяє будь-який вхідний трафік для цих Podʼів.
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
Це забезпечить ізоляцію вхідного трафіку навіть для Podʼів, які не вибрані жодною іншою NetworkPolicy. Ця політика не впливає на ізоляцію egress трафіку з будь-якого Podʼа.
Дозвіл на весь вхідний трафік
Якщо ви хочете дозволити всі вхідні підключення до всіх Podʼів в просторі імен, ви можете створити політику, яка явно це дозволяє.
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-ingress
spec:
podSelector: {}
ingress:
- {}
policyTypes:
- Ingress
З цією політикою ніяка додаткова політика або політики не можуть призвести до відмови у ingress підключенні до цих Podʼів. Ця політика не впливає на ізоляцію вихідного трафіку з будь-якого Podʼа.
Стандартна заборона всього вихідного трафіку
Ви можете створити стандартну політику ізоляції вихідного трафіку для простору імен, створивши NetworkPolicy, яка вибирає всі Podʼи, але не дозволяє будь-який egress трафік від цих Podʼів.
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
spec:
podSelector: {}
policyTypes:
- Egress
Це забезпечить те, що навіть Podʼи, які не вибрані жодною іншою NetworkPolicy, не матимуть дозволу на вихідний трафік. Ця політика не змінює ізоляційну поведінку egress трафіку з будь-якого Podʼа.
Дозвіл на весь вихідний трафік
Якщо ви хочете дозволити всі підключення з усіх Podʼів в просторі імен, ви можете створити політику, яка явно дозволяє всім вихідним зʼєднанням з Podʼів в цьому просторі імені.
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-egress
spec:
podSelector: {}
egress:
- {}
policyTypes:
- Egress
З цією політикою ніяка додаткова політика або політики не можуть призвести до відмови у вихідному підключенні з цих Podʼів. Ця політика не впливає на ізоляцію ingress трафіку до будь-якого Podʼа.
Стандартна заборона всього вхідного та всього вихідного трафіку
Ви можете створити "стандартну" політику для простору імен, яка забороняє весь ingress та egress трафік, створивши наступний NetworkPolicy в цьому просторі імені.
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Це забезпечить те, що навіть Podʼи, які не вибрані жодною іншою NetworkPolicy, не матимуть дозволу на трафік ingress та egress напрямку.
Фільтрація мережевого трафіку
NetworkPolicy визначений для зʼєднань layer 4 (TCP, UDP та за необхідності SCTP). Для всіх інших протоколів поведінка може варіюватися залежно від мережевих втулків.
Примітка:
Вам потрібно використовувати втулок CNI, який підтримує мережеві політики для протоколу SCTP.Коли визначена мережева політика deny all
, гарантується тільки відмова в TCP, UDP та SCTP зʼєднаннях. Для інших протоколів, таких як ARP чи ICMP, поведінка невизначена. Те ж саме стосується правил дозволу (allow
): коли певний Pod дозволений як джерело ingress або призначення egress, не визначено, що відбувається з (наприклад) пакетами ICMP. Такі протоколи, як ICMP, можуть бути дозволені одними мережевими втулками та відхилені іншими.
Спрямування трафіку на діапазон портів
Kubernetes v1.25 [stable]
При написанні 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
.- Обидва порти повинні бути числовими значеннями.
Примітка:
Ваш кластер повинен використовувати втулок CNI, який підтримує полеendPort
в специфікаціях NetworkPolicy. Якщо ваш мережевий втулок не підтримує поле endPort
, і ви вказуєте NetworkPolicy з таким полем, політика буде застосована лише для одного поля port
.Спрямування трафіку на кілька просторів імен за допомогою міток
У цім сценарії ця ваша Egress
NetworkPolicy спрямована на більше ніж один простір імен, використовуючи їх мітки. Для цього необхідно додати мітки до цільових просторів імен. Наприклад:
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"]
Примітка:
Неможливо безпосередньо вказати імʼя простору імен в NetworkPolicy. Ви повинні використовуватиnamespaceSelector
з matchLabels
або matchExpressions
, щоб вибрати простори імен на основі їх міток.Спрямування трафіку на простір імен за його іменем
Керівництво Kubernetes встановлює незмінювану мітку kubernetes.io/metadata.name
на всі простори імен, значення мітки — це імʼя простору імен.
Хоча NetworkPolicy не може спрямовуватися на простір імен за його іменем з допомогою поля обʼєкта, ви можете використовувати стандартизовану мітку для спрямування на конкретний простір імен.
Життєвий цикл Podʼа
Примітка:
Наведене нижче стосується кластерів із сумісним мережевим втулком та сумісною реалізацією NetworkPolicy.При створенні нового обʼєкта NetworkPolicy може знадобитися певний час для обробки нового обʼєкта мережевим втулком. Якщо Pod, який стосується NetworkPolicy, створено до того, як мережевий втулок завершить обробку NetworkPolicy, цей Pod може бути запущений в незахищеному стані, і правила ізоляції будуть застосовані, коли обробка NetworkPolicy буде завершена.
Щойно NetworkPolicy оброблено мережевим втулком,
Усі нові Podʼи, які стосуються даної NetworkPolicy, будуть ізольовані перед тим, як їх запустять. Реалізації NetworkPolicy повинні забезпечити, що фільтрація є ефективною впродовж усього життєвого циклу Podʼа, навіть з моменту першого запуску будь-якого контейнера у цьому Podʼі. Оскільки вони застосовуються на рівні Podʼа, NetworkPolicies однаково застосовуються до init-контейнерів, контейнерів-супутників та звичайних контейнерів.
Правила дозволів будуть застосовані, остаточно після правил ізоляції (або можуть бути застосовані одночасно). У найгіршому випадку новий Pod може не мати жодного мережевого зʼєднання взагалі при першому запуску, якщо правила ізоляції вже були застосовані, але правила дозволів ще не були застосовані.
Кожна створена NetworkPolicy буде врешті-решт застосована мережевим втулком, але немає способу визначити з API Kubernetes, коли саме це станеться.
Отже, Podʼи повинні бути стійкими до того, що їх можуть запускати з різним ступенем мережевого зʼєднання, ніж очікувалося. Якщо вам потрібно переконатися, що Pod може досягти певних місць перед тим, як його запустять, ви можете використовувати init контейнер чекати, доки ці місця стануть доступними, перш ніж kubelet запустить контейнери застосунків.
Кожна NetworkPolicy буде застосована до всіх вибраних Podʼів врешті-решт. Оскільки мережевий втулок може реалізовувати NetworkPolicy розподіленим чином, можливо, що Podʼи можуть бачити трохи неузгоджений вид мережевих політик при першому створенні Podʼа або при зміні Podʼів або політик. Наприклад, новий створений Pod, який повинен бути в змозі досягти як Podʼа на вузлі 1, так і Podʼа на вузлі 2, може знайти, що він може досягати Podʼа А негайно, але не може досягати Podʼа B впродовж кількох секунд.
NetworkPolicy та Podʼи з hostNetwork
Поведінка NetworkPolicy для Podʼів із hostNetwork
є невизначеною, але вона повинна обмежуватися двома можливостями:
- Мережевий втулок може відрізняти трафік Podʼів з
hostNetwork
від усього іншого трафіку (включаючи можливість відрізняти трафік від різних Podʼів зhostNetwork
на тому ж вузлі) та застосовувати NetworkPolicy до Podʼів ізhostNetwork
, , так само як і до Podʼів мережі Podʼа. - Мережевий втулок не може належним чином відрізняти трафік Podʼів із
hostNetwork
, тому він ігнорує Podʼи зhostNetwork
при відповідностіpodSelector
таnamespaceSelector
. Трафік до/від 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
.
Що ви не можете зробити за допомогою мережевих політик (принаймні, зараз) {#what-you-can't-do-with-network-policies-at-least-not-yet}
В Kubernetes 1.32, наступна функціональність відсутня в API NetworkPolicy, але, можливо, ви зможете реалізувати обходні шляхи, використовуючи компоненти операційної системи (такі як SELinux, OpenVSwitch, IPTables та інші) або технології Layer 7 (контролери Ingress, реалізації Service Mesh) чи контролери допуску. У випадку, якщо ви новачок в мережевому захисті в Kubernetes, варто відзначити, що наступні випадки не можна (ще) реалізувати за допомогою API NetworkPolicy.
- Примусова маршрутизація внутрішньокластерного трафіку через загальний шлюз (це, можливо, найкраще реалізувати за допомогою сервіс-мешу чи іншого проксі).
- Будь-яка функціональність, повʼязана з TLS (для цього можна використовувати сервіс-меш чи контролер ingress).
- Політики, специфічні для вузла (ви можете використовувати нотацію CIDR для цього, але ви не можете визначати вузли за їхніми ідентифікаторами Kubernetes).
- Спрямування трафіку на service за іменем (проте ви можете спрямовувати трафік на Podʼи чи простори імен за їх мітками, що часто є прийнятним обхідним варіантом).
- Створення або управління "Policy request", які виконуються третьою стороною.
- Типові політики, які застосовуються до всіх просторів імен чи Podʼів (є деякі дистрибутиви Kubernetes від сторонніх постачальників та проєкти, які можуть це робити).
- Розширені засоби надсилання запитів та інструменти перевірки досяжності політики.
- Можливість ведення логу подій з мережевої безпеки (наприклад, заблоковані чи прийняті зʼєднання).
- Можливість явно відмовляти в політиках (наразі модель для NetworkPolicy — це типова відмова, з можливістю додавання тільки правил дозволу).
- Можливість уникнення loopback чи вхідного трафіку від хоста (Podʼи наразі не можуть блокувати доступ до localhost, і вони не мають можливості блокувати доступ від їхнього вузла-резидента).
Вплив мережевих політик на існуючі зʼєднання
Коли набір мережевих політик, які застосовуються до існуючого зʼєднання, змінюється — це може трапитися через зміну мережевих політик або якщо відповідні мітки обраних просторів імен/Podʼів, обраних політикою (як субʼєкт і peers), змінюються під час існуючого зʼєднання — не визначено в реалізації, чи буде врахована зміна для цього існуючого зʼєднання чи ні. Наприклад: створено політику, яка призводить до відмови в раніше дозволеному зʼєднанні, реалізація базового мережевого втулка відповідальна за визначення того, чи буде ця нова політика закривати існуючі зʼєднання чи ні. Рекомендується утримуватися від змін політик/Podʼів/просторів імен таким чином, що може вплинути на існуючі зʼєднання.
Що далі
- Перегляньте оголошення мережевої політики для отримання додаткових прикладів.
- Дивіться більше рецептів для звичайних сценаріїв, які підтримує ресурс NetworkPolicy.