Мережева модель Kubernetes складається з кількох частин:
Кожен pod у кластері отримує
власну унікальну кластерну IP-адресу.
Pod має власний приватний мережевий простір імен, який спільно використовують всі контейнери всередині podʼа. Процеси, що працюють у різних контейнерах в одному podʼі, можуть спілкуватися між собою через localhost.
Мережа podʼів (також називається кластерною мережею) керує комунікацією між podʼами. Вона забезпечує, що (за відсутності навмисної сегментації мережі):
Модель мережі Kubernetes складається з кількох компонентів:
Кожен pod у кластері отримує
свою унікальну кластерну IP-адресу.
Pod має власний приватний мережевий простір імен, який спільно використовують усі контейнери в pod. Процеси, що працюють у різних контейнерах в одному pod, можуть спілкуватися між собою через localhost.
Мережа pod (також називається кластерною мережею) керує комунікацією між podʼами. Вона забезпечує, що (за відсутності навмисної сегментації мережі):
Усі podʼи можуть спілкуватися з усіма іншими podʼами, незалежно від того, чи знаходяться вони на одному вузлі, чи на різних. Podʼи можуть спілкуватися безпосередньо, без використання проксі-серверів чи трансляції адрес (NAT).
У Windows це правило не застосовується до podʼів з мережею вузла.
Агенти на вузлі (такі як системні демони чи kubelet) можуть спілкуватися з усіма podʼами на цьому вузлі.
API Service дозволяє надати стабільну (довготривалу) IP-адресу або імʼя хосту для сервісу, реалізованого одним або кількома podʼами, при цьому окремі podʼи, що складають сервіс, можуть змінюватися з часом.
Kubernetes автоматично керує обʼєктами EndpointSlice, які надають інформацію про podʼи, що підтримують сервіс.
Реалізація проксі сервісу відстежує набір обʼєктів Service та EndpointSlice і програмує панель даних для маршрутизації трафіку сервісу до його бекендів, використовуючи API операційної системи або хмарних провайдерів для перехоплення або переписування пакетів.
API Gateway (або його попередник Ingress) дозволяє зробити сервіси доступними для клієнтів поза кластером.
NetworkPolicy — це вбудований API Kubernetes, який дозволяє контролювати трафік між podʼами або між podʼами та зовнішнім світом.
У старіших контейнерних системах не було автоматичної зʼєднуваності між контейнерами на різних вузлах, тому часто було необхідно явно створювати посилання між контейнерами або призначати порти контейнерів на порти хосту, щоб зробити їх доступними для інших контейнерів. Це не потрібно в Kubernetes, оскільки модель Kubernetes передбачає, що podʼи можна розглядати подібно до віртуальних машин або фізичних хостів з погляду виділення портів, іменування, виявлення сервісів, балансування навантаження, налаштування застосунків та міграції.
Тільки кілька частин цієї моделі реалізовані безпосередньо Kubernetes. Для решти Kubernetes визначає API, але відповідна функціональність надається зовнішніми компонентами, деякі з яких є опціональними:
Налаштування простору імен мережі pod виконується системним програмним забезпеченням, яке реалізує Container Runtime Interface.
Мережею pod керує реалізація мережі pod. На Linux більшість середовищ виконання контейнерів використовують Container Networking Interface (CNI), щоб взаємодіяти з реалізацією мережі pod, тому ці реалізації часто називаються _CNI втулками.
Kubernetes надає стандартну реалізацію для проксі сервісів, яка називається kube-proxy, але деякі реалізації мережі pod використовують власний сервісний проксі, який тісніше інтегрований з іншими компонентами.
NetworkPolicy зазвичай також реалізується мережею pod. (Деякі простіші реалізації мережі pod не підтримують NetworkPolicy, або адміністратор може вирішити налаштувати мережу pod без підтримки NetworkPolicy. У таких випадках API буде присутній, але не матиме жодного ефекту.)
Існує багато реалізацій Gateway API, деякі з яких специфічні для певних хмарних середовищ, інші більше орієнтовані на середовища "bare metal", а інші є більш універсальними.
Стаття Мережа кластера пояснює, як налаштувати мережу для вашого кластера, а також надає огляд задіяних технологій.
1 - Service
Надайте доступ до застосунку, що працює в кластері, за допомогою однієї точки доступу, навіть якщо робота розподілена між декількома бекендами.
В Kubernetes, Service — це метод надання доступу ззовні до мережевого застосунку, який працює як один чи кілька Podʼів у вашому кластері.
Ключова мета Service в Kubernetes — це те, що вам не потрібно модифікувати ваш поточний застосунок для використання незнайомого механізму виявлення Service. Ви можете виконувати код в Podʼах, чи це буде код, призначений для світу, орієнтованого на хмари, або старий застосунок, який ви контейнеризували. Ви використовуєте Service, щоб зробити цей набір Podʼіів доступним в мережі, так щоб клієнти могли взаємодіяти з ним.
Якщо ви використовуєте Deployment для запуску вашого застосунку, цей Deployment може динамічно створювати та знищувати Podʼи. З одного моменту і до наступного, ви не знаєте, скільки з цих Podʼів працюють і є справними; ви навіть не можете знати,
як називаються ці справні Podʼи. Podʼи Kubernetes створюються та знищуються для відповідності бажаному стану вашого кластера. Podʼи є ефемерними ресурсами (ви не повинні очікувати, що індивідуальний Pod є надійним та довговічним).
Кожен Pod отримує свою власну IP-адресу (Kubernetes очікує, що мережеві втулки гарантують це). Для даного Deployment у вашому кластері набір Podʼів, який працює в один момент часу, може відрізнятися від набору Pod, який працює для цього застосунку наступний момент часу.
Це призводить до проблеми: якщо певний набір Podʼів (назвемо їх "backend") надає функціонал іншим Podʼам (назвемо їх "frontend") всередині вашого кластера, як фронтенд дізнається та відстежує, яку IP-адресу підключати, щоб він міг використовувати частину робочого навантаження?
Познайомтесь з Service.
Service в Kubernetes
API Service, що є частиною Kubernetes, є абстракцією, яка допомагає вам давати групі Podʼів доступ в мережі. Кожен обʼєкт Service визначає логічний набір endpoint (зазвичай endpoint — Pod) разом із політикою того, як робити ці Podʼи доступними.
Наприклад, розгляньте stateless бекенд для обробки зображень, який працює з 3 репліками. Ці репліки замінюються одна одною — фронтендам не важливо, який бекенд вони використовують. Хоча конкретні Podʼи, що складають бекенд, можуть змінюватися,
клієнти фронтенду не мають на це звертати уваги, і вони не повинні вести облік набору елементів бекендів самі.
Абстракція Service дозволяє таке відокремлення.
Набір Podʼів, яким призначається Service, зазвичай визначається
селектором, який ви визначаєте. Щоб дізнатися про інші способи визначення endpointʼів сервісу, дивіться Сервіси без селекторів.
Якщо ваше навантаження використовує HTTP, ви можете викорисовувати Ingress для контролю над тим, як вебтрафік досягає цього навантаження. Ingress не є типом сервісу, але він діє як точка входу до вашого кластера. Ingress дозволяє обʼєднати ваші правила маршрутизації в один ресурс, щоб ви могли
експонувати кілька компонентів вашого навантаження, що працюють окремо в вашому кластері, під одним зовнішнім URL.
API Gateway для Kubernetes надає додаткові можливості, які виходять за межі Ingress і Service. Ви можете додати Gateway до вашого кластера — це родина розширених API, реалізованих за допомогою CustomResourceDefinitions — і потім використовувати їх для налаштування доступу до мережевих сервісів, що працюють у вашому кластері.
Хмарно-нативне виявлення сервісів
Якщо ви можете використовувати API Kubernetes для виявлення сервісів у вашому застосунку, ви можете звертатись до сервера API
по відповідні EndpointSlices. Kubernetes оновлює EndpointSlices для сервісу кожного разу, коли набір Podʼів у сервісі змінюється.
Для не-нативних застосунків Kubernetes пропонує способи розміщення мережевого порту чи балансувальника між вашим застосунком та Podʼами бекенду.
В будь-якому випадку ваше навантаження може використовувати ці засоби виявлення сервісів для пошуку цільового сервісу, до якого воно хоче підʼєднатися.
Визначення Сервісу
Service — це обʼєкт (так само як Pod чи ConfigMap є обʼєктами). Ви можете створювати, переглядати або змінювати визначення Service, використовуючи API Kubernetes. Зазвичай для цього ви використовуєте інструмент, такий як kubectl, який звертається до API.
Наприклад, припустимо, у вас є набір Podʼів, які слухають TCP-порт 9376 і мають мітку app.kubernetes.io/name=MyApp. Ви можете визначити Сервіс, щоб
опублікувати цього TCP-слухача:
Застосування цього маніфесту створює новий Сервіс з назвою "my-service" зі стандартним типом служби ClusterIP. Сервіс обслуговує TCP-порт 9376 на будь-якому Podʼі з міткою app.kubernetes.io/name: MyApp.
Kubernetes призначає цьому Сервісу IP-адресу (так званий кластерний IP), що використовується механізмом віртуалізації IP-адрес. Для отримання докладнішої інформації про цей механізм, читайте Віртуальні IP та Проксі-сервіси.
Контролер для цього Сервісу постійно сканує Podʼи, які відповідають його селектору, а потім вносить будь-які необхідні оновлення до набору EndpointSlices для Сервісу.
Сервіс може повʼязувати будь-який вхідний port з targetPort. Типово та для зручності, targetPort встановлено на те ж саме значення, що й поле port.
Визначення портів
Визначення портів в Podʼах мають назви, і ви можете посилатися на ці назви в атрибуті targetPort Сервісу. Наприклад, ми можемо привʼязати targetPort Сервісу до порту Podʼа таким чином:
Це працює навіть у випадку, якщо у Сервісу є суміш Podʼів з використанням одного налаштованого імені, з однаковим мережевим протоколом, доступним через різні номери портів. Це надає багато гнучкості для розгортання та розвитку вашого Сервісу. Наприклад, ви можете змінити номери портів, які Podʼи прослуховують в наступній версії вашого програмного забезпечення бекенду, без руйнівних наслідків для клієнтів.
Станадртним протоколом для Service є TCP; ви також можете використовувати будь-який інший підтримуваний протокол.
Оскільки багато Сервісів повинні працювати більше ніж з одним портом, Kubernetes підтримує визначення кількох портів для одного Сервісу. Кожне визначення порту може мати той же протокол або різні.
Сервіси без селекторів
Сервіси найчастіше абстрагують доступ до Podʼів Kubernetes завдяки селектору, але коли вони використовуються разом із відповідним набором EndpointSlices обʼєктів та без селектора, Сервіс може абстрагувати інші типи бекендів, включаючи ті, які працюють поза кластером.
Наприклад:
Ви хочете мати зовнішній кластер баз даних у вашому експлуатаційному оточенні, але у своєму тестовому середовищі ви використовуєте свої власні бази даних.
Ви хочете спрямувати ваш Сервіс на Сервіс в іншому Namespace чи в іншому кластері.
Ви мігруєте робоче навантаження в Kubernetes. Під час оцінки цього підходу, ви запускаєте лише частину своїх бекендів в Kubernetes.
У будь-якому з цих сценаріїв ви можете визначити Сервіс без вказівки селектора для відповідності Podʼам. Наприклад:
Оскільки у цього Сервісу немає селектора, відповідні обʼєкти EndpointSlice (та застарілі Endpoints) не створюються автоматично. Ви можете повʼязувати Сервіс з мережевою адресою та портом, де він працює, додавши обʼєкт EndpointSlice вручну. Наприклад:
apiVersion:discovery.k8s.io/v1kind:EndpointSlicemetadata:name:my-service-1# за звичай, використовуйте назву Сервісу# як префікс для назви EndpointSlicelabels:# Ви повинні встановити мітку "kubernetes.io/service-name".# Встановіть її значення, щоб відповідати назві Сервісуkubernetes.io/service-name:my-serviceaddressType:IPv4ports:- name:http# Має збігатись з іменем порту у визначенні Service# визначеному вищеappProtocol:httpprotocol:TCPport:9376endpoints:- addresses:- "10.4.5.6"- addresses:- "10.1.2.3"
Власні EndpointSlices
Коли ви створюєте обʼєкт EndpointSlice для Сервісу, ви можете
використовувати будь-яку назву для EndpointSlice. Кожен EndpointSlice в просторі імен повинен мати унікальну назву. Ви поєднуєте EndpointSlice із Сервісом, встановлюючи labelkubernetes.io/service-name на цьому EndpointSlice.
Примітка:
IP-адреси endpoint не повинні бути: локальними (127.0.0.0/8 для IPv4, ::1/128 для IPv6), або (169.254.0.0/16 та 224.0.0.0/24 для IPv4, fe80::/64 для IPv6).
IP-адреси endpoint не можуть бути кластерними IP-адресами інших Сервісів Kubernetes, оскільки kube-proxy не підтримує віртуальні IP-адреси як призначення.
Для EndpointSlice, який ви створюєте самостійно або у своєму власному коді,
вам також слід вибрати значення для мітки endpointslice.kubernetes.io/managed-by. Якщо ви створюєте свій власний код контролера для управління EndpointSlice, розгляньте можливість використання значення, схожого на "my-domain.example/name-of-controller". Якщо ви використовуєте інструмент від стороннього постачальника, використовуйте назву інструменту в нижньому регістрі та замініть пробіли та інші знаки пунктуації на дефіси (-). Якщо ви безпосередньо використовуєте інструмент, такий як kubectl, для управління EndpointSlice, використовуйте назву, яка описує це ручне управління, таку як "staff" або "cluster-admins". Ви повинні уникати використання захищеного значення "controller", яке ідентифікує EndpointSlices, які керуються власною панеллю управління Kubernetes.
Доступ до Сервісу без селектора
Доступ до Сервісу без селектора працює так само, якби він мав селектор. У прикладі Сервісу без селектора, трафік маршрутизується до одного з двох endpoint, визначених у маніфесті EndpointSlice: TCP-зʼєднання до 10.1.2.3 або 10.4.5.6, на порт 9376.
Примітка:
Сервер API Kubernetes не дозволяє проксіювання до endpoint, які не повʼязані з Podʼами. Дії, такі як kubectl port-forward service/<service-name> forwardedPort:servicePort, де сервіс не має селектора, зазнають збою через це обмеження. Це запобігає використанню сервера API Kubernetes як проксі до endpoint, до яких викликач може не мати авторизації на доступ.
ExternalName Сервіс — це особливий випадок Сервісу, який не має селекторів і використовує DNS-імена замість них. Для отримання доклдадної інформації, див. розділ
ExternalName.
EndpointSlices
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.21 [stable]
EndpointSlices — це обʼєкти, які представляють підмножину (зріз) мережевих endpoint, які підтримують Сервіс.
Ваш кластер Kubernetes відстежує кількість endpointʼів, які представляє кожен EndpointSlice. Якщо для Сервісу є настільки багато endpointʼів, що досягається порогове значення, тоді Kubernetes додає ще один порожній EndpointSlice і зберігає там нову інформацію про endpoint. Типово Kubernetes створює новий EndpointSlice, як тільки наявні EndpointSlice всі містять принаймні 100 endpoint. Kubernetes не створює новий EndpointSlice, поки не буде потрібно додати додатковий endpoint.
Див. EndpointSlices для отримання додаткової інформації про цей API.
Endpoint
В API Kubernetes, Endpoints (тип ресурсу у множині) визначають список мережевих endpointʼів, зазвичай використовується Сервісом для визначення того, до яких Podʼів можна направляти трафік.
API EndpointSlice — це рекомендована заміна для Endpoints.
Endpoints з перевищеним обсягом
Kubernetes обмежує кількість endpointʼів, які можуть поміститися в один обʼєкт Endpoints. Коли є понад 1000 endpointʼів, які підтримують Сервіс, Kubernetes розмішує дані в обʼєкті Endpoints. Оскільки Сервіс може бути повʼязаним
з більше ніж одним EndpointSlice, обмеження в 1000 endpointʼів впливає лише
на застарілий API Endpoints.
У цьому випадку Kubernetes вибирає не більше 1000 можливих endpointʼів, які слід зберегти в обʼєкті Endpoints, і встановлює анотацію на Endpoints: endpoints.kubernetes.io/over-capacity: truncated. Панель управління також видаляє цю анотацію, якщо кількість бекенд-Podʼів впадає нижче 1000.
Трафік все ще відсилається на бекенди, але будь-який механізм балансування навантаження, який покладається на застарілий API Endpoints, відсилає трафік не більше, ніж до 1000 доступних бекенд-endpointʼів.
Той самий ліміт API означає, що ви не можете вручну оновлювати Endpoints так, щоб у них було понад 1000 endpointʼів.
Протокол застосунку
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.20 [stable]
Поле appProtocol надає можливість вказати протокол застосунку для кожного порту Сервісу. Це використовується як підказка для реалізацій для надання розширеної поведінки для протоколів, які вони розуміють. Значення цього поля відображається відповідними обʼєктами Endpoints та EndpointSlice.
Це поле відповідає стандартному синтаксису міток Kubernetes. Дійсні значення — це одне з:
Для деяких Сервісів вам може знадобитися використовувати більше одного порту. Kubernetes дозволяє конфігурувати кілька визначень портів в обʼєкті Service. При використанні кількох портів для Сервісу, вам слід надавати всім портам імена,
щоб вони були однозначними. Наприклад:
Так само як і з іменами в Kubernetes взагалі, імена портів мають містити лише буквено-цифрові символи в нижньому регістрі та -. Імена портів також повинні починатися та закінчуватися буквено-цифровим символом.
Наприклад, імена 123-abc та web є допустимими, але 123_abc та -web - ні.
Тип Сервісу
Для деяких частин вашого застосунку (наприклад, фронтенду) ви можете знадобитись звʼязати Сервіс з зовнішньою IP-адресою, доступну з-поза вашого кластера.
Типи Сервісів Kubernetes дозволяють вам вказати, який тип Сервісу ви потрібен.
Повʼязує Сервіс з внутрішньою IP-адресою кластера. Вибір цього значення робить Сервіс доступним лише зсередини кластера. Це значення використовується стандартно, якщо ви не вказали явно type для Сервісу. Ви можете дати Сервісу доступ в Інтернет за допомогою Ingress або Gateway.
Повʼязує Сервіс на кожному IP-адресі вузла зі статичним портом (NodePort). Щоб зробити порт вузла доступним, Kubernetes налаштовує IP-адресу кластера, так само якби ви запросили Сервіс з type: ClusterIP.
Повʼязує Сервіс із зовнішніми споживачами за допомогою зовнішнього балансувальника навантаження. Kubernetes не надає безпосередньо компонент балансування навантаження; вам слід надати його, або ви можете інтегрувати свій кластер Kubernetes з постачальником хмарних послуг.
Повʼязує Сервіс зі змістом поля externalName (наприклад, на імʼя хоста api.foo.bar.example). Це конфігурує сервер DNS вашого кластера повертати запис CNAME з вказаною зовнішньою назвою хосту. Ніякого проксінгу не налаштовується.
Поле type в API Сервісу розроблене як вкладена функціональність — кожен рівень додається до попереднього. Однак існує виняток з цього вкладеного дизайну. Ви можете визначити Сервіс LoadBalancer, відключивши використання порту вузла для балансування навантаження.
type: ClusterIP
Цей тип Сервісу типово призначає IP-адресу з пулу IP-адрес, який ваш кластер зарезервував для цієї мети.
Кілька інших типів Сервісу базуються на типі ClusterIP.
Якщо ви визначаєте Сервіс, у якому .spec.clusterIP встановлено в "None", тоді Kubernetes не призначає IP-адресу. Див. сервіси headless для отримання додаткової інформації.
Вибір власної IP-адреси
Ви можете вказати власну IP-адресу кластера як частину запиту на створення Service. Для цього встановіть поле .spec.clusterIP. Наприклад, якщо у вас вже є наявний запис DNS, який ви хочете повторно використовувати, або старі системи, які налаштовані на певну IP-адресу і важко переналаштовуються.
IP-адреса, яку ви вибираєте, повинна бути дійсною IPv4 або IPv6 адресою з діапазону CIDR, який налаштований для сервера API за допомогою service-cluster-ip-range. Якщо ви намагаєтеся створити Сервіс із недійсною IP-адресою clusterIP, сервер API поверне HTTP-відповідь зі статус-кодом 422 для позначення проблеми.
Читайте уникнення конфліктів, щоб дізнатися, як Kubernetes допомагає зменшити ризик та вплив двох різних Сервісів, що намагаються використовувати однакову IP-адресу.
type: NodePort
Якщо ви встановлюєте поле type в NodePort, панель управління Kubernetes виділяє порт з діапазону, вказаного прапорцем --service-node-port-range (типово: 30000-32767). Кожен вузол проксіює цей порт (той самий номер порту на кожному вузлі) у ваш Сервіс. Ваш Сервіс повідомляє виділений порт у полі .spec.ports[*].nodePort.
Використання NodePort дає вам свободу налаштувати власне рішення з балансування навантаження, конфігурувати середовища, які не повністю підтримуються Kubernetes, або навіть експонувати один або кілька IP-адрес вузлів безпосередньо.
Для Сервісу з портом вузла Kubernetes додатково виділяє порт (TCP, UDP або SCTP для відповідності протоколу Сервісу). Кожен вузол у кластері конфігурується на прослуховування цього призначеного порту і пересилання трафіку на одну з готових точок доступу, повʼязаних із цим Сервісом. Ви зможете звертатися до Сервісу з type: NodePort, ззовні кластера, підключаючись до будь-якого вузла за відповідним протоколом (наприклад: TCP) та відповідним портом (який призначено цьому Сервісу).
Вибір власного порту
Якщо вам потрібен певний номер порту, ви можете вказати значення у полі nodePort.Панель управління вибере для вас цей порт або повідомить, що транзакція API не вдалася. Це означає, що вам потрібно самостійно дбати про можливі конфлікти портів. Вам також слід використовувати дійсний номер порту, який знаходиться в межах налаштованого діапазону для використання NodePort.
Ось приклад маніфесту для Сервісу з type: NodePort, який вказує значення NodePort (30007 у цьому прикладі):
apiVersion:v1kind:Servicemetadata:name:my-servicespec:type:NodePortselector:app.kubernetes.io/name:MyAppports:- port:80# Стандартно та для зручності, `targetPort` встановлено# в те ж значення, що й поле `port`.targetPort:80# Необовʼязкове поле# Стандартно та для зручності, панель управління Kubernetes# виділить порт з діапазону (станадртно: 30000-32767)nodePort:30007
Резервування діапазонів NodePort для уникнення конфліктів
Політика виділення портів для NodePort-сервісів застосовується як до автоматичного, так і до ручного виділення. Коли користувач хоче створити NodePort-сервіс, який використовує певний порт, цей цільовий порт може конфліктувати з іншим портом, який вже виділено.
Щоб уникнути цієї проблеми, діапазон портів для NodePort-сервісів розбито на дві частини. Типово для динамічного виділення портів використовується верхній діапазон, і він може використовувати нижній діапазон, якщо верхній діапазон вичерпано. Користувачі можуть виділяти порти з нижнього діапазону з меншим ризиком конфлікту портів.
Налаштування власної IP-адреси для Сервісів type: NodePort
Ви можете налаштувати вузли у своєму кластері використовувати певну IP-адресу для обслуговування сервісів з портом вузла. Ви можете це зробити, якщо кожен вузол підключений до декількох мереж (наприклад: одна мережа для трафіку застосунків, а інша мережа для трафіку між вузлами та панеллю управління).
Якщо ви хочете вказати певні IP-адреси для проксі-порта, ви можете встановити прапорець --nodeport-addresses для kube-proxy або еквівалентне поле nodePortAddresses у файлі конфігурації kube-proxy на конкретні блоки IP.
Цей прапорець приймає список IP-блоків через кому (наприклад, 10.0.0.0/8, 192.0.2.0/25) для вказівки діапазонів IP-адрес, які kube-proxy повинен вважати локальними для цього вузла.
Наприклад, якщо ви запускаєте kube-proxy з прапорцем --nodeport-addresses=127.0.0.0/8, kube-proxy вибирає лише інтерфейс loopback для NodePort-сервісів. Типово для --nodeport-addresses є порожній список. Це означає, що kube-proxy повинен вважати всі доступні мережеві інтерфейси локальними для NodePort. (Це також сумісно з раніше випущеними версіями Kubernetes.)
Примітка:
Цей Сервіс видно як <NodeIP>:spec.ports[*].nodePort та .spec.clusterIP:spec.ports[*].port. Якщо встановлено прапорець --nodeport-addresses для kube-proxy або еквівалентне поле у файлі конфігурації kube-proxy, <NodeIP> буде IP-адресою вузла (або можливо IP-адресами) для фільтрування.
type: LoadBalancer
У хмарних постачальників, які підтримують зовнішні балансувальники навантаження, встановлення поле type в LoadBalancer надає балансувальник навантаження для вашого Сервісу. Створення балансувальника навантаження відбувається асинхронно, і інформація про створений балансувальник публікується у поле .status.loadBalancer Сервісу. Наприклад:
Трафік від зовнішнього балансувальника навантаження направляється на бекенд-Podʼи. Хмарний постачальник вирішує, як він балансує навантаження.
Для реалізації Сервісу з type: LoadBalancer, Kubernetes зазвичай починає з того, що вносить зміни, які еквівалентні вашим запитам на Сервіс type: NodePort. Компонент cloud-controller-manager потім налаштовує зовнішній балансувальник для пересилання трафіку на цей призначений порт вузла.
Ви можете налаштувати балансований за навантаженням Сервіс для виключення призначення порта вузла, за умови, що реалізація постачальника хмари це підтримує.
Деякі постачальники хмар дозволяють вам вказати loadBalancerIP. У цих випадках балансувальник створюється з вказаною користувачем loadBalancerIP. Якщо поле loadBalancerIP не вказано, то балансувальник налаштовується з ефемерною IP-адресою. Якщо ви вказали loadBalancerIP, але ваш постачальник хмари не підтримує цю функцію, то вказане вами поле loadbalancerIP ігнорується.
Примітка:
Поле .spec.loadBalancerIP для Сервісу було визнане застарілим в Kubernetes v1.24.
Це поле було недостатньо визначеним, і його значення різниться в різних реалізаціях. Воно також не підтримує мережі з подвійним стеком. Це поле може бути вилучено в майбутніх версіях API.
Якщо ви інтегруєтеся з постачальником, який підтримує вказання IP-адреси(в) балансувальника навантаження для Сервісу через анотацію (специфічну для постачальника), вам слід перейти на цей метод.
Якщо ви пишете код для інтеграції балансувальника з Kubernetes, уникайте використання цього поля. Ви можете інтегрувати його з Gateway замість Service, або ви можете визначити власні анотації (специфічні для постачальника) для Сервісу, які визначають еквівалентну деталь.
Вплив життєздатності вузла на трафік балансувальника навантаження
Перевірки стану балансувальника навантаження є критичними для сучасних застосунків. Вони використовуються для визначення того, на який сервер (віртуальна машина або IP-адреса) повинен бути направлений трафік балансувальника навантаження. API Kubernetes не визначає, як мають бути реалізовані перевірки стану для керованих Kubernetes балансувальників навантаження; замість цього це роблять хмарні постачальники (і люди, які створюють код інтеграції), які визначають поведінку. Перевірки стану балансувальника навантаження широко використовуються в контексті підтримки поля externalTrafficPolicy для Service.
Балансувальники з мішаними типами протоколів
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.26 [stable] (стандартно увімкнено: true)
Типово для Сервісів типу LoadBalancer, коли визначено більше одного порту, всі порти повинні мати один і той же протокол, і цей протокол повинен бути підтримуваний
постачальником хмари.
Feature gate MixedProtocolLBService (стандартно увімкнено для kube-apiserver з версії v1.24) дозволяє використовувати різні протоколи для Сервісів типу LoadBalancer, коли визначено більше одного порту.
Примітка:
Набір протоколів, які можна використовувати для балансованих навантажень Сервісів, визначається вашим постачальником хмари; вони можуть накладати обмеження поза тим, що накладає API Kubernetes.
Вимкнення виділення порту вузла для балансувальника навантаження
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.24 [stable]
Ви можете вимкнути виділення порту вузла для Сервісу з type: LoadBalancer, встановивши поле spec.allocateLoadBalancerNodePorts в false. Це слід використовувати тільки для реалізацій балансувальників, які маршрутизують трафік безпосередньо до Podʼів, а не використовують порти вузла. Стандартно spec.allocateLoadBalancerNodePorts дорівнює true, і Сервіси типу LoadBalancer будуть продовжувати виділяти порти вузла. Якщо spec.allocateLoadBalancerNodePorts встановлено в false для існуючого Сервісу з виділеними портами вузла, ці порти вузла не будуть автоматично видалятися. Вам слід явно видалити запис nodePorts в кожному порту Сервісу для деалокації цих портів вузла.
Вказання класу реалізації балансувальника
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.24 [stable]
Для Сервісу з type встановленим на LoadBalancer, поле .spec.loadBalancerClass
дозволяє вам використовувати реалізацію балансувальника, відмінну від тієї, яку типово встановлено постачальником хмари.
Типово .spec.loadBalancerClass не встановлено, і Сервіс з LoadBalancer використовує реалізацію балансувальника що постачається в хмарі, якщо кластер налаштовано постачальником хмари за допомогою прапорця компоненту --cloud-provider. Якщо ви вказуєте .spec.loadBalancerClass, вважається, що реалізація балансувальника, яка відповідає вказаному класу, відстежує Сервіси. Будь-яка стандартн реалізація балансувальника (наприклад, та, яку надає постачальник хмари), ігнорує Сервіси, у яких встановлено це поле. spec.loadBalancerClass може бути встановлено тільки для Сервісу типу LoadBalancer. Після встановлення його не можна змінити. Значення spec.loadBalancerClass повинно бути ідентифікатором у формі мітки, з необовʼязковим префіксом, таким як "internal-vip" або "example.com/internal-vip". Безпрефіксні імена зарезервовані для кінцевих користувачів.
Режим IP-адреси балансувальника навантаження
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.32 [stable] (стандартно увімкнено: true)
Для Service з типом type: LoadBalancer, контролер може встановити .status.loadBalancer.ingress.ipMode. .status.loadBalancer.ingress.ipMode вказує, як веде себе IP-адреса балансувальника. Воно може бути вказано лише тоді, коли вказано поле .status.loadBalancer.ingress.ip.
Є два можливі значення для .status.loadBalancer.ingress.ipMode: "VIP" та "Proxy".Типово встановлене значення "VIP", що означає, що трафік подається на вузол з призначенням, встановленим на IP та порт балансувальника. Є два випадки, коли встановлено значення "Proxy", залежно від того, як постачальник хмари балансує трафік:
Якщо трафік подається на вузол, а потім перенаправляється до Podʼа, призначення буде встановлено на IP та порт вузла;
Якщо трафік подається безпосередньо до Podʼа, призначення буде встановлено на IP та порт Podʼа.
Реалізації Сервісів можуть використовувати цю інформацію для налаштування маршрутизації трафіку.
Внутрішній балансувальник
У змішаному середовищі іноді необхідно направляти трафік від Сервісів всередині того ж (віртуального) мережевого блоку.
У середовищі DNS із подвійним горизонтом вам може знадобитися два Сервіси для маршрутизації зовнішнього і внутрішнього трафіку до ваших ендпоінтів.
Щоб встановити внутрішній балансувальник, додайте одну з наступних анотацій до Сервісу в залежності від постачальника хмари, який ви використовуєте:
Сервіси типу ExternalName звʼязують Сервіс з DNS-іменем, а не на типовим селектором, таким як my-service або cassandra. Ви вказуєте ці Сервіси параметром spec.externalName.
Наприклад, це визначення Сервісу звʼязує Сервіс my-service в просторі імен prod з my.database.example.com:
Сервіс типу ExternalName приймає рядок IPv4 адреси, але трактує цей рядок як імʼя DNS, що складається з цифр, а не як IP-адресу (інтернет, однак, не дозволяє такі імена в DNS). Сервіси зовнішніх імен, які нагадують IPv4 адреси, не вирішуються DNS-серверами.
Якщо ви хочете звʼязати Сервіс безпосередньо з конкретною IP-адресою, розгляньте можливість використання headless Services.
При пошуку хоста my-service.prod.svc.cluster.local, DNS-сервіс кластера повертає запис CNAME із значенням my.database.example.com. Доступ до my-service працює так само, як і для інших Сервісів, але з важливою різницею в тому, що перенаправлення відбувається на рівні DNS, а не через проксі або переадресацію. Якщо ви пізніше вирішите перемістити свою базу даних в кластер, ви можете запустити його Podʼи, додати відповідні селектори чи endpointʼи та змінити тип Сервісу.
Увага:
Можливі проблеми з використанням ExternalName для деяких загальних протоколів, таких як HTTP та HTTPS. Якщо ви використовуєте ExternalName, імʼя хоста, яке використовують клієнти всередині вашого кластера, відрізняється від
імені, на яке посилається ExternalName.
Для протоколів, які використовують імена хостів, ця різниця може призвести до помилок або непередбачуваних відповідей. HTTP-запити матимуть заголовок Host:, який сервер-джерело не визнає; сервери TLS не зможуть надати сертифікат, що відповідає імені хоста, до якого приєдно клієнта.
Headless Services
Іноді вам не потрібен балансувальник навантаження та одна IP-адреса Сервісу. У цьому випадку ви можете створити так звані headless Services, якщо явно вказати "None" для IP-адреси кластера (.spec.clusterIP).
Ви можете використовувати headless Сервіс для взаємодії з іншими механізмами виявлення служб, не будучи привʼязаним до реалізації Kubernetes.
Для headless Сервісів кластерна IP-адреса не видається, kube-proxy не обслуговує ці Сервіси, і для них платформа не виконує балансування навантаження чи проксіюваня.
Headless Сервіси дозволяють клієнту приєднуватись до будь-якого Pod безпосередньо. Ці Сервіси не встановлюють маршрути та перенаправлення пакетів з використанням віртуальних IP-адрес та проксі; натомість вони повідомляють про IP-адреси точок доступу окремих Podʼів через внутрішні записи DNS, які обслуговуються службою DNS кластера. Для визначення headless Сервіса вам потрібно створити Service з .spec.type встановленим на ClusterIP (що також є типовим значенням) та .spec.clusterIP встановленим у None.
Рядкове значення None є спеціальним випадком та не є тотожноми тому, якщо поле .spec.clusterIP не вказане.
Те, як автоматично налаштовано DNS, залежить від того, чи визначені селектори Сервісу:
З селекторами
Для headless Сервісів, які визначають селектори, контролер endpointʼів створює обʼєкти EndpointSlice в Kubernetes API та змінює конфігурацію DNS так, щоб повертати записи A або AAAA (IPv4 або IPv6 адреси), які напрямую вказують на Podʼи, які підтримують Сервіс.
Без селекторів
Для headless Сервісів, які не визначають селектори, панель управління не створює обʼєкти EndpointSlice. Проте система DNS шукає та налаштовує або:
DNS-записи A / AAAA для всіх IP-адрес Сервісу з готовими endpointʼами, для всіх типів Сервісів, крім ExternalName.
Для IPv4 endpointʼів система DNS створює A-записи.
Для IPv6 endpointʼів система DNS створює AAAA-записи.
Коли ви визначаєте headless Сервіс без селектора, поле port повинно відповідати полю targetPort.
Виявлення сервісів
Для клієнтів, що працюють всередині вашого кластера, Kubernetes підтримує два основних способи виявлення Сервісу: змінні середовища та DNS.
Змінні середовища
Коли Pod запускається на вузлі, kubelet додає набір змінних середовища для кожного активного Сервісу. Додаються змінні середовища {SVCNAME}_SERVICE_HOST та {SVCNAME}_SERVICE_PORT, де імʼя Сервісу перетворюється у верхній регістр, а тире конвертуються у підкреслення.
Наприклад, Сервіс redis-primary, який використовує TCP-порт 6379 та має присвоєну IP-адресу кластера 10.0.0.11, створює наступні змінні середовища:
Коли у вас є Pod, який потребує доступу до Сервісу, і ви використовуєте метод змінної середовища для публікації порту та кластерного IP для Podʼів клієнта, ви повинні створити Сервіс перед створенням Podʼів клієнта. В іншому випадку ці Podʼи клієнта не матимуть заповнених змінних середовища.
Якщо ви використовуєте лише DNS для визначення кластерного IP для Сервісу, вам не потрібно турбуватися про цю проблему порядку.
Kubernetes також підтримує та надає змінні, які сумісні з "legacy container links" Docker Engine. Ви можете переглянути makeLinkVariables щоб побачити, як це реалізовано в Kubernetes.
DNS
Ви можете (і майже завжди повинні) налаштувати службу DNS для вашого кластера Kubernetes, використовуючи надбудову.
Сервер DNS, знається на кластерах, такий як CoreDNS, стежить за Kubernetes API для виявлення нових Сервісів і створює набір DNS-записів для кожного з них. Якщо DNS увімкнено в усьому кластері, то всі Podʼи повинні автоматично мати можливість знаходити Сервіси за їхнім DNS-імʼям.
Наприклад, якщо у вас є Сервіс з назвою my-service в просторі імен Kubernetes my-ns, то разом панель управління та служба DNS створюють DNS-запис для my-service.my-ns. Podʼи в просторі імен my-ns повинні мати можливість знаходити Сервіс, роблячи запит за іменем my-service (my-service.my-ns також працюватиме).
Podʼи в інших просторах імен повинні вказати імʼя як my-service.my-ns. Ці імена будуть розповсюджуватись на призначений кластером IP для Сервісу.
Kubernetes також підтримує DNS SRV (Service) записи для іменованих портів. Якщо Сервіс my-service.my-ns має порт з іменем http і протоколом, встановленим в TCP, ви можете виконати DNS SRV-запит для _http._tcp.my-service.my-ns, щоб дізнатися номер порту для http, а також IP-адресу.
Сервер DNS Kubernetes — єдиний спосіб доступу до Сервісів ExternalName. Ви можете знайти більше інформації про вирішення ExternalName в DNS для Сервісів та Podʼів.
Ви можете встановити поля .spec.internalTrafficPolicy та .spec.externalTrafficPolicy, щоб контролювати, як Kubernetes маршрутизує трафік до справних ("готових") бекендів.
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.31 [beta] (стандартно увімкнено: true)
Поле .spec.trafficDistribution надає ще один спосіб впливу на маршрутизацію трафіку в межах Сервісу Kubernetes. Хоча політика трафіку зосереджується на строгих семантичних гарантіях, розподіл трафіку дозволяє виражати уподобання (наприклад, маршрутизацію до топологічно ближчих точок доступу). Це може допомогти оптимізувати продуктивність, вартість або надійність. Це необовʼязкове поле можна використовувати, якщо ви ввімкнули функціональну можливістьServiceTrafficDistribution для вашого кластера та всіх його вузлів. У Kubernetes 1.32, підтримується таке значення поля:
PreferClose
Вказує на уподобання маршрутизації трафіку до точок доступу, які є топологічно близькими до клієнта. Інтерпретація "топологічної близькості" може варіюватися в залежності від реалізацій і може охоплювати точки доступу всередині того самого вузла, стійки, зони або навіть регіони. Встановлення цього значення надає реалізаціям дозвіл на прийняття різних компромісів, наприклад, оптимізацію на користь близькості замість рівномірного розподілу навантаження. Користувачам не слід встановлювати це значення, якщо такі компроміси неприйнятні.
Якщо поле не встановлено, реалізація застосує свою стандартну стратегію маршрутизації.
Якщо ви хочете переконатися, що зʼєднання з певного клієнта щоразу передаються до одного і того ж Pod, ви можете налаштувати спорідненість сеансу на основі IP-адреси клієнта. Докладніше читайте спорідненість сесії.
Зовнішні IP
Якщо існують зовнішні IP-адреси, які маршрутизують до одного чи декількох вузлів кластера, Сервіси Kubernetes можна використовувати на цих externalIPs. Коли мережевий трафік потрапляє в кластер із зовнішнім IP (як IP призначення) та портом, який відповідає цьому Сервісу, правила та маршрути, які Kubernetes налаштовує, забезпечують маршрутизацію трафіку до одного з кінцевих пунктів цього Сервісу.
При визначенні Сервісу ви можете вказати externalIPs для будь-якого типу сервісу. У наведеному нижче прикладі Сервіс з іменем "my-service" може отримати доступ від клієнтів за допомогою TCP за адресою "198.51.100.32:80" (розраховано із .spec.externalIPs[] та .spec.ports[].port).
Робить вашу мережеву службу HTTP (або HTTPS) доступною за допомогою конфігурації, яка розуміє протокол та враховує вебконцепції, такі як URI, імена хостів, шляхи та інше. Концепція Ingress дозволяє вам направляти трафік на різні бекенди на основі правил, які ви визначаєте через API Kubernetes.
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.19 [stable]
Обʼєкт API, який управляє зовнішнім доступом до служб в кластері, зазвичай HTTP.
Ingress може надавати балансування навантаження, розшифровування SSL-трафіку та віртуальний хостинг на основі імен.
Примітка:
Ingress заморожений. Нові функції додаються до Gateway API.
Термінологія
Для ясності цей посібник визначає наступні терміни:
Вузол: Робоча машина в Kubernetes, що є частиною кластера.
Кластер: Набір вузлів, на яких виконуються контейнеризовані застосунки, керовані Kubernetes. У прикладі та в більшості типових розгортань Kubernetes вузли кластера не є частиною відкритої мережі Інтернет.
Edge маршрутизатор: Маршрутизатор, який застосовує політику брандмауера для вашого кластера. Це може бути шлюз, керований хмарним постачальником, або фізичний пристрій.
Кластерна мережа: Набір зʼєднань, логічних або фізичних, які сприяють комунікації в межах кластера згідно з мережевою моделлю Kubernetes.
Service: Service Kubernetes, що ідентифікує набір Podʼів за допомогою селекторів label. Якщо не вказано інше, припускається, що служби мають віртуальні IP-адреси, які можна маршрутизувати лише в межах кластерної мережі.
Що таке Ingress?
Ingress відкриває маршрути HTTP та HTTPS із зовні кластера до Services всередині кластера. Маршрутизацію трафіку контролюють правила, визначені в ресурсі Ingress.
Ось простий приклад, де Ingress спрямовує весь свій трафік на один Service:Схема. Ingress
Ingress може бути налаштований таким чином, щоб надавати Service зовнішньодоступні URL, балансувати трафік, термінувати SSL/TLS та пропонувати іменований віртуальний хостинг. Контролер Ingress відповідає за виконання Ingress, зазвичай з допомогою балансувальника навантаження, хоча він також може конфігурувати ваш edge маршрутизатор або додаткові фронтенди для допомоги в обробці трафіку.
Ingress не відкриває довільні порти або протоколи. Для експозиції служб, відмінних від HTTP та HTTPS, в Інтернет зазвичай використовується служба типу Service.Type=NodePort або
Service.Type=LoadBalancer.
Передумови
Вам потрібно мати контролер Ingress, щоб виконувати Ingress. Лише створення ресурсу Ingress не має ефекту.
Для Ingress необхідні поля apiVersion, kind, metadata та spec.
Назва обʼєкта Ingress повинна бути дійсним DNS-піддоменом. Для загальної інформації щодо роботи з файлами конфігурації дивіться розгортання застосунків, налаштування контейнерів, управління ресурсами. Ingress часто використовує анотації для налаштування деяких параметрів залежно від контролера Ingress, прикладом чого є анотація для перезапису. Різні контролери Ingress підтримують різні анотації. Ознайомтеся з документацією контролера Ingress, який ви вибрали, щоб дізнатися, які анотації підтримуються.
У специфікації Ingress міститься вся інформація, необхідна для налаштування балансувальника навантаження чи проксі-сервера. Важливою є наявність списку правил, які порівнюються з усіма вхідними запитами. Ресурс Ingress підтримує правила тільки для направлення трафіку HTTP(S).
Є контролери Ingress, які працюють без визначення типового IngressClass. Наприклад, контролер Ingress-NGINX може бути налаштований за допомогою прапора--watch-ingress-without-class. З усім тим, рекомендується вказати типовий IngressClass, як показано нижче.
Правила Ingress
Кожне правило HTTP містить наступну інформацію:
Необовʼязковий хост. У цьому прикладі хост не вказаний, тому правило застосовується до всього вхідного HTTP-трафіку через вказану IP-адресу. Якщо вказано хост (наприклад, foo.bar.com), правила застосовуються до цього хосту.
Список шляхів (наприклад, /testpath), кожен з яких має повʼязаний бекенд, визначений імʼям service.name та service.port.name або service.port.number. Як хост, так і шлях повинні відповідати вмісту вхідного запиту, перш ніж балансувальник навантаження направить трафік до зазначеного Service.
Бекенд — це комбінація імені Service та порту, як описано в документації Service або ресурсом бекенду користувача за допомогою CRD. HTTP (та HTTPS) запити до Ingress, які відповідають хосту та шляху правила, надсилаються до вказаного бекенду.
Зазвичай в Ingress контролері налаштований defaultBackend, який обслуговує будь-які запити, які не відповідають шляху в специфікації.
DefaultBackend
Ingress без правил спрямовує весь трафік до єдиного стандартного бекенду, і .spec.defaultBackend — це бекенд, який повинен обробляти запити в цьому випадку. Зазвичай defaultBackend — це опція конфігурації контролера Ingress і не вказується в ресурсах вашого Ingress. Якщо не вказано .spec.rules, то повинен бути вказаний .spec.defaultBackend. Якщо defaultBackend не встановлено, обробка запитів, які не відповідають жодному з правил, буде покладена на контролер ingress (звертайтеся до документації свого контролера Ingress, щоб дізнатися, як він обробляє цей випадок).
Якщо жоден із хостів або шляхів не відповідає HTTP-запиту в обʼєктах Ingress, трафік направляється до вашого стандартного бекенду.
Бекенд Resource
Бекенд Resource — це ObjectRef на інший ресурс Kubernetes всередині того ж простору імен, що й обʼєкт Ingress. Resource — є несумісним з Service, перевірка налаштувань виявить помилку, якщо вказані обидва. Звичайне використання для бекенду Resource — це направлення даних в обʼєкт зберігання зі статичними ресурсами.
Для кожного шляху в Ingress обовʼязково повинен бути відповідний тип шляху. Шляхи, які не включають явний pathType, не пройдуть валідацію. Існує три типи шляхів, що підтримуються:
ImplementationSpecific: З цим типом шляху визначення відповідності залежить від IngressClass. Реалізації можуть розглядати це як окремий pathType або обробляти його так само як типи шляхів Prefix або Exact.
Exact: Відповідає URL-шляху точно і з урахуванням регістрів.
Prefix: Відповідає на основі префіксу URL-шляху, розділеному /. Відповідність визначається з урахуванням регістру і виконується поелементно за кожним елементом шляху. Елемент шляху вказує на список міток у шляху, розділених роздільником /. Запит відповідає шляху p, якщо кожен p є префіксом елемента p запиту.
Примітка:
Якщо останній елемент шляху є підрядком останнього елементу в шляху запиту, це не вважається відповідністю (наприклад: /foo/bar відповідає /foo/bar/baz, але не відповідає /foo/barbaz).
Приклади
Тип
Шлях(и)
Шлях запиту
Відповідає?
Префікс
/
(всі шляхи)
Так
Точний
/foo
/foo
Так
Точний
/foo
/bar
Ні
Точний
/foo
/foo/
Ні
Точний
/foo/
/foo
Ні
Префікс
/foo
/foo, /foo/
Так
Префікс
/foo/
/foo, /foo/
Так
Префікс
/aaa/bb
/aaa/bbb
Ні
Префікс
/aaa/bbb
/aaa/bbb
Так
Префікс
/aaa/bbb/
/aaa/bbb
Так, ігнорує кінцевий слеш
Префікс
/aaa/bbb
/aaa/bbb/
Так, співпадає з кінцевим слешем
Префікс
/aaa/bbb
/aaa/bbb/ccc
Так, співпадає з підшляхом
Префікс
/aaa/bbb
/aaa/bbbxyz
Ні, не співпадає з префіксом рядка
Префікс
/, /aaa
/aaa/ccc
Так, співпадає з префіксом /aaa
Префікс
/, /aaa, /aaa/bbb
/aaa/bbb
Так, співпадає з префіксом /aaa/bbb
Префікс
/, /aaa, /aaa/bbb
/ccc
Так, співпадає з префіксом /
Префікс
/aaa
/ccc
Ні, використовується типовий backend
Змішаний
/foo (Префікс), /foo (Точний)
/foo
Так, віддає перевагу Точному
Декілька збігів
У деяких випадках одночасно можуть збігатися кілька шляхів в межах Ingress. У цих випадках перевага буде надаватися спочатку найдовшому збігу шляху. Якщо два шляхи все ще однаково збігаються, перевага буде надаватися шляхам із точним типом шляху перед префіксним типом шляху.
Шаблони імен хостів
Хости можуть бути точними збігами (наприклад, "foo.bar.com") або містити шаблони (наприклад, "*.foo.com"). Точні збіги вимагають, щоб заголовок HTTP host відповідав полю host. Шаблони вимагають, щоб заголовок HTTP host був рівним суфіксу правила з символами підстановки.
Хост
Заголовок хоста
Збіг?
*.foo.com
bar.foo.com
Збіг на основі спільного суфіксу
*.foo.com
baz.bar.foo.com
Немає збігу, символ підстановки охоплює лише одну DNS-мітку
*.foo.com
foo.com
Немає збігу, символ підстановки охоплює лише одну DNS-мітку
Ingressʼи можуть бути реалізовані різними контролерами, часто з різною конфігурацією. Кожен Ingress повинен вказати клас — посилання на ресурс IngressClass, який містить додаткову конфігурацію, включаючи імʼя контролера, який повинен реалізувати цей клас.
Стандартна область застосування параметрів IngressClass — це весь кластер.
Якщо ви встановлюєте поле .spec.parameters і не встановлюєте .spec.parameters.scope, або ви встановлюєте .spec.parameters.scope на Cluster, тоді IngressClass посилається на ресурс, який є на рівні кластера. kind (в поєднанні з apiGroup) параметрів вказує на API на рівні кластера (можливо, власний ресурс), і name параметрів ідентифікує конкретний ресурс на рівні кластера для цього API.
Наприклад:
---apiVersion:networking.k8s.io/v1kind:IngressClassmetadata:name:external-lb-1spec:controller:example.com/ingress-controllerparameters:# Параметри для цього IngressClass вказані в ClusterIngressParameter# (API group k8s.example.net) імені "external-config-1".# Це визначення вказує Kubernetes шукати ресурс параметрів на рівні кластера.scope:ClusterapiGroup:k8s.example.netkind:ClusterIngressParametername:external-config-1
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.23 [stable]
Якщо ви встановлюєте поле .spec.parameters і встановлюєте .spec.parameters.scope на Namespace, тоді IngressClass посилається на ресурс на рівні простору імен. Ви також повинні встановити поле namespace в межах .spec.parameters на простір імен, який містить параметри, які ви хочете використовувати.
kind (в поєднанні з apiGroup) параметрів вказує на API на рівні простору імен (наприклад: ConfigMap), і name параметрів ідентифікує конкретний ресурс у просторі імен, який ви вказали в namespace.
Параметри на рівні простору імен допомагають оператору кластера делегувати контроль над конфігурацією (наприклад: налаштування балансувальника трафіку, визначення шлюзу API) що використовується для робочого навантаження. Якщо ви використовуєте параметр на рівні кластера, то або:
команда операторів кластера повинна схвалити зміни іншої команди кожен раз,
коли застосовується нова конфігураційна зміна.
оператор кластера повинен визначити конкретні засоби керування доступом, такі як RBAC ролі та привʼязки, що дозволяють команді застосунків вносити зміни в ресурс параметрів на рівні кластера.
Сам API IngressClass завжди має область застосування на рівні кластера.
Ось приклад IngressClass, який посилається на параметри на рівні простору імен:
---apiVersion:networking.k8s.io/v1kind:IngressClassmetadata:name:external-lb-2spec:controller:example.com/ingress-controllerparameters:# Параметри для цього IngressClass вказані в IngressParameter# (API group k8s.example.com) імені "external-config",# що знаходиться в просторі імен "external-configuration".scope:NamespaceapiGroup:k8s.example.comkind:IngressParameternamespace:external-configurationname:external-config
Застарілі анотації
Перед тим, як в Kubernetes 1.18 були додані ресурс IngressClass та поле ingressClassName, класи Ingress вказувалися за допомогою анотації kubernetes.io/ingress.class в Ingress. Ця анотація ніколи не була формально визначена, але отримала широку підтримку контролерами Ingress.
Нове поле ingressClassName в Ingress — це заміна для цієї анотації, але не є прямим еквівалентом. Хоча анотація, як правило, використовувалася для посилання на імʼя контролера Ingress, який повинен реалізувати Ingress, поле є посиланням на ресурс IngressClass, який містить додаткову конфігурацію Ingress, включаючи
імʼя контролера Ingress.
Стандартний IngressClass
Ви можете визначити певний IngressClass як стандартний для вашого кластера. Встановлення анотації ingressclass.kubernetes.io/is-default-class зі значенням true на ресурсі IngressClass забезпечить те, що новим Ingress буде призначений цей типовий IngressClass, якщо в них не вказано поле ingressClassName.
Увага:
Якщо у вас є більше одного IngressClass, відзначеного як стандартного для вашого кластера, контролер доступу завадить створенню нових обʼєктів Ingress, в яких не вказано поле ingressClassName. Ви можете вирішити це, забезпечивши, те що в вашому кластері визначено не більше 1 типового IngressClass.
Є контролери Ingress, які працюють без визначення типового IngressClass. Наприклад, контролер Ingress-NGINX може бути налаштований з прапорцем--watch-ingress-without-class. Однак рекомендується визначати типовий IngressClass явно:
Існують концепції в Kubernetes, що дозволяють вам використовувати один Service (див. альтернативи). Ви також можете зробити це за допомогою Ingress, вказавши стандартний бекенд без правил.
Якщо ви створите його за допомогою kubectl apply -f, ви повинні мати можливість переглядати стан доданого Ingress:
kubectl get ingress test-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
test-ingress external-lb * 203.0.113.123 80 59s
Де 203.0.113.123 — це IP-адреса, яку надав контролер Ingress для виконання цього Ingress.
Примітка:
Для контролерів Ingress та балансувальників навантаження це може тривати хвилину або дві для виділення IP-адреси. Тож ви часто можете побачити, що адреса вказана як <pending>.
Простий розподіл
Конфігурація розподілу дозволяє маршрутизувати трафік з одної IP-адреси до більше ніж одного сервісу, виходячи з HTTP URI, що запитується. Ingress дозволяє зберігати кількість балансувальників на мінімальному рівні. Наприклад, налаштування як:
Коли ви створюєте Ingress за допомогою kubectl apply -f:
kubectl describe ingress simple-fanout-example
Name: simple-fanout-example
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:4200 (10.8.0.90:4200)
/bar service2:8080 (10.8.0.91:8080)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 22s loadbalancer-controller default/test
Контролер Ingress надає реалізаційно-специфічний балансувальник що влаштовує Ingress, за умови, що існують сервіси (service1, service2). Коли це сталося, ви можете побачити адресу балансувальника в полі Address.
Примітка:
Залежно від контролера Ingress, який ви використовуєте, можливо, вам доведеться створити сервіс default-http-backend Service.
Віртуальний хостинг на основі імен
Віртуальні хости на основі імен підтримують маршрутизацію HTTP-трафіку до кількох імен хостів за однією IP-адресою.
Схема. Ingress віртуального хостингу на основі імен
Наступний Ingress вказує балансувальнику направляти запити на основі заголовка Host.
Якщо ви створюєте ресурс Ingress без визначених хостів в правилах, то будь-який вебтрафік на IP-адресу вашого контролера Ingress може відповідати без необхідності в імені заснованому віртуальному хості.
Наприклад, наступний Ingress маршрутизує трафік спрямований для first.bar.com до service1, second.bar.com до service2, і будь-який трафік, який має заголовок запиту хоста, який не відповідає first.bar.com і second.bar.com до service3.
Ви можете захистити Ingress, вказавши Secret, що містить приватний ключ TLS та сертифікат. Ресурс Ingress підтримує лише один TLS-порт, 443, та передбачає термінування TLS на точці входу (трафік до Service та його Podʼів передається у вигляді звичайного тексту). Якщо розділ конфігурації TLS в Ingress вказує різні хости, вони мультиплексуються на одному порту відповідно до імені хоста, вказаного через розширення TLS з SNI (за умови, що контролер Ingress підтримує SNI). TLS-секрет повинен містити ключі з іменами tls.crt та tls.key, які містять сертифікат та приватний ключ для використання TLS. Наприклад:
Посилання на цей секрет в Ingress дозволяє контролеру Ingress захистити канал, що йде від клієнта до балансувальника навантаження за допомогою TLS. Вам потрібно переконатися, що TLS-секрет, який ви створили, містить сертифікат, який містить Common Name (CN), також Fully Qualified Domain Name (FQDN) для https-example.foo.com.
Примітка:
Майте на увазі, що TLS не працюватиме типове для правил, оскільки сертифікати повинні бути видані для всіх можливих піддоменів. Таким чином, hosts в розділі tls повинні явно відповідати host в розділі rules.
Є різниця між можливостями TLS, які підтримуються різними Ingress контролерами. Будь ласка, зверніться до документації nginx, GCE, або будь-якого іншого платформозалежного контролера Ingress, щоб зрозуміти, як TLS працює в вашому середовищі.
Балансування навантаження
Контролер Ingress створюється з певними параметрами політики балансування навантаження, які він застосовує до всіх Ingress, таких як алгоритм балансування навантаження, схема коефіцієнтів ваги бекенду та інші. Більш розширені концепції балансування навантаження (наприклад, постійні сесії, динамічні коефіцієнти ваги) наразі не експонуються через Ingress. Замість цього ви можете отримати ці функції через балансувальник, що використовується для Service.
Також варто зазначити, що навіть якщо перевірки стану не експоновані безпосередньо через Ingress, існують паралельні концепції в Kubernetes, такі як перевірки готовності, що дозволяють досягти того ж самого результату. Будь ласка, ознайомтеся з документацією конкретного контролера, щоб переглянути, як вони обробляють перевірки стану (наприклад: nginx або GCE).
Оновлення Ingress
Щоб оновити існуючий Ingress і додати новий хост, ви можете відредагувати ресурс таким чином:
kubectl describe ingress test
Name: test
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:80 (10.8.0.90:80)
Annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 35s loadbalancer-controller default/test
kubectl edit ingress test
Це відкриє редактор з поточною конфігурацією у форматі YAML. Змініть її, щоб додати новий хост:
Після збереження змін, kubectl оновлює ресурс у API-сервері, що повідомляє Ingress-контролеру переконфігурувати балансувальник.
Перевірте це:
kubectl describe ingress test
Name: test
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:80 (10.8.0.90:80)
bar.baz.com
/foo service2:80 (10.8.0.91:80)
Annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 45s loadbalancer-controller default/test
Ви можете досягти того самого результату, викликавши kubectl replace -f із зміненим файлом YAML для Ingress.
Збій у різних зонах доступності
Методи розподілу трафіку між доменами відмови відрізняються між хмарними провайдерами. Будь ласка, перевірте документацію відповідного контролера Ingress для отримання деталей.
Альтернативи
Ви можете використовувати різні способи надання доступу до Service, які безпосередньо не стосуються ресурсу Ingress:
Для того, щоб ресурс Ingress працював у вашому кластері, повинен бути запущений контролер Ingress. Вам потрібно вибрати принаймні один контролер Ingress та переконатися, що він налаштований у вашому кластері. На цій сторінці перелічені поширені контролери Ingress, які ви можете встановити.
Для того, щоб ресурс Ingress працював, у кластері повинен бути запущений контролер Ingress.
На відміну від інших типів контролерів, які працюють як частина бінарного файлу kube-controller-manager, контролери Ingress не запускаються автоматично разом з кластером. Використовуйте цю сторінку, щоб вибрати реалізацію контролера Ingress, яка найкраще підходить для вашого кластера.
Проєкт Kubernetes підтримує контролери Ingress для AWS, GCE та nginx.
Додаткові контролери
Примітка: Цей розділ містить посилання на проєкти сторонніх розробників, які надають функціонал, необхідний для Kubernetes. Автори проєкту Kubernetes не несуть відповідальності за ці проєкти. Проєкти вказано в алфавітному порядку. Щоб додати проєкт до цього списку, ознайомтеся з посібником з контенту перед надсиланням змін. Докладніше.
ngrok Kubernetes Ingress Controller — це контролер Ingress з відкритим кодом для надання безпечного публічного доступу до ваших служб K8s за допомогою платформи ngrok.
Контролер Ingress OCI Native — це контролер Ingress для Oracle Cloud Infrastructure, який дозволяє керувати OCI Load Balancer.
Контролер Ingress Pomerium — це контролер Ingress на основі Pomerium, який пропонує політику доступу з урахуванням контексту.
Skipper — це HTTP-маршрутизатор та зворотний проксі для композиції служб, включаючи випадки використання, такі як Kubernetes Ingress, розроблений як бібліотека для побудови вашого власного проксі.
Tyk Operator розширює Ingress за допомогою власних ресурсів для надання можливостей управління API Ingress. Tyk Operator працює з відкритими шлюзами Tyk та хмарною системою управління Tyk.
Контролер Ingress Wallarm — це контролер Ingress, який надає можливості WAAP (WAF) та захисту API.
Використання кількох контролерів Ingress
Ви можете розгортати будь-яку кількість контролерів Ingress за допомогою класу Ingress у межах кластера. Зверніть увагу на значення .metadata.name вашого ресурсу класу Ingress. При створенні Ingress вам слід вказати це імʼя для визначення поля ingressClassName в обʼєкті Ingress (див. специфікацію IngressSpec v1). ingressClassName є заміною застарілого методу анотації.
Якщо ви не вказуєте IngressClass для Ingress, і у вашому кластері рівно один IngressClass відзначений як типовий, тоді Kubernetes застосовує типовий IngressClass кластера до Ingress. Ви вказуєте IngressClass як типовий, встановлюючи анотацію ingressclass.kubernetes.io/is-default-class для цього IngressClass, зі значенням "true".
В ідеалі, всі контролери Ingress повинні відповідати цій специфікації, але різні контролери Ingress працюють трошки по-різному.
Примітка:
Переконайтеся, що ви ознайомилися з документацією вашого контролера Ingress, щоб зрозуміти особливості вибору.
Gateway API є різновидом видів API, які забезпечують динамічне надання інфраструктури та розширений маршрутизації трафіку.
Забезпечте доступ до мережевих служб за допомогою розширюваного, орієнтованого на ролі та протокол обізнаного механізму конфігурації. Gateway API є надбудовою, що містить види API, які надають динамічну інфраструктуру надання та розширену маршрутизацію трафіку.
Принципи дизайну
Наведені нижче принципи визначили дизайн та архітектуру Gateway API:
Орієнтований на ролі: Види Gateway API моделюються за організаційними ролями, які відповідають за управління мережевою службою Kubernetes:
Постачальник інфраструктури: Управляє інфраструктурою, яка дозволяє кільком ізольованим кластерам обслуговувати кілька орендарів, наприклад, хмарний постачальник.
Оператор кластера: Управляє кластерами та зазвичай цікавиться політиками, мережевим доступом, дозволами застосунків тощо.
Розробник застосунків: Управляє застосунком, який працює в кластері та, як правило, цікавиться конфігурацією рівня застосунку та складом Service.
Переносний: Специфікації Gateway API визначаються як власні ресурси та підтримуються багатьма реалізаціями.
Експресивний: Види Gateway API підтримують функціональність для загальних випадків маршрутизації трафіку, таких як відповідність на основі заголовків, визначенні пріоритету трафіку та інших, які були можливі тільки в Ingress за допомогою власних анотацій.
Розширюваний: Gateway дозволяє повʼязувати власні ресурси на різних рівнях API. Це робить можливим докладне налаштування на відповідних рівнях структури API.
Модель ресурсів
Gateway API має три стабільні види API:
GatewayClass: Визначає набір шлюзів зі спільною конфігурацією та керується контролером, який реалізує цей клас.
Gateway: Визначає екземпляр інфраструктури обробки трафіку, такої як хмарний балансувальник.
HTTPRoute: Визначає правила, специфічні для HTTP, для передачі трафіку з Gateway listener на мережеві точки доступу бекенду. Ці точки доступу часто представлені як Service.
Gateway API організовано за різними видами API, які мають взаємозалежні відносини для підтримки організаційно орієнтованої природи організацій. Обʼєкт Gateway повʼязаний із саме одним GatewayClass; GatewayClass описує контролер шлюзу, відповідального за керування шлюзами цього класу. Один чи кілька видів маршрутів, таких як HTTPRoute, потім повʼязуються з Gateways. Gateway може фільтрувати маршрути, які можуть бути прикріплені до його слухачів, утворюючи двоспрямовану довірчу модель з маршрутами.
Наступна схема ілюструє звʼязок між трьома стабільними видами Gateway API:
GatewayClass
Шлюзи можуть бути реалізовані різними контролерами, часто з різними конфігураціями. Шлюз має посилатися на GatewayClass, який містить імʼя контролера, що реалізує цей клас.
У цьому прикладі контролер, який реалізував Gateway API, налаштований для управління GatewayClasses з іменем контролера example.com/gateway-controller. Шлюзи цього класу будуть керуватися контролером реалізації.
Gateway описує екземпляр інфраструктури обробки трафіку. Він визначає мережеву точку доступу з використанням якої можна обробляти трафік, тобто фільтрувати, балансувати, розділяти тощо для таких бекендів як Service. Наприклад, шлюз може представляти хмарний балансувальник навантаження або внутрішній проксі-сервер, налаштований для отримання HTTP-трафіку.
У цьому прикладі екземпляр інфраструктури обробки трафіку програмується на прослуховування HTTP-трафіку на порту 80. Оскільки поле addresses не вказано, адреса чи імʼя хосту надається Gateway контролером реалізації. Ця адреса використовується як мережева точка доступу для обробки трафіку бекенду, визначеного в маршрутах.
Вид HTTPRoute визначає поведінку маршрутизації HTTP-запитів від слухача Gateway до бекенду мережевих точок доступу. Для бекенду Service реалізація може представляти мережеву точку доступу як IP-адресу Service чи поточні Endpointʼи Service. HTTPRoute представляє конфігурацію, яка застосовується до внутрішньої реалізації Gateway. Наприклад, визначення нового HTTPRoute може призвести до налаштування додаткових маршрутів трафіку в хмарному балансувальнику або внутрішньому проксі-сервері.
У цьому прикладі HTTP-трафік від Gateway example-gateway із заголовком Host: www.example.com та вказаним шляхом запиту /login буде направлений до Service example-svc на порт 8080.
Ось простий приклад маршрутизації HTTP-трафіку до Service за допомогою Gateway та HTTPRoute:
У цьому прикладі потік запиту для Gateway, реалізованого як зворотний проксі, є таким:
Клієнт починає готувати HTTP-запит для URL http://www.example.com
DNS-resolver клієнта запитує імʼя призначення та дізнається про звʼязок між однією чи кількома IP-адресами, повʼязаними з Gateway.
Клієнт надсилає запит на IP-адресу Gateway; зворотній проксі отримує HTTP запит і використовує заголовок Host: заголовок має збігатись з налаштуваннями, які були отримані від Gateway та прикріпленого HTTPRoute. Опційно зворотній проксі може виконати порівняння заголовків або шляху запиту на основі правил відповідності HTTPRoute.
Опційно зворотній проксі може змінювати запит; наприклад, додавати чи видаляти заголовки, відповідно до правил фільтрації HTTPRoute.
Наприкінці зворотній проксі пересилає запит на один чи кілька бекендів.
Відповідність
Gateway API охоплює широкий набір функцій та має широке впровадження. Ця комбінація вимагає чітких визначень відповідності та тестів, щоб гарантувати, що API забезпечує однаковий підхід, де б він не використовувався.
Дивіться документацію щодо відповідності для розуміння деталей, таких як канали випусків, рівні підтримки та виконання тестів відповідності.
Міграція з Ingress
Gateway API є наступником Ingress API. Однак він не включає вид Ingress. Внаслідок цього необхідно провести одноразове перетворення з наявних ресурсів Ingress на ресурси Gateway API.
Дивіться посібник з міграції з Ingress для отримання деталей щодо міграції ресурсів Ingress на ресурси Gateway API.
Що далі
Замість того, щоб ресурси Gateway API були реалізовані нативно в Kubernetes, специфікації визначаються як Власні ресурси та підтримуються широким спектром реалізацій.
Встановіть CRD Gateway API або виконайте інструкції щодо встановлення обраної реалізації. Після встановлення реалізації скористайтесь розділом Початок роботи для швидкого початку роботи з Gateway API.
Примітка:
Обовʼязково ознайомтесь з документацією обраної вами реалізації, щоб розуміти можливі обмеження.
Дивіться специфікацію API для отримання додаткових деталей про всі види API Gateway API.
5 - EndpointSlices
API EndpointSlice — це механізм, який Kubernetes використовує, щоб ваш Service масштабувався для обробки великої кількості бекендів і дозволяє кластеру ефективно оновлювати свій список справних бекендів.
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.21 [stable]
EndpointSlice API Kubernetes надає можливість відстежувати мережеві точки доступу в межах кластера Kubernetes. EndpointSlices пропонують більш масштабований та розширюваний альтернативний варіант Endpoints.
EndpointSlice API
У Kubernetes, EndpointSlice містить посилання на набір мережевих точок доступу. Панель управління автоматично створює EndpointSlices для будь-якої служби Kubernetes, яка має вказаний селектор. Ці EndpointSlices містять посилання на всі Podʼи, які відповідають селектору Service. EndpointSlices групують мережеві точки доступу за унікальними комбінаціями протоколу, номеру порту та імені Service. Імʼя обʼєкта EndpointSlice повинно бути дійсним імʼям піддомену DNS.
Наприклад, ось приклад обʼєкта EndpointSlice, яким володіє Service Kubernetes з імʼям example.
Типово, панель управління створює та керує EndpointSlices так, щоб в кожному з них було не більше 100 мережевих точок доступу. Це можна налаштувати за допомогою прапорця --max-endpoints-per-slicekube-controller-manager, до максимуму 1000.
EndpointSlices можуть виступати джерелом правди для kube-proxy щодо того, як маршрутизувати внутрішній трафік.
Типи адрес
EndpointSlices підтримують три типи адрес:
IPv4
IPv6
FQDN (Fully Qualified Domain Name — Повністю Кваліфіковане Доменне Імʼя)
Кожен обʼєкт EndpointSlice представляє конкретний тип IP-адреси. Якщо у вас
є Service, який доступний через IPv4 та IPv6, буде принаймні два обʼєкти EndpointSlice (один для IPv4 та один для IPv6).
Стани
API EndpointSlice зберігає стани точок доступу, які можуть бути корисні для споживачів. Три стани: ready, serving та terminating.
Ready
ready — це стан, який відповідає стану Ready Pod. Запущений Pod зі станом Ready встановленим в True повинен мати стан ready також встановлений в true. З міркувань сумісності, ready НІКОЛИ не буває true, коли Pod видаляється. Споживачі повинні звертатися до стану serving, щоб перевірити готовність Podʼів, які видаляються. Єдиний виняток є для Services з spec.publishNotReadyAddresses, встановленим в true. Podʼи для цих служб завжди матимуть стан ready, встановлений в true.
Serving
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.26 [stable]
Стан serving майже ідентичний стану ready. Різниця полягає в тому, що
споживачі API EndpointSlice повинні перевіряти стан serving, якщо їм важливо перевірити готовність Podʼів в той час, коли Pod також примусово припиняє свою роботу.
Примітка:
Хоча serving майже ідентичний ready, його додано для того, щоб не порушувати поточне значення ready. Для наявних клієнтів може бути неочікуваним, якщо ready може бути true для точок доступу, що припиняють роботу, оскільки історично точки доступу, що припиняють роботу ніколи не включалися в Endpoints або
EndpointSlice API. З цієї причини readyзавждиfalse для таких точок доступу, і новий стан serving було додано у версії v1.20, щоб клієнти могли відстежувати готовність Podʼів, що примусово припиняють роботу, від наявної семантики ready.
Terminating
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.22 [beta]
Terminating — це стан, що вказує, чи Pod видаляється. Для Podʼів це буде будь-який Pod з встановленою часовою міткою видалення.
Інформація про топологію
Кожна точка доступу в межах EndpointSlice може містити відповідну інформацію про топологію. Інформація про топологію включає місцезнаходження точки доступу та інформацію про відповідний вузол та зону. Ця інформація доступна в наступних
полях на кожній кінцевій точці в EndpointSlices:
nodeName — Назва вузла, на якому знаходиться ця точка доступу.
zone — Зона, в якій знаходиться ця точка доступу.
Примітка:
В API v1 поле топології на кожній кінцевій точці було фактично видалено на користь
спеціальних полів nodeName та zone.
Встановлення довільних полів топології в поле endpoint ресурсу EndpointSlice було визнане застарілим і не підтримується в API v1. Замість цього, API v1 підтримує встановлення окремих полів nodeName та zone. Ці поля автоматично перемикаються між версіями API. Наприклад, значення ключа "topology.kubernetes.io/zone" у полі topology в v1beta1 API є доступним як поле zone в API v1.
Управління
Зазвичай обʼєкти EndpointSlice створюються та керуються панеллю управління зокрема, контролером EndpointSlice. Є різноманітні інші випадки використання EndpointSlices, такі як реалізації Service mesh, які можуть призвести до інших сутностей або контролерів, які керують додатковими наборами EndpointSlices.
Щоб забезпечити можливість кількох сутностей керувати EndpointSlices без взаємодії одна з одною, Kubernetes визначає labelendpointslice.kubernetes.io/managed-by, яка вказує сутність, яка керує EndpointSlice. Контролер встановлює значення endpointslice-controller.k8s.io для цієї мітки на всіх точках доступу, якими він керує. Інші сутності, які керують EndpointSlices, також повинні встановити унікальне значення для цієї мітки.
Власність
У більшості випадків EndpointSlices належать Service, за яким обʼєкт EndpointSlices стежить для виявлення точок доступу. Право власності вказується власником
посиланням на кожен EndpointSlice, а також міткою kubernetes.io/service-name
для простого пошуку всіх EndpointSlices, які належать Service.
Віддзеркалення EndpointSlice
У деяких випадках застосунки створюють власні ресурси Endpoints. Щоб забезпечити що ці застосунки не повинні одночасно записувати як в ресурси Endpoints, так і
в ресурси EndpointSlice, панель управління кластера віддзеркалює більшість ресурсів Endpoints на відповідні ресурси EndpointSlices.
Панель управління віддзеркалює ресурси Endpoints, якщо:
ресурс Endpoints має мітку endpointslice.kubernetes.io/skip-mirror встановлену в true.
ресурс Endpoints має анотацію control-plane.alpha.kubernetes.io/leader.
відповідний ресурс Service не існує.
відповідний ресурс Service має ненульовий селектор.
Окремі ресурси Endpoints можуть транслюватись в кілька ресурсів EndpointSlices. Це може відбуватись, якщо ресурс Endpoints має кілька підмножин або включає точки доступу з кількома сімействами IP (IPv4 та IPv6). Максимально 1000 адрес на підмножину буде віддзеркалено на EndpointSlices.
Розподіл EndpointSlices
Кожен EndpointSlice має набір портів, які застосовуються до всіх точок доступу ресурсу. При використанні іменованих портів для Service, Podʼи можуть мати різні номери цільового порту для того самого іменованого порту, що вимагає різних EndpointSlices. Це схоже на логіку того, як підмножини групуються з Endpoints.
Панель управління намагається заповнити EndpointSlices так повно, як це можливо, але не активно перерозподіляє їх. Логіка досить проста:
Пройдіться по наявних EndpointSlices, вилучіть точки доступу, які вже не потрібні, і оновіть відповідні точки, які змінилися.
Пройдіться по EndpointSlices, які були змінені на першому етапі, і заповніть їх будь-якими новими точками доступу, які потрібно додати.
Якщо ще залишилися нові точки доступу для додавання, спробуйте додати їх в раніше не змінений EndpointSlice та/або створіть новий.
Важливо, що третій крок надає пріоритет обмеженню оновлень EndpointSlice над ідеально повним розподілом EndpointSlices. Наприклад, якщо є 10 нових точок доступу для додавання та 2 EndpointSlices з простором для ще 5 точок доступу кожна, цей підхід створить новий EndpointSlice замість заповнення 2 наявних EndpointSlices. Іншими словами, одне створення EndpointSlice краще, ніж кілька оновлень EndpointSlice.
З kube-proxy, який працює на кожному вузлі та слідкує за EndpointSlices, кожна зміна EndpointSlice стає відносно дорогою, оскільки вона буде передана кожному вузлу в кластері. Цей підхід призначений для обмеження кількості змін, які потрібно надіслати кожному вузлу, навіть якщо це може призвести до декількох EndpointSlices, які не є повністю заповненими.
На практиці це рідко трапляється. Більшість змін опрацьовуються контролером EndpointSlice буде достатньо малою, щоб поміститися в наявний EndpointSlice, і якщо ні, новий EndpointSlice, ймовірно, буде потрібен невдовзі. Поступові оновлення Deploymentʼів також надають природню перепаковку EndpointSlices з всіма Podʼами та їх відповідними точками доступу, що заміняються.
Дублікати endpoints
Через характер змін EndpointSlice точки доступу можуть бути представлені в більш ніж одному EndpointSlice одночасно. Це, природно, відбувається, оскільки зміни до різних обʼєктів EndpointSlice можуть надходити до клієнта Kubernetes watch / cache в різний час.
Примітка:
Клієнти API EndpointSlice повинні переглянути всі наявні EndpointSlices повʼязані з Service та побудувати повний список унікальних мережевих точок доступу. Важливо зазначити, що мережеві точки доступу можуть бути дубльовані в різних EndpointSlices.
Ви можете знайти посилання на референтну реалізацію того, як виконати це агрегування точок доступу та вилучення дублікатів як частину коду EndpointSliceCache всередині kube-proxy.
Порівняння з Endpoints
Оригінальний API Endpoints надавав простий і зрозумілий спосіб
відстеження мережевих точок доступу в Kubernetes. Однак з ростом кластерів Kubernetes та Serviceʼів, які обробляють більше трафіку і надсилають трафік до більшої кількості підзадач, обмеження оригінального API стали більш помітними. Зокрема, до них входили проблеми масштабування до більшої кількості мережевих точок доступу.
Оскільки всі мережеві точки доступу для Service зберігалися в одному ресурсі Endpoints, ці обʼєкти Endpoints могли бути досить великими. Для служб, які залишалися стабільними (тобто тим самим набором точок доступу протягом тривалого періоду часу), вплив був менше помітний; навіть тоді деякі випадки використання Kubernetes працювали не дуже добре.
Коли у Service було багато точок доступу бекенду, а робочі навантаження або часто масштабуються, або до них часто вносилися нові зміни, кожне оновлення єдиного обʼєкта Endpoints для цього Service означало багато трафіку між компонентами кластера Kubernetes (в межах панелі управління, а також між вузлами та сервером API). Цей додатковий трафік також мав вартість у термінах використання ЦП.
З EndpointSlices додавання або видалення одного окремого Podʼа призводить до такого ж кількості оновлень для клієнтів, які спостерігають за змінами, але розмір цих оновлень на багато менший на великій кількості точок доступу.
EndpointSlices також включили інновації щодо нових можливостей, таких як мережі з подвійним стеком і маршрутизація з урахуванням топології.
Якщо ви хочете контролювати потік трафіку на рівні IP-адреси чи порту (рівень OSI 3 або 4), мережеві політики Kubernetes дозволяють вам визначати правила потоку трафіку всередині вашого кластера, а також між Podʼами та зовнішнім світом. Ваш кластер повинен використовувати мережевий втулок, який підтримує NetworkPolicy.
Якщо ви хочете контролювати потік трафіку на рівні 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 може виглядати наступним чином:
Надсилання (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 nf 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
Існує чотири види селекторів, які можна вказати в розділі from для ingress або to для egress:
podSelector: Вибирає певні Podʼи в тому ж просторі імен, що і NetworkPolicy, які мають бути допущені як джерела ingress або призначення egress.
namespaceSelector: Вибирає певні простори імен, для яких всі Podʼи повинні бути допущені як джерела ingress або призначення egress.
namespaceSelectorтаpodSelector: Один елемент to/from, який вказує як namespaceSelector, так і podSelector, вибирає певні Podʼи в певних просторах імен. Будьте уважні при використанні правильного синтаксису YAML. Наприклад:
Ця політика містить один елемент from, який дозволяє підключення від Podʼів з міткою role=client в просторах імен з міткою user=alice. Але наступна політика відрізняється:
Вона містить два елементи у масиві 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ʼів.
Це забезпечить ізоляцію вхідного трафіку навіть для Podʼів, які не вибрані жодною іншою NetworkPolicy. Ця політика не впливає на ізоляцію egress трафіку з будь-якого Podʼа.
Дозвіл на весь вхідний трафік
Якщо ви хочете дозволити всі вхідні підключення до всіх Podʼів в просторі імен, ви можете створити політику, яка явно це дозволяє.
З цією політикою ніяка додаткова політика або політики не можуть призвести до відмови у ingress підключенні до цих Podʼів. Ця політика не впливає на ізоляцію вихідного трафіку з будь-якого Podʼа.
Стандартна заборона всього вихідного трафіку
Ви можете створити стандартну політику ізоляції вихідного трафіку для простору імен, створивши NetworkPolicy, яка вибирає всі Podʼи, але не дозволяє будь-який egress трафік від цих Podʼів.
Це забезпечить те, що навіть Podʼи, які не вибрані жодною іншою NetworkPolicy, не матимуть дозволу на вихідний трафік. Ця політика не змінює ізоляційну поведінку egress трафіку з будь-якого Podʼа.
Дозвіл на весь вихідний трафік
Якщо ви хочете дозволити всі підключення з усіх Podʼів в просторі імен, ви можете створити політику, яка явно дозволяє всім вихідним зʼєднанням з Podʼів в цьому просторі імені.
З цією політикою ніяка додаткова політика або політики не можуть призвести до відмови у вихідному підключенні з цих Podʼів. Ця політика не впливає на ізоляцію ingress трафіку до будь-якого Podʼа.
Стандартна заборона всього вхідного та всього вихідного трафіку
Ви можете створити "стандартну" політику для простору імен, яка забороняє весь ingress та egress трафік, створивши наступний NetworkPolicy в цьому просторі імені.
Це забезпечить те, що навіть 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, як показано в наступному прикладі:
Вищевказане правило дозволяє будь-якому 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 спрямована на більше ніж один простір імен, використовуючи їх мітки. Для цього необхідно додати мітки до цільових просторів імен. Наприклад:
Неможливо безпосередньо вказати імʼя простору імен в 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.
В той самий час, оскільки 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.
7 - DNS для Service та Podʼів
Ваше робоче навантаження може виявляти Serviceʼи всередині вашого кластеру за допомогою DNS; ця сторінка пояснює, як це працює.
Kubernetes створює DNS-записи для Service та Podʼів. Ви можете звертатися до Service за допомогою стійких імен DNS замість IP-адрес.
Kubernetes публікує інформацію про Podʼи та Serviceʼи, яка використовується для налаштування DNS. Kubelet конфігурує DNS Podʼів так, щоб запущені контейнери могли знаходити Service за іменем, а не за IP.
Service, визначеним у кластері, призначаються імена DNS. Типово список пошуку DNS клієнта Pod включає власний простір імен Pod та стандартний домен кластера.
Простори імен Serviceʼів
DNS-запит може повертати різні результати залежно від простору імен Podʼа, який його створив. DNS-запити, які не вказують простір імен, обмежені простором імен Podʼа. Для доступу до Service в інших просторах імен, вказуйте його в DNS-запиті.
Наприклад, розгляньте Pod в просторі імен test. Service data перебуває в просторі імен prod.
Запит для data не повертає результатів, оскільки використовує простір імен Podʼа test.
Запит для data.prod повертає бажаний результат, оскільки вказує простір імен.
DNS-запити можуть бути розширені за допомогою /etc/resolv.conf Podʼа. Kubelet налаштовує цей файл для кожного Podʼа. Наприклад, запит лише для data може бути розширений до data.test.svc.cluster.local. Значення опції search використовуються для розширення запитів. Щоб дізнатися більше про DNS-запити, див. сторінку довідки resolv.conf.
Отже, узагальнюючи, Pod у просторі імен test може успішно знаходити як data.prod, так і data.prod.svc.cluster.local.
DNS-записи
Для яких обʼєктів створюються DNS-записи?
Serviceʼи
Podʼи
У наступних розділах детально розглядаються підтримувані типи записів DNS та структура, яка їх підтримує. Будь-яка інша структура, імена чи запити, які випадково працюють, вважаються реалізаційними деталями та можуть змінюватися без попередження. Для отримання більш актуальної специфікації див. Виявлення Serviceʼів на основі DNS у Kubernetes.
Serviceʼи
Записи A/AAAA
"Звичайні" (не headless) Serviceʼи отримують DNS-запис A та/або AAAA, залежно від IP-сімейства або сімейств Serviceʼів, з імʼям у вигляді my-svc.my-namespace.svc.cluster-domain.example. Це розгортається в кластерний IP Serviceʼу.
Headless Services
(без кластерного IP) теж отримують DNS-записи A та/або AAAA, з імʼям у вигляді my-svc.my-namespace.svc.cluster-domain.example. На відміну від звичайних Serviceʼів, це розгортається в набір IP-адрес всіх Podʼів, вибраних Serviceʼом. Очікується, що клієнти будуть використовувати цей набір або використовувати стандартний round-robin вибір із набору.
Записи SRV
Записи SRV створюються для іменованих портів, які є частиною звичайних або headless сервісів. Для кожного іменованого порту запис SRV має вигляд _port-name._port-protocol.my-svc.my-namespace.svc.cluster-domain.example. Для звичайного Serviceʼу це розгортається в номер порту та доменне імʼя: my-svc.my-namespace.svc.cluster-domain.example. Для headless Serviceʼу це розгортається в кілька відповідей, по одній для кожного Podʼа, які підтримує Service, і містить номер порту та доменне імʼя Podʼа у вигляді hostname.my-svc.my-namespace.svc.cluster-domain.example.
Podʼи
Записи A/AAAA
Версії Kube-DNS, до впровадження специфікації DNS, мали наступне DNS-подання:
Наразі, при створенні Podʼа, його імʼя (як його видно зсередини Podʼа) визначається як значення metadata.name Podʼа.
У специфікації Podʼа є необовʼязкове поле hostname, яке можна використовувати для вказівки відмінного від імʼя Podʼа імені хосту. Коли вказано, воно має пріоритет над іменем Podʼа та стає імʼям хосту Podʼа (знову ж таки, в спостереженнях зсередини Podʼа). Наприклад, якщо у Podʼа вказано spec.hostname зі значенням "my-host", то у Podʼа буде імʼя хосту "my-host".
Специфікація Podʼа також має необовʼязкове поле subdomain, яке може використовуватися для вказівки того, що Pod є частиною підгрупи простору імен. Наприклад, Pod з spec.hostname встановленим на "foo", та spec.subdomain встановленим на "bar", у просторі імен "my-namespace", матиме імʼя хосту "foo" та повністю визначене доменне імʼя (FQDN) "foo.bar.my-namespace.svc.cluster.local" (знову ж таки, в спостереженнях зсередини Podʼа).
Якщо існує headless Service в тому ж просторі імен, що і Pod, із тим самим імʼям, що і піддомен, DNS-сервер кластера також поверне записи A та/або AAAA для повної доменної назви Podʼа.
Приклад:
apiVersion:v1kind:Servicemetadata:name:busybox-subdomainspec:selector:name:busyboxclusterIP:Noneports:- name:foo# імʼя не є обовʼязковим для Serviceʼів з одним портомport:1234---apiVersion:v1kind:Podmetadata:name:busybox1labels:name:busyboxspec:hostname:busybox-1subdomain:busybox-subdomaincontainers:- image:busybox:1.28command:- sleep- "3600"name:busybox---apiVersion:v1kind:Podmetadata:name:busybox2labels:name:busyboxspec:hostname:busybox-2subdomain:busybox-subdomaincontainers:- image:busybox:1.28command:- sleep- "3600"name:busybox
У вище наведеному Прикладі, із Service "busybox-subdomain" та Podʼами, які встановлюють spec.subdomain на "busybox-subdomain", перший Pod побачить своє власне FQDN як "busybox-1.busybox-subdomain.my-namespace.svc.cluster-domain.example". DNS повертає записи A та/або AAAA під цим іменем, що вказують на IP-адресу Podʼа. Обидва Podʼа "busybox1" та "busybox2" матимуть свої власні записи адрес.
EndpointSlice може визначати DNS-hostname для будь-якої адреси endpoint, разом з його IP.
Примітка:
Записи A та AAAA не створюються для назв Pod'ів, оскільки для них відсутній hostname. Pod без hostname, але з subdomain, створить запис A або AAAA лише для headless Service (busybox-subdomain.my-namespace.svc.cluster-domain.example), що вказує на IP-адреси Podʼів. Крім того, Pod повинен бути готовий, щоб мати запис, якщо не встановлено publishNotReadyAddresses=True для Service.
Поле setHostnameAsFQDN Podʼа
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.22 [stable]
Коли Pod налаштовано так, що він має повне доменне імʼя (FQDN), його імʼя хосту — це коротке імʼя хосту. Наприклад, якщо у вас є Pod із повним доменним імʼям busybox-1.busybox-subdomain.my-namespace.svc.cluster-domain.example, то стандартно команда hostname в цьому Podʼі повертає busybox-1, а команда hostname --fqdn повертає FQDN.
Коли ви встановлюєте setHostnameAsFQDN: true у специфікації Podʼа, kubelet записує FQDN Podʼа в імʼя хосту для простору імен цього Podʼа. У цьому випадку як hostname, так і hostname --fqdn повертають FQDN Podʼа.
Примітка:
У Linux поле hostname ядра (поле nodename структури struct utsname) обмежено 64 символами.
Якщо Pod активує цю функцію і його FQDN довше за 64 символи, запуск буде неуспішним. Pod залишиться у статусі Pending (ContainerCreating, як це бачить kubectl), генеруючи події помилок, такі як "Не вдалося побудувати FQDN з імені хосту Podʼа та домену кластера, FQDN long-FQDN занадто довгий (максимально 64 символи, запитано 70)". Один зі способів поліпшення досвіду користувача у цьому сценарії — створення контролера admission webhook для контролю розміру FQDN при створенні користувачами обʼєктів верхнього рівня, наприклад, Deployment.
Політика DNS Podʼа
Політику DNS можна встановлювати для кожного Podʼа окремо. Наразі Kubernetes підтримує наступні політики DNS, вказані у полі dnsPolicy в специфікації Podʼа:
"Default": Pod успадковує конфігурацію розпізнавання імені від вузла, на якому працюють Podʼи. Деталі можна переглянути у відповідному описі.
"ClusterFirst": Будь-який DNS-запит, який не відповідає налаштованому суфіксу домену кластера, такому як "www.kubernetes.io", пересилається на вихідний DNS-сервер DNS-сервером. Адміністратори кластера можуть мати додаткові налаштовані піддомени та вихідні DNS-сервери. Деталі щодо обробки DNS-запитів у цих випадках можна знайти відповідному дописі.
"ClusterFirstWithHostNet": Для Podʼів, які працюють із hostNetwork, ви повинні явно встановити для них політику DNS "ClusterFirstWithHostNet". В іншому випадку Podʼи, що працюють із hostNetwork та "ClusterFirst", будуть використовувати поведінку політики "Default".
Примітка: Це не підтримується в Windows. Деталі дивіться нижче.
"None": Це дозволяє Podʼу ігнорувати налаштування DNS з оточення Kubernetes. Всі налаштування DNS повинні надаватися за допомогою поля dnsConfig у специфікації Podʼа. Деталі дивіться у підрозділі DNS-конфігурація Podʼа нижче.
Примітка:
"Default" — це не стандартно політика DNS. Якщо поле dnsPolicy не вказано явно, то використовується "ClusterFirst".
Наведений нижче приклад показує Pod із встановленою політикою DNS "ClusterFirstWithHostNet", оскільки у нього встановлено hostNetwork в true.
Конфігурація DNS для Podʼа дозволяє користувачам мати більше контролю над налаштуваннями DNS для конкретного Podʼа.
Поле dnsConfig є необовʼязковим і може використовуватися з будь-якими налаштуваннями dnsPolicy. Однак, коли поле dnsPolicy Podʼа встановлено в "None", поле dnsConfig повинно бути вказано.
Нижче наведені значення, які користувач може вказати у полі dnsConfig:
nameservers: список IP-адрес, які будуть використовуватися як DNS-сервери для Podʼа. Можна вказати не більше 3 IP-адрес, але коли політика DNS Podʼа встановлена на "None", список повинен містити принаймні одну IP-адресу, інакше ця властивість є необовʼязковою. Зазначені сервери будуть обʼєднані з базовими серверами, згенерованими з вказаною політикою DNS, з вилученням дубльованих адрес.
searches: список доменів пошуку DNS для пошуку імен в хостах у Podʼі. Ця властивість є необовʼязковою. При вказанні, вказаний список буде обʼєднаний з базовими доменами пошуку, згенерованими з вибраної політики DNS. Дубльовані доменні імена вилучаються. Kubernetes дозволяє до 32 доменів пошуку.
options: необовʼязковий список обʼєктів, де кожний обʼєкт може мати властивість name (обовʼязкова) і властивість value (необовʼязкова). Зміст цієї властивості буде обʼєднаний з параметрами, згенерованими з вказаної політики DNS. Дубльовані елементи вилучаються.
Тут наведено приклад Podʼа з власними налаштуваннями DNS:
Kubernetes сам по собі не обмежує конфігурацію DNS до тих пір, поки довжина списку
доменів пошуку не перевищить 32 або загальна довжина всіх доменів пошуку не
перевищить 2048. Це обмеження стосується файлу конфігурації резолвера вузла,
конфігурації DNS Podʼа та обʼєднаної конфігурації DNS відповідно.
Примітка:
Деякі середовища виконання контейнерів раніших версій можуть мати власні обмеження щодо кількості доменів пошуку DNS. Залежно від середовища виконання контейнерів,
Podʼи з великою кількістю доменів пошуку DNS можуть залишатися в стані очікування.
Відомо, що containerd версії 1.5.5 або раніше та CRI-O версії 1.21 або раніше мають цю проблему.
DNS на вузлах з операційною системою Windows
ClusterFirstWithHostNet не підтримується для Podʼів, які працюють на вузлах з операційною системою Windows. У Windows всі імена з крапкою . розглядаються як повністю кваліфіковані та пропускають розгортання FQDN.
На Windows існують кілька резолверів DNS, які можна використовувати. Оскільки вони мають трохи відмінну поведінку, рекомендується використовувати Resolve-DNSName для отримання імені.
У Linux у вас є список суфіксів DNS, який використовується після того, як розгортання імені як повністю кваліфіковане не вдалося. У Windows можна вказати лише 1 суфікс DNS, який є суфіксом DNS, повʼязаним з простором імен цього Podʼа (наприклад, mydns.svc.cluster.local). Windows може розгортати FQDN, служби або мережеве імʼя, яке може бути розгорнуто за допомогою цього єдиного суфікса. Наприклад, Pod, створений у просторі імен default, матиме суфікс DNS default.svc.cluster.local. Всередині Windows імʼя Podʼа можна розгортати як kubernetes.default.svc.cluster.local, так і kubernetes, але не в частково кваліфіковані імена (kubernetes.default або kubernetes.default.svc).
Kubernetes дозволяє налаштувати мережеве зʼєднання з одним стеком IPv4, з одним стеком IPv6 або з подвійним стеком з обома сімействами мереж. Ця сторінка пояснює, як це зробити.
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.23 [stable]
Двостекова мережа IPv4/IPv6 дозволяє виділяти як адреси IPv4, так і IPv6 для
Podʼів та Serviceʼів.
Двостекова мережа IPv4/IPv6 є стандартно увімкненою у вашому кластері Kubernetes починаючи з версії 1.21, що дозволяє одночасно призначати адреси як IPv4, так і IPv6.
Підтримувані функції
Двостекова мережа IPv4/IPv6 у вашому кластері Kubernetes надає наступні можливості:
Мережа Pod із двома стеками (призначення адреси IPv4 і IPv6 на один Pod)
Serviceʼи з підтримкою IPv4 і IPv6
Маршрутизація egress Pod за межі кластера (наприклад, в Інтернет) через інтерфейси IPv4 та IPv6
Передумови
Для використання двостекових кластерів Kubernetes IPv4/IPv6 потрібні наступні передумови:
Kubernetes 1.20 або новіше
Для отримання інформації щодо використання двостекових Serviceʼів із попередніми версіями Kubernetes, дивіться документацію для відповідної версії Kubernetes.
Підтримка постачальником двостекової мережі (постачальник хмари або інший повинен забезпечити вузлам Kubernetes маршрутизовані мережеві інтерфейси IPv4/IPv6)
--node-cidr-mask-size-ipv4|--node-cidr-mask-size-ipv6 типово /24 для IPv4 та /64 для IPv6
kube-proxy:
--cluster-cidr=<CIDR IPv4>,<CIDR IPv6>
kubelet:
--node-ip=<IP IPv4>,<IP IPv6>
Ця опція є обовʼязковою для bare metal двостекових вузлів (вузлів, які не визначають постачальника хмари прапорцем --cloud-provider). Якщо ви використовуєте постачальника хмари та вирішили перевизначити IP-адреси вузлів, визначені постачальником хмари, встановіть опцію --node-ip.
(Вбудовані застарілі постачальники хмари не підтримують двостековий параметр --node-ip.)
Примітка:
Приклад CIDR IPv4: 10.244.0.0/16 (хоча ви повинні вказати свій власний діапазон адрес)
Приклад CIDR IPv6: fdXY:IJKL:MNOP:15::/64 (це показує формат, але не є дійсною адресою — дивіться RFC 4193)
Serviceʼи
Ви можете створювати Serviceʼи, які можуть використовувати адреси IPv4, IPv6 або обидві.
Сімейство адрес Service типово відповідає сімейству адрес першого діапазону IP Service кластера (налаштованого через прапорець --service-cluster-ip-range у kube-apiserver).
При визначенні Service ви можете конфігурувати його як двостековий за власним бажанням. Щоб вказати потрібну поведінку, ви встановлюєте в поле .spec.ipFamilyPolicy одне з наступних значень:
SingleStack: Service з одним стеком. Панель управління виділяє IP кластера для Service, використовуючи перший налаштований діапазон IP кластера для Service.
PreferDualStack: Виділяє IP-адреси кластерів IPv4 та IPv6 для Service, коли ввімкнено подвійний стек. Якщо подвійний стек не ввімкнено або не підтримується, він повертається до одностекового режиму.
RequireDualStack: Виділяє IP-адреси Service .spec.clusterIP з діапазонів адрес IPv4 та IPv6, якщо увімкнено подвійний стек. Якщо подвійний стек не ввімкнено або не підтримується, створення обʼєкта Service API завершиться невдачею.
Вибирає .spec.clusterIP зі списку .spec.clusterIPs на основі сімейства адрес першого елемента у масиві .spec.ipFamilies.
Якщо ви хочете визначити, яке сімейство IP використовувати для одностекової конфігурації або визначити порядок IP для двостекової, ви можете вибрати сімейства адрес, встановивши необовʼязкове поле .spec.ipFamilies в Service.
Примітка:
Поле .spec.ipFamilies умовно змінюване: ви можете додавати або видаляти вторинне
сімейство IP-адрес, але не можете змінювати основне сімейство IP-адрес наявного Service.
Ви можете встановити .spec.ipFamilies в будь-яке з наступних значень масиву:
["IPv4"]
["IPv6"]
["IPv4","IPv6"] (два стеки)
["IPv6","IPv4"] (два стеки)
Перше сімейство, яке ви перераховуєте, використовується для легасі-поля .spec.clusterIP.
Сценарії конфігурації двостекового Service
Ці приклади демонструють поведінку різних сценаріїв конфігурації двостекового Service.
Параметри подвійного стека в нових Service
Специфікація цього Service явно не визначає .spec.ipFamilyPolicy. Коли ви створюєте цей Service, Kubernetes виділяє кластерний IP для Service з першого налаштованого service-cluster-ip-range та встановлює значення .spec.ipFamilyPolicy на SingleStack. (Service без селекторів та headless Services із селекторами будуть працювати так само.)
Специфікація цього Service явно визначає PreferDualStack в .spec.ipFamilyPolicy. Коли ви створюєте цей Service у двостековому кластері, Kubernetes призначає як IPv4, так і IPv6 адреси для Service. Панель управління оновлює .spec для Service, щоб зафіксувати адреси IP. Поле .spec.clusterIPs є основним полем і містить обидві призначені адреси IP; .spec.clusterIP є вторинним полем зі значенням, обчисленим з .spec.clusterIPs.
Для поля .spec.clusterIP панель управління записує IP-адресу, яка є з того ж самого сімейства адрес, що й перший діапазон кластерних IP Service.
У одностековому кластері поля .spec.clusterIPs та .spec.clusterIP містять лише одну адресу.
У кластері з увімкненими двома стеками вказання RequireDualStack в .spec.ipFamilyPolicy працює так само як і PreferDualStack.
Специфікація цього Service явно визначає IPv6 та IPv4 в .spec.ipFamilies, а також визначає PreferDualStack в .spec.ipFamilyPolicy. Коли Kubernetes призначає IPv6 та IPv4 адреси в .spec.clusterIPs, .spec.clusterIP встановлюється на IPv6 адресу, оскільки це перший елемент у масиві .spec.clusterIPs, що перевизначає типові значення.
Ці приклади демонструють типову поведінку при увімкненні двостековості в кластері, де вже існують Service. (Оновлення наявного кластера до версії 1.21 або новіше вмикає двостековість.)
Коли двостековість увімкнена в кластері, наявні Service (безперебійно IPv4 або IPv6) конфігуруються панеллю управління так, щоб встановити .spec.ipFamilyPolicy на SingleStack та встановити .spec.ipFamilies на сімейство адрес наявного Service. Кластерний IP наявного Service буде збережено в .spec.clusterIPs.
Коли двостековість увімкнена в кластері, наявні headless Services з селекторами конфігуруються панеллю управління так, щоб встановити .spec.ipFamilyPolicy на SingleStack та встановити .spec.ipFamilies на сімейство адрес першого діапазону кластерних IP Service (налаштованого за допомогою прапорця --service-cluster-ip-range для kube-apiserver), навіть якщо .spec.clusterIP встановлено в None.
Перемикання Service між одностековим та двостековим режимами
Service можна перемикати з одностекового режиму на двостековий та навпаки.
Для того щоби перемикнути Service з одностекового режиму на двостековий, змініть .spec.ipFamilyPolicy з SingleStack на PreferDualStack або RequireDualStack за необхідності. Коли ви змінюєте цей Service з одностекового режиму на двостековий, Kubernetes призначає відсутнє адресне сімейство, так що тепер Service має адреси IPv4 та IPv6.
Відредагуйте специфікацію Service, оновивши .spec.ipFamilyPolicy з SingleStack на PreferDualStack.
До:
spec:ipFamilyPolicy:SingleStack
Після:
spec:ipFamilyPolicy:PreferDualStack
Для того щоби змінити Service з двостекового режиму на одностековий, змініть .spec.ipFamilyPolicy з PreferDualStack або RequireDualStack на SingleStack. Коли ви змінюєте цей Service з двостекового режиму на одностековий, Kubernetes залишає лише перший елемент у масиві .spec.clusterIPs, і встановлює .spec.clusterIP на цю IP-адресу і встановлює .spec.ipFamilies на адресне сімейство .spec.clusterIPs.
Headless Services без селекторів
Для Headless Services без селекторів і без явно вказаного .spec.ipFamilyPolicy, поле .spec.ipFamilyPolicy має типове значення RequireDualStack.
Тип Service — LoadBalancer
Щоб налаштувати двостековий балансувальник навантаження для вашого Service:
Встановіть значення поля .spec.type в LoadBalancer
Встановіть значення поля .spec.ipFamilyPolicy в PreferDualStack або RequireDualStack
Примітка:
Для використання двостекового Service типу LoadBalancer, ваш постачальник хмари повинен підтримувати балансувальники навантаження IPv4 та IPv6.
Трафік Egress
Якщо ви хочете увімкнути трафік Egress, щоб досягти призначення за межами кластера (наприклад, публічний Інтернет) з Podʼа, який використовує непублічно марковані адреси IPv6, вам потрібно увімкнути Pod для використання публічно-маршрутизованих адрес IPv6 за допомогою механізму, такого як прозорий проксі або IP маскування. Проєкт ip-masq-agent підтримує IP-маскування у двохстекових кластерах.
Примітка:
Переконайтеся, що ваш постачальник CNI підтримує IPv6.
Підтримка Windows
Kubernetes на Windows не підтримує одностекову мережу "лише IPv6". Однак
підтримується двохстекова мережа IPv4/IPv6 для Podʼів та вузлів з одностековими Service.
Ви можете використовувати двохстекову мережу IPv4/IPv6 з мережами l2bridge.
Примітка:
Мережі VXLAN на Windows не підтримують двохстекову мережу.
Ви можете дізнатися більше про різні режими мережі для Windows в розділі Мережа у Windows.
Маршрутизацію з урахуванням топології надає механізм для збереження мережевого трафіку в межах зони, з якої він походить. Віддача переваги трафіку в межах однієї зони між Podʼами в вашому кластері може допомогти з надійністю, продуктивністю (мережевою затримкою та пропускною здатністю) або вартістю.
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.23 [beta]
Примітка:
До Kubernetes 1.27 ця функція відома як Topology Aware Hints.
Маршрутизація з урахуванням топології налаштовує поведінку маршрутизації для того, щоб надавати перевагу зберіганню трафіку в межах тієї зони, з якої він походить. У деяких випадках це може допомогти зменшити витрати або покращити мережеву продуктивність.
Мотивація
Кластери Kubernetes все частіше розгортаються в багатозональних середовищах. Маршрутизацію з урахуванням топології забезпечує механізм для збереження трафіку в межах зони, з якої він походить. При розрахунку точок доступу для Service, контролер EndpointSlice враховує топологію (регіон і зону) кожної точки доступу та заповнює поле підказок для виділення її в зону. Компоненти кластера, такі як kube-proxy, можуть використовувати ці підказки для впливу на маршрутизацію трафіку (надання переваги точкам доступу, які знаходяться в топологічно ближчих зонах).
Увімкнення маршрутизації з урахуванням топології
Примітка:
До Kubernetes 1.27 така поведінка контролювалася за допомогою анотації service.kubernetes.io/topology-aware-hints.
Ви можете увімкнути маршрутизацію з урахуванням топології, для Service, встановивши анотацію service.kubernetes.io/topology-mode в значення Auto. Коли є достатня кількість точок доступу у кожній зоні, в EndpointSlice будуть заповнені підказки щодо топології для виділення окремих точок доступу конкретним зонам, що призводить до того, що трафік буде маршрутизуватися ближче до місця, звідки він походить.
Найкращий випадок застосування
Ця функція працює найкраще, коли:
1. Вхідний трафік рівномірно розподілений
Якщо значна частина трафіку походить з однієї зони, цей трафік може перенавантажити підмножину точок доступу, які були виділені для цієї зони. Не рекомендується використовувати цю функцію, коли очікується, що вхідний трафік буде походити з однієї зони.
2. У Service є 3 чи більше точок доступу на зону
У кластері з трьома зонами це означає 9 чи більше точок доступу. Якщо кількість точок доступу менше ніж 3 на зону, існує висока (≈50%) ймовірність, що контролер EndpointSlice не зможе рівномірно розподілити точки доступу та повернеться до застосування типового підходу до маршрутизації на рівні кластера.
Як це працює
Характеристика "Auto" намагається пропорційно виділити кількість точок доступу кожній зоні. Зверніть увагу, що цей підхід працює найкраще для сервісів зі значною кількістю точок доступу.
Контролер EndpointSlice
Контролер EndpointSlice відповідає за встановлення підказок на EndpointSlice, коли цей евристичний підхід увімкнено. Контролер виділяє пропорційну кількість точок доступу кожній зоні. Ця пропорція ґрунтується на виділеному обсязі ядер ЦП для вузлів, що працюють в цій зоні. Наприклад, якщо в одній зоні є 2 ядра ЦП, а в іншій зоні лише 1 ядро ЦП, контролер виділить подвійну кількість точок доступу для зони з 2 ядрами ЦП.
Нижче наведено приклад того, як виглядає EndpointSlice, коли підказки вже заповнено:
Компонент kube-proxy фільтрує точки доступу, до яких він направляє трафік, на підставі підказок, встановлених контролером EndpointSlice. У більшості випадків це означає, що kube-proxy може направляти трафік до точок доступу в тій самій зоні. Іноді контролер вибирає точки доступу з іншої зони, щоб забезпечити більш рівномірний розподіл точок доступу між зонами. Це може призвести до того, що деякий трафік буде направлятися до інших зон.
Запобіжники
Панель управління Kubernetes та kube-proxy на кожному вузлі застосовують деякі правила захисту перед використанням Topology Aware Hints. Якщо ці перевірки не пройдуть, kube-proxy вибирає точки доступу з будь-якої частини вашого кластера, незалежно від зони.
Недостатня кількість точок доступу: Якщо точок доступу менше, ніж зон в кластері, контролер не буде додавати жодних підказок.
Неможливо досягнути збалансованого розподілу: У деяких випадках може бути неможливо досягти збалансованого розподілу точок доступу між зонами. Наприклад, якщо zone-a удвічі більша, ніж zone-b, але є лише 2 точки доступу, точка доступу, призначена zone-a, може отримати вдвічі більше трафіку, ніж zone-b. Контролер не призначає підказок, якщо він не може знизити це значення "очікуваного перевантаження" нижче прийнятного порогу для кожної зони. Важливо, що це не ґрунтується на зворотньому звʼязку в режимі реального часу. Можливе перенавантаження окремих точок доступу.
Один чи декілька вузлів має недостатню інформацію: Якщо який-небудь вузол не має мітки topology.kubernetes.io/zone або не повідомляє значення виділеного ЦП, панель управління не встановлює жодних підказок точок доступу з відомостями про зони, і, отже, kube-proxy не фільтрує точки доступу за зоною.
Одна чи декілька точок доступу не має підказки щодо зони: Коли це трапляється, kube-proxy припускає, що відбувається перехід до або з Topology Aware Hints. Фільтрація точок доступу для Serviceʼу в цьому стані була б небезпечною, тому kube-proxy використовує всі точки доступу.
Зона не представлена в підказках: Якщо kube-proxy не може знайти принаймні одну точку доступу із підказкою для зони, в якій він працює, він припускається до використання точок доступу з усіх зон. Це ймовірніше станеться, коли ви додаєте нову зону до вашого наявного кластера.
Обмеження
Topology Aware Hints не використовуються, коли internalTrafficPolicy встановлено в Local для Service. Можливе використання обох функцій у тому ж кластері для різних Serviceʼів, просто не на одному і тому ж Service.
Цей підхід не дуже підходить для Serviceʼів, від яких значна частина трафіку походить від підмножини зон. Замість цього передбачається, що вхідний трафік буде приблизно пропорційним місткості Вузлів у кожній зоні.
Контролер EndpointSlice ігнорує непридатні вузли під час розрахунку пропорцій для кожної зони. Це може мати неочікувані наслідки, якщо велика частина вузлів непридатна.
Контролер EndpointSlice ігнорує вузли з мітками node-role.kubernetes.io/control-plane або node-role.kubernetes.io/master. Це може бути проблематичним, якщо також на цих вузлах працюють робочі навантаження.
Контролер EndpointSlice не враховує tolerations при розгортанні або розрахунку пропорцій для кожної зони. Якщо Podʼи, які підтримують Service, обмежені у підмножині вузлів у кластері, це не буде враховано.
Це може не добре працювати з автомасштабуванням. Наприклад, якщо багато трафіку походить з однієї зони, тільки точки доступу, виділені для цієї зони, будуть обробляти цей трафік. Це може призвести до того, що Horizontal Pod Autoscaler або не помічає такої події, або нові Podʼи стартують в іншій зоні.
Власні евристики
Kubernetes може розгортатися різними способами, і для кожного випадку не існує єдиної евристики, яка працюватиме для виділення точок доступу в зони. Одна з ключових цілей цього функціоналу — надання можливості розробки власних евристик, якщо вбудована евристика не працює для вашого випадку використання. Перші кроки для увімкнення власних евристик були включені у випуск 1.27. Це обмежена реалізація, яка може ще не враховувати деякі актуальні та вірогідні ситуації.
Дізнайтесь про поле trafficDistribution, що тісно повʼязане з анотацією service.kubernetes.io/topology-mode та надає гнучкість управління маршрутизацією трафіку в Kubernetes.
10 - Мережеві аспекти Windows
Kubernetes підтримує використання як вузлів Linux, так і Windows, і можливе одночасне використання обох типів вузлів у межах одного кластеру. Ця сторінка надає огляд мережевих аспектів, специфічних для операційної системи Windows.
Мережева взаємодія контейнерів у Windows
Мережевий стек для контейнерів у Windows використовує CNI-втулки. Контейнери у Windows працюють схоже до віртуальних машин з погляду мережі. Кожен контейнер має віртуальний мережевий адаптер (vNIC), який підключений до віртуального комутатора Hyper-V (vSwitch). Host Networking Service (HNS) та Host Compute Service (HCS) спільно працюють для створення контейнерів і підключення віртуальних мережевих адаптерів контейнера до мереж. HCS відповідає за управління контейнерами, тоді як HNS відповідає за управління ресурсами мережі, такими як:
Віртуальні мережі (включаючи створення vSwitches)
Endpoint / vNIC
Namespaces
Політика, включаючи інкапсуляцію пакетів, правила балансування навантаження, ACL, та правила NAT.
Windows HNS та vSwitch реалізують простір імен та можуть створювати віртуальні мережеві адаптери за потреби для Podʼів чи контейнерів. Однак багато конфігурацій,
таких як DNS, маршрути та метрики, зберігаються в базі даних реєстру Windows, а не як файли в /etc, як це робить Linux. Реєстр Windows для контейнера відрізняється від реєстру хосту, тому концепції, такі як передавання /etc/resolv.conf з хосту в контейнер, не мають такого ж ефекту, як у Linux. Їх потрібно налаштовувати за допомогою API Windows, що виконуються в контексті контейнера. Таким чином, реалізації CNI повинні викликати HNS, а не покладатися на доступ до файлів для передачі мережевих деталей у Pod чи контейнер.
Режими мережі
Windows підтримує пʼять різних драйверів/режимів мережі: L2bridge, L2tunnel, Overlay (Beta), Transparent та NAT. У гетерогенному кластері з вузлами Windows і Linux необхідно вибрати мережеве рішення, яке сумісне як з Windows, так і з Linux. У таблиці нижче наведено втулки, що не є частиною Kubernetes, які підтримуються у Windows, з рекомендаціями щодо використання кожного CNI:
Драйвер мережі
Опис
Модифікації контейнерних пакетів
Втулки мережі
Характеристики втулків мережі
L2bridge
Контейнери підключені до зовнішнього vSwitch. Контейнери підключені до мережі нижнього рівня, хоча фізична мережа не повинна знати MAC-адреси контейнера, оскільки вони переписуються при вході/виході.
MAC переписується на MAC хосту, IP може бути переписаний на IP хосту за допомогою політики HNS OutboundNAT.
win-bridge використовує режим мережі L2bridge, підключаючи контейнери до нижнього рівня хостів, пропонуючи найкращу продуктивність. Вимагає маршрутів, визначених користувачем (UDR) для міжвузлової звʼязності.
L2Tunnel
Це спеціальний випадок l2bridge, але використовується тільки на Azure. Всі пакети відсилаються на віртуальний хост, де застосовується політика SDN.
MAC переписується, IP видно в мережі нижнього рівня
Azure-CNI дозволяє інтегрувати контейнери з Azure vNET та використовувати набір можливостей, які Azure Virtual Network надає. Наприклад, безпечно підключатися до служб Azure або використовувати NSG Azure. Див. azure-cni для прикладів
Overlay
Контейнерам надається vNIC, підключений до зовнішнього vSwitch. Кожна мережа має власну підмережу IP, визначену власним IP-префіксом. Драйвер мережі використовує інкапсуляцію VXLAN.
win-overlay слід використовувати, коли потрібна ізоляція віртуальних мереж контейнерів від нижнього рівня хостів (наприклад, з міркувань безпеки). Дозволяє використовувати однакові IP для різних віртуальних мереж (які мають різні теґи VNID), якщо у вас обмеження на IP в вашому датацентрі. Цей варіант вимагає KB4489899 у Windows Server 2019.
Вимагає зовнішнього vSwitch. Контейнери підключені до зовнішнього vSwitch, що дозволяє взаємодію всередині Podʼа за допомогою логічних мереж (логічні свічі та маршрутизатори).
Пакет капсулюється через GENEVE або STT для доступу до Podʼів, які не знаходяться на тому самому хості. Пакети пересилаються чи відкидаються через інформацію про тунель, яку надає контролер мережі ovn. NAT виконується для комунікації північ-південь.
Розгортається за допомогою ansible. Розподілені ACL можна застосовувати за допомогою політик Kubernetes. Підтримка IPAM. Балансування навантаження можливе без використання kube-proxy. NAT виконується без використання iptables/netsh.
NAT (не використовується в Kubernetes)
Контейнерам надається віртуальний мережевий адаптер (vNIC), підключений до внутрішнього vSwitch. DNS/DHCP надається за допомогою внутрішнього компонента, називається WinNAT
Цей втулок підтримує делегування до одного з втулків CNI за вибором користувача (win-overlay, win-bridge), для співпраці з демоном Flannel у Windows (Flanneld) для автоматичного присвоєння лізингу підмережі вузлу та створення мережі HNS. Цей втулок читає власний файл конфігурації (cni.conf) та агрегує його зі змінними середовища зі створеного FlannelD файлу subnet.env. Потім він делегує одному з втулків CNI для роботи з мережею, надсилаючи правильну конфігурацію, що містить призначену вузлом підмережу до IPAM-втулку (наприклад: host-local).
Для обʼєктів Node, Pod та Service підтримуються наступні потоки даних мережі для TCP/UDP-трафіку:
Service Kubernetes є абстракцією, яка визначає логічний набір Podʼів та засіб доступу до них мережею. У кластері, який включає вузли Windows, можна використовувати наступні типи Service:
У Windows можна використовувати наступні налаштування для конфігурації Service та поведінки балансування навантаження:
Налаштування Сервісів для Windows
Функція
Опис
Мінімальна підтримувана версія Windows OS
Як ввімкнути
Подібність сесій (Session affinity)
Забезпечує, що підключення від певного клієнта передається тому самому Podʼу кожен раз.
Windows Server 2022
Встановіть у service.spec.sessionAffinity значення "ClientIP"
Direct Server Return (DSR)
Режим балансування навантаження, де виправлення IP-адреси та LBNAT відбуваються на порту vSwitch контейнера напряму; трафік служби приходить з набору вихідних IP, встановленого як IP походження Podʼа.
Windows Server 2019
Встановіть наступні прапорці в kube-proxy: --feature-gates="WinDSR=true" --enable-dsr=true
Збереження-Призначення
Пропускає DNAT-трафік Servicʼу, тим самим зберігаючи віртуальну IP цільового Service в пакетах, що досягають фронтенду Podʼа. Також вимикає пересилання вузол-вузол.
Windows Server, версія 1903
Встановіть "preserve-destination": "true" в анотаціях служби та увімкніть DSR в kube-proxy.
Подвійний мережевий стек IPv4/IPv6
Нативна підтримка IPv4-до-IPv4 поряд з IPv6-до-IPv6 комунікацією до, з і всередині кластера
Забезпечує збереження джерела ingress трафіку. Також вимикає пересилання вузол-вузол.
Windows Server 2019
Встановіть service.spec.externalTrafficPolicy у "Local" та увімкніть DSR в kube-proxy
Попередження:
Існують відомі проблеми з Serviceʼами NodePort в мережі оверлея, якщо вузол призначення працює під управлінням Windows Server 2022. Щоб уникнути проблеми повністю, ви можете налаштувати Service з externalTrafficPolicy: Local.
Існують відомі проблеми зі зʼєднаннями Pod-Pod в режимі мережі l2bridge у Windows Server 2022 з KB5005619 або вище. Для усунення проблеми та відновлення зʼєднаності Pod-Pod ви можете вимкнути функцію WinDSR в kube-proxy.
Наступні функції мережі не підтримуються на вузлах Windows:
Режим мережі хосту
Локальний доступ NodePort з вузла (працює для інших вузлів або зовнішніх клієнтів)
Більше 64 бекенд-Podʼів (або унікальних адрес призначення) для одного Service
Звʼязок IPv6 між Pods Windows, підключеними до мереж оверлея
Local Traffic Policy в режимі без DSR
Вихідна комунікація за допомогою протоколу ICMP через win-overlay, win-bridge, або використовуючи втулок Azure-CNI. Зокрема панель даних Windows (VFP)
не підтримує ICMP-перетворення пакетів, і це означає:
Пакети ICMP, спрямовані до пунктів призначення в одній мережі (наприклад, звʼязок Pod-Pod за допомогою ping), працюють належним чином;
TCP/UDP-пакети працюють, як очікується;
Пакети ICMP, спрямовані на проходження через віддалену мережу (наприклад, Pod-зовнішньої точки в інтернет через ping), не можуть бути перенесені та, таким чином, не будуть перенаправлені назад до свого джерела;
Оскільки TCP/UDP-пакети все ще можуть бути перетворені, ви можете замінити ping <destination> на curl <destination> при налагодженні зʼєднаності з зовнішнім світом.
Інші обмеження:
Референсні мережеві втулки Windows, такі як win-bridge та win-overlay, не мають реалізації специфікації CNI v0.4.0, через відсутність реалізації CHECK.
Втулок Flannel VXLAN має наступні обмеження на Windows:
Зʼєднаність Node-Pod можлива лише для локальних Podʼів з Flannel v0.12.0 (або вище).
Flannel обмежений використанням VNI 4096 та UDP-порту 4789. Див. офіційну
Flannel VXLAN документацію про бекенд Flannel VXLAN щодо цих параметрів.
11 - Виділення IP-адрес ClusterIP Serviceʼам
У Kubernetes Service — це абстракція для експозиції застосунку, який працює на наборі Podʼів. Serviceʼи можуть мати віртуальну IP-адресу, доступну на рівні кластера (за допомогою Service з type: ClusterIP). Клієнти можуть підключатися за допомогою цієї віртуальної IP-адреси, і Kubernetes балансує трафік до цього Service між його Podʼами.
Як виділяються IP-адреси ClusterIP Сервісу?
Коли Kubernetes потрібно призначити віртуальну IP-адресу для Service, це відбувається одним із двох способів:
динамічно
панель управління кластера автоматично вибирає вільну IP-адресу з налаштованого діапазону IP для Service з type: ClusterIP.
статично
ви вказуєте IP-адресу за своїм вибором, з налаштованого діапазону IP для Service.
Для всього вашого кластера кожен Service ClusterIP повинен бути унікальним. Спроба створення Service із конкретним ClusterIP, що вже був призначений, призведе до помилки.
З чого випливає необхідність резервування IP-адрес для ClusterIP Service?
Іноді вам може знадобитися мати Serviceʼи, які працюють на відомих IP-адресах, щоб інші компоненти та користувачі в кластері могли їх використовувати.
Найкращим прикладом є Service DNS для кластера. Як мʼяка конвенція, деякі встановлювачі Kubernetes відводять 10-ту IP-адресу з діапазону IP-адрес Service для служби DNS. Припустимо, ви налаштували кластер із діапазоном IP-адрес Service 10.96.0.0/16 і хочете, щоб ваша IP-адреса Service DNS була 10.96.0.10, вам доведеться створити Service, подібний до цього:
Але, як це було пояснено раніше, IP-адреса 10.96.0.10 не була зарезервована. Якщо інші Service створюються перед або паралельно з динамічним виділенням, існує шанс, що вони можуть зайняти цю IP-адресу, тому ви не зможете створити Service DNS, оскільки це призведе до конфлікту.
Як уникнути конфліктів IP-адрес ClusterIP Сервісу?
Стратегія виділення, реалізована в Kubernetes для виділення ClusterIPs Service, зменшує ризик колізій.
ClusterIP діапазон поділений на основі формули min(max(16, cidrSize / 16), 256), описано як ніколи менше ніж 16 або більше за 256 із поступовим кроком між ними.
Динамічне призначення IP типово використовує верхній діапазон, якщо цей діапазон вичерпано, то буде використано нижній діапазон. Це дозволить користувачам використовувати статичні виділення в нижньому діапазоні із низьким ризиком колізій.
Приклади
Приклад 1
У цьому прикладі використовується діапазон IP-адрес: 10.96.0.0/24 (нотація CIDR) для IP-адрес Serviceʼів.
Розмір діапазону: 28 - 2 = 254
Зсув діапазону: min(max(16, 256/16), 256) = min(16, 256) = 16
Початок статичного діапазону: 10.96.0.1
Кінець статичного діапазону: 10.96.0.16
Кінець діапазону: 10.96.0.254
Приклад 2
У цьому прикладі використовується діапазон IP-адрес: 10.96.0.0/20 (нотація CIDR) для IP-адрес Service.
Розмір діапазону: 212 - 2 = 4094
Зсув діапазону: min(max(16, 4096/16), 256) = min(256, 256) = 256
Початок статичного діапазону: 10.96.0.1
Кінець статичного діапазону: 10.96.1.0
Кінець діапазону: 10.96.15.254
Приклад 3
У цьому прикладі використовується діапазон IP-адрес: 10.96.0.0/16 (нотація CIDR) для IP-адрес Service.
Розмір діапазону: 216 - 2 = 65534
Зсув діапазону: min(max(16, 65536/16), 256) = min(4096, 256) = 256
Початок статичного діапазону: 10.96.0.1
Кінець статичного діапазону: 10.96.1.0
Кінець діапазону: 10.96.255.254
Якщо два Podʼа в вашому кластері хочуть взаємодіяти, і вони обидва фактично працюють на одному й тому ж вузлі, використовуйте Політики внутрішнього трафіку Service, щоб утримувати мережевий трафік в межах цього вузла. Уникнення зворотного зв’язку через кластерну мережу може допомогти підвищити надійність, продуктивність (затримку мережі та пропускну здатність) або вартість.
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.26 [stable]
Політика внутрішнього трафіку Service дозволяє обмежувати внутрішній трафік, маршрутизуючи його лише до endpoint у межах вузла, з якого походить трафік. Тут "внутрішній" трафік означає трафік, який виник з Podʼів у поточному кластері. Це може допомогти зменшити витрати та покращити продуктивність.
Використання політики внутрішнього трафіку Service
Ви можете увімкнути політику тільки для внутрішнього трафіку для Service, встановивши його .spec.internalTrafficPolicy в Local. Це вказує kube-proxy використовувати лише вузлові локальні endpoint для внутрішнього трафіку кластера.
Примітка:
Для Podʼів на вузлах без endpoint для певного Service, Service буде працювати так, ніби в нього немає endpoint (для Podʼів на цьому вузлі), навіть якщо у Service є endpointʼи на інших вузлах.
У наступному прикладі показано, як виглядає Service, коли ви встановлюєте
.spec.internalTrafficPolicy в Local:
Kube-proxy фільтрує endpointʼи, до яких він виконує маршрутизацію, на основі налаштувань spec.internalTrafficPolicy. Коли вона встановлена в Local, розглядаються тільки вузлові локальні endpointʼи. Коли вона встановлена в Cluster (стандартно), або не встановлена взагалі, Kubernetes розглядає всі endpointʼи.