Це багатосторінковий друкований вигляд цього розділу. Натисність щоб друкувати.

Повернутися до звичайного перегляду сторінки.

Адміністрування кластера

Деталі низького рівня, що стосуються створення та адміністрування кластера Kubernetes.

Огляд адміністрування кластера призначений для всіх, хто створює або адмініструє кластер Kubernetes. Він передбачає певний рівень знайомства з основними концепціями.

Планування кластера

Ознайомтеся з посібниками в розділі Встановлення для прикладів планування, налаштування та конфігурації кластерів Kubernetes. Рішення, перераховані в цій статті, називаються distros.

Перед вибором посібника врахуйте наступні моменти:

  • Чи хочете ви спробувати Kubernetes на своєму компʼютері, чи хочете побудувати кластер високої доступності з кількома вузлами? Вибирайте distros, які найкраще підходять для ваших потреб.
  • Чи будете ви використовувати кластер Kubernetes, розміщений на хостингу, такому як Google Kubernetes Engine, чи створюватимете свій власний кластер?
  • Чи буде ваш кластер на місці, чи в хмарі (IaaS)? Kubernetes напряму не підтримує гібридні кластери. Замість цього ви можете налаштувати кілька кластерів.
  • Якщо ви налаштовуєте Kubernetes на місці, розгляньте, яка модель мережі підходить найкраще.
  • Чи будете ви запускати Kubernetes на "bare metal" обладнанні чи на віртуальних машинах (VMs)?
  • Ви хочете мати робочий кластер, чи плануєте активний розвиток коду проєкту Kubernetes? Якщо останнє, вибирайте distros, які активно розвиваються. Деякі distros використовують лише бінарні релізи, але пропонують більшу різноманітність вибору.
  • Ознайомтеся з компонентами, необхідними для запуску кластера.

Адміністрування кластера

Захист кластера

Захист kubelеt

Додаткові служби кластера

1 - Вимикання вузлів

У кластері Kubernetes вузол може бути вимкнутий плановим відповідним способом або несподівано через такі причини, як відключення електропостачання або інші зовнішні обставини. Вимкнення вузла може призвести до відмови робочого навантаження, якщо вузол не буде виводитись з обслуговування перед вимкненням. Вимкнення вузла може бути відповідним або невідповідним (graceful or non-graceful).

Належне вимикання вузла

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.21 [beta] (стандартно увімкнено: true)

Kubelet намагається виявити вимикання системи вузла та завершує виконання Podʼів на вузлі.

Kubelet забезпечує виконання нормального процесу завершення роботи Podʼа під час вимикання вузла. Під час вимикання вузла kubelet не приймає нові Podʼи (навіть якщо ці Podʼи вже призначені вузлу).

Можливість належного вимикання вузла (Graceful node shutdown) залежить від systemd, оскільки вона використовує блокування інгібіторів systemd для затримки вимкнення вузла на певний час.

Вимикання вузла керується функціональною можливістю GracefulNodeShutdown, що є типово увімкненим з версії 1.21.

Зауважте, що типово обидва налаштування конфігурації, описані нижче, shutdownGracePeriod та shutdownGracePeriodCriticalPods, встановлені на нуль, таким чином, не активуючи функціональність належного вимикання вузла. Для активації цієї функції, два налаштування конфігурації kubelet повинні бути належним чином налаштовані та встановлені на значення, відмінні від нуля.

Як тільки systemd виявляє або повідомляє про вимикання вузла, kubelet встановлює умову NotReady на вузлі з причиною "node is shutting down". Kube-scheduler дотримується цієї умови та не планує жодних Podʼів на цьому вузлі; очікується, що інші планувальники сторонніх постачальників дотримуватимуться такої ж логіки. Це означає, що нові Podʼи не будуть плануватися на цьому вузлі, і, отже, жоден із них не розпочне роботу.

Kubelet також відхиляє Podʼи під час фази PodAdmission, якщо виявлено поточне вимикання вузла, так що навіть Podʼи з toleration для node.kubernetes.io/not-ready:NoSchedule не почнуть виконання там.

Водночас коли kubelet встановлює цю умову на своєму вузлі через API, kubelet також починає завершення будь-яких Podʼів, які виконуються локально.

Під час вимикання kubelet завершує Podʼи у два етапи:

  1. Завершує роботу звичайних Podʼів, які виконуються на вузлі.
  2. Завершує роботу критичних Podʼів, які виконуються на вузлі.

Функція належного вимикання вузла налаштовується двома параметрами конфігурації kubelet:

  • shutdownGracePeriod:
    • Визначає загальний час, протягом якого вузол повинен затримати вимикання. Це загальний термін допомагає завершити Podʼи як звичайні, так і критичні.
  • shutdownGracePeriodCriticalPods:
    • Визначає термін, який використовується для завершення критичних Podʼів під час вимикання вузла. Це значення повинно бути менше за shutdownGracePeriod.

Наприклад, якщо shutdownGracePeriod=30s, а shutdownGracePeriodCriticalPods=10s, kubelet затримає вимикання вузла на 30 секунд. Під час вимикання перші 20 (30-10) секунд будуть зарезервовані для належного завершення звичайних Podʼів, а останні 10 секунд будуть зарезервовані для завершення критичних Podʼів.

Належне вимикання вузла на основі пріоритету Podʼа

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.24 [beta] (стандартно увімкнено: true)

Щоб забезпечити більше гнучкості під час належного вимикання вузла щодо порядку Podʼів під час вимикання, належне вимикання вузла враховує PriorityClass для Podʼів, за умови, що ви активували цю функцію у своєму кластері. Функція дозволяє адміністраторам кластера явно визначити порядок Podʼів під час належного вимикання вузла на основі priority classes.

Функція належного вимикання вузла, яка описана вище, вимикає Podʼи у дві фази: звичайні Podʼи, а потім критичні Podʼи. Якщо потрібна додаткова гнучкість для явного визначення порядку Podʼа під час вимикання в більш деталізований спосіб, можна використовувати належне (graceful) вимикання вузла на основі пріоритету Podʼа.

Коли вимикання вузла враховує пріоритет Podʼів, це дозволяє виконувати вимикання вузла у кілька етапів, кожен етап — це завершення роботи Podʼів певного класу пріоритету. Kubelet можна налаштувати з точним числом етапів та часом вимикання для кожного етапу.

Припустимо, що в кластері існують наступні власні класи пріоритету Podʼів:

Назва класу пріоритету PodʼаЗначення класу пріоритету Podʼа
custom-class-a100000
custom-class-b10000
custom-class-c1000
regular/unset0

В межах конфігурації kubelet налаштування для shutdownGracePeriodByPodPriority може виглядати так:

Значення класу пріоритету PodʼаПеріод вимкнення
10000010 seconds
10000180 seconds
1000120 seconds
060 seconds

Відповідна конфігурація YAML kubelet виглядатиме так:

shutdownGracePeriodByPodPriority:
  - priority: 100000
    shutdownGracePeriodSeconds: 10
  - priority: 10000
    shutdownGracePeriodSeconds: 180
  - priority: 1000
    shutdownGracePeriodSeconds: 120
  - priority: 0
    shutdownGracePeriodSeconds: 60

Вищеописана таблиця означає, що будь-який Pod зі значенням priority >= 100000 отримає лише 10 секунд на зупинку, будь-який Pod зі значенням >= 10000 і < 100000 отримає 180 секунд для зупинки, будь-який Pod зі значенням >= 1000 і < 10000 отримає 120 секунд для зупинки. Нарешті, всі інші Podʼи отримають 60 секунд для зупинки.

Не обовʼязково вказувати значення, відповідні всім класам. Наприклад, можна використовувати ці налаштування:

Значення класу пріоритету PodʼаПеріод вимкнення
100000300 seconds
1000120 seconds
060 seconds

У вищезазначеному випадку Podʼи з custom-class-b потраплять в ту ж саму групу, що й custom-class-c для вимкнення.

Якщо в певному діапазоні відсутні Podʼи, то kubelet не чекатиме на Podʼи у цьому діапазоні пріоритетів. Замість цього, kubelet безпосередньо перейде до наступного діапазону значень пріоритету.

Якщо ця функція увімкнена, а жодна конфігурація не надана, то дії з упорядкування не будуть виконані.

Використання цієї функції передбачає активацію функціональної можливості GracefulNodeShutdownBasedOnPodPriority, та встановлення ShutdownGracePeriodByPodPriority в kubelet config до потрібної конфігурації, яка містить значення класу пріоритету Podʼа та відповідні періоди вимкнення.

Метрики graceful_shutdown_start_time_seconds та graceful_shutdown_end_time_seconds публікуються у підсистему kubelet для моніторингу вимкнень вузлів.

Обробка неналежних вимкнень вузлів

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.28 [stable] (стандартно увімкнено: true)

Дія вимкнення вузла може бути не виявленою Node Shutdown Manager вузла kubelet, чи то через те, що команда не активує механізм блокування інгібітора, який використовується kubelet, чи через помилку користувача, тобто ShutdownGracePeriod та ShutdownGracePeriodCriticalPods налаштовані неправильно. Будь ласка, зверніться до вищезазначеної секції Належне вимикання вузла для отримання докладнішої інформації.

Коли вузол вимикається, але це не виявляється Node Shutdown Manager вузла kubelet, Podʼи, які є частиною StatefulSet, залишаться в стані завершення на вимкненому вузлі та не зможуть перейти до нового робочого вузла. Це тому, що kubelet на вимкненому вузлі недоступний для видалення Podʼів, і StatefulSet не може створити новий Pod із такою ж назвою. Якщо є томи, які використовуються Podʼами, то VolumeAttachments не буде видалено з оригінального вимкненого вузла, і тому томи використовувані цими Podʼами не можуть бути приєднані до нового робочого вузла. В результаті застосунок, що виконується з StatefulSet, не може працювати належним чином. Якщо оригінальний вимкнений вузол вмикається, Podʼи будуть видалені kubelet, і нові Podʼи будуть створені на іншому робочому вузлі. Якщо оригінальний вимкнений вузол не повертається, ці Podʼи залишаться в стані завершення на вимкненому вузлі назавжди.

Для помʼякшення вищезазначеної ситуації користувач може вручну додати позначку (taint) node.kubernetes.io/out-of-service з ефектом NoExecute чи NoSchedule до вузла, вказавши, що він вийшов із ладу. Якщо вузол відзначений як такий, що вийшов з ладу з такою позначкою, Podʼи на вузлі будуть примусово видалені, якщо на них немає відповідних toleration, і операції відʼєднання томів для завершення Podʼів на вузлі відбудуться негайно. Це дозволяє Podʼам на вузлі, що вийшов з ладу, швидко відновитися на іншому вузлі.

Під час такого (non-graceful) вимикання робота Podʼів завершується у дві фази:

  1. Насильно видаляються Podʼи, які не мають відповідних toleration out-of-service.
  2. Негайно виконується операція відʼєднання томів для таких Podʼів.

Примусове відʼєднання сховища при перевищенні часу очікування

У будь-якій ситуації, де видалення Podʼа не вдалося протягом 6 хвилин, Kubernetes примусово відʼєднає томи, які розмонтувалися, якщо в цей момент вузол несправний. Будь-яке робоче навантаження, що все ще працює на вузлі та використовує том, який примусово відʼєднується, спричинить порушення специфікації CSI, яка стверджує, що ControllerUnpublishVolume "повинен бути викликаний після всіх викликів NodeUnstageVolume та NodeUnpublishVolume в томі, і вони успішно завершилися". В таких обставинах томи на такому вузлі можуть зіткнутися з пошкодженням даних.

Поведінка примусового відʼєднання сховища є необовʼязковою; користувачі можуть вибрати використання функції "Non-graceful node shutdown" замість цього.

Примусове відʼєднання сховища при перевищенні часу очікування можна вимкнути, встановивши поле конфігурації disable-force-detach-on-timeout в kube-controller-manager. Вимкнення функції примусового відʼєднання при перевищенні часу очікування означає, що у тому, який розміщено на вузлі, який несправний протягом понад 6 хвилин, не буде видалено його повʼязаний VolumeAttachment.

Після застосування цього налаштування, несправні Podʼи, які все ще приєднані до томів, повинні бути відновлені за допомогою процедури Обробки неналежних вимкнень вузлів, згаданої вище.

Належне припинення роботи вузла Windows

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.32 [alpha] (стандартно увімкнено: false)

Функція Windows graceful node shutdown залежить від того, чи працює kubelet як служба Windows, тоді він матиме зареєстрований service control handler для затримки події вимкнення на задану тривалість.

Керування вимкненням вузла Windows здійснюється за допомогою функціональної можливості WindowsGracefulNodeShutdown, яку було представлено у 1.32 як альфа-версію.

Належне завершення роботи вузла у Windows не може бути скасовано.

Якщо Kubelet не запущено як службу Windows, він не зможе встановити та відстежувати подію Preshutdown, вузол буде змушений пройти через процедуру Non-Graceful Node Shutdown, згадану вище.

У випадку, якщо у Windows увімкнено функцію належного завершення роботи вузла, але kubelet не запущено як службу Windows, kubelet продовжить роботу, а не завершить її. Однак, він буде реєструвати помилку, яка вказує на те, що його потрібно запустити як службу Windows.

Що далі

Дізнайтеся більше про наступне:

2 - Сертифікати

Щоб дізнатись, як генерувати сертифікати для вашого кластера, дивіться розділ Завдань — Сертифікати.

3 - Мережа в кластері

Мережі є центральною частиною Kubernetes, але часто важко зрозуміти, як саме вони мають працювати. Існують 4 відмінних мережевих проблеми, які потрібно вирішити:

  1. Взаємодія контейнерів між собою: цю проблему вирішує використання Podʼів та взаємодія з localhost.
  2. Взаємодія між Podʼами: це основна ціль даного документа.
  3. Взаємодія між Podʼом та Service: ця проблема описана у Service.
  4. Взаємодія Service із зовнішнім світом: це також описано в контексті Service.

Kubernetes — це система розподілу машин між застосунками. Зазвичай для розподілу машин потрібно переконатися, що два застосунки не намагаються використовувати одні й ті самі порти. Координацію портів між кількома розробниками дуже важко зробити в масштабі та наражає користувачів на проблеми на рівні кластера, що знаходяться поза їхнім контролем.

Динамічне призначення портів приносить багато ускладнень в систему — кожен застосунок має приймати порти як прапорці, серверам API потрібно знати, як вставляти динамічні номери портів у блоки конфігурації, сервісам потрібно знати, як знаходити один одного тощо. Замість цього Kubernetes обирає інший підхід.

Ознайомтесь докладніше з мережевою моделлю Kubernetes.

Діапазони IP-адрес Kubernetes

Кластери Kubernetes потребують виділення IP-адрес, які не перекриваються, для Podʼів, Service та Вузлів, з діапазону доступних адрес, налаштованих у наступних компонентах:

  • Втулок мережі налаштований для призначення IP-адрес Podʼам.
  • Kube-apiserver налаштований для призначення IP-адрес Service.
  • Kubelet або cloud-controller-manager налаштовані для призначення IP-адрес Вузлам.
Схема, яка ілюструє різні діапазони мережі у кластері Kubernetes

Типи мереж в кластері

Кластери Kubernetes, залежно від налаштованих типів IP адрес, можуть бути категоризовані на:

  • Лише IPv4: Втулок мережі, kube-apiserver та kubelet/cloud-controller-manager налаштовані для призначення лише IPv4-адрес.
  • Лише IPv6: Втулок мережі, kube-apiserver та kubelet/cloud-controller-manager налаштовані для призначення лише IPv6-адрес.
  • IPv4/IPv6 або IPv6/IPv4 подвійний стек:
    • Втулок мережі налаштований для призначення IPv4 та IPv6-адрес.
    • Kube-apiserver налаштований для призначення IPv4 та IPv6-адрес.
    • Kubelet або cloud-controller-manager налаштовані для призначення IPv4 та IPv6-адрес.
    • Усі компоненти повинні узгоджуватися щодо налаштованої основного типу IP адрес.

Кластери Kubernetes враховують лише типи IP, які присутні в обʼєктах Podʼів, Service та Вузлів, незалежно від наявних IP-адрес представлених обʼєктів. Наприклад, сервер або Pod може мати кілька IP-адрес на своїх інтерфейсах, але для реалізації мережевої моделі Kubernetes та визначення типу кластера беруться до уваги лише IP-адреси в node.status.addresses або pod.status.ips.

Як реалізувати мережеву модель Kubernetes

Модель мережі реалізується середовищем виконання контейнерів на кожному вузлі. Найпоширеніші середовища використовують Інтерфейс мережі контейнера (CNI) для керування своєю мережею та забезпечення безпеки. Існує багато різних CNI-втулків від різних вендорів. Деякі з них надають лише базові можливості додавання та видалення мережевих інтерфейсів, тоді як інші надають складніші рішення, такі як інтеграція з іншими системами оркестрування контейнерів, запуск кількох CNI-втулків, розширені функції IPAM та інше.

Див. цю сторінку для неповного переліку мережевих надбудов, які підтримуються в Kubernetes.

Що далі

Ранній дизайн мережевої моделі та її обґрунтування докладно описані у документі дизайну мережі. Щодо майбутніх планів та деяких поточних зусиль, спрямованих на поліпшення мережевих функцій Kubernetes, будь ласка, звертайтеся до SIG-Network KEPs.

4 - Архітектура логування

Логи застосунків можуть допомогти вам зрозуміти, що відбувається у нього всередині. Логи особливо корисні для виправлення проблем та моніторингу активності кластера. Більшість сучасних застосунків мають деякий механізм логування. Так само, рушії виконання контейнерів розроблені з підтримкою логування. Найпростіший і найбільш прийнятий метод логування для контейнеризованих застосунків — це запис у стандартні потоки виводу та помилок.

Однак, природня функціональність, яку надає рушій виконання контейнерів або середовище виконання, зазвичай недостатня для повного вирішення завдань логування.

Наприклад, вам може бути необхідно дістатись до логів вашого застосунку, якщо контейнер зазнає збою, Pod видаляється, або вузол припиняє роботу.

У кластері логи повинні мати окреме сховище та життєвий цикл незалежно від вузлів, Podʼів або контейнерів. Ця концепція називається логування на рівні кластера.

Архітектури логування на рівні кластера вимагають окремого бекенду для зберігання, аналізу, та отримання логів. Kubernetes не надає власного рішення для зберігання даних логів. Натомість існує багато рішень для логування, які інтегруються з Kubernetes. Наступні розділи описують, як обробляти та зберігати логи на вузлах.

Логи Podʼів та контейнерів

Kubernetes збирає логи з кожного контейнера в запущеному Podʼі.

Цей приклад використовує маніфест для Podʼу з контейнером, який записує текст у стандартний потік виводу, раз на секунду.

apiVersion: v1
kind: Pod
metadata:
  name: counter
spec:
  containers:
  - name: count
    image: busybox:1.28
    args: [/bin/sh, -c,
            'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']

Для запуску цього Podʼа використовуйте наступну команду:

kubectl apply -f https://k8s.io/examples/debug/counter-pod.yaml

Вивід буде таким:

pod/counter created

Для отримання логів використовуйте команду kubectl logs, як показано нижче:

kubectl logs counter

Вивід буде схожим на:

0: Fri Apr  1 11:42:23 UTC 2022
1: Fri Apr  1 11:42:24 UTC 2022
2: Fri Apr  1 11:42:25 UTC 2022

Ви можете використовувати kubectl logs --previous для отримання логів з попереднього запуску контейнера. Якщо ваш Pod має кілька контейнерів, вкажіть, логи якого контейнера ви хочете переглянути, додавши назву контейнера до команди з прапорцем -c, ось так:

kubectl logs counter -c count

Потоки логів контейнерів

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.32 [alpha] (стандартно увімкнено: false)

Як альфа-функція, kubelet може розділяти логи з двох стандартних потоків, що створюються контейнером: стандартний вивід та стандартна помилка. Щоб скористатися такою поведінкою, вам слід увімкнути функціональну можливість PodLogsQuerySplitStreams. З її увімкненням Kubernetes 1.32 надає доступ до цих потоків логів безпосередньо за допомогою Pod API. Ви можете отримати конкретний потік, вказавши назву потоку (або Stdout, або Stderr) за допомогою рядка запиту stream. Ви повинні мати доступ до читання підресурсу log цього Pod.

Щоб продемонструвати цю можливість, ви можете створити Pod, який періодично записуватиме текст як до стандартного потоку виводу, так і до потоку помилок.

apiVersion: v1
kind: Pod
metadata:
  name: counter-err
spec:
  containers:
  - name: count
    image: busybox:1.28
    args: [/bin/sh, -c,
            'i=0; while true; do echo "$i: $(date)"; echo "$i: err" >&2 ; i=$((i+1)); sleep 1; done']

Для запуску цього podʼа скористайтесь наступною командою:

kubectl apply -f https://k8s.io/examples/debug/counter-pod-err.yaml

Щоб отримати лише потік логу stderr, ви можете виконати команду:

kubectl get --raw "/api/v1/namespaces/default/pods/counter-err/log?stream=Stderr"

Дивіться документацію kubectl logs для отримання додаткових деталей.

Як вузли обробляють логи контейнерів

Логування на рівні вузла

Система управління контейнерами обробляє та перенаправляє будь-який вивід, створений потоками stdout та stderr контейнеризованого застосунку. Різні системи управління контейнерами реалізують це по-різному; однак, інтеграція з kubelet стандартизована як формат логування CRI.

Стандартно, якщо контейнер перезапускається, kubelet зберігає один зупинений контейнер з його логами. Якщо Pod видаляється з вузла, всі відповідні контейнери також видаляються разом з їхніми логами.

Kubelet надає доступ до логів клієнтам через спеціальну функцію Kubernetes API. Зазвичай доступ до неї здійснюється за допомогою команди kubectl logs.

Ротація логів

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.21 [stable]

Kubelet відповідає за ротацію логів контейнерів та управління структурою тек логів. Kubelet передає цю інформацію до системи управління контейнерами (використовуючи CRI), а середовище виконання записує логи контейнерів у вказане місце.

Ви можете налаштувати два параметри конфігурації kubelet containerLogMaxSize (типово 10Mi) та containerLogMaxFiles (типово 5), використовуючи файл конфігурації kubelet. Ці параметри дозволяють вам налаштувати максимальний розмір для кожного файлу лога та максимальну кількість файлів, дозволених для кожного контейнера відповідно.

Для ефективної ротації логів у кластерах, де обсяг логів, згенерованих робочим навантаженням, великий, kubelet також надає механізм налаштування ротації логів з погляду кількості одночасних ротацій логів та інтервалу, з яким логи відстежуються та ротуються за потребою. Ви можете налаштувати два параметри конфігурації kubelet, containerLogMaxWorkers та containerLogMonitorInterval за допомогою файлу конфігурації kubelet.

Коли ви виконуєте kubectl logs як у прикладі базового логування, kubelet на вузлі обробляє запит і безпосередньо читає з файлу лога. Kubelet повертає вміст файлу лога.

Логи системних компонентів

Існують два типи системних компонентів: ті, які зазвичай працюють у контейнерах, та ті компоненти, які безпосередньо відповідають за запуск контейнерів. Наприклад:

  • Kubelet та система управління контейнерами не працюють у контейнерах. Kubelet виконує ваші контейнери (згруповані разом у Podʼи).
  • Планувальник Kubernetes, менеджер контролерів та сервер API працюють у Podʼах (зазвичай статичних Podʼах). Компонент etcd працює у планувальнику, і зазвичай також як статичний Pod. Якщо ваш кластер використовує kube-proxy, зазвичай ви запускаєте його як DaemonSet.

Знаходження логів

Спосіб, яким kubelet та система управління контейнерами записують логи, залежить від операційної системи, яку використовує вузол:

На вузлах Linux, які використовують systemd, типово kubelet та система управління контейнерами записують логи у журнал systemd. Ви можете використовувати journalctl для читання журналу systemd; наприклад: journalctl -u kubelet.

Якщо systemd відсутній, kubelet та система управління контейнерами записують логи у файли .log в директорії /var/log. Якщо ви хочете, щоб логи були записані в інше місце, ви можете опосередковано запустити kubelet через допоміжний інструмент, kube-log-runner, та використовувати цей інструмент для перенаправлення логів kubelet у вибрану вами теку.

Типово, kubelet спрямовує систему управління контейнерами на запис логів у теці всередині /var/log/pods.

Для отримання додаткової інформації про kube-log-runner, читайте Системні логи.

Типово kubelet записує логи у файли всередині теки C:\var\logs (⚠️ зверніть увагу, що це не C:\var\log).

Хоча C:\var\log є типовим місцем для цих логів Kubernetes, деякі інструменти розгортання кластера налаштовують вузли Windows так, щоб логи записувались у C:\var\log\kubelet.

Якщо ви хочете, щоб логи були записані в інше місце, ви можете опосередковано запустити kubelet через допоміжний інструмент, kube-log-runner, та використовувати цей інструмент для перенаправлення логів kubelet у вибрану вами директорію.

Проте, типово kubelet скеровує систему управління контейнерами на запис логів у теці всередині C:\var\log\pods.

Для отримання додаткової інформації про kube-log-runner, читайте Системні логи.


Для компонентів кластера Kubernetes, які працюють у Podʼах, логи записуються у файли всередині директорії /var/log, оминаючи типовий механізм логування (компоненти не записуються у журнал systemd). Ви можете використовувати механізми зберігання Kubernetes для відображення постійного зберігання у контейнері, який виконує компонент.

Kubelet дозволяє змінювати теку логів Podʼів зі стандартної /var/log/pods на власну. Це можна зробити за допомогою параметра podLogsDir у конфігураційному файлі kubelet.

Для отримання детальної інформації про etcd та його логи, перегляньте документацію etcd. Знову ж таки, ви можете використовувати механізми зберігання Kubernetes для відображення постійного зберігання у контейнері, який виконує компонент.

Архітектури логування на рівні кластера

Хоча Kubernetes не надає власного рішення для логування на рівні кластера, існують кілька загальних підходів, які ви можете розглянути. Ось деякі варіанти:

  • Використання агента логування на рівні вузла, який працює на кожному вузлі.
  • Додавання в Pod з застосунком в спеціального sidecaar-контейнера для логування.
  • Пряме надсилання логів безпосередньо до бекенду з застосунка.

Використання агента логування на рівні вузла

Використання агента логування на рівні вузла

Ви можете реалізувати логування на рівні кластера, включивши агента логування на рівні вузла на кожному вузлі. Агент логування — це спеціальний інструмент, який надає логи або надсилає їх до бекенду. Зазвичай агент логування є контейнером, який має доступ до теки з файлами логів з усіх контейнерів застосунків на цьому вузлі.

Оскільки агент логування повинен працювати на кожному вузлі, рекомендується запускати агента як DaemonSet.

Логування на рівні вузла створює лише одного агента на вузол і не вимагає жодних змін в застосунках, що працюють на вузлі.

Контейнери пишуть у stdout та stderr, але без узгодженого формату. Агент на рівні вузла збирає ці логи та пересилає їх для агрегації.

Використання sidecar контейнера з агентом логування

Ви можете використовувати sidecar контейнер у такий спосіб:

  • sidecar контейнер транслює логи застосунку у свій власний stdout.
  • sidecar контейнер запускає агента логування, який налаштований на збір логів з контейнера застосунку.

Sidecar контейнер для трансляції

Sidecar контейнер з контейнером для трансляції

Маючи свої sidecar контейнери які пишуть у власні stdout та stderr, ви можете скористатися kubelet та агентом логування, які вже працюють на кожному вузлі. Sidecar контейнери читають логи з файлу, сокета або журналу. Кожен sidecar контейнер виводить лог у свій власний потік stdout або stderr.

Цей підхід дозволяє вам розділити кілька потоків логів з різних частин вашого застосунку деякі з яких можуть не підтримувати запис у stdout або stderr. Логіка перенаправлення логів мінімальна, тому це не становить значного навантаження. Крім того, оскільки stdout та stderr обробляються kubelet, ви можете використовувати вбудовані інструменти, такі як kubectl logs.

Наприклад, Pod запускає один контейнер, і контейнер записує до двох різних файлів логів з використанням двох різних форматів. Ось маніфест для Podʼа:

apiVersion: v1
kind: Pod
metadata:
  name: counter
spec:
  containers:
  - name: count
    image: busybox:1.28
    args:
    - /bin/sh
    - -c
    - >
      i=0;
      while true;
      do
        echo "$i: $(date)" >> /var/log/1.log;
        echo "$(date) INFO $i" >> /var/log/2.log;
        i=$((i+1));
        sleep 1;
      done      
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  volumes:
  - name: varlog
    emptyDir: {}

Не рекомендується записувати записи логів з різними форматами у той самий потік логу, навіть якщо вам вдалося перенаправити обидва компоненти до потоку stdout контейнера. Замість цього ви можете створити два додаткових sidecar контейнери. Кожен додатковий sidecar контейнер може перехоплювати певний файл логів зі спільного тома та перенаправляти логи до власного потоку stdout.

Ось маніфест для Podʼа, в якому є два sidecar контейнери:

apiVersion: v1
kind: Pod
metadata:
  name: counter
spec:
  containers:
  - name: count
    image: busybox:1.28
    args:
    - /bin/sh
    - -c
    - >
      i=0;
      while true;
      do
        echo "$i: $(date)" >> /var/log/1.log;
        echo "$(date) INFO $i" >> /var/log/2.log;
        i=$((i+1));
        sleep 1;
      done      
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  - name: count-log-1
    image: busybox:1.28
    args: [/bin/sh, -c, 'tail -n+1 -F /var/log/1.log']
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  - name: count-log-2
    image: busybox:1.28
    args: [/bin/sh, -c, 'tail -n+1 -F /var/log/2.log']
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  volumes:
  - name: varlog
    emptyDir: {}

Тепер, коли ви запускаєте цей Pod, ви можете отримати доступ до кожного потоку логів окремо, запустивши такі команди:

kubectl logs counter count-log-1

Результат буде подібним до:

0: Fri Apr  1 11:42:26 UTC 2022
1: Fri Apr  1 11:42:27 UTC 2022
2: Fri Apr  1 11:42:28 UTC 2022
...
kubectl logs counter count-log-2

Результат буде подібним до:

Fri Apr  1 11:42:29 UTC 2022 INFO 0
Fri Apr  1 11:42:30 UTC 2022 INFO 0
Fri Apr  1 11:42:31 UTC 2022 INFO 0
...

Якщо ви встановили агент на рівні вузла у свій кластер, цей агент автоматично перехоплює ці потоки логів без будь-якої додаткової конфігурації. Якщо вам цікаво, ви можете налаштувати агента для розбору рядків логів залежно від вихідного контейнера.

Навіть для Podʼів, які використовують низьке використання CPU та памʼяті (наприклад, декілька мілікорів (millicore) для CPU та кілька мегабайтів для памʼяті), запис логів до файлу та їх трансляція до stdout можуть подвоїти обсяг памʼяті, необхідний на вузлі. Якщо у вас є застосунок, який записує у єдиний файл, рекомендується встановити /dev/stdout як призначення, а не впроваджувати підхід з sidecar контейнером для трансляції.

Sidecar контейнери також можуть використовуватися для ротації файлів логів, ротація яких не може бути зроблена самим застосунком. Прикладом такого підходу є малий контейнер, який періодично запускає logrotate. Однак набагато простіше використовувати stdout та stderr безпосередньо і залишити ротації та політику зберігання kubelet.

Sidecar контейнер з агентом логування

Sidecar контейнер з агентом логування

Якщо агент логування на рівні вузла не має достатньої гнучкості для вашої ситуації, ви можете створити sidecar контейнер з окремим агентом логування, який ви налаштували спеціально для роботи з вашим застосунком.

Ось два приклади маніфестів, які ви можете використати для впровадження sidecar контейнера з агентом логування. Перший маніфест містить ConfigMap, щоб налаштувати fluentd.

apiVersion: v1
kind: ConfigMap
metadata:
  name: fluentd-config
data:
  fluentd.conf: |
    <source>
      type tail
      format none
      path /var/log/1.log
      pos_file /var/log/1.log.pos
      tag count.format1
    </source>

    <source>
      type tail
      format none
      path /var/log/2.log
      pos_file /var/log/2.log.pos
      tag count.format2
    </source>

    <match **>
      type google_cloud
    </match>    

Другий маніфест описує Pod, в якому є sidecar контейнер, що запускає fluentd. Pod монтує том, де fluentd може отримати свої дані конфігурації.

apiVersion: v1
kind: Pod
metadata:
  name: counter
spec:
  containers:
  - name: count
    image: busybox:1.28
    args:
    - /bin/sh
    - -c
    - >
      i=0;
      while true;
      do
        echo "$i: $(date)" >> /var/log/1.log;
        echo "$(date) INFO $i" >> /var/log/2.log;
        i=$((i+1));
        sleep 1;
      done      
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  - name: count-agent
    image: registry.k8s.io/fluentd-gcp:1.30
    env:
    - name: FLUENTD_ARGS
      value: -c /etc/fluentd-config/fluentd.conf
    volumeMounts:
    - name: varlog
      mountPath: /var/log
    - name: config-volume
      mountPath: /etc/fluentd-config
  volumes:
  - name: varlog
    emptyDir: {}
  - name: config-volume
    configMap:
      name: fluentd-config

Викладення логів безпосередньо з застосунку

Викладення логів безпосередньо з застосунку

Кластерне логування, яке викладає або надсилає логи безпосередньо з кожного застосунку, виходить за межі цілей Kubernetes.

Що далі

5 - Версія сумісності для компонентів панелі управління Kubernetes

Починаючи з версії 1.32, ми додали до компонентів панелі управління Kubernetes параметри сумісності версій та емуляції, що налаштовуються, щоб зробити оновлення безпечнішими, надаючи більше контролю та збільшуючи деталізацію кроків, доступних адміністраторам кластерів.

Емульована версія

Параметр емуляції задається прапорцем --emulated-version компонентів панелі управління. Він дозволяє компоненту емулювати поведінку (API, функції ...) більш ранньої версії Kubernetes.

При його використанні доступні можливості будуть відповідати емульованій версії:

  • Будь-які можливості, присутні в двійковій версії, які були додані після версії емуляції, будуть недоступні.
  • Будь-які можливості, вилучені після версії емуляції, будуть доступними.

Це дозволяє двійковій версії певного випуску Kubernetes емулювати поведінку попередньої версії з достатньою точністю, щоб можна було визначити сумісність з іншими компонентами системи у термінах емульованої версії.

Значення --emulated-version має бути <= binaryVersion. Діапазон підтримуваних емульованих версій див. у довідці до прапорця --emulated-version.

6 - Метрики для компонентів системи Kubernetes

Метрики системних компонентів можуть краще показати, що відбувається всередині. Метрики особливо корисні для побудови інформаційних панелей та сповіщень.

Компоненти Kubernetes видають метрики у форматі Prometheus. Цей формат являє собою структурований звичайний текст, призначений для зручного сприйняття як людьми, так і машинами.

Метрики в Kubernetes

У більшості випадків метрики доступні на точці доступу /metrics HTTP сервера. Для компонентів, які типово не показують цю точку, її можна активувати за допомогою прапорця --bind-address.

Приклади таких компонентів:

У промисловому середовищі ви, можливо, захочете налаштувати Prometheus Server або інший інструмент збору метрик для їх періодичного отримання і доступу у якомусь виді бази даних часових рядів.

Зверніть увагу, що kubelet також викладає метрики на /metrics/cadvisor, /metrics/resource та /metrics/probes. Ці метрики не мають того самого життєвого циклу.

Якщо ваш кластер використовує RBAC, для читання метрик потрібна авторизація через користувача, групу або ServiceAccount з ClusterRole, що дозволяє доступ до /metrics. Наприклад:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus
rules:
  - nonResourceURLs:
      - "/metrics"
    verbs:
      - get

Життєвий цикл метрик

Метрики альфа → Стабільні метрики → Застарілі метрики → Приховані метрики → Видалені метрики

Альфа метрики не мають гарантій щодо їх стабільності. Ці метрики можуть бути змінені або навіть вилучені в будь-який момент.

Стабільні метрики гарантують, що їх формат залишиться незмінним. Це означає що:

  • Стабільні метрики, які не мають позначки "DEPRECATED", не будуть змінені чи вилучені.
  • Тип стабільних метрик не буде змінений.

Метрики, які позначені як застарілі, заплановані для видалення, але все ще доступні для використання. Ці метрики мають анотацію щодо версії, у якій вони стали застарілими.

Наприклад:

  • Перед застарінням

    # HELP some_counter this counts things
    # TYPE some_counter counter
    some_counter 0
    
  • Після застаріння

    # HELP some_counter (Deprecated since 1.15.0) this counts things
    # TYPE some_counter counter
    some_counter 0
    

Приховані метрики більше не публікуються для збирання, але все ще доступні для використання. Щоб використовувати приховану метрику, будь ласка, звертайтесь до розділу Показ прихованих метрик.

Видалені метрики більше не публікуються і не можуть бути використані.

Показ прихованих метрик

Як описано вище, адміністратори можуть увімкнути приховані метрики через прапорець командного рядка для конкретного бінарного файлу. Це призначено для використання адміністраторами, якщо вони пропустили міграцію метрик, які стали застарілими в останньому релізі.

Прапорець show-hidden-metrics-for-version приймає версію, для якої ви хочете показати метрики, які стали застарілими у цьому релізі. Версія зазначається як x.y, де x — головна версія, y — мінорна версія. Версія патчу не потрібна, хоча метрика може бути застарілою в патч-релізі, причина в тому, що політика застарілих метрик працює з мінорними релізами.

Прапорець може приймати тільки попередню мінорну версію як своє значення. Усі метрики, які були приховані в попередній версії, будуть доступні, якщо адміністратори встановлять попередню версію на show-hidden-metrics-for-version. Занадто стара версія не дозволяється, оскільки це порушує політику застарілих метрик.

Візьміть метрику A як приклад, тут припускається, що A застаріла в 1.n. Згідно з політикою застарілих метрик, ми можемо зробити наступні висновки:

  • У випуску 1.n, метрика застаріла і може бути типово доступною.
  • У випуску 1.n+1, метрика є типово прихованою і може бути доступна через параметр командного рядка show-hidden-metrics-for-version=1.n.
  • У випуску 1.n+2, метрику слід видалити з кодової бази. Більше немає можливості її отримання.

Якщо ви оновлюєтеся з випуску 1.12 до 1.13, але все ще залежите від метрики A, яка застаріла в 1.12, ви повинні встановити приховані метрики через командний рядок: --show-hidden-metrics=1.12 і памʼятати про те, щоб видалити цю залежність від метрики до оновлення до 1.14.

Метрики компонентів

Метрики kube-controller-manager

Метрики менеджера контролера надають важливі відомості про продуктивність та стан контролера. Ці метрики включають загальні метрики часу виконання мови програмування Go, такі як кількість go_routine, а також специфічні для контролера метрики, такі як час виконання запитів до etcd або час виконання API Cloudprovider (AWS, GCE, OpenStack), які можна використовувати для оцінки стану кластера.

Починаючи з Kubernetes 1.7, доступні докладні метрики Cloudprovider для операцій зберігання для GCE, AWS, Vsphere та OpenStack. Ці метрики можуть бути використані для моніторингу стану операцій з постійними томами.

Наприклад, для GCE ці метрики називаються:

cloudprovider_gce_api_request_duration_seconds { request = "instance_list"}
cloudprovider_gce_api_request_duration_seconds { request = "disk_insert"}
cloudprovider_gce_api_request_duration_seconds { request = "disk_delete"}
cloudprovider_gce_api_request_duration_seconds { request = "attach_disk"}
cloudprovider_gce_api_request_duration_seconds { request = "detach_disk"}
cloudprovider_gce_api_request_duration_seconds { request = "list_disk"}

Метрики kube-scheduler

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.21 [beta]

Планувальник надає опціональні метрики, які повідомляють про запитані ресурси та бажані обмеження всіх запущених Podʼів. Ці метрики можна використовувати для побудови панелей управління ресурсами, оцінки поточних або історичних обмежень планування, швидкого виявлення навантажень, які не можуть бути розміщені через відсутність ресурсів, і порівняння фактичного використання з запитом Podʼа.

kube-scheduler ідентифікує ресурсні запити та обмеження для кожного Podʼа; коли запит або обмеження не дорівнює нулю, kube-scheduler повідомляє про метричні часові ряди. Часові ряди мають мітки:

  • простір імен
  • імʼя Podʼа
  • вузол, на якому запущений Pod, або пустий рядок, якщо він ще не запущений
  • пріоритет
  • призначений планувальник для цього Podʼа
  • назва ресурсу (наприклад, cpu)
  • одиниця ресурсу, якщо відома (наприклад, core)

Як тільки Pod досягає завершення (має restartPolicy Never або OnFailure і перебуває в стані Succeeded або Failed, або був видалений і всі контейнери мають стан завершення), часова послідовність більше не повідомляється, оскільки тепер планувальник вільний для розміщення інших Podʼів для запуску. Дві метрики називаються kube_pod_resource_request та kube_pod_resource_limit.

Метрики доступні за адресою HTTP /metrics/resources та вимагають такої ж авторизації, що і точка доступу /metrics планувальника. Вам потрібно використовувати прапорець --show-hidden-metrics-for-version=1.20, щоб показати ці альфа-метрики.

Вимкнення метрик

Ви можете явно вимкнути метрики за допомогою прапорця командного рядка --disabled-metrics. Це може бути бажано, наприклад, якщо метрика викликає проблеми з продуктивністю. Вхідні дані — це список вимкнених метрик (тобто --disabled-metrics=метрика1,метрика2).

Забезпечення послідовності метрик

Метрики з нескінченними розмірами можуть викликати проблеми з памʼяттю в компонентах, які їх інструментують. Щоб обмежити використання ресурсів, ви можете використовувати опцію командного рядка --allow-metric-labels, щоб динамічно налаштувати список дозволених значень міток для метрики.

На стадії альфа, цей прапорець може приймати лише серію зіставлень як список дозволених міток метрики. Кожне зіставлення має формат <metric_name>,<label_name>=<allowed_labels>, де <allowed_labels> — це розділені комами допустимі назви міток.

Загальний формат виглядає так:

--allow-metric-labels <metric_name>,<label_name>='<allow_value1>, <allow_value2>...', <metric_name2>,<label_name>='<allow_value1>, <allow_value2>...', ...

Ось приклад:

--allow-metric-labels number_count_metric,odd_number='1,3,5', number_count_metric,even_number='2,4,6', date_gauge_metric,weekend='Saturday,Sunday'

Крім того, що це можна вказати з командного рядка, теж саме можна зробити за допомогою конфігураційного файлу. Ви можете вказати шлях до цього файлу конфігурації, використовуючи аргумент командного рядка --allow-metric-labels-manifest для компонента. Ось приклад вмісту цього конфігураційного файлу:

"metric1,label2": "v1,v2,v3"
"metric2,label1": "v1,v2,v3"

Додатково, метрика cardinality_enforcement_unexpected_categorizations_total записує кількість неочікуваних категоризацій під час вказання послідовності, тобто кожного разу, коли значення мітки зустрічається, що не дозволяється з урахуванням обмежень списку дозволених значень.

Що далі

7 - Метрики для станів обʼєктів Kubernetes

kube-state-metrics — це агент-надбудова для генерації та надання метрик на рівні кластера.

Стан обʼєктів Kubernetes у Kubernetes API може бути поданий у вигляді метрик. Агент-надбудова kube-state-metrics може підключатися до сервера Kubernetes API та надавати доступ до точки доступу з метриками, що генеруються зі стану окремих обʼєктів у кластері. Він надає різні дані про стан обʼєктів, такі як мітки та анотації, час запуску та завершення, статус або фазу, в яких обʼєкт знаходиться зараз. Наприклад, контейнери, що працюють у Podʼах, створюють метрику kube_pod_container_info. Вона включає імʼя контейнера, імʼя Podʼа, до якого він належить, простір імен, в якому працює Pod, імʼя образу контейнера, ідентифікатор образу, імʼя образу з опису контейнера, ідентифікатор працюючого контейнера та ідентифікатор Podʼа як мітки.

Зовнішній компонент, який може зчитувати точку доступу kube-state-metrics (наприклад, за допомогою Prometheus), можна використовувати для активації наступних варіантів використання.

Приклад: використання метрик з kube-state-metrics для запиту стану кластера

Серії метрик, що генеруються kube-state-metrics, допомагають отримати додаткові уявлення про кластер, оскільки їх можна використовувати для запитів.

Якщо ви використовуєте Prometheus або інструмент, який використовує ту саму мову запитів, наступний запит PromQL поверне кількість Podʼів, які не готові:

count(kube_pod_status_ready{condition="false"}) by (namespace, pod)

Приклад: сповіщення на основі kube-state-metrics

Метрики, що генеруються з kube-state-metrics, також дозволяють сповіщати про проблеми в кластері.

Якщо ви використовуєте Prometheus або схожий інструмент, який використовує ту саму мову правил сповіщень, наступне сповіщення буде активовано, якщо є Podʼи, які перебувають у стані Terminating протягом понад 5 хвилин:

groups:
- name: Pod state
  rules:
  - alert: PodsBlockedInTerminatingState
    expr: count(kube_pod_deletion_timestamp) by (namespace, pod) * count(kube_pod_status_reason{reason="NodeLost"} == 0) by (namespace, pod) > 0
    for: 5m
    labels:
      severity: page
    annotations:
      summary: Pod {{$labels.namespace}}/{{$labels.pod}} blocked in Terminating state.

8 - Системні логи

Логи компонентів системи фіксують події, які відбуваються в кластері, що може бути дуже корисним для налагодження. Ви можете налаштувати рівень деталізації логів, щоб бачити більше або менше деталей. Логи можуть бути настільки грубими, що вони показують лише помилки у компоненті, або настільки дрібними, що вони показують крок за кроком слідування за подіями (наприклад, логи доступу HTTP, зміни стану події, дії контролера або рішення планувальника).

Klog

klog — це бібліотека реєстрації подій для системних компонентів Kubernetes. klog генерує повідомлення логу для системних компонентів Kubernetes.

Kubernetes знаходиться в процесі спрощення реєстрації подій у своїх компонентах. Наступні прапорці командного рядка klog є застарілими починаючи з Kubernetes v1.23 і будуть видалені у Kubernetes v1.26:

  • --add-dir-header
  • --alsologtostderr
  • --log-backtrace-at
  • --log-dir
  • --log-file
  • --log-file-max-size
  • --logtostderr
  • --one-output
  • --skip-headers
  • --skip-log-headers
  • --stderrthreshold

Вивід буде завжди записуватися у stderr, незалежно від формату виводу. Очікується, що перенаправлення виводу буде оброблено компонентом, який викликає компонент Kubernetes. Це може бути оболонка POSIX або інструмент, такий як systemd.

У деяких випадках, наприклад, у контейнері distroless або службі Windows, ці параметри недоступні. У цьому випадку можна використовувати бінарний файл kube-log-runner як обгортку навколо компонента Kubernetes для перенаправлення виводу. Вже скомпільований бінарний файл включено в декілька базових образів Kubernetes під його традиційною назвою /go-runner та як kube-log-runner в архівах випусків сервера та вузла.

Ця таблиця показує відповідність викликів kube-log-runner перенаправленню оболонки:

ВикористанняPOSIX оболонка (напр. bash)kube-log-runner <options> <cmd>
Обʼєднати stderr і stdout, записати у stdout2>&1kube-log-runner (типова поведінка)
Перенаправити обидва в лог1>>/tmp/log 2>&1kube-log-runner -log-file=/tmp/log
Скопіювати в лог і до stdout2>&1 | tee -a /tmp/logkube-log-runner -log-file=/tmp/log -also-stdout
Перенаправити лише stdout в лог>/tmp/logkube-log-runner -log-file=/tmp/log -redirect-stderr=false

Вивід klog

Приклад традиційного формату виводу klog:

I1025 00:15:15.525108       1 httplog.go:79] GET /api/v1/namespaces/kube-system/pods/metrics-server-v0.3.1-57c75779f-9p8wg: (1.512ms) 200 [pod_nanny/v0.0.0 (linux/amd64) kubernetes/$Format 10.56.1.19:51756]

Рядок повідомлення може містити перенесення рядків:

I1025 00:15:15.525108       1 example.go:79] This is a message
which has a line break.

Структуроване ведення логів

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.23 [beta]

Структуроване ведення логів вводить єдину структуру в повідомлення логів, що дозволяє програмно отримувати інформацію. Ви можете зберігати та обробляти структуровані логи з меншими зусиллями та витратами. Код, який генерує повідомлення логів, визначає, чи використовує він традиційний неструктурований вивід klog, чи структуроване ведення логів.

Формат структурованих повідомлень логів є типово текстовим, у форматі, який зберігає сумісність з традиційним klog:

<klog заголовок> "<повідомлення>" <ключ1>="<значення1>" <ключ2>="<значення2>" ...

Приклад:

I1025 00:15:15.525108       1 controller_utils.go:116] "Pod status updated" pod="kube-system/kubedns" status="ready"

Рядки беруться в лапки. Інші значення форматуються за допомогою %+v, що може призводити до того, що повідомлення логів продовжуватимуться на наступному рядку залежно від даних.

I1025 00:15:15.525108       1 example.go:116] "Example" data="This is text with a line break\nand \"quotation marks\"." someInt=1 someFloat=0.1 someStruct={StringField: First line,
second line.}

Контекстне ведення логів

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.30 [beta]

Контекстне ведення логів базується на структурованому веденні логів. Це переважно стосується того, як розробники використовують системні виклики ведення логів: код, побудований на цьому концепті, є більш гнучким і підтримує додаткові варіанти використання, як описано в KEP щодо контекстного ведення логів.

Якщо розробники використовують додаткові функції, такі як WithValues або WithName, у своїх компонентах, то записи в журнал міститимуть додаткову інформацію, яка передається у функції своїм абонентам.

Для Kubernetes Kubernetes 1.32, це керується через функціональну можливість ContextualLogging, що є типово увімкненою. Інфраструктура для цього була додана в 1.24 без модифікації компонентів. Команда component-base/logs/example показує, як використовувати нові виклики ведення логів та як компонент поводиться, якщо він підтримує контекстне ведення логів.

$ cd $GOPATH/src/k8s.io/kubernetes/staging/src/k8s.io/component-base/logs/example/cmd/
$ go run . --help
...
      --feature-gates mapStringBool  Набір пар ключ=значення, які описують feature gate для експериментальних функцій. Опції:
                                     AllAlpha=true|false (ALPHA - стандартно=false)
                                     AllBeta=true|false (BETA - стандартно=false)
                                     ContextualLogging=true|false (BETA - default=true)
$ go run . --feature-gates ContextualLogging=true
...
I0222 15:13:31.645988  197901 example.go:54] "runtime" logger="example.myname" foo="bar" duration="1m0s"
I0222 15:13:31.646007  197901 example.go:55] "another runtime" logger="example" foo="bar" duration="1h0m0s" duration="1m0s"

Ключ logger та foo="bar" були додані абонентом функції, яка записує повідомлення runtime та значення duration="1m0s", без необхідності модифікувати цю функцію.

Коли контекстне ведення логів вимкнене, функції WithValues та WithName нічого не роблять, а виклики ведення логів пройшли через глобальний реєстратор klog. Отже, ця додаткова інформація більше не виводиться в журнал:

$ go run . --feature-gates ContextualLogging=false
...
I0222 15:14:40.497333  198174 example.go:54] "runtime" duration="1m0s"
I0222 15:14:40.497346  198174 example.go:55] "another runtime" duration="1h0m0s" duration="1m0s"

Формат логу у форматі JSON

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.19 [alpha]

Прапорець --logging-format=json змінює формат логу з власного формату klog на формат JSON. Приклад формату логу у форматі JSON (форматований для зручності):

{
   "ts": 1580306777.04728,
   "v": 4,
   "msg": "Pod status updated",
   "pod":{
      "name": "nginx-1",
      "namespace": "default"
   },
   "status": "ready"
}

Ключі з особливим значенням:

  • ts — відмітка часу у форматі Unix (обовʼязково, дійсне число)
  • v — деталізація (тільки для інформаційних повідомлень, а не для повідомлень про помилки, ціле число)
  • err — рядок помилки (необовʼязково, рядок)
  • msg — повідомлення (обовʼязково, рядок)

Список компонентів, що наразі підтримують формат JSON:

Рівень деталізації логів

Прапорець -v керує рівнем деталізації логу. Збільшення значення збільшує кількість зареєстрованих подій. Зменшення значення зменшує кількість зареєстрованих подій. Збільшення рівнів деталізації записує все менш важливі події. На рівні деталізації 0 журнал реєструє лише критичні події.

Розташування логів

Існують два типи системних компонентів: ті, які працюють у контейнері, та ті, які не працюють у контейнері. Наприклад:

На машинах з systemd, kubelet та середовище виконання контейнерів записують логи в journald. В іншому випадку вони записуються в файли .log в теці /var/log. Системні компоненти всередині контейнерів завжди записуються в файли .log у теці /var/log, обходячи типовий механізм ведення логу. Аналогічно логам контейнерів, вам слід регулярно виконувати ротацію логів системних компонентів у теці /var/log. У кластерах Kubernetes, створених сценарієм kube-up.sh, ротація логів налаштована за допомогою інструменту logrotate. Інструмент logrotate виконує ротацію логів щоденно або якщо розмір логу перевищує 100 МБ.

Отримання логів

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.30 [beta] (стандартно увімкнено: false)

Для допомоги у розвʼязанні проблем на вузлах Kubernetes версії v1.27 введено функцію, яка дозволяє переглядати логи служб, що працюють на вузлі. Щоб скористатися цією функцією, переконайтеся, що для цього вузла увімкнути функціональну можливість NodeLogQuery, а також що параметри конфігурації kubelet enableSystemLogHandler та enableSystemLogQuery обидва встановлені в значення true. На Linux ми припускаємо, що логи служб доступні через journald. На Windows ми припускаємо, що логи служб доступні в постачальнику логів застосунків. В обох операційних системах логи також доступні за допомогою читання файлів у теці /var/log/.

Якщо у вас є дозвіл на взаємодію з обʼєктами Node, ви можете спробувати цю функцію на всіх ваших вузлах або лише на їх підмножині. Ось приклад отримання логу служби kubelet з вузла:

# Отримати логи kubelet з вузла під назвою node-1.example
kubectl get --raw "/api/v1/nodes/node-1.example/proxy/logs/?query=kubelet"

Ви також можете отримувати файли, за умови, що файли знаходяться в теці, для якої kubelet дозволяє читання логів. Наприклад, ви можете отримати лог з /var/log/ на вузлі Linux:

kubectl get --raw "/api/v1/nodes/<назва-вузла>/proxy/logs/?query=/<назва-файлу-логу>"

Kubelet використовує евристику для отримання логів. Це допомагає, якщо ви не знаєте, чи даний системний сервіс записує логи до стандартного реєстратора операційної системи, такого як journald, чи до файлу логу у /var/log/. Спочатку евристика перевіряє стандартний реєстратор, а якщо його немає, вона намагається отримати перші логи з /var/log/<імʼя-служби> або /var/log/<назва-служби>.log або /var/log/<назва-служби>/<назва-служби>.log.

Повний перелік параметрів, які можна використовувати:

ОпціяОпис
bootпоказує повідомлення про завантаження з певного завантаження системи
patternфільтрує записи логу за заданим регулярним виразом, сумісним з Perl
queryвказує службу(и) або файли, з яких слід повернути логи (обовʼязково)
sinceTimeчас відображення логу, починаючи з RFC3339 (включно)
untilTimeчас до якого показувати логи, за RFC3339 (включно)
tailLinesвказує, скільки рядків з кінця логу отримати; типово отримується весь журнал

Приклад складнішого запиту:

# Отримати логи kubelet з вузла під назвою node-1.example, у яких є слово "error"
kubectl get --raw "/api/v1/nodes/node-1.example/proxy/logs/?query=kubelet&pattern=error"

Що далі

9 - Трейси для системних компонентів Kubernetes

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.27 [beta]

Трейси системних компонентів реєструють затримку та звʼязки між операціями у кластері.

Компоненти Kubernetes відправляють трейси за допомогою Протоколу OpenTelemetry з експортером gRPC і можуть бути зібрані та направлені до різних систем відслідковування за допомогою OpenTelemetry Collector.

Збір трейсів

Компоненти Kubernetes мають вбудовані експортери gRPC для OTLP для експорту трейсів, або через OpenTelemetry Collector, або без нього.

Для повного посібника зі збору трейсів та використання колектора див. Початок роботи з OpenTelemetry Collector. Однак є кілька речей, на які варто звернути увагу, що є специфічними для компонентів Kubernetes.

Типово компоненти Kubernetes експортують трейси за допомогою експортера grpc для OTLP на порт IANA OpenTelemetry, 4317. Наприклад, якщо колектор працює як sidecar контейнер для компонента Kubernetes, наступна конфігурація приймача збере спани (spans) та відправить їх у стандартний вивід:

receivers:
  otlp:
    protocols:
      grpc:
exporters:
  # Замініть цей експортер на експортер для вашої системи
  logging:
    logLevel: debug
service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [logging]

Для безпосереднього надсилання трейсів до бекенду без використання колектора, вкажіть поле endpoint у конфігурації Kubernetes з адресою бекенду. Цей метод усуває потребу в колекторі та спрощує загальну структуру.

Для конфігурації заголовків backend trace, включаючи дані автентифікації, можна використовувати змінні середовища з OTEL_EXPORTER_OTLP_HEADERS, див. Конфігурація Експортера OTLP.

Додатково, для конфігурації атрибутів ресурсів trace, таких як назва кластера Kubernetes, простір імен, імʼя Pod і т. д., також можна використовувати змінні середовища з OTEL_RESOURCE_ATTRIBUTES, див. Ресурс Kubernetes OTLP.

Трейси компонентів

Трейси kube-apiserver

Kube-apiserver генерує спани для вхідних HTTP-запитів та для вихідних запитів до веб-хуків, etcd та повторних запитів. Він передає W3C Trace Context з вихідними запитами, але не використовує контекст трейса, доданий до вхідних запитів, оскільки kube-apiserver часто є загальнодоступною точкою доступу.

Увімкнення трейсів в kube-apiserver

Щоб увімкнути трейси, надайте kube-apiserver файл конфігурації тресів з --tracing-config-file=<шлях-до-конфігу>. Це приклад конфігурації, яка записує спани для 1 з 10000 запитів та використовує типову точку доступу OpenTelemetry:

apiVersion: apiserver.config.k8s.io/v1beta1
kind: TracingConfiguration
# типове значення
#endpoint: localhost:4317
samplingRatePerMillion: 100

Для отримання додаткової інформації про структуру TracingConfiguration, див. API сервера конфігурації (v1beta1).

Трейси kubelet

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.27 [beta] (стандартно увімкнено: true)

Інтерфейс CRI kubelet та автентифіковані http-сервери інструментовані для генерації спанів трейсів. Як і apiserver, адресу та частоту зразків можна налаштувати. Контекст трейсів також налаштований. Рішення про зразок батьківського спану завжди береться до уваги. Частота зразків трейсів, надана в конфігурації, застосовуватиметься до спанів без батьків. Ввімкнено без налаштованої точки доступу, типова адреса приймача OpenTelemetry Collector — "localhost:4317".

Увімкнення трейсів в kubelet

Щоб увімкнути трейси, застосуйте конфігурацію. Це приклад шматка конфігурації kubelet, що записує спани для 1 з 10000 запитів та використовує типову точку доступу OpenTelemetry:

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
featureGates:
  KubeletTracing: true
tracing:
  # типове значення
  #endpoint: localhost:4317
  samplingRatePerMillion: 100

Якщо samplingRatePerMillion встановлено на мільйон (1000000), то кожен спан буде відправлений до експортера.

Kubelet у Kubernetes v1.32 збирає спани зі збирання сміття, процесів синхронізації Podʼів, а також кожного методу gRPC. Kubelet передає контекст трейсів із запитами gRPC, щоб контейнерні середовища з інструментованими трейсами, такі як CRI-O та containerd, могли асоціювати їх експортовані спани з контекстом трейсів від kubelet. Отримані трейси будуть мати посилання батько-дитина між спанами kubelet та контейнерним середовищем, надаючи корисний контекст при налагодженні вузла.

Зверніть увагу, що експортування спанів завжди супроводжується невеликим перевантаженням мережі та CPU, залежно від загальної конфігурації системи. Якщо в кластері, в якому увімкнено трейси, виникає будь-яка проблема, така як ця, то помʼякшіть проблему шляхом зменшення samplingRatePerMillion або повністю вимкніть трейси, видаливши конфігурацію.

Стабільність

Інструментування трейсів все ще перебуває в активній розробці та може змінюватися різними способами. Це стосується назв спанів, приєднаних атрибутів, інструментованих точок доступу та інших. До того часу, поки ця функція не стане стабільною, не надається жодних гарантій зворотної сумісності для інструментів трейсів.

Що далі

10 - Проксі у Kubernetes

На цій сторінці пояснюються проксі, що використовуються з Kubernetes.

Проксі

У вас можуть зустрітися декілька різних проксі, коли ви використовуєте Kubernetes:

  1. Проксі kubectl:

    • працює на робочому столі користувача або в контейнері
    • забезпечує проксі з локальної адреси до apiserver Kubernetes
    • клієнт до проксі використовує HTTP
    • проксі до apiserver використовує HTTPS
    • знаходить apiserver
    • додає заголовки автентифікації
  2. Проксі apiserver:

    • є бастіоном, вбудованим в apiserver
    • зʼєднує користувача поза кластером з IP-адресами кластера, які інакше можуть бути недоступними
    • працює в процесах apiserver
    • клієнт до проксі використовує HTTPS (або http, якщо apiserver налаштовано так)
    • проксі до цілі може використовувати HTTP або HTTPS, як вибрав проксі за наявною інформацією
    • може бути використаний для доступу до Node, Pod або Service
    • виконує балансування навантаження при використанні для доступу до Service
  3. kube proxy:

    • працює на кожному вузлі
    • забезпечує проксі UDP, TCP та SCTP
    • не розуміє HTTP
    • надає балансування навантаження
    • використовується лише для доступу до Service
  4. Проксі/балансувальник перед apiserver(s):

    • існування та реалізація різниться від кластера до кластера (наприклад, nginx)
    • розташований між всіма клієнтами та одним або кількома apiservers
    • діє як балансувальник навантаження, якщо є кілька apiservers.
  5. Хмарні балансувальники навантаження на зовнішньому Service:

    • надаються деякими хмарними провайдерами (наприклад, AWS ELB, Google Cloud Load Balancer)
    • створюються автоматично, коли у Service Kubernetes тип — LoadBalancer
    • зазвичай підтримують лише UDP/TCP
    • підтримка SCTP залежить від реалізації балансувальника навантаження хмарного провайдера
    • реалізація відрізняється від провайдера хмарних послуг.

Зазвичай користувачі Kubernetes не повинні турбуватися про щось, крім перших двох типів. Зазвичай адміністратор кластера забезпечує правильне налаштування останніх типів.

Запит на перенаправлення

Проксі замінили можливості перенаправлення. Перенаправлення були визнані застарілими.

11 - API Priority та Fairness

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.29 [stable]

Контроль поведінки сервера API Kubernetes у ситуації перевантаження є основним завданням для адміністраторів кластера. У kube-apiserver є деякі елементи керування (тобто прапорці командного рядка --max-requests-inflight та --max-mutating-requests-inflight), щоб обмежити обсяг невиконаної роботи, яка буде прийнята, запобігаючи перевантаженню потоку вхідних запитів та потенційному збою сервера API, але цих прапорців недостатньо для забезпечення проходження найважливіших запитів у період високого навантаження.

Елементи API Priority та Fairness (APF) є альтернативою, яка покращує зазначені обмеження щодо максимального числа невиконаних завдань. APF класифікує та ізолює запити більш деталізованим способом. Вони також вводять обмеження на черги, щоб ніякі запити не були відхилені в разі дуже коротких вибухів. Запити надсилаються з черг за допомогою техніки справедливих черг, так що, наприклад, контролер, який погано поводиться не має вичерпати інші ресурси (навіть на тому ж рівні пріоритету).

Ця функція розроблена для співпраці зі стандартними контролерами, які використовують інформатори та реагують на невдачі запитів API з експоненційним збільшенням часу очікування, та іншими клієнтами, які також працюють таким чином.

Увімкнення/вимкнення API Priority та Fairness

API Priority та Fairness контролюється прапорцем командного рядка та є типово увімкненим. Див. Опції для загального пояснення доступних опцій командного рядка kube-apiserver та того, як їх увімкнути та вимкнути. Назва параметра командного рядка для APF — "--enable-priority-and-fairness". Ця функція також включає API Group, яка має: (a) стабільну версію v1, введена у версії 1.29, і типово увімкнена, (b) версію v1beta3, типово увімкнена та застаріла у версії v1.29. Ви можете вимкнути бета-версію групи API v1beta3, додавши наступні параметри командного рядка до запуску kube-apiserver:

kube-apiserver \
--runtime-config=flowcontrol.apiserver.k8s.io/v1beta3=false \
 # …і інші прапорці, як завжди

Параметр командного рядка --enable-priority-and-fairness=false вимкне API Priority та Fairness.

Рекурсивні сценарії сервера

API Priority and Fairness повинні використовуватися обережно в рекурсивних сценаріях сервера. Це сценарії, в яких сервер A, обробляючи запит, надсилає допоміжний запит на сервер B. Можливо, сервер B може навіть зробити подальший допоміжний виклик назад до сервера A. У ситуаціях, коли контроль Пріоритету і Справедливості застосовується як до оригінального запиту, так і до деяких допоміжних, незалежно від глибини рекурсії, існує небезпека пріоритетних інверсій та/або взаємоблокувань.

Прикладом рекурсії є випадок, коли kube-apiserver робить виклик admission webhook на сервер B, і під час обробки цього виклику сервер B робить подальший допоміжний запит назад до kube-apiserver. Інший приклад рекурсії — коли обʼєкт APIService спрямовує kube-apiserver делегувати запити щодо певної групи API на власний зовнішній сервер B користувача (це один з аспектів, які називаються "агрегацією").

Коли відомо, що оригінальний запит належить до певного рівня пріоритету, і допоміжні контрольовані запити класифікуються на вищі рівні пріоритету, це може бути одним з можливих рішень. Коли оригінальні запити можуть належати до будь-якого рівня пріоритету, допоміжні контрольовані запити повинні бути звільнені від обмежень Priority and Fairness. Один із способів це зробити — за допомогою обʼєктів, які налаштовують класифікацію та обробку, обговорених нижче. Інший спосіб — повністю відключити Priority and Fairness на сервері B, використовуючи техніки, обговорені вище. Третій спосіб, який найпростіше використовувати, коли сервер B не є kube-apiserver, це побудувати сервер B з відключеним у коді Priority and Fairness.

Концепції

API Priority та Fairness включає кілька різних функцій. Вхідні запити класифікуються за атрибутами запиту за допомогою FlowSchemas, і призначаються пріоритетним рівням. Пріоритетні рівні додають ступінь ізоляції, підтримуючи окремі обмеження паралелізму, так що запити, які призначені для різних пріоритетних рівнів, не можуть позбавляти ресурсів один одного. У межах пріоритетного рівня алгоритм справедливого чергування не дозволяє запитам з різних потоків позбавляти ресурсів один одного, і дозволяє чергувати запити, щоб запобігти відмовам від запитів у випадках, коли середнє навантаження прийнятно низьке.

Рівні пріоритету

Без увімкненої функції APF загальний паралелізм в API-сервері обмежується прапорцями --max-requests-inflight та --max-mutating-requests-inflight у kube-apiserver. З увімкненою функцією APF ліміти паралелізму, визначені цими прапорцями, сумуються, а потім сума розподіляється серед налаштованого набору рівнів пріоритету. Кожен вхідний запит призначається одному з рівнів пріоритету, і кожен рівень пріоритету буде обробляти лише стільки одночасних запитів, скільки дозволяє його конкретний ліміт.

Наприклад, у типовій конфігурації існують окремі рівні пріоритету для запитів на вибір лідера, запитів від вбудованих контролерів і запитів від Podʼів. Це означає, що Podʼи, які поводяться погано і завалюють API-сервер запитами, не можуть перешкодити вибору лідера або виконанню дій вбудованими контролерами.

Межі паралелізму рівнів пріоритету періодично коригуються, що дозволяє недостатньо використовуваним рівням пріоритету тимчасово надавати паралелізм сильно використовуваних рівнів. Ці обмеження базуються на номінальних обмеженнях та межах того, скільки паралелізму може позичити рівень пріоритету та скільки він може позичити, всі отримані з обʼєктів конфігурації, згаданих нижче.

Місця, зайняті за запитом

Наведений вище опис управління паралелізмом є базовою поведінкою. Запити мають різну тривалість, але враховуються однаково в будь-який момент при порівнянні з лімітом паралелізму на рівні пріоритету. У базовій поведінці кожен запит займає одну одиницю паралелізму. Слово "місце" (seat) використовується для позначення однієї одиниці паралелізму, під впливом від того, як кожен пасажир у поїзді або літаку займає одне з фіксованих місць.

Але деякі запити займають більше, ніж одне місце. Деякі з них — це запити list, які сервер оцінює, що повертають велику кількість обʼєктів. Вони виявилися надзвичайно важкою ношею для сервера. З цієї причини сервер оцінює кількість обʼєктів, які будуть повернуті, і вважає, що запит займає кількість місць, пропорційну цій оцінці.

Коригування часу виконання для запитів watch

API Priority та Fairness керує запитами watch, але це передбачає ще кілька відступів від базової поведінки. Перше стосується того, як довго запит watch вважається таким, що займає своє місце. Залежно від параметрів запиту, відповідь на запит на watch може або не може розпочинатися зі сповіщень create для всіх відповідних попередніх обʼєктів. API Priority та Fairness вважає, що запит watch завершено зі своїм місцем, як тільки цей початковий вибух сповіщень, якщо такі є, закінчився.

Нормальні сповіщення надсилаються у паралельному сплеску на всі потрібні потоки відповіді на watch, коли сервер отримує сповіщення про створення/оновлення/видалення обʼєкта. Для врахування цієї роботи API Priority та Fairness вважає, що кожен записний запит витрачає додатковий час, займаючи місця після завершення фактичного запису. Сервер оцінює кількість сповіщень, які будуть надіслані, і коригує кількість місць та час зайнятості місця для записного запиту, щоб врахувати цю додаткову роботу.

Черги

Навіть на рівні пріоритету може бути велика кількість різних джерел трафіку. У ситуації перевантаження важливо запобігти тому, щоб один потік вичерпував ресурси інших (зокрема, у відносно поширеному випадку, коли один помилковий клієнт переповнює kube-apiserver запитами, цей помилковий клієнт в ідеалі взагалі не мав би помітного впливу на інших клієнтів). Це обробляється за допомогою алгоритму справедливої черги для обробки запитів, яким присвоєно однаковий рівень пріоритету. Кожен запит присвоюється потоку, ідентифікованому за назвою відповідної FlowSchema плюс розрізнювач потоку - який є або запитуючим користувачем, або простором імен цільового ресурсу, або нічим - і система намагається надати приблизно однакову вагу запитам у різних потоках одного і того ж рівня пріоритету. Щоб забезпечити чітку обробку різних екземплярів, контролери, які мають багато екземплярів, повинні автентифікуватися за допомогою різних імен користувачів

Це забезпечується за допомогою алгоритму справедливих черг обробки запитів, які призначені для того ж рівня пріоритету. Кожен запит призначається для потоку, ідентифікованого імʼям відповідного FlowSchema плюс розрізнювач потоку — яким є або користувач-абонент, або простір імен цільового ресурсу, або нічого — і система намагається надати приблизно рівну вагу запитам в різних потоках того ж рівня пріоритету.

Після класифікації запиту у потік, API Priority та Fairness може призначити запит до черги. Це призначення використовує техніку, відому як shuffle sharding, яка досить ефективно використовує черги для ізоляції потоків низької інтенсивності від потоків високої інтенсивності.

Деталі алгоритму черг налаштовуються для кожного рівня пріоритету і дозволяють адміністраторам збалансувати використання памʼяті, справедливість (властивість того, що незалежні потоки всі рухатимуться вперед, коли загальний трафік перевищує потужність), толерантність до бурхливого трафіку та доданий час очікування, що виникає через черги.

Ексклюзивні запити

Деякі запити вважаються достатньо важливими, щоб не підлягати жодним обмеженням, які накладає ця функція. Ці винятки запобігають тому, щоб неправильно налаштована конфігурація керування потоком повністю вимкнула API-сервер.

Ресурси

API керування потоком включає два види ресурсів. Конфігурації рівня пріоритету визначають доступні рівні пріоритету, частку доступного бюджету паралелізму, яку кожен може обробити, та дозволяють налаштовувати поведінку черги. FlowSchemas використовуються для класифікації окремих вхідних запитів, відповідність кожного з PriorityLevelConfiguration.

PriorityLevelConfiguration

PriorityLevelConfiguration представляє один рівень пріоритету. Кожен PriorityLevelConfiguration має незалежні обмеження на кількість невиконаних запитів та обмеження на кількість запитів у черзі.

Номінальне обмеження паралелізму для PriorityLevelConfiguration не визначається в абсолютній кількості місць, а в "номінальних частках паралелізму". Загальне обмеження паралелізму для API-сервера розподіляється серед наявних конфігурацій рівня пріоритету пропорційно цим часткам, щоб кожен рівень отримав своє номінальне обмеження у вигляді місць. Це дозволяє адміністратору кластера збільшувати або зменшувати загальний обсяг трафіку до сервера, перезапускаючи kube-apiserver з іншим значенням для --max-requests-inflight (або --max-mutating-requests-inflight), і всі PriorityLevelConfiguration побачать, що їх максимально допустимий паралелізм збільшиться (або зменшиться) на ту саму частку.

Межі того, скільки паралелізму може надати рівень пріоритету та скільки він може позичити, виражені в PriorityLevelConfiguration у відсотках від номінального обмеження рівня. Ці значення перетворюються на абсолютні числа місць, множачи їх на номінальне обмеження / 100.0 та округлюючи. Динамічно кориговане обмеження паралелізму рівня пріоритету обмежене нижньою межею його номінального обмеження мінус кількість місць, які він може позичити, та верхньою межею його номінального обмеження плюс місця, які він може позичити. Під час кожного налаштування динамічні межі визначаються кожним рівнем пріоритету, відновлюючи будь-які позичені місця, на які востаннє зʼявлявся попит, та спільно відповідаючи на попит за місцями на рівнях пріоритету в межах вищезазначених меж.

Коли обсяг вхідних запитів, які призначені для одного PriorityLevelConfiguration, перевищує його дозволений рівень паралелізму, поле type його специфікації визначає, що відбудеться з додатковими запитами. Тип Reject означає, що зайвий трафік буде негайно відхилено з помилкою HTTP 429 (Too Many Requests). Тип Queue означає, що запити, які перевищують поріг, будуть ставитися у чергу, із використанням технік випадкового розміщення та справедливої черги для збалансування прогресу між потоками запитів.

Конфігурація черги дозволяє налаштувати алгоритм справедливої черги для рівня пріоритету. Деталі алгоритму можна знайти у пропозиції про вдосконалення, ось скорочено:

  • Збільшення queues зменшує швидкість зіткнень між різними потоками, коштом збільшення використання памʼяті. Значення 1 тут фактично вимикає логіку справедливої черги, але все ще дозволяє ставити запити в чергу.

  • Збільшення queueLengthLimit дозволяє підтримувати більші потоки трафіку без відкидання будь-яких запитів, коштом збільшення затримки та використання памʼяті.

  • Зміна handSize дозволяє вам налаштувати ймовірність зіткнень між різними потоками та загальний паралелізм, доступний для одного потоку в ситуації перевантаження.

Нижче наведена таблиця з цікавою колекцією конфігурацій випадкового розміщення, що показує для кожної ймовірність те, що певна миша (потік низької інтенсивності) буде розчавлена слонами (потоками високої інтенсивності) для ілюстративної колекції числа слонів. Див. https://play.golang.org/p/Gi0PLgVHiUg, який обчислює цю таблицю.

Приклади конфігурацій випадкового розміщення
HandSizeЧерги1 слон4 слони16 слонів
12324.428838398950118e-090.114313488300991440.9935089607656024
10321.550093439632541e-080.06264798402235450.9753101519027554
10646.601827268370426e-120.000455713209903707760.49999929150089345
9643.6310049976037345e-110.000455012123041122730.4282314876454858
8642.25929199850899e-100.00048866970530404460.35935114681123076
81286.994461389026097e-133.4055790161620863e-060.02746173137155063
71281.0579122850901972e-116.960839379258192e-060.02406157386340147
72567.597695465552631e-146.728547142019406e-080.0006709661542533682
62562.7134626662687968e-122.9516464018476436e-070.0008895654642000348
65124.116062922897309e-144.982983350480894e-092.26025764343413e-05
610246.337324016514285e-168.09060164312957e-114.517408062903668e-07

FlowSchema

FlowSchema — це визначення, яке відповідає деяким вхідним запитам і призначає їх певному рівню пріоритету. Кожний вхідний запит перевіряється на відповідність FlowSchemas, починаючи з тих, що мають найменше числове значення matchingPrecedence, і працюючи вгору. Перший збіг перемагає.

FlowSchema відповідає даному запиту, якщо принаймні одне з rules має збіг. Правило має збіг, якщо принаймні один з його subjects та принаймні один з його resourceRules або nonResourceRules (залежно від того, чи є вхідний запит для ресурсу, чи нересурсного URL) відповідає запиту.

Для поля name в підсумках та полів verbs, apiGroups, resources, namespaces та nonResourceURLs правил ресурсів та нересурсних правил можна вказати маску *, щоб відповідати всім значенням для вказаного поля, яке фактично видаляє його з використання.

Тип distinguisherMethod.type FlowSchema визначає, як запити, які відповідають цій схемі, будуть розділені на потоки. Це може бути ByUser, коли один користувач має можливість позбавити інших користувачів можливості використовувати ресурси; ByNamespace, коли запити до ресурсів в одному просторі імен не можуть позбавити запити до ресурсів в інших просторах імен можливості використовувати їх; або порожнє значення (або distinguisherMethod може бути пропущений повністю), коли всі запити, які відповідають цій FlowSchema, будуть вважатися частиною одного потоку. Правильний вибір для даної FlowSchema залежить від ресурсу та вашого конкретного середовища.

Стандартні

Кожен kube-apiserver підтримує два різновиди обʼєктів API Priority та Fairnes: обовʼязкові та рекомендовані.

Обовʼязкові обʼєкти конфігурації

Чотири обовʼязкові обʼєкти конфігурації відображають фіксовану вбудовану поведінку обмежень безпеки. Це поведінка, яку сервери мають до того, як ці обʼєкти почнуть існувати, і коли ці обʼєкти існують, їх специфікації відображають цю поведінку. Чотири обовʼязкові обʼєкти є такими:

  • Обовʼязковий пріоритетний рівень exempt використовується для запитів, які взагалі не підлягають контролю потоку: вони завжди будуть надсилатися негайно. Обовʼязкова FlowSchema exempt класифікує всі запити з групи system:masters у цей рівень пріоритету. Ви можете визначити інші FlowSchemas, які направляють інші запити на цей рівень пріоритету, якщо це доцільно.

  • Обовʼязковий пріоритетний рівень catch-all використовується в поєднанні з обовʼязковою FlowSchema catch-all, щоб переконатися, що кожен запит отримує якийсь вид класифікації. Зазвичай ви не повинні покладатися на цю універсальну catch-all конфігурацію і повинні створити свою власну FlowSchema та PriorityLevelConfiguration для обробки всіх запитів. Оскільки очікується, що він не буде використовуватися нормально, обовʼязковий рівень пріоритету catch-all має дуже невелику частку паралелізму і не ставить запити в чергу.

Рекомендовані обʼєкти конфігурації

Рекомендовані FlowSchema та PriorityLevelConfigurations складають обґрунтовану типову конфігурацію. Ви можете змінювати їх або створювати додаткові обʼєкти конфігурації за необхідності. Якщо ваш кластер може зазнати високого навантаження, то варто розглянути, яка конфігурація працюватиме краще.

Рекомендована конфігурація групує запити в шість рівнів пріоритету:

  • Рівень пріоритету node-high призначений для оновлень стану вузлів.

  • Рівень пріоритету system призначений для запитів, які не стосуються стану справності, з групи system:nodes, тобто Kubelets, які повинні мати можливість звʼязатися з сервером API, щоб завдання могли плануватися на них.

  • Рівень пріоритету leader-election призначений для запитів на вибір лідера від вбудованих контролерів (зокрема, запити на endpoints, configmaps або leases, що надходять від користувачів та облікових записів служб з групи system:kube-controller-manager або system:kube-scheduler в просторі імен kube-system). Ці запити важливо ізолювати від іншого трафіку, оскільки невдачі у виборі лідера призводять до збоїв їх контролерів і перезапуску, що в свою чергу призводить до більших витрат трафіку, оскільки нові контролери синхронізують свої сповіщувачі.

  • Рівень пріоритету workload-high призначений для інших запитів від вбудованих контролерів.

  • Рівень пріоритету workload-low призначений для запитів від будь-якого іншого облікового запису служби, що зазвичай включає всі запити від контролерів, що працюють в капсулах.

  • Рівень пріоритету global-default обробляє весь інший трафік, наприклад, інтерактивні команди kubectl, запущені непривілейованими користувачами.

Рекомендовані FlowSchema служать для направлення запитів на вищезазначені рівні пріоритету, і тут вони не перераховані.

Підтримка обовʼязкових та рекомендованих обʼєктів конфігурації

Кожен kube-apiserver незалежно підтримує обовʼязкові та рекомендовані обʼєкти конфігурації, використовуючи початкову та періодичну поведінку. Отже, в ситуації з сумішшю серверів різних версій може відбуватися турбулентність, поки різні сервери мають різні погляди на відповідний вміст цих обʼєктів.

Кожен kube-apiserver робить початковий обхід обовʼязкових та рекомендованих обʼєктів конфігурації, а після цього здійснює періодичну обробку (один раз на хвилину) цих обʼєктів.

Для обовʼязкових обʼєктів конфігурації підтримка полягає в тому, щоб забезпечити наявність обʼєкта та, якщо він існує, мати правильну специфікацію. Сервер відмовляється дозволити створення або оновлення зі специфікацією, яка не узгоджується з поведінкою огородження сервера.

Підтримка рекомендованих обʼєктів конфігурації призначена для того, щоб дозволити перевизначення їх специфікації. Видалення, з іншого боку, не враховується: підтримка відновить обʼєкт. Якщо вам не потрібен рекомендований обʼєкт конфігурації, то вам потрібно залишити його, але встановити його специфікацію так, щоб мінімально впливати на систему. Підтримка рекомендованих обʼєктів також призначена для підтримки автоматичної міграції при виході нової версії kube-apiserver, хоча, можливо, з турбулентністю при змішаній популяції серверів.

Підтримка рекомендованого обʼєкта конфігурації включає його створення, зі специфікацією, яку пропонує сервер, якщо обʼєкт не існує. З іншого боку, якщо обʼєкт вже існує, поведінка підтримка залежить від того, чи контролюють обʼєкт kube-apiservers чи користувачі. У першому випадку сервер забезпечує, що специфікація обʼєкта відповідає тому, що пропонує сервер; у другому випадку специфікація залишається без змін.

Питання про те, хто контролює обʼєкт, вирішується спочатку шляхом пошуку анотації з ключем apf.kubernetes.io/autoupdate-spec. Якщо така анотація є і її значення true, то обʼєкт контролюється kube-apiservers. Якщо така анотація існує і її значення false, то обʼєкт контролюють користувачі. Якщо жодна з цих умов не виконується, тоді перевіряється metadata.generation обʼєкта. Якщо вона дорівнює 1, то обʼєкт контролюють kube-apiservers. В іншому випадку обʼєкт контролюють користувачі. Ці правила були введені у версії 1.22, і врахування ними metadata.generation призначена для міграції з більш простої попередньої поведінки. Користувачі, які хочуть контролювати рекомендований обʼєкт конфігурації, повинні встановити анотацію apf.kubernetes.io/autoupdate-spec в false.

Підтримка обовʼязкового або рекомендованого обʼєкта конфігурації також включає забезпечення наявності анотації apf.kubernetes.io/autoupdate-spec, яка точно відображає те, чи контролюють kube-apiservers обʼєкт.

Підтримка також включає видалення обʼєктів, які не є обовʼязковими або рекомендованими, анотованих як apf.kubernetes.io/autoupdate-spec=true.

Звільнення від паралелізму перевірки справності

Запропонована конфігурація не надає спеціального поводження запитам на перевірку стану здоровʼя на kube-apiservers від їхніх локальних kubelets, які зазвичай використовують захищений порт, але не надають жодних облікових даних. Запити цього типу вказаної конфігурації призначаються до FlowSchema global-default і відповідного пріоритетного рівня global-default, де інші запити можуть їх перенавантажувати.

Якщо ви додасте наступний додатковий FlowSchema, це звільнить ці запити від обмежень.

apiVersion: flowcontrol.apiserver.k8s.io/v1
kind: FlowSchema
metadata:
  name: health-for-strangers
spec:
  matchingPrecedence: 1000
  priorityLevelConfiguration:
    name: exempt
  rules:
    - nonResourceRules:
      - nonResourceURLs:
          - "/healthz"
          - "/livez"
          - "/readyz"
        verbs:
          - "*"
      subjects:
        - kind: Group
          group:
            name: "system:unauthenticated"

Спостережуваність

Метрики

Після увімкнення функції API Priority та Fairness, kube-apiserver експортує додаткові метрики. Моніторинг цих метрик може допомогти вам визначити, чи правильно ваша конфігурація обробляє важливий трафік, або знайти проблемні робочі навантаження, які можуть шкодити справності системи.

Рівень зрілості BETA

  • apiserver_flowcontrol_rejected_requests_total — це вектор лічильника (накопичувальний з моменту запуску сервера) запитів, які були відхилені, розбитий за мітками flow_schema (показує той, який підходить до запиту), priority_level (показує той, до якого був призначений запит) і reason. Мітка reason буде мати одне з наступних значень:

    • queue-full, що вказує на те, що занадто багато запитів вже було в черзі.
    • concurrency-limit, що вказує на те, що конфігурація PriorityLevelConfiguration налаштована відхиляти замість того, щоб ставити в чергу зайві запити.
    • time-out, що вказує на те, що запит все ще перебував в черзі, коли його обмеження часу в черзі закінчилося.
    • cancelled, що вказує на те, що запит не закріплений і викинутий з черги.
  • apiserver_flowcontrol_dispatched_requests_total — це вектор лічильника (накопичувальний з моменту запуску сервера) запитів, які почали виконуватися, розбитий за flow_schema та priority_level.

  • apiserver_flowcontrol_current_inqueue_requests — це вектор мітки миттєвого числа запитів, які знаходяться в черзі (не виконуються), розбитий за priority_level та flow_schema.

  • apiserver_flowcontrol_current_executing_requests — це вектор мітки миттєвого числа виконуваних (не очікуючих в черзі) запитів, розбитий за priority_level та flow_schema.

  • apiserver_flowcontrol_current_executing_seats — це вектор мітки миттєвого числа зайнятих місць, розбитий за priority_level та flow_schema.

  • apiserver_flowcontrol_request_wait_duration_seconds — це вектор гістограми того, скільки часу запити провели в черзі, розбитий за мітками flow_schema, priority_level та execute. Мітка execute вказує, чи почалося виконання запиту.

  • apiserver_flowcontrol_nominal_limit_seats — це вектор вектор, що містить номінальну межу паралелізму кожного рівня пріоритету, обчислювану з загального ліміту паралелізму сервера API та налаштованих номінальних спільних ресурсів паралелізму рівня пріоритету.

Рівень зрілості ALPHA

  • apiserver_current_inqueue_requests — це вектор вимірювання останніх найвиших значень кількості запитів, обʼєднаних міткою request_kind, значення якої можуть бути mutating або readOnly. Ці величини описують найбільше значення спостереження в односекундному вікні процесів, що недавно завершилися. Ці дані доповнюють старий графік apiserver_current_inflight_requests, що містить високу точку кількості запитів в останньому вікні, які активно обслуговуються.

  • apiserver_current_inqueue_seats — це вектор мітки миттєвого підсумку запитів, які будуть займати найбільшу кількість місць, згрупованих за мітками з назвами flow_schema та priority_level.

  • apiserver_flowcontrol_read_vs_write_current_requests — це гістограма спостережень, зроблених в кінці кожної наносекунди, кількості запитів, розбита за мітками phase (приймає значення waiting та executing) та request_kind (приймає значення mutating та readOnly). Кожне спостереження є коефіцентом, від 0 до 1, кількості запитів, поділеним на відповідний ліміт кількості запитів (обмеження обсягу черги для очікування та обмеження паралелізму для виконання).

  • apiserver_flowcontrol_request_concurrency_in_use — це вектор мітки миттєвого числа зайнятих місць, розбитий за priority_level та flow_schema.

  • apiserver_flowcontrol_priority_level_request_utilization — це гістограма спостережень, зроблених в кінці кожної наносекунди, кількості запитів, розбита за мітками phase (яка приймає значення waiting та executing) та priority_level. Кожне спостереження є відношенням, від 0 до 1, кількості запитів поділеної на відповідний ліміт кількості запитів (обмеження обсягу черги для очікування та обмеження паралелізму для виконання).

  • apiserver_flowcontrol_priority_level_seat_utilization — це гістограма спостережень, зроблених в кінці кожної наносекунди, використання обмеження пріоритету паралелізму, розбита за priority_level. Це використання є часткою (кількість зайнятих місць) / (обмеження паралелізму). Цей показник враховує всі етапи виконання (як нормальні, так і додаткові затримки в кінці запису для відповідного сповіщення про роботу) всіх запитів, крім WATCH; для них він враховує лише початковий етап, що доставляє сповіщення про попередні обʼєкти. Кожна гістограма в векторі також має мітку phase: executing (для фази очікування не існує обмеження на кількість місць).

  • apiserver_flowcontrol_request_queue_length_after_enqueue — це гістограма вектора довжини черги для черг, розбита за priority_level та flow_schema, як вибірка за запитом у черзі. Кожен запит, який потрапив в чергу, вносить один зразок в свою гістограму, що вказує довжину черги негайно після додавання запиту. Зверніть увагу, що це дає інші показники, ніж неупереджене опитування.

  • apiserver_flowcontrol_request_concurrency_limit такий же, як apiserver_flowcontrol_nominal_limit_seats. До введення пралелізму запозичення між рівнями пріоритету, це завжди дорівнювало apiserver_flowcontrol_current_limit_seats (який не існував як окремий метричний показник).

  • apiserver_flowcontrol_lower_limit_seats — це вектор мітки миттєвої нижньої межі динамічного обмеження паралелізму для кожного рівня пріоритету.

  • apiserver_flowcontrol_upper_limit_seats — це вектор мітки миттєвої верхньої межі динамічного обмеження паралелізму для кожного рівня пріоритету.

  • apiserver_flowcontrol_demand_seats — це гістограма вектора підрахунку спостережень, в кінці кожної наносекунди, відношення кожного рівня пріоритету до (вимоги місць) / (номінального обмеження паралелізму). Вимога місць на рівні пріоритету — це сума, як віконаних запитів, так і тих, які перебувають у початковій фазі виконання, максимум кількості зайнятих місць у початкових та кінцевих фазах виконання запиту.

  • apiserver_flowcontrol_demand_seats_high_watermark — це вектор мітки миттєвого максимального запиту на місця, що спостерігався протягом останнього періоду адаптації до позичання паралелізму для кожного рівня пріоритету.

  • apiserver_flowcontrol_demand_seats_average - це вектор мітки миттєвого часового середнього значення вимог місць для кожного рівня пріоритету, що спостерігався протягом останнього періоду адаптації до позичання паралелізму.

  • apiserver_flowcontrol_demand_seats_stdev - це вектор мітки миттєвого стандартного відхилення популяції вимог місць для кожного рівня пріоритету, що спостерігався протягом останнього періоду адаптації до позичання паралелізму.

  • apiserver_flowcontrol_demand_seats_smoothed - це вектор мітки миттєвого вирівняного значення вимог місць для кожного рівня пріоритету, визначений на останній період адаптації.

  • apiserver_flowcontrol_target_seats - це вектор мітки миттєвого усередненого значення вимог місць для кожного рівня пріоритету, яке виходить в алокації позичання.

  • apiserver_flowcontrol_seat_fair_frac - це мітка миттєвого значення частки справедливого розподілу, визначеного при останній адаптації позичання.

  • apiserver_flowcontrol_current_limit_seats - це вектор мітки миттєвого динамічного обмеження паралелізму для кожного рівня пріоритету, яке було виведено в останню корекцію.

  • apiserver_flowcontrol_request_execution_seconds - це гістограма, яка показує, скільки часу займає виконання запитів, розбита за flow_schema та priority_level.

  • apiserver_flowcontrol_watch_count_samples - це гістограма вектора кількості активних WATCH-запитів, що стосуються певного запису, розбита за flow_schema та priority_level.

  • apiserver_flowcontrol_work_estimated_seats - це гістограма вектора кількості оцінених місць (максимум початкової та кінцевої стадії виконання) для запитів, розбита за flow_schema та priority_level.

  • apiserver_flowcontrol_request_dispatch_no_accommodation_total - це лічильник вектора кількості подій, які в принципі могли призвести до відправки запиту, але не зробили цього через відсутність доступного паралелізму, розбитий за flow_schema та priority_level.

  • apiserver_flowcontrol_epoch_advance_total - це лічильник вектора кількості спроб зрушити вимірювач прогресу рівня пріоритету назад, щоб уникнути переповнення числових значень, згрупований за priority_level та success.

Поради щодо використання API Priority та Fairness

Коли певний рівень пріоритету перевищує свій дозволений паралелізм, запити можуть зазнавати збільшеного часу очікування або бути відкинуті з HTTP 429 (Забагато запитів) помилкою. Щоб запобігти цим побічним ефектам APF, ви можете змінити ваше навантаження або налаштувати ваші налаштування APF, щоб забезпечити достатню кількість місць для обслуговування ваших запитів.

Щоб виявити, чи відкидаються запити через APF, перевірте наступні метрики:

  • apiserver_flowcontrol_rejected_requests_total — загальна кількість відкинутих запитів за FlowSchema та PriorityLevelConfiguration.
  • apiserver_flowcontrol_current_inqueue_requests — поточна кількість запитів в черзі за FlowSchema та PriorityLevelConfiguration.
  • apiserver_flowcontrol_request_wait_duration_seconds — затримка, додана до запитів, що очікують у черзі.
  • apiserver_flowcontrol_priority_level_seat_utilization — використання місць на рівні пріоритету за PriorityLevelConfiguration.

Зміни в навантаженні

Щоб запобігти встановленню запитів у чергу та збільшенню затримки або їх відкиданню через APF, ви можете оптимізувати ваші запити шляхом:

  • Зменшення швидкості виконання запитів. Менша кількість запитів протягом фіксованого періоду призведе до меншої потреби у місцях в будь-який момент часу.
  • Уникання видачі великої кількості дороговартісних запитів одночасно. Запити можна оптимізувати, щоб вони використовували менше місць або мали меншу затримку, щоб ці запити утримували ці місця протягом коротшого часу. Запити списку можуть займати більше 1 місця в залежності від кількості обʼєктів, отриманих під час запиту. Обмеження кількості обʼєктів, отриманих у запиті списку, наприклад, за допомогою розбиття на сторінки (pagination), буде використовувати менше загальних місць протягом коротшого періоду. Крім того, заміна запитів списку запитами перегляду потребуватиме менше загальних часток паралелізму, оскільки запити перегляду займають лише 1 місце під час свого початкового потоку повідомлень. Якщо використовується потоковий перегляд списків у версіях 1.27 і пізніше, запити перегляду займатимуть таку ж кількість місць, як і запит списку під час його початкового потоку повідомлень, оскільки всі стани колекції мають бути передані по потоку. Зауважте, що в обох випадках запит на перегляд не буде утримувати жодних місць після цієї початкової фази.

Памʼятайте, що встановлення запитів у чергу або їх відкидання через APF можуть бути викликані як збільшенням кількості запитів, так і збільшенням затримки для існуючих запитів. Наприклад, якщо запити, які зазвичай виконуються за 1 секунду, починають виконуватися за 60 секунд, це може призвести до того, що APF почне відкидати запити, оскільки вони займають місця протягом тривалого часу через це збільшення затримки. Якщо APF починає відкидати запити на різних рівнях пріоритету без значного змінення навантаження, можливо, існує проблема з продуктивністю контролера, а не з навантаженням або налаштуваннями APF.

Налаштування Priority та fairness

Ви також можете змінити типові обʼєкти FlowSchema та PriorityLevelConfiguration або створити нові обʼєкти цих типів, щоб краще врахувати ваше навантаження.

Налаштування APF можна змінити для:

  • Надання більшої кількості місць для запитів високого пріоритету.
  • Ізоляція необовʼязкових або дорогих запитів, які можуть забрати рівень паралелізму, якщо він буде спільно використовуватися з іншими потоками.

Надання більшої кількості місць для запитів високого пріоритету

  1. У разі можливості кількість місць, доступних для всіх рівнів пріоритету для конкретного kube-apiserver, можна збільшити, збільшивши значення прапорців max-requests-inflight та max-mutating-requests-inflight. Іншим варіантом є горизонтальне масштабування кількості екземплярів kube-apiserver, що збільшить загальну одночасність на рівень пріоритету по всьому кластеру за умови належного балансування навантаження запитів.
  2. Ви можете створити новий FlowSchema, який посилається на PriorityLevelConfiguration з більшим рівнем паралелізму. Ця нова PriorityLevelConfiguration може бути існуючим рівнем або новим рівнем зі своїм набором номінальних поширень паралелізму. Наприклад, новий FlowSchema може бути введений для зміни PriorityLevelConfiguration для ваших запитів з global-default на workload-low з метою збільшення кількості місць, доступних для ваших користувачів. Створення нової PriorityLevelConfiguration зменшить кількість місць, призначених для існуючих рівнів. Нагадаємо, що редагування типових FlowSchema або PriorityLevelConfiguration потребує встановлення анотації apf.kubernetes.io/autoupdate-spec в значення false.
  3. Ви також можете збільшити значення NominalConcurrencyShares для PriorityLevelConfiguration, що обслуговує ваші запити високого пріоритету. Як альтернативу, для версій 1.26 та пізніших, ви можете збільшити значення LendablePercent для конкуруючих рівнів пріоритету, щоб даний рівень пріоритету мав вищий пул місць, які він може позичати.

Ізоляція неважливих запитів, для попередження виснаження інших потоків

Для ізоляції запитів можна створити FlowSchema, чий субʼєкт збігається з користувачеві, що робить ці запити, або створити FlowSchema, яка відповідає самому запиту (відповідає resourceRules). Далі цю FlowSchema можна зіставити з PriorityLevelConfiguration з низьким пулом місць.

Наприклад, припустимо, що запити на перегляд подій з Podʼів, що працюють в стандартному просторі імен, використовують по 10 місць кожен і виконуються протягом 1 хвилини. Щоб запобігти впливу цих дорогих запитів на інші запити від інших Podʼів, які використовують поточну FlowSchema для сервісних облікових записів, можна застосувати таку FlowSchema для ізоляції цих викликів списків від інших запитів.

Приклад обʼєкта FlowSchema для ізоляції запитів на перегляд подій:

apiVersion: flowcontrol.apiserver.k8s.io/v1
kind: FlowSchema
metadata:
  name: list-events-default-service-account
spec:
  distinguisherMethod:
    type: ByUser
  matchingPrecedence: 8000
  priorityLevelConfiguration:
    name: catch-all
  rules:
    - resourceRules:
      - apiGroups:
          - '*'
        namespaces:
          - default
        resources:
          - events
        verbs:
          - list
      subjects:
        - kind: ServiceAccount
          serviceAccount:
            name: default
            namespace: default
  • FlowSchema захоплює всі виклики списків подій, виконані типовим сервісним обліковим записом у стандартному просторі імен. Пріоритет відповідності 8000 менший за значення 9000, що використовується поточною FlowSchema для сервісних облікових записів, тому ці виклики списків подій будуть відповідати list-events-default-service-account, а не service-accounts.
  • Використовується конфігурація пріоритету catch-all для ізоляції цих запитів. Пріоритетний рівень catch-all має дуже малий пул місць і не ставить запитів в чергу.

Що далі

12 - Автомасштабування кластера

Автоматичне керування вузлами кластера для адаптації до попиту.

Kubernetes потрібні вузли у вашому кластері для роботи Podʼів. Це означає, що потрібно забезпечити місце для робочих Podʼів та для самого Kubernetes.

Ви можете автоматично налаштувати кількість ресурсів, доступних у вашому кластері: автомасштабування вузлів. Ви можете змінювати кількість вузлів або змінювати потужність, яку надають вузли. Перший підхід називається горизонтальним масштабуванням, а другий — вертикальним масштабуванням.

Kubernetes може навіть забезпечити багатовимірне автоматичне масштабування для вузлів.

Керування вузлами вручну

Ви можете вручну керувати потужністю на рівні вузла, де ви налаштовуєте фіксовану кількість вузлів; ви можете використовувати цей підхід навіть якщо забезпечення (процес встановлення, управління та виведення з експлуатації) для цих вузлів автоматизоване.

Ця сторінка присвячена наступному кроку, а саме автоматизації управління обсягом потужності вузла (ЦП, памʼяті та інших ресурсів вузла), доступним у вашому кластері.

Автоматичне горизонтальне масштабування

Автомасштабувальник

Ви можете використовувати Автомасштабувальник, щоб автоматично керувати масштабуванням ваших вузлів. Автомасштабувальник може інтегруватися з хмарним постачальником або з кластерним API Kubernetes, щоб забезпечити фактичне управління вузлами, яке потрібно.

Автомасштабувальник додає вузли, коли неможливо розмістити потоки, і видаляє вузли, коли ці вузли порожні.

Інтеграції з хмарними постачальниками

README для кластерного масштабувальника містить список деяких доступних інтеграцій з хмарними постачальниками.

Багатовимірне масштабування з урахуванням вартості

Karpenter

Karpenter підтримує пряме керування вузлами через втулки, які інтегруються з конкретними хмарними постачальниками та можуть керувати вузлами для вас, оптимізуючи загальну вартість.

Karpenter автоматично запускає саме ті обчислювальні ресурси, які потрібні вашим застосункам. Його спроєктовано, щоб ви могли повною мірою скористатись можливостями хмари з швидким та простим розгортанням обчислювальних ресурсів для вашого кластера Kubernetes.

Інструмент Karpenter призначений для інтеграції з хмарним постачальником, який надає управління серверами через API, і де інформація про ціни на доступні сервери також доступна через веб-API.

Наприклад, якщо ви маєте декілька Podʼів у вашому кластері, інструмент Karpenter може купити новий вузол, який більший за один з вузлів, які ви вже використовуєте, а потім вимкнути наявний вузол, як тільки новий вузол буде готовий до використання.

Інтеграції з постачальниками хмарних послуг

Існують інтеграції між ядром Karpenter та наступними постачальниками хмарних послуг:

Descheduler

Descheduler може допомогти консолідувати Podʼи на меншій кількості вузлів, щоб впоратись з автоматичним масштабуванням, коли у кластера зʼявляються вільні потужності.

Визначення розміру навантаження на основі розміру кластера

Пропорційне автомасштабування кластера

Для навантажень, які потрібно масштабувати залежно від розміру кластера, таких як cluster-dns або інші системні компоненти, ви можете використовувати Cluster Proportional Autoscaler.

Cluster Proportional Autoscaler спостерігає за кількістю придатних до планування вузлів та ядер, і масштабує кількість реплік цільового навантаження відповідно.

Вертикальний пропорційний автомасштабувальник кластера

Якщо кількість реплік має залишитися незмінною, ви можете масштабувати ваші робочі навантаження вертикально відповідно до розміру кластера, використовуючи Cluster Proportional Vertical Autoscaler. Цей проєкт перебуває в бета-версії та знаходиться на GitHub.

У той час, як Cluster Proportional Autoscaler масштабує кількість реплік робочого навантаження, Cluster Proportional Vertical Autoscaler налаштовує запити ресурсів для робочого навантаження (наприклад, Deployment або DaemonSet) на основі кількості вузлів та/або ядер у кластері.

Що далі

13 - Встановлення надбудов

Надбудови розширюють функціональність Kubernetes.

Ця сторінка містить список доступних надбудов та посилання на відповідні інструкції з встановлення. Список не намагається бути вичерпним.

Мережа та політика мережі

  • ACI надає інтегровану мережу контейнерів та мережеву безпеку з Cisco ACI.
  • Antrea працює на рівні 3/4, щоб надати мережеві та служби безпеки для Kubernetes, використовуючи Open vSwitch як мережеву панель даних. Antrea є проєктом CNCF на рівні Sandbox.
  • Calico є постачальником мережі та мережевої політики. Calico підтримує гнучкий набір мережевих опцій, щоб ви могли вибрати найефективнішу опцію для вашої ситуації, включаючи мережі з та без оверлею, з або без BGP. Calico використовує однаковий рушій для забезпечення мережевої політики для хостів, Podʼів та (якщо використовуєте Istio та Envoy) застосунків на рівні шару сервісної мережі.
  • Canal обʼєднує Flannel та Calico, надаючи мережу та мережеву політику.
  • Cilium: це рішення для мережі, спостереження та забезпечення безпеки з eBPF-орієнтованою панеллю даних. Cilium надає просту мережу Layer 3 з можливістю охоплення декількох кластерів в режимі маршрутизації або режимі налагодження/інкапсуляції та може застосовувати політики мережі на рівнях L3-L7 з використанням моделі безпеки на основі ідентифікації, що відʼєднана від мережевого адресування. Cilium може діяти як заміна для kube-proxy; він також пропонує додаткові функції спостереження та безпеки.
  • CNI-Genie: Дозволяє Kubernetes безперешкодно підключатися до вибору втулків CNI, таких як Calico, Canal, Flannel або Weave.
  • Contiv: надає налаштовану мережу (L3 з використанням BGP, оверлей за допомогою vxlan, класичний L2 та Cisco-SDN/ACI) для різних варіантів використання та повнофункціональний фреймворк політик. Проєкт Contiv є проєктом з повністю відкритими сирцями. Встановлювач надає як варіанти установки, як з, так і без, kubeadm.
  • Contrail: оснований на Tungsten Fabric, це відкритою платформою мережевої віртуалізації та управління політикою для кількох хмар. Contrail і Tungsten Fabric інтегровані з системами оркестрування, такими як Kubernetes, OpenShift, OpenStack і Mesos, і надають режими ізоляції для віртуальних машин, контейнерів/Podʼів та обробки робочих навантажень на bare metal.
  • Flannel: постачальник мережі на основі оверлеїв, який можна використовувати з Kubernetes.
  • Gateway API: відкритий проєкт, керований SIG Network, який надає виразний, розширюваний та рольовий API для моделювання сервісних мереж.
  • Knitter є втулком для підтримки кількох мережевих інтерфейсів в Podʼі Kubernetes.
  • Multus: мультивтулок для підтримки кількох мереж у Kubernetes для підтримки всіх втулків CNI (наприклад, Calico, Cilium, Contiv, Flannel), а також навантаження SRIOV, DPDK, OVS-DPDK та VPP у Kubernetes.
  • OVN-Kubernetes: постачальник мережі для Kubernetes на основі OVN (Open Virtual Network), віртуальної мережевої реалізації, яка вийшла з проєкту Open vSwitch (OVS). OVN-Kubernetes забезпечує реалізацію мережі на основі оверлеїв для Kubernetes, включаючи реалізацію балансування навантаження на основі OVS та політики мережі.
  • Nodus: втулок контролера CNI на основі OVN для надання хмарних послуг на основі послуг хмарної обробки (SFC).
  • NSX-T Container Plug-in (NCP): забезпечує інтеграцію між VMware NSX-T та оркестраторами контейнерів, такими як Kubernetes, а також інтеграцію між NSX-T та контейнерними платформами CaaS/PaaS, такими як Pivotal Container Service (PKS) та OpenShift.
  • Nuage: платформа SDN, яка забезпечує мережеву політику між кластерами Kubernetes Pods та некластерними середовищами з можливістю моніторингу видимості та безпеки.
  • Romana: рішення мережі рівня Layer 3 для мережевих мереж Podʼів, яке також підтримує NetworkPolicy API.
  • Spiderpool: рішення мережі основи та RDMA для Kubernetes. Spiderpool підтримується на bare metal, віртуальних машинах та публічних хмарних середовищах.
  • Weave Net: надає мережу та політику мережі, буде продовжувати працювати з обох боків розділу мережі та не потребує зовнішньої бази даних.

Виявлення служб

  • CoreDNS — це гнучкий, розширюваний DNS-сервер, який може бути встановлений як DNS в кластері для Podʼів.

Візуалізація та управління

  • Dashboard — це вебінтерфейс для управління Kubernetes.

Інфраструктура

  • KubeVirt — це додатковий інструмент для запуску віртуальних машин на Kubernetes. Зазвичай використовується на кластерах на bare metal.
  • Виявлення проблем вузла — працює на вузлах Linux та повідомляє про проблеми системи як події або стан вузла.

Інструментування

Старі надбудови

Існують ще кілька інших надбудов, які документуються в застарілій теці cluster/addons.

Добре підтримувані мають бути вказані тут. Приймаються запити на включення!

14 - Координовані вибори лідера

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.31 [alpha] (стандартно увімкнено: false)

Kubernetes 1.32 включає альфа-функцію, яка дозволяє компонентам панелі управління детерміновано обирати лідера через координовані вибори лідера. Це корисно для задоволення обмежень щодо несумісності версій Kubernetes під час оновлення кластера. Наразі єдина вбудована стратегія вибору — це OldestEmulationVersion, що надає перевагу лідеру з найнижчою версією емуляції, за яким йде бінарна версія, а потім позначка часу створення.

Увімкнення координованих виборів лідера

Переконайтеся, що функціональну можливість CoordinatedLeaderElection увімкнено під час запуску API Server та що група API coordination.k8s.io/v1alpha1 увімкнена також.

Це можна зробити, встановивши прапорці --feature-gates="CoordinatedLeaderElection=true" та --runtime-config="coordination.k8s.io/v1alpha1=true".

Конфігурація компонентів

За умови, що ви увімкнули функціональну можливість CoordinatedLeaderElection та увімкнули групу API coordination.k8s.io/v1alpha1, сумісні компоненти панелі управління автоматично використовують LeaseCandidate та Lease API для вибору лідера за потреби.

Для Kubernetes 1.32 два компоненти панелі управління (kube-controller-manager і kube-scheduler) автоматично використовують координовані вибори лідера, коли функціональну можливість та група API увімкнені.