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

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

Podʼи

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

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

Окрім контейнерів застосунків, Pod може містити init-контейнери, які запускаються під час старту Podʼа. Ви також можете впровадити ефемерні контейнери для налагодження запущеного Podʼа.

Що таке Pod?

Примітка:

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

Спільний контекст Podʼа — це набір просторів імен Linux, cgroups та, можливо, інших аспектів ізоляції — тих самих речей, що забезпечують ізоляцію контейнера. В межах контексту Podʼа окремі застосунки можуть мати додаткові рівні ізоляції.

Pod схожий на набір контейнерів зі спільними просторами імен та спільними томами файлової системи.

Podʼи в кластері Kubernetes використовуються двома основними способами:

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

Групування в одному Podʼі кількох контейнерів, які розміщені разом і керуються спільно, — відносно складний сценарій використання. Використовуйте цей підхід лише в тих конкретних випадках, коли ваші контейнери тісно повʼязані.

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

Використання Podʼів

Нижче наведено приклад Podʼа, який складається з контейнера, що запускає образ nginx:1.14.2.

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

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

kubectl apply -f https://k8s.io/examples/pods/simple-pod.yaml

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

Ресурси робочих навантажень для керування Podʼами

Зазвичай вам не потрібно створювати Podʼи напряму, навіть одиничні Podʼи. Натомість створюйте їх за допомогою ресурсів робочих навантажень, таких як Deployment або Job. Якщо ваші Podʼи потребують відстеження стану, розгляньте використання ресурсу StatefulSet.

Кожен Pod призначений для запуску одного екземпляра певного застосунку. Якщо ви хочете масштабувати свій застосунок горизонтально (щоб надати більше ресурсів загалом, запустивши більше екземплярів), вам слід використовувати кілька Podʼів, по одному для кожного екземпляра. У Kubernetes це зазвичай називається реплікацією. Репліковані Podʼи зазвичай створюються ресурсом робочого навантаження та його контролером, які й керують ними як групою.

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

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

Робота з Podʼами

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

Примітка:

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

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

Операційна система Podʼа

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.25

Ви маєте встановити значення поля .spec.os.name як windows або linux, щоб визначити операційну систему, яку потребують контейнери в цьому Podʼі. Наразі це єдині операційні системи, які підтримує Kubernetes. У майбутньому цей список може бути розширено.

kubelet відмовляється запускати Pod, якщо значення .spec.os.name не збігається з операційною системою вузла. Однак у Kubernetes v1.37 значення .spec.os.name не впливає на те, як kube-scheduler обирає вузол для запуску Podʼа. У будь-якому кластері, де вузли працюють під керуванням більш ніж однієї операційної системи, слід правильно встановити мітку kubernetes.io/os на кожному вузлі та визначати Podʼи з nodeSelector на основі мітки операційної системи. Якщо ви не вкажете nodeSelector на основі ОС, kube-scheduler може призначити Pod на вузол, ОС якого не підходить для його контейнерів. Стандарти безпеки Podʼів також використовують поле .spec.os.name, щоб уникнути застосування політик, які не стосуються цієї операційної системи.

Podʼи та контролери

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

Ось кілька прикладів ресурсів робочих навантажень, які керують одним чи більше Podʼами:

Визначення групи планування

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the GenericWorkload feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Стандартно Kubernetes планує кожний Pod окремо. Однак деякі тісно повʼязані застосунки потребують одночасного планування групи Podʼів для коректної роботи.

Ви можете повʼязати Pod з PodGroup за допомогою поля групи планування (spec.schedulingGroup). Це повідомляє kube-scheduler, що Pod належить до певної групи, і дає йому змогу застосовувати скоординовані рішення щодо розміщення на рівні групи одразу для всієї групи.

Шаблони Podʼів

Контролери ресурсів робочих навантажень створюють Podʼи із шаблону Podʼа (pod template) та керують цими Podʼами від вашого імені.

PodTemplate — це специфікації для створення Podʼів, які входять до складу ресурсів робочих навантажень, таких як Deployments, Jobs та DaemonSets.

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

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

Нижче наведено маніфест простого Job із template, який запускає один контейнер. Контейнер в цьому Podʼі виводить повідомлення, а потім призупиняється.

apiVersion: batch/v1
kind: Job
metadata:
  name: hello
spec:
  template:
    # Це шаблон Podʼа
    spec:
      containers:
      - name: hello
        image: busybox:1.28
        command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
      restartPolicy: OnFailure
    # Кінець шаблону Podʼа

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

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

Кожен ресурс робочого навантаження реалізує власні правила для обробки змін у шаблоні Podʼа. Якщо ви хочете дізнатися більше саме про StatefulSet, прочитайте розділ Стратегія оновлення у навчальному матеріалі «Основи StatefulSet».

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

Оновлення та заміна Podʼів

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

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

  • Більшість метаданих Podʼа є незмінними. Наприклад, ви не можете змінити поля namespace, name, uid або creationTimestamp.
  • Якщо metadata.deletionTimestamp встановлено, новий запис не може бути доданий до списку metadata.finalizers.
  • Оновлення Podʼа не можуть змінювати поля, крім spec.containers[*].image, spec.initContainers[*].image, spec.activeDeadlineSeconds, spec.terminationGracePeriodSeconds, spec.tolerations або spec.schedulingGates. Для spec.tolerations ви можете додавати лише нові записи.
  • Під час оновлення поля spec.activeDeadlineSeconds дозволені два типи оновлень:
    1. присвоєння незаданому полю додатного числа;
    2. зміна значення поля з додатного числа на менше невідʼємне число.

Субресурси Podʼів

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

  • Resize: Субресурс resize дозволяє оновлювати ресурси контейнерів (spec.containers[*].resources). Дивіться Зміна розміру ресурсів контейнера для більш детальної інформації.
  • Ефемерні контейнери: Субресурс ephemeralContainers дозволяє додавати ефемерні контейнери до Podʼа. Дивіться Ефемерні контейнери для більш детальної інформації.
  • Status: Субресурс status дозволяє оновлювати статус Podʼа. Зазвичай його використовують лише kubelet та інші системні контролери.
  • Binding: Субресурс binding дозволяє встановити spec.nodeName Podʼа за допомогою запиту Binding. Зазвичай його використовує лише планувальник.

Покоління Podʼа

  • Поле metadata.generation є унікальним. Воно автоматично встановлюється системою таким чином, що нові Podʼи мають значення metadata.generation, рівне 1, і кожне оновлення змінюваних полів у специфікації Podʼа збільшуватиме значення metadata.generation на 1.
СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.35
More information about this feature

This is a stable feature in Kubernetes, and has been since version v1.35. It was first available in the v1.33 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate PodObservedGenerationTracking, Kubernetes ignores it but does not report any error.

  • observedGeneration — це поле, яке фіксується в розділі status обʼєкта Pod. kubelet встановлює status.observedGeneration, щоб повʼязати стан Podʼа з його поточним статусом. Поле status.observedGeneration Podʼа відображатиме metadata.generation Podʼа в момент, коли повідомляється про статус Podʼа.

Примітка:

Полем status.observedGeneration керує kubelet, і зовнішні контролери не повинні його змінювати.

Різні поля статусу можуть бути повʼязані або з metadata.generation поточного циклу синхронізації, або з metadata.generation попереднього циклу синхронізації. Ключова відмінність полягає в тому, чи зміна в spec відображається безпосередньо в status, чи є опосередкованим результатом запущеного процесу.

Безпосередні оновлення статусу

Для полів статусу, у яких безпосередньо відображається виділена специфікація, observedGeneration буде повʼязано з поточним metadata.generation (покоління N).

Ця поведінка застосовується до:

  • Статусу Resize: Статус операції зміни розміру ресурсу.
  • Виділених ресурсів: Ресурси, виділені Podʼу після зміни розміру.
  • Ефемерних контейнерів: Коли додається новий ефемерний контейнер, і він перебуває у стані Waiting.

Опосередковані оновлення статусу

Для полів статусу, які є опосередкованим результатом виконання специфікації, observedGeneration буде повʼязано з metadata.generation попереднього циклу синхронізації (покоління N-1).

Ця поведінка застосовується до:

  • Образу контейнера: ContainerStatus.ImageID показує образ з попереднього покоління, поки новий образ не буде завантажено, а контейнер не буде оновлено.
  • Фактичних ресурсів: Під час незавершеної зміни розміру фактичні ресурси, що використовуються, все ще належать запиту попереднього покоління.
  • Стану контейнера: Під час незавершеної зміни розміру стан контейнера з політикою, що вимагає перезапуску, відображає запит попереднього покоління.
  • activeDeadlineSeconds, terminationGracePeriodSeconds та deletionTimestamp: Вплив цих полів на статус Podʼа є результатом раніше отриманої специфікації.

Спільні ресурси та комунікація

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

Зберігання в Podʼах

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

Мережеві можливості Podʼа

Кожному Podʼу присвоюється унікальна IP-адреса для кожного сімейства адрес. Кожен контейнер у Podʼі використовує спільний мережевий простір імен, що включає IP-адресу та мережеві порти. Всередині Podʼа (і тільки там) контейнери, що належать до Podʼа, можуть спілкуватися один з одним за допомогою localhost. Коли контейнери в Podʼі спілкуються із сутностями поза межами Podʼа, вони повинні координувати використання спільних мережевих ресурсів (таких як порти). Всередині Podʼа контейнери використовують спільну IP-адресу та простір портів і можуть знаходити один одного через localhost. Контейнери в Podʼі також можуть спілкуватися між собою, використовуючи стандартні засоби міжпроцесної комунікації, такі як семафори SystemV або спільну памʼять POSIX. Контейнери в різних Podʼах мають різні IP-адреси і не можуть спілкуватися за допомогою IPC на рівні ОС без спеціальної конфігурації. Контейнери, які хочуть взаємодіяти з контейнером, що працює в іншому Podʼі, можуть використовувати IP-мережу для спілкування.

Контейнери в межах Podʼа сприймають імʼя хоста системи як імʼя, що збігається з налаштованим name для Podʼа. Більше інформації про це можна знайти в розділі Мережа в кластері.

Налаштування безпеки Podʼів

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

Для базової конфігурації безпеки слід дотримуватися стандарту безпеки Podʼів Baseline та запускати контейнери з правами, відмінними від root. Ви можете налаштувати прості контексти безпеки:

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  containers:
  - name: sec-ctx-demo
    image: busybox
    command: ["sh", "-c", "sleep 1h"]

Щоб дізнатися про розширені налаштування контексту безпеки, зокрема про можливості (capabilities), профілі seccomp та детальні параметри безпеки, перейдіть до розділу Концепції безпеки.

Запити та обмеження ресурсів

Коли ви визначаєте Pod, ви можете за бажанням вказати, скільки кожного ресурсу потрібно контейнеру. Найчастіше вказують CPU та памʼять (RAM).

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

Обмеження CPU застосовуються через тротлінг CPU. Коли контейнер наближається до свого обмеження CPU, ядро обмежує його доступ до CPU. Обмеження памʼяті застосовуються ядром через завершення процесів за нестачі памʼяті (OOM kills), коли контейнер перевищує своє обмеження.

Примітка:

Встановлення обмежень CPU повʼязане з компромісами. Обмеження CPU допомагають запобігти проблемам «шумного сусіда», коли одне робоче навантаження позбавляє ресурсів інші на тому ж вузлі. Це особливо важливо в багатокористувацьких середовищах. Однак обмеження CPU можуть призводити до тротлінгу навіть тоді, коли на вузлі є вільні ресурси CPU, що потенційно погіршує продуктивність робочих навантажень, чутливих до затримок. Рішення про встановлення обмежень CPU залежить від вашого середовища, характеристик робочого навантаження та вимог до ізоляції.

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

Статичні Podʼи

Статичні Podʼи керуються безпосередньо демоном kubelet на конкретному вузлі, без спостереження за ними з боку API-сервера. У той час як більшістю Podʼів керує панель управління (наприклад, Deployment), для статичних Podʼів kubelet безпосередньо наглядає за кожним статичним Podʼом (та перезапускає його, якщо він зазнає збою).

Статичні Podʼи завжди привʼязані до одного kubelet на конкретному вузлі. Основне призначення статичних Podʼів — запуск самостійно розміщеної панелі управління: іншими словами, використання kubelet для нагляду за окремими компонентами панелі управління.

За докладнішою інформацією звертайтесь до розділу Статичні Podʼи.

Podʼи з кількома контейнерами

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

Podʼи в кластері Kubernetes використовуються двома основними способами:

  • Podʼи, що запускають один контейнер. Модель «один контейнер на Pod» є найпоширенішим сценарієм використання Kubernetes. У цьому випадку Pod можна розглядати як обгортку навколо одного контейнера; Kubernetes керує Podʼами, а не контейнерами безпосередньо.
  • Podʼи, що запускають кілька контейнерів, які мають працювати разом. Pod може інкапсулювати застосунок, який складається з кількох розміщених разом контейнерів, що тісно повʼязані та мають спільно використовувати ресурси. Ці розміщені разом контейнери утворюють єдину цілісну одиницю сервісу — наприклад, один контейнер надає публічний доступ до даних, збережених у спільному томі, тоді як окремий sidecar-контейнер оновлює ці файли. Pod обгортає ці контейнери, ресурси зберігання та ефемерну мережеву ідентичність в єдину одиницю.

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

Діаграма створення Podʼа

Деякі Podʼи мають init-контейнери та контейнери застосунку. Стандартно init-контейнери запускаються та завершують роботу до запуску контейнерів застосунку.

У вас також можуть бути sidecar-контейнери, які надають допоміжні сервіси основному Podʼу застосунку (наприклад, service mesh).

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.33
More information about this feature

This is a stable feature in Kubernetes, and has been since version v1.33. It was first available in the v1.28 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate SidecarContainers, Kubernetes ignores it but does not report any error.

Стандартно увімкнена функціональна можливість SidecarContainers дозволяє вказати restartPolicy: Always для init-контейнерів. Встановлення політики перезапуску Always гарантує, що контейнери, для яких ви її встановили, вважатимуться sidecar-контейнерами, що працюють протягом усього життєвого циклу Podʼа. Контейнери, які ви явно визначаєте як sidecar-контейнери, запускаються перед основним Podʼом застосунку та працюють, доки Pod не завершить роботу.

Проби контейнерів

Проба — це діагностика, яку kubelet періодично виконує для контейнера. Для виконання діагностики kubelet може використовувати різні дії:

  • ExecAction (виконується за допомогою середовища виконання контейнерів)
  • TCPSocketAction (перевіряється безпосередньо kubelet)
  • HTTPGetAction (перевіряється безпосередньо kubelet)

Ви можете дізнатися більше про проби в документації про життєвий цикл Podʼа.

Що далі

  • Дізнайтесь про життєвий цикл Podʼа.
  • Дізнайтесь про PodDisruptionBudget та як ви можете використовувати його для керування доступністю застосунку під час переривань роботи.
  • Pod є ресурсом найвищого рівня в REST API Kubernetes. Визначення обʼєкта Pod детально описує цей обʼєкт.
  • Допис в блозі The Distributed System Toolkit: Patterns for Composite Containers пояснює типові конфігурації Podʼів з більш ніж одним контейнером.
  • Дізнайтесь про Обмеження топології розміщення Podʼів
  • Прочитайте про Розширену конфігурацію Podʼів, щоб дізнатися про цю тему докладніше. На цій сторінці висвітлюються аспекти конфігурації Podʼів, що виходять за межі основних положень, зокрема:
    • PriorityClasses
    • RuntimeClasses
    • розширені способи налаштування планування: того, як Kubernetes вирішує, на якому вузлі має працювати Pod.

Для розуміння контексту того, чому Kubernetes обгортає загальний API Pod іншими ресурсами (такими як StatefulSets або Deployments), ви можете ознайомитися з попередніми розробками, зокрема:

1 - Життєвий цикл Podʼа

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

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

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

Час життя Podʼа

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

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

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

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

Podʼи та відновлення після збоїв

Якщо один з контейнерів у Podʼі виходить з ладу, Kubernetes може спробувати перезапустити саме цей контейнер. Щоб дізнатися більше, прочитайте «Як Podʼи вирішують проблеми з контейнерами».

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

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

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

Конкретний Pod (визначений UID) ніколи не «переплановується» на інший вузол; натомість цей Pod може бути замінений новим, майже ідентичним Podʼом. Якщо ви створюєте Pod-замінник, він може навіть мати ту саму назву (як у .metadata.name), що й старий Pod, але замінник матиме інший .metadata.uid, ніж старий Pod.

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

Повʼязаний час життя

Коли говорять, що щось має такий самий час життя, як і Pod, наприклад том, це означає, що ця річ існує стільки часу, скільки існує цей конкретний Pod (саме з цим UID). Якщо цей Pod буде видалений з будь-якої причини, і навіть якщо буде створений ідентичний замінник, повʼязана річ (у цьому прикладі — том) також буде знищена і створена знову.

Багатоконтейнерний Pod, який містить sidecar-контейнер для завантаження файлів і вебсервер. Pod використовує ефемерний том emptyDir як спільне сховище для контейнерів.

Малюнок 1.

Багатоконтейнерний Pod, який містить sidecar-контейнер для завантаження файлів і вебсервер. Pod використовує ефемерний том emptyDir як спільне сховище для контейнерів.

Фаза Podʼа

Поле status Podʼа — це обʼєкт PodStatus, який має поле phase.

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

Кількість і значення фаз Podʼа суворо контролюються. Окрім того, що задокументовано тут, не слід нічого припускати про Podʼи з певним значенням phase.

Ось можливі значення для phase:

ЗначенняОпис
PendingPod прийнято кластером Kubernetes, але один чи кілька контейнерів ще не налаштовано й не підготовлено до запуску. Це включає час, який Pod витрачає на очікування планування, а також час, який витрачається на завантаження образів контейнерів з мережі.
RunningPod привʼязаний до вузла, і всі контейнери створені. Принаймні один контейнер все ще працює або перебуває у процесі запуску чи перезапуску.
SucceededВсі контейнери в Podʼі завершили роботу успішно і не будуть перезапущені.
FailedВсі контейнери в Podʼі завершили роботу, і принаймні один контейнер завершився зі збоєм. Іншими словами, контейнер вийшов зі статусом, відмінним від нуля, або його роботу завершила система, і контейнер не налаштований на автоматичний перезапуск.
UnknownЗ якоїсь причини не вдалося отримати стан Podʼа. Ця фаза, як правило, виникає через помилку у звʼязку з вузлом, де повинен виконуватися Pod.

Примітка:

Якщо Podʼу раз у раз не вдається запуститися, у полі Status деяких команд kubectl може зʼявитися CrashLoopBackOff. Аналогічно, під час видалення Podʼа у полі Status деяких команд kubectl може зʼявитися Terminating.

Не плутайте Status, поле відображення kubectl, призначене для зручності користувача, з phase Podʼа. Фаза Podʼа є явною частиною моделі даних Kubernetes і API Pod.

  NAMESPACE               NAME               READY   STATUS             RESTARTS   AGE
  alessandras-namespace   alessandras-pod    0/1     CrashLoopBackOff   200        2d9h

Pod отримує час на коректне завершення, який стандартно становить 30 секунд. Ви можете використовувати прапорець --force для примусового завершення роботи Podʼа.

Починаючи з Kubernetes 1.27, kubelet переводить видалені Podʼи в термінальну фазу (Failed або Succeeded залежно від статусів завершення роботи контейнерів Podʼа) перед їх видаленням з API-сервера, за винятком двох випадків:

Якщо вузол виходить з ладу або втрачає звʼязок з рештою кластера, Kubernetes застосовує політику встановлення phase всіх Podʼів на втраченому вузлі у Failed.

Стани контейнера

Окрім фази Podʼа загалом, Kubernetes відстежує стан кожного контейнера всередині Podʼа. Ви можете використовувати хуки життєвого циклу контейнера, щоб запускати події на певних етапах життєвого циклу контейнера.

Як тільки планувальник призначає Pod вузлу, kubelet починає створювати контейнери для цього Podʼа, використовуючи середовище виконання контейнерів. Існує три можливі стани контейнера: Waiting (Очікування), Running (Виконання) та Terminated (Завершено).

Щоб перевірити стан контейнерів Podʼа, ви можете використовувати kubectl describe pod <name-of-pod>. Вивід показує стан для кожного контейнера в межах цього Podʼа.

Кожен стан має конкретне значення:

Waiting

Якщо контейнер не перебуває ні в стані Running, ні в стані Terminated, то він перебуває в стані Waiting. Контейнер у стані Waiting усе ще виконує операції, необхідні для завершення запуску: наприклад, завантажує образ контейнера з реєстру образів контейнерів або застосовує дані Secret. Коли ви використовуєте kubectl для опитування Podʼа із контейнером, який перебуває в стані Waiting, ви також бачите поле Reason, яке стисло пояснює, чому контейнер перебуває в цьому стані.

Running

Статус Running вказує на те, що виконання контейнера відбувається без проблем. Якщо було налаштовано хук postStart, він уже виконався і завершився. Коли ви використовуєте kubectl для опитування Podʼа із контейнером, який перебуває в стані Running, ви також бачите інформацію про те, коли контейнер перейшов у стан Running.

Terminated

Контейнер у стані Terminated розпочав виконання і потім або виконався до кінця, або зазнав збою з певної причини. Коли ви використовуєте kubectl для опитування Podʼа із контейнером, який перебуває в стані Terminated, ви бачите причину, код виходу та час початку та завершення періоду виконання цього контейнера.

Якщо у контейнера є налаштований хук preStop, цей хук запускається перед тим, як контейнер перейде в стан Terminated.

Як Podʼи вирішують проблеми з контейнерами

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

  1. Початковий збій: Kubernetes намагається негайно перезапустити контейнер на основі restartPolicy Podʼа.
  2. Повторні збої: Після початкового збою Kubernetes застосовує експоненційну затримку для наступних перезапусків, описану в restartPolicy. Це запобігає перевантаженню системи швидкими повторними спробами перезапуску.
  3. Стан CrashLoopBackOff: Це означає, що для певного контейнера зараз діє механізм затримки, бо цей контейнер перебуває в циклі збоїв: він раз у раз зазнає збою та перезапускається.
  4. Скидання затримки: Якщо контейнер успішно працює протягом певного часу (наприклад, 10 хвилин), Kubernetes скидає затримку, розглядаючи будь-який новий збій як перший.

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

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

CrashLoopBackOff може бути спричинений такими проблемами:

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

Щоб розібратися у причинах проблеми CrashLoopBackOff, користувач може:

  1. Перевірити логи: Використовуйте kubectl logs <name-of-pod>, щоб перевірити логи контейнера. Часто це найпряміший спосіб діагностики проблеми, що спричиняє збої.
  2. Перевірити події: Використовуйте kubectl describe pod <name-of-pod> для перегляду подій для Podʼа, які можуть надати підказки про проблеми конфігурації або ресурсів.
  3. Перевірити конфігурацію: Переконайтеся, що конфігурація Podʼа, включаючи змінні середовища та змонтовані томи, є правильною і що всі необхідні зовнішні ресурси доступні.
  4. Перевірити обмеження ресурсів: Переконайтеся, що контейнеру виділено достатньо CPU та памʼяті. Іноді збільшення ресурсів у визначенні Podʼа може вирішити проблему.
  5. Налагодити застосунок: У коді застосунку можуть бути помилки або неправильні налаштування. Запуск цього образу контейнера локально або в середовищі розробки може допомогти діагностувати проблеми, специфічні для застосунку.

Перезапуск контейнера

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

Перезапуск контейнера та відмовостійкість

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

Політика перезапуску контейнера на рівні Podʼа

spec Podʼа має поле restartPolicy із можливими значеннями Always, OnFailure та Never. Стандартне значення — Always.

restartPolicy для Podʼа застосовується до контейнерів застосунків в Podʼі та до звичайних init-контейнерів. Sidecar-контейнери не враховують поле restartPolicy на рівні Podʼа: у Kubernetes sidecar визначається як запис всередині initContainers, у якого restartPolicy на рівні контейнера встановлено в Always. Для init-контейнерів, які завершують роботу з помилкою, kubelet виконує їх перезапуск, якщо restartPolicy на рівні Podʼа — OnFailure або Always:

  • Always: автоматично перезапускає контейнер після будь-якого завершення.
  • OnFailure: перезапускає контейнер тільки після його завершення з помилкою (код виходу відмінний від нуля).
  • Never: ніколи автоматично не перезапускає контейнер, що завершив роботу.
Порівняння поведінки перезапуску

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

Код виходуrestartPolicy: AlwaysrestartPolicy: OnFailurerestartPolicy: NeverSidecar-контейнери
0 (Успіх)ПерезапускаєтьсяНе перезапускаєтьсяНе перезапускаєтьсяЗавжди перезапускається
Ненульовий (Збій)ПерезапускаєтьсяПерезапускаєтьсяНе перезапускаєтьсяЗавжди перезапускається

Примітка:

Поведінка перезапуску особливо важлива під час вибору між Deployments та Jobs:

  • Deployments зазвичай використовують restartPolicy: Always (єдине дозволене значення) для безперервної роботи застосунків.
  • Jobs зазвичай використовують restartPolicy: OnFailure або restartPolicy: Never для належного оброблення завдань пакетної обробки.
  • Sidecar-контейнери є init-контейнерами, які завжди перезапускаються незалежно від restartPolicy Podʼа, оскільки вони мають власну політику перезапуску на рівні контейнера restartPolicy: Always.
Приклади сценаріїв

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

Приклад 1: Вебсервер з restartPolicy: Always (типово для Deployments)

apiVersion: v1
kind: Pod
metadata:
  name: web-server
spec:
  restartPolicy: Always  # Контейнер перезапускається незалежно від коду виходу
  containers:
  - name: nginx
    image: nginx:1.14.2
    # Якщо цей контейнер аварійно завершить роботу або завершиться з будь-якої причини, його буде перезапущено

Приклад 2: Завдання пакетної обробки з restartPolicy: OnFailure

apiVersion: batch/v1
kind: Job
metadata:
  name: data-processor
spec:
  template:
    spec:
      restartPolicy: OnFailure  # Перезапускається лише за ненульового коду виходу
      containers:
      - name: processor
        image: busybox:1.28
        command: ['sh', '-c', 'echo "Processing data..."; exit 0']
        # Код виходу 0: Job успішно завершено, перезапуск не відбувається
        # Код виходу 1+: Контейнер перезапускається для повторної спроби завдання

Приклад 3: Одноразове завдання з restartPolicy: Never

apiVersion: v1
kind: Pod
metadata:
  name: migration-task
spec:
  restartPolicy: Never  # Ніколи не перезапускається, незалежно від коду виходу
  containers:
  - name: migrate
    image: busybox:1.28
    command: ['sh', '-c', 'echo "Running migration..."; exit 1']
    # Навіть із кодом виходу 1 (збій) контейнер не буде перезапущено
    # Pod залишиться в стані Failed
Sidecar-контейнери та політики перезапуску

Sidecar-контейнери мають особливу поведінку перезапуску, яка відрізняється від звичайних контейнерів застосунків:

  • Sidecar-контейнери ігнорують restartPolicy на рівні Podʼа: Вони використовують власне поле restartPolicy на рівні контейнера, яке завжди встановлено в Always
  • Незалежний життєвий цикл: Sidecar-контейнери можуть перезапускатися незалежно від основного контейнера застосунку
  • Постійна робота: Sidecar-контейнери продовжують працювати протягом усього часу життя Podʼа, надаючи допоміжні сервіси

Приклад: Pod із sidecar-контейнером

apiVersion: v1
kind: Pod
metadata:
  name: app-with-sidecar
spec:
  restartPolicy: OnFailure  # Застосовується лише до основного контейнера
  initContainers:
  - name: logging-sidecar    # Це sidecar-контейнер
    image: fluent/fluent-bit:1.8
    restartPolicy: Always    # Sidecar завжди перезапускається незалежно від коду виходу
    # Надає сервіси логування протягом усього часу життя Podʼа
  containers:
  - name: main-app          # Дотримується політики перезапуску на рівні Podʼа
    image: nginx:1.14.2
    # Перезапускається лише у разі помилки (ненульовий код виходу) через політику OnFailure Podʼа

Примітка:

Хоча основний контейнер застосунку дотримується політики restartPolicy: OnFailure на рівні Podʼа, sidecar-контейнер буде перезапущений незалежно від його коду виходу, оскільки sidecar-контейнери завжди мають restartPolicy: Always на рівні контейнера.

Коли kubelet обробляє перезапуск контейнера згідно з налаштованою політикою перезапуску, це стосується лише перезапусків, які призводять до заміни контейнерів всередині того ж Podʼа та на тому ж вузлі. Після завершення контейнерів у Podʼі kubelet перезапускає їх із затримкою, що зростає експоненційно (10 с, 20 с, 40 с, …), і обмеженою пʼятьма хвилинами (300 секунд). Якщо контейнер виконується протягом 10 хвилин без проблем, kubelet скидає таймер затримки перезапуску для цього контейнера. У розділі Sidecar-контейнери та життєвий цикл Podʼа пояснюється поведінка init containers, коли для них вказано поле restartPolicy.

Політика та правила перезапуску окремих контейнерів

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.35; (стандартно увімкнено)

Якщо у вашому кластері увімкнено функціональну можливість ContainerRestartRules, ви можете вказати restartPolicy та restartPolicyRules для окремих контейнерів, щоб перевизначити політику перезапуску Podʼа. Політика перезапуску контейнера та правила застосовуються до контейнерів застосунків в Podʼі та до звичайних init-контейнерів.

Нативний для Kubernetes sidecar-контейнер має restartPolicy на рівні контейнера, встановлену в Always.

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

  • Always: автоматично перезапускає контейнер після будь-якого завершення.
  • OnFailure: перезапускає контейнер тільки після його завершення з помилкою (код виходу відмінний від нуля).
  • Never: ніколи автоматично не перезапускає контейнер, що завершив роботу.

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

Наприклад, Pod з політикою перезапуску OnFailure, який має контейнер try-once. Це дозволяє Podʼу перезапускати лише певні контейнери:

apiVersion: v1
kind: Pod
metadata:
  name: on-failure-pod
spec:
  restartPolicy: OnFailure
  containers:
  - name: try-once-container    # Цей контейнер буде запущено лише один раз, оскільки політика перезапуску — Never.
    image: registry.k8s.io/busybox:1.27.2
    command: ['sh', '-c', 'echo "Only running once" && sleep 10 && exit 1']
    restartPolicy: Never
  - name: on-failure-container  # Цей контейнер буде перезапущено у разі збою.
    image: registry.k8s.io/busybox:1.27.2
    command: ['sh', '-c', 'echo "Keep restarting" && sleep 1800 && exit 1']

Pod з політикою перезапуску Always, який має init-контейнер, що виконується лише один раз. Якщо init-контейнер зазнає збою, Pod зазнає збою. Це дозволяє Podʼу завершитися зі збоєм, якщо ініціалізація не вдалася, але продовжувати працювати після успішної ініціалізації:

apiVersion: v1
kind: Pod
metadata:
  name: fail-pod-if-init-fails
spec:
  restartPolicy: Always
  initContainers:
  - name: init-once      # Цей init-контейнер спробує запуститися лише один раз. Якщо він зазнає збою, Pod зазнає збою.
    image: registry.k8s.io/busybox:1.27.2
    command: ['sh', '-c', 'echo "Failing initialization" && sleep 10 && exit 1']
    restartPolicy: Never
  containers:
  - name: main-container # Цей контейнер завжди перезапускатиметься після успішної ініціалізації.
    image: registry.k8s.io/busybox:1.27.2
    command: ['sh', '-c', 'sleep 1800 && exit 0']

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

apiVersion: v1
kind: Pod
metadata:
  name: restart-on-exit-codes
spec:
  restartPolicy: Never
  containers:
  - name: restart-on-exit-codes
    image: registry.k8s.io/busybox:1.27.2
    command: ['sh', '-c', 'sleep 60 && exit 0']
    restartPolicy: Never     # Політика перезапуску контейнера повинна бути вказана, якщо вказані правила
    restartPolicyRules:      # Перезапускати контейнер, лише якщо він завершується з кодом 42
    - action: Restart
      exitCodes:
        operator: In
        values: [42]

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

Перезапуск усіх контейнерів

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.36; (стандартно увімкнено)

Якщо у вашому кластері увімкнено функціональну можливість RestartAllContainersOnContainerExits, ви можете вказати RestartAllContainers як дію в restartPolicyRules на рівні контейнера. Коли завершення контейнера відповідає правилу з цією дією, весь Pod завершується і перезапускається на місці.

Такий перезапуск «на місці» є ефективнішим способом скидання стану Podʼа порівняно з повним видаленням і повторним створенням. Це особливо цінно для робочих навантажень, де перепланування є дорогим, наприклад, для пакетних завдань або завдань навчання AI/ML.

Як працюють перезапуски Podʼів на місці

Коли спрацьовує дія RestartAllContainers, kubelet виконує такі кроки:

  1. Швидке завершення: Усі запущені контейнери в Podʼі завершуються. Налаштований параметр terminationGracePeriodSeconds не враховується, а налаштовані хуки preStop не виконуються. Це забезпечує швидке вимкнення.
  2. Збереження ресурсів Podʼа: Основні ресурси Podʼа зберігаються:
    • UID Podʼа, IP-адреса та мережевий простір імен
    • Пісочниця Podʼа та будь-які підключені пристрої
    • Усі томи, включаючи томи emptyDir та змонтовані томи
  3. Оновлення статусу Podʼа: Статус Podʼа оновлюється: стан PodRestartInPlace встановлюється в True. Це робить процес перезапуску спостережуваним.
  4. Повна послідовність перезапуску: Після завершення роботи всіх контейнерів стан PodRestartInPlace встановлюється в False, і Pod починає стандартний процес запуску:
    • Init-контейнери запускаються повторно по черзі.
    • Запускаються sidecar-контейнери та звичайні контейнери.

Ключовим аспектом цієї можливості є те, що всі контейнери перезапускаються, включаючи ті, які раніше успішно завершилися або зазнали збою. Дія RestartAllContainers перевизначає будь-яку налаштовану restartPolicy на рівні контейнера або Podʼа.

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

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

Розглянемо робоче навантаження, де sidecar-спостерігач відповідає за перезапуск основного застосунку з відомого справного стану, якщо той натрапляє на помилку. Спостерігач може завершитися з певним кодом, щоб ініціювати повний перезапуск робочого Podʼа на місці.

apiVersion: v1
kind: Pod
metadata:
  name: ml-worker
spec:
  restartPolicy: Never # The pod itself should not restart unless explicitly told to.
  initContainers:
  - name: setup-environment
    image: registry.k8s.io/busybox:1.27.2
    command: ['sh', '-c', 'echo "Setting up environment"']
    # This init container runs once to prepare the environment.
    # It will run again after a RestartAllContainers action.
  - name: watcher-sidecar
    image: registry.k8s.io/busybox:1.27.2
    # In a real-world scenario, this would be a dedicated watcher image.
    # This command simulates the watcher exiting with a special code.
    command: ['sh', '-c', 'sleep 60; exit 88']
    restartPolicy: Always
    restartPolicyRules:
    - action: RestartAllContainers
      exitCodes:
        # Exit code 88 triggers a full pod restart.
        operator: In
        values: [88]
  containers:
  - name: main-application
    image: registry.k8s.io/busybox:1.27.2
    command: ['sh', '-c', 'echo "Application is running"; sleep 3600']

У цьому прикладі:

  • Загальна політика перезапуску Podʼа — Never.
  • watcher-sidecar виконує команду, а потім завершується з кодом 88.
  • Код завершення відповідає правилу, що запускає дію RestartAllContainers.
  • Потім весь Pod, включаючи init-контейнер setup-environment і контейнер main-application, перезапускається на місці. Pod зберігає свій UID, пісочницю, IP-адресу та томи.

Зменшена затримка перезапуску контейнера

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.33; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the ReduceDefaultCrashLoopBackOffDecay feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

З увімкненою альфа-функціональною можливістю ReduceDefaultCrashLoopBackOffDecay затримка повторних спроб запуску контейнера у вашому кластері починатиметься з 1 с (замість 10 с) і експоненційно зростатиме у 2 рази з кожним перезапуском до максимальної затримки 60 с (замість 300 с, тобто 5 хвилин).

Якщо ви використовуєте цю можливість з альфа-можливістю KubeletCrashLoopBackOffMax (описано нижче), окремі вузли можуть мати різні значення максимальної затримки.

Налаштовувана затримка перезапуску контейнера

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.35; (стандартно увімкнено)

З увімкненою функціональною можливістю KubeletCrashLoopBackOffMax ви можете змінити максимальну затримку між повторними спробами запуску контейнера, яка стандартно становить 300 секунд (5 хвилин). Ця конфігурація встановлюється для кожного вузла за допомогою конфігурації kubelet. У вашій конфігурації kubelet у полі crashLoopBackOff встановіть значення поля maxContainerRestartPeriod між "1s" і "300s". Як описано вище у Політиці перезапуску контейнерів, затримки на цьому вузлі все одно починатимуться з 10 секунд і збільшуватимуться експоненційно у 2 рази з кожним перезапуском, але тепер вони будуть обмежені вашим налаштованим максимумом. Якщо значення maxContainerRestartPeriod, яке ви налаштували, менше початкового стандартного значення у 10 секунд, початкову затримку буде встановлено на налаштоване максимальне значення.

Дивіться такі приклади налаштування kubelet:

# затримки перезапуску контейнерів починаються з 10 секунд і збільшуються
# у 2 рази з кожним перезапуском, максимум до 100 с
kind: KubeletConfiguration
crashLoopBackOff:
    maxContainerRestartPeriod: "100s"
# затримки між перезапусками контейнера завжди будуть дорівнювати 2 с
kind: KubeletConfiguration
crashLoopBackOff:
    maxContainerRestartPeriod: "2s"

Якщо ви використовуєте цю можливість разом з альфа-можливістю ReduceDefaultCrashLoopBackOffDecay (описано вище), стандартні значення кластера для початкової та максимальної затримки будуть уже не 10 і 300 секунд, а 1 і 60 секунд. Конфігурація для кожного вузла має пріоритет над стандартними значеннями, встановленими ReduceDefaultCrashLoopBackOffDecay, навіть якщо це призведе до того, що вузол матиме довшу максимальну затримку, ніж інші вузли у кластері.

Стани Podʼа

Pod має PodStatus, який містить масив PodConditions, через які Pod пройшов або не пройшов. Kubelet керує такими PodConditions:

  • PodScheduled: Pod заплановано на вузол.
  • PodReadyToStartContainers: пісочницю Podʼа успішно створено, мережу налаштовано, томи зберігання змонтовано, а будь-які динамічні ресурси (якщо їх запитано) виділено.
  • ContainersReady: всі контейнери в Podʼі готові.
  • Initialized: всі init-контейнери успішно завершили виконання.
  • Ready: Pod може обслуговувати запити і його слід додати до пулів балансування навантаження всіх відповідних Services.
  • DisruptionTarget: Pod скоро буде завершено через переривання роботи (наприклад, витіснення, виселення або збір сміття).
  • PodResizePending: було запитано зміну розміру Podʼа, але її неможливо застосувати. Дивіться Статус зміни розміру Podʼа.
  • PodResizeInProgress: Pod перебуває в процесі зміни розміру. Дивіться Статус зміни розміру Podʼа.
Назва поляОпис
typeНазва цього стану Podʼа.
statusВказує, чи застосовується цей стан, з можливими значеннями "True", "False" або "Unknown".
lastProbeTimeМітка часу останньої перевірки стану Podʼа.
lastTransitionTimeМітка часу останнього переходу Podʼа з одного статусу в інший.
reasonМашиночитаний текст у форматі UpperCamelCase, який вказує причину останнього переходу стану.
messageЗрозуміле людині повідомлення з подробицями щодо останнього переходу статусу.

Готовність Podʼа

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.14

Ваш застосунок може внести додатковий зворотний звʼязок або сигнали в PodStatus: готовність Podʼа. Щоб використовувати це, встановіть readinessGates в spec Podʼа, щоб вказати список додаткових станів, які kubelet оцінює для визначення готовності Podʼа.

Шлюзи готовності (readiness gates) визначаються поточним станом полів status.condition Podʼа. Якщо Kubernetes не може знайти такий стан у полі status.conditions Podʼа, статус цього стану стандартно вважається "False".

Наприклад:

kind: Pod
...
spec:
  readinessGates:
    - conditionType: "www.example.com/feature-1"
status:
  conditions:
    - type: Ready                              # вбудований стан Podʼа
      status: "False"
      lastProbeTime: null
      lastTransitionTime: 2018-01-01T00:00:00Z
    - type: "www.example.com/feature-1"        # додатковий стан Podʼа
      status: "False"
      lastProbeTime: null
      lastTransitionTime: 2018-01-01T00:00:00Z
  containerStatuses:
    - containerID: docker://abcd...
      ready: true
...

Стани Podʼа, які ви додаєте, повинні мати назви, що відповідають формату ключа міток Kubernetes.

Статус для готовності Podʼа

Команда kubectl patch не підтримує зміну статусу обʼєкта накладанням патчів. Щоб встановити ці status.conditions для Podʼа, застосунки та оператори повинні використовувати дію PATCH. Ви можете використовувати клієнтську бібліотеку Kubernetes для написання коду, який встановлює власні стани Podʼа для готовності Podʼа.

Pod, який використовує власні стани, оцінюється як готовий лише тоді, коли істинні обидва такі твердження:

  • Всі контейнери в Podʼі готові.
  • Усі стани, вказані в readinessGates, мають значення True.

Коли контейнери Podʼа перебувають у стані Ready, але принаймні один власний стан відсутній або має значення False, kubelet встановлює стан Podʼа в ContainersReady.

Готовність Podʼа до запуску контейнерів

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.37

Примітка:

На ранніх етапах розробки цей стан називали PodHasNetwork.

Після того, як Pod заплановано на вузол, kubelet має його допустити, а всі необхідні томи зберігання мають бути змонтовані. Щойно ці фази завершаться, kubelet працює із середовищем виконання контейнерів (використовуючи Container Runtime Interface (CRI)), щоб налаштувати пісочницю середовища виконання та мережу для Podʼа. Якщо Pod використовує Динамічне виділення ресурсів, ці ресурси також виділяються під час цієї фази. Стан PodReadyToStartContainers додається до поля status.conditions Podʼа.

Kubelet встановлює цей стан в False, коли виявляє, що Pod не має пісочниці середовища виконання з налаштованою мережею. Це трапляється в таких випадках:

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

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

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

Зміна розміру Podʼів

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.35
More information about this feature

This is a stable feature in Kubernetes, and has been since version v1.35. It was first available in the v1.27 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate InPlacePodVerticalScaling, Kubernetes ignores it but does not report any error.

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.36; (стандартно увімкнено)

Kubernetes підтримує зміну ресурсів CPU та памʼяті, виділених для Podʼів, після їх створення. (Для інших ресурсів інфраструктури потрібно використовувати інші методи, специфічні для цих ресурсів.) Існує два основні підходи до зміни розміру CPU та памʼяті:

Зміна розміру Podʼа на місці

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

Якщо ви вказали ресурси на рівні Podʼа, ви також можете змінювати їх на місці. Для отримання додаткової інформації див. Зміна розміру CPU та памʼяті, призначених Podʼам.

Щоб виконати зміну розміру на місці, оновіть бажаний стан Podʼа за допомогою субресурсу /resize. Kubelet спробує застосувати нові значення ресурсів до контейнерів, що працюють. Стани Podʼа PodResizePending та PodResizeInProgress (описані в розділі Стани Podʼа) вказують на статус операції зміни розміру. Для отримання додаткової інформації про статус зміни розміру див. Статус зміни розміру контейнера.

Основні моменти, які слід враховувати під час зміни розміру на місці:

  • На місці можна змінювати розмір лише ресурсів CPU та памʼяті.
  • Клас якості обслуговування (QoS) Podʼа визначається під час створення і не може бути змінений шляхом зміни розміру.
  • Ви можете налаштувати, чи потрібно перезапускати контейнер для зміни розміру, використовуючи resizePolicy у специфікації контейнера.

Детальні інструкції щодо зміни розміру на місці див. Зміна розміру CPU та памʼяті, призначених контейнерам.

Зміна розміру шляхом запуску Podʼів-замінників

Більш cloud native підхід до зміни ресурсів Podʼа полягає у використанні ресурсу робочого навантаження, який ним керує (наприклад, Deployment або StatefulSet). Коли ви оновлюєте специфікації ресурсів у шаблоні Podʼа, контролер робочого навантаження створює нові Podʼи з оновленими ресурсами та завершує старі Podʼи відповідно до своєї стратегії оновлення.

Цей підхід:

  • Працює з будь-якою версією Kubernetes.
  • Може змінювати будь-яку специфікацію Podʼа, а не тільки ресурси.
  • Призводить до заміни Podʼа, тому вам слід спроєктувати робоче навантаження таким чином, щоб воно могло обробляти заплановані переривання роботи. Розгляньте можливість використання PodDisruptionBudget для контролю доступності.
  • Вимагає, щоб вашими Podʼами керував ресурс робочого навантаження.

Ви також можете використовувати VerticalPodAutoscaler для автоматичного керування рекомендаціями та оновленнями ресурсів Podʼів.

Проби контейнерів

Kubernetes дозволяє визначати проби для безперервного моніторингу стану контейнерів у Podʼі. Проба — це діагностика, яку періодично виконує kubelet для контейнера. Для виконання діагностики kubelet або виконує код всередині контейнера, або виконує мережевий запит.

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

Kubelet може за бажанням виконувати три типи проб для запущених контейнерів і реагувати на них, кожен із цих типів має своє призначення. Для механізмів проб (exec, grpc, httpGet, tcpSocket), полів конфігурації та детальних рекомендацій щодо використання дивіться Проби життєздатності, готовності та запуску.

Проба запуску

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

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

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

Проба життєздатності

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

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

Проба готовності

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

Якщо проба готовності повертає невдалий результат, контролер EndpointSlice видаляє IP-адресу Podʼа з EndpointSlices усіх Services, які відповідають Podʼу.

Проби готовності виконуються в контейнері протягом усього його життєвого циклу.

Завершення роботи Podʼів

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

Мета дизайну полягає в тому, щоб ви могли запитувати видалення і знати, коли процеси завершуються, а також мати можливість гарантувати, що видалення врешті-решт завершиться. Коли ви запитуєте видалення Podʼа, кластер реєструє та відстежує призначений період коректного завершення до того, як буде дозволено примусово знищити Pod. Завдяки цьому відстеженню примусового вимкнення kubelet намагається виконати коректне вимкнення.

Зазвичай під час такого коректного завершення роботи Podʼа kubelet надсилає запити до середовища виконання контейнерів, щоб спробувати зупинити контейнери в Podʼі, спочатку надсилаючи сигнал TERM (також відомий як SIGTERM) основному процесу в кожному контейнері з тайм-аутом періоду коректного завершення. Запити на зупинку контейнерів обробляються середовищем виконання контейнерів асинхронно. Порядок обробки цих запитів не гарантується. Багато середовищ виконання контейнерів враховують значення STOPSIGNAL, визначене в образі контейнера і, якщо воно відрізняється, надсилають значення STOPSIGNAL, визначене в образі контейнера, замість TERM. Після закінчення періоду коректного завершення сигнал KILL надсилається всім залишковим процесам, а потім Pod видаляється з API-сервера. Якщо kubelet або сервіс керування середовищем виконання контейнерів перезапускається під час очікування завершення процесів, кластер повторює спробу спочатку, включаючи повний початковий період коректного завершення.

Сигнали зупинки

Сигнал зупинки, який використовується для завершення роботи контейнера, може бути визначено в образі контейнера за допомогою інструкції STOPSIGNAL. Якщо в образі контейнера не визначено жодного сигналу зупинки, для завершення роботи контейнера буде використано стандартний сигнал середовища виконання контейнерів (SIGTERM як для containerd, так і для CRI-O).

Визначення власних сигналів зупинки

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.33; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the ContainerStopSignals feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Якщо увімкнено функціональну можливість ContainerStopSignals, ви можете налаштувати власний сигнал зупинки для ваших контейнерів з життєвого циклу контейнера. Щоб визначати сигнали зупинки в життєвому циклі контейнера, поле spec.os.name Podʼа має бути заданим. Перелік допустимих сигналів залежить від ОС, на яку заплановано Pod. Для Podʼів, запланованих на вузли Windows, ми підтримуємо тільки SIGTERM і SIGKILL як допустимі сигнали.

Ось приклад специфікації Podʼа, що визначає власний сигнал зупинки:

spec:
  os:
    name: linux
  containers:
    - name: my-container
      image: container-image:latest
      lifecycle:
        stopSignal: SIGUSR1

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

Порядок завершення роботи Podʼа

Порядок завершення роботи Podʼа на прикладі:

  1. Ви використовуєте інструмент kubectl, щоб вручну видалити певний Pod, зі стандартним періодом коректного завершення (30 секунд).

  2. Pod в API-сервері оновлюється: записується час, після якого Pod вважається «мертвим», разом із періодом коректного завершення. Якщо ви використовуєте kubectl describe для перевірки Podʼа, який ви видаляєте, цей Pod показується як «Terminating». На вузлі, де працює Pod: щойно kubelet бачить, що Pod позначено як такий, що завершує роботу (встановлено тривалість коректного вимкнення), kubelet розпочинає локальний процес вимкнення Podʼа.

    1. Якщо один із контейнерів Podʼа має визначений хук preStop і terminationGracePeriodSeconds у специфікації Podʼа не встановлено в 0, kubelet виконує цей хук всередині контейнера. Стандартне значення terminationGracePeriodSeconds — 30 секунд.

      Якщо хук preStop все ще виконується після закінчення періоду коректного завершення, kubelet запитує невелике одноразове подовження цього періоду на 2 секунди.

      Примітка:

      Якщо хуку preStop потрібно більше часу для завершення, ніж дозволяє стандартний період коректного завершення, вам слід змінити terminationGracePeriodSeconds відповідно до цього.
    2. Kubelet ініціює надсилання середовищем виконання контейнерів сигналу TERM процесу 1 всередині кожного контейнера.

      Є спеціальний порядок, якщо для Podʼа вказані будь-які sidecar-контейнери. В іншому випадку контейнери в Podʼі отримують сигнал TERM у різний час і в довільному порядку. Якщо порядок завершення роботи має значення, розгляньте можливість використання хука preStop для синхронізації (або перейдіть на використання sidecar-контейнерів).

  3. Одночасно з тим, як kubelet розпочинає коректне вимкнення Podʼа, панель управління оцінює, чи слід вилучити цей Pod, що вимикається, з обʼєктів EndpointSlice, де ці обʼєкти представляють Service із налаштованим селектором. ReplicaSets та інші ресурси робочого навантаження більше не вважають такий Pod дійсною реплікою, що обслуговує запити.

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

    Будь-які точки доступу, які представляють Podʼи, що завершують роботу, не вилучаються негайно з EndpointSlices, а статус, який вказує на стан завершення, надається через API EndpointSlice. Точки доступу, що завершують роботу, завжди мають статус ready зі значенням false (для зворотної сумісності з версіями до 1.26), тому балансувальники навантаження не використовуватимуть їх для звичайного трафіку.

    Якщо потрібне очищення трафіку на Podʼі, що завершує роботу, фактичну готовність можна перевірити за станом serving. Докладніше про те, як реалізувати очищення зʼєднань, можна дізнатися в навчальному матеріалі Порядок завершення роботи Podʼів та Endpointʼів

  4. kubelet забезпечує завершення та вимкнення Podʼа.

    1. Коли період коректного завершення спливає, а в Podʼі все ще працює якийсь контейнер, kubelet ініціює примусове вимкнення. Середовище виконання контейнерів надсилає SIGKILL усім процесам, які ще працюють у будь-якому контейнері в Podʼі. Kubelet також прибирає прихований контейнер pause, якщо це середовище виконання контейнерів його використовує.
    2. kubelet переводить Pod у термінальну фазу (Failed або Succeeded залежно від кінцевого стану його контейнерів).
    3. kubelet ініціює примусове видалення обʼєкта Pod з API-сервера, встановлюючи період коректного завершення в 0 (негайне видалення).
    4. API-сервер видаляє API-обʼєкт Podʼа, який після цього більше не видимий для жодного клієнта.

Примусове завершення Podʼів

Увага:

Примусове видалення може потенційно порушити роботу деяких робочих навантажень та їхніх Podʼів.

Стандартно всі видалення є коректними протягом 30 секунд. Команда kubectl delete підтримує опцію --grace-period=<seconds>, яка дозволяє перевизначити стандартне значення власним.

Встановлення періоду коректного завершення в 0 примусово та негайно видаляє Pod з API-сервера. Якщо Pod все ще працював на вузлі, це примусове видалення змушує kubelet негайно розпочати прибирання.

Використовуючи kubectl, ви повинні вказати додатковий прапорець --force разом із --grace-period=0, щоб виконати примусове видалення.

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

Увага:

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

Якщо вам потрібно примусово видалити Podʼи, які є частиною StatefulSet, дивіться документацію для видалення Podʼів з StatefulSet.

Завершення роботи Podʼа та sidecar-контейнери

Якщо ваш Pod містить один або більше sidecar-контейнерів (init-контейнерів з політикою перезапуску Always), kubelet затримає надсилання сигналу TERM цим sidecar-контейнерам, доки останній основний контейнер повністю не завершить роботу. Sidecar-контейнери будуть завершені у зворотному порядку, в якому вони визначені в специфікації Podʼа. Це забезпечує продовження обслуговування sidecar-контейнерами інших контейнерів у Podʼі, доки вони не стануть непотрібними.

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

Аналогічно, якщо Pod має хук preStop, який перевищує період коректного завершення, може статися аварійне завершення. Загалом, якщо ви використовували хуки preStop для керування порядком завершення без sidecar-контейнерів, тепер ви можете видалити їх і дозволити kubelet автоматично керувати завершенням роботи sidecar-контейнерів.

Збір сміття Podʼів

Для Podʼів, що завершилися зі збоєм, обʼєкти API залишаються в API кластера, поки людина чи контролер явно їх не видалять.

Збирач сміття Podʼів (PodGC), який є контролером панелі управління, прибирає завершені Podʼи (з фазою Succeeded або Failed), коли кількість Podʼів перевищує налаштований поріг (визначений параметром terminated-pod-gc-threshold в kube-controller-manager). Це запобігає витоку ресурсів під час створення та завершення Podʼів з часом.

Крім того, PodGC очищує будь-які Podʼи, які відповідають одній з таких умов:

  1. є осиротілими Podʼами — привʼязаними до вузла, якого вже не існує,
  2. є незапланованими Podʼами у стані завершення,
  3. є Podʼами у стані завершення, привʼязаними до неготового вузла з taint node.kubernetes.io/out-of-service.

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

Поведінка Podʼа під час перезапуску kubelet

Якщо ви перезапускаєте kubelet, Podʼи (та їхні контейнери) продовжують працювати навіть під час перезапуску. Коли на вузлі працюють Podʼи, зупинка або перезапуск kubelet на цьому вузлі не призводить до того, що kubelet зупиняє всі локальні Podʼи перед тим, як зупинитися сам. Щоб зупинити Podʼи на вузлі, ви можете використовувати kubectl drain.

Виявлення перезапусків kubelet

СТАН ФУНКЦІОНАЛУ: Deprecated since Kubernetes v1.35; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the ChangeContainerStatusOnKubeletRestart feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Коли kubelet запускається, він перевіряє, чи є вже вузол із привʼязаними Podʼами. Якщо стан Ready вузла залишається незмінним, тобто стан не змінився з true на false, Kubernetes виявляє це як перезапуск kubelet. (Можна перезапустити kubelet іншими способами, наприклад, щоб виправити помилку вузла, але в таких випадках Kubernetes вибирає безпечний варіант і розглядає це як зупинку kubelet, а потім його запуск).

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

  • Стандартно kubelet не змінює статуси контейнерів після перезапуску. Контейнери, для яких було встановлено ready: true, залишаються готовими.

    Якщо ви зупините kubelet на достатньо довгий час, щоб він не пройшов серію перевірок пульсу вузла, а потім зачекаєте, перш ніж знову запустити kubelet, Kubernetes може почати виселяти Podʼи з цього вузла. Однак, навіть якщо виселення Podʼів починається, Kubernetes не позначає окремі контейнери в цих Podʼах як ready: false. Виселення на рівні Podʼа відбувається після того, як панель управління додає вузлу taint node.kubernetes.io/not-ready (через провал перевірок пульсу).

  • У Kubernetes 1.37 ви можете вибрати стару поведінку, за якої kubelet завжди змінює значення контейнерів ready після перезапуску kubelet на false.

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

Що далі

2 - Стани Podʼа

У Kubernetes багато обʼєктів мають стани (conditions). Стан — це показник певного аспекту фактичного становища того, що представляє обʼєкт. Podʼи мають стани, і стани Podʼів у Kubernetes є важливим аспектом, що дозволяє контролерам (а також тим, хто займається усуненням несправностей) оцінювати справність Podʼів.

Фаза Podʼа надає високорівневий огляд того, на якому етапі життєвого циклу перебуває Pod, але одне значення не може показати повну картину. Наприклад, Pod може перебувати у фазі Running, але не бути готовим до обслуговування трафіку. Стани Podʼа доповнюють фазу, відстежуючи незалежно один від одного різні аспекти статусу Podʼа, наприклад, чи було його заплановано, чи готові його контейнери, чи триває зміна розміру, або чи буде робота Podʼа незабаром перервана через taint.

Структура стану Podʼа

Статус Podʼа включає масив PodConditions, які вказують, чи пройшов Pod певні контрольні точки.

Кожен елемент масиву PodCondition має такі поля:

Поля PodCondition
ПолеОпис
typeНазва стану Podʼа.
statusВказує, чи застосовний цей стан, з можливими значеннями "True", "False" або "Unknown".
lastProbeTimeЧас останньої перевірки стану Podʼа.
lastTransitionTimeЧас останнього переходу Podʼа з одного стану в інший.
reasonТекст у форматі UpperCamelCase, придатний для машинного зчитування, що вказує причину останнього переходу стану.
messageПовідомлення, придатне для сприйняття людиною, що містить детальну інформацію про останній перехід стану.
observedGeneration.metadata.generation Podʼа на момент запису стану. Див. Генерація Podʼа.

Вбудовані стани Podʼа

Kubernetes керує такими станами Podʼа:

Стани життєвого циклу: встановлюються під час проходження Podʼом свого життєвого циклу, приблизно в такому порядку: PodScheduled, PodReadyToStartContainers, Initialized, ContainersReady, Ready.

Інші стани: встановлюються у відповідь на конкретні операції або події: DisruptionTarget, PodResizePending, PodResizeInProgress.

Крім вбудованих станів, ви можете визначати власні стани за допомогою шлюзів готовності Podʼа (readiness gates).

Стани життєвого циклу Podʼа

У міру проходження Podʼом свого життєвого циклу kubelet встановлює такі стани приблизно в такому порядку:

  1. PodScheduled: Pod було заплановано на вузол.
  2. PodReadyToStartContainers: пісочницю Podʼа було успішно створено та налаштовано мережу. Пісочницю та мережу налаштовують середовище виконання контейнерів та втулок CNI.
  3. Initialized: всі init-контейнери успішно завершилися. Для Podʼа без init-контейнерів встановлюється в True перед створенням пісочниці.
  4. ContainersReady: всі контейнери в Podʼі готові. Готовність контейнера визначається його пробою готовності, якщо вона налаштована.
  5. Ready: Pod здатний обслуговувати запити і повинен бути доданий до пулів балансування навантаження всіх відповідних Services. Podʼи, які не є Ready, видаляються з точок доступу Service.

Примітка:

Стан Ready залежить не лише від ContainersReady. Якщо Pod вказує readinessGates, всі ці власні стани також повинні бути True, щоб Pod був Ready. Див. Готовність Podʼа для деталей.

Ви можете перевірити стани Podʼа за допомогою kubectl:

kubectl get pod <pod-name> -o yaml

Цей вивід показує, як виглядає поле status.conditions для запущеного Podʼа:

status:
  conditions:
    - type: PodScheduled
      status: "True"
      lastProbeTime: null
      lastTransitionTime: "2026-03-29T08:52:21Z"
      observedGeneration: 1
    - type: PodReadyToStartContainers
      status: "True"
      lastProbeTime: null
      lastTransitionTime: "2026-04-11T06:02:16Z"
      observedGeneration: 1
    - type: Initialized
      status: "True"
      lastProbeTime: null
      lastTransitionTime: "2026-03-29T08:52:21Z"
      observedGeneration: 1
    - type: ContainersReady
      status: "True"
      lastProbeTime: null
      lastTransitionTime: "2026-04-11T06:02:45Z"
      observedGeneration: 1
    - type: Ready
      status: "True"
      lastProbeTime: null
      lastTransitionTime: "2026-04-11T06:02:45Z"
      observedGeneration: 1

PodReadyToStartContainers

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.37
More information about this feature

This is a stable feature in Kubernetes, and has been since version v1.37. It was first available in the v1.28 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate PodReadyToStartContainersCondition, Kubernetes ignores it but does not report any error.

Примітка:

Під час ранньої розробки цей стан називався PodHasNetwork.

Після того, як Pod заплановано на вузол, kubelet має його допустити, а всі необхідні томи зберігання мають бути змонтовані. Після завершення цих фаз kubelet працює із середовищем виконання контейнерів (використовуючи Container Runtime Interface, CRI), щоб налаштувати пісочницю середовища виконання та мережу для Podʼа. Стан PodReadyToStartContainers додається до поля status.conditions Podʼа.

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

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

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

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

Інші стани Podʼа

Такі стани не є частиною нормального проходження життєвого циклу Podʼа. Вони встановлюються у відповідь на конкретні операції або події.

DisruptionTarget

Спеціальний стан Podʼа DisruptionTarget додається для того, щоб вказати, що Pod буде видалено через переривання роботи. Поле reason цього стану додатково вказує одну з таких причин завершення Podʼа:

PreemptionByScheduler
Pod підлягає витісненню планувальником, щоб звільнити місце для нового Podʼа з вищим пріоритетом. Для отримання додаткової інформації див. Пріоритет та витіснення Podʼів.
DeletionByTaintManager
Pod підлягає видаленню менеджером Taint (який є частиною контролера життєвого циклу вузла в kube-controller-manager) через NoExecute taint, який Pod не толерує; див. виселення на основі taint.
EvictionByEvictionAPI
Pod підлягає виселенню за допомогою API Kubernetes.
DeletionByPodGC
Pod, який привʼязаний до вузла, що більше не існує, підлягає видаленню за допомогою механізму збору сміття Podʼів.
TerminationByKubelet
Pod було завершено kubelet через виселення внаслідок тиску на вузол, коректне вимкнення вузла або витіснення заради системно критичних Podʼів.

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

Примітка:

Процес переривання роботи Podʼа може бути зупинено. Панель управління може повторно спробувати продовжити переривання роботи того самого Podʼа, але це не гарантовано. В результаті стан DisruptionTarget може бути додано до Podʼа, але цей Pod може фактично не бути видаленим. У такій ситуації через деякий час стан переривання роботи Podʼа буде очищено.

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

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

Для отримання додаткової інформації див. Переривання роботи.

PodResizePending та PodResizeInProgress

Kubelet оновлює стани Podʼа, щоб вказати статус запиту на зміну розміру:

  • type: PodResizePending: Kubelet не може негайно виконати запит. Поле message надає пояснення, чому.
    • reason: Infeasible: Запитана зміна розміру неможлива на поточному вузлі (наприклад, запит більше ресурсів, ніж є на вузлі).
    • reason: Deferred: Запитана зміна розміру наразі неможлива, але може стати можливою пізніше (наприклад, якщо інший Pod буде видалено). Kubelet повторно спробує зміну розміру.
  • type: PodResizeInProgress: Kubelet прийняв зміну розміру та виділив ресурси, але зміни ще застосовуються. Зазвичай це триває недовго, але може зайняти більше часу залежно від типу ресурсу та поведінки середовища виконання. Будь-які помилки під час виконання повідомляються у полі message (разом з reason: Error).

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

Докладніше див. Зміна розміру CPU та памʼяті, призначених контейнерам.

Розширена готовність Podʼів

Ваш застосунок може додавати додаткові відгуки або сигнали в .status Podʼа; це відомо як розширена готовність Podʼів. Щоб використовувати це, встановіть readinessGates у spec Podʼа, щоб вказати список додаткових станів, які kubelet оцінює для готовності Podʼа. Потім ви реалізуєте або встановлюєте контролер, який керує цими власними станами, і kubelet використовує це як додаткове вхідне значення для визначення готовності Podʼа.

Шлюзи готовності (readiness gates) визначаються поточним станом полів status.condition для Podʼа. Якщо Kubernetes не може знайти такий стан у полі status.conditions Podʼа, його статус стандартно дорівнює "False".

kind: Pod
...
spec:
  readinessGates:
    - conditionType: "www.example.com/feature-1"
status:
  conditions:
    - type: Ready                              # вбудована PodCondition
      status: "False"
      lastProbeTime: null
      lastTransitionTime: 2018-01-01T00:00:00Z
    - type: "www.example.com/feature-1"        # додаткова PodCondition
      status: "False"
      lastProbeTime: null
      lastTransitionTime: 2018-01-01T00:00:00Z
  containerStatuses:
    - containerID: docker://abcd...
      ready: true
...

Стани Podʼа, які ви додаєте, повинні мати назви, що відповідають формату ключів міток Kubernetes.

Статус готовності Podʼа

Щоб встановити ці status.conditions для Podʼа, застосунки та оператори повинні використовувати дію PATCH на субресурсі статусу Podʼа. Ви можете використовувати kubectl patch з --subresource=status, або бібліотеку клієнта Kubernetes, щоб написати код, який встановлює власні стани Podʼа для готовності Podʼа.

Pod, який використовує власні стани, вважається готовим тільки тоді, коли виконуються обидва такі твердження:

  • Всі контейнери в Podʼі готові.
  • Усі стани, зазначені в readinessGates, мають значення True.

Коли контейнери Podʼа готові, але принаймні один власний стан відсутній або має значення False, kubelet встановлює стан Ready Podʼа в status: "False" з reason: ReadinessGatesNotReady.

Що далі

3 - Init-контейнери

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

Ви можете вказати init-контейнери в специфікації Podʼа разом із масивом containers (який описує контейнери застосунку).

У Kubernetes sidecar-контейнер — це контейнер, який запускається перед основним контейнером застосунку і продовжує працювати. Цей документ стосується init-контейнерів — контейнерів, які виконуються до завершення під час ініціалізації Podʼа.

Що таке init-контейнери

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

Init-контейнери точно такі самі, як і звичайні контейнери, за винятком того, що:

  • Init-контейнери завжди виконуються до завершення.
  • Кожен init-контейнер повинен успішно завершити свою роботу, перш ніж почне роботу наступний.

Якщо init-контейнер Podʼа зазнає збою, kubelet повторно перезапускає цей init-контейнер, доки він не завершиться успішно. Однак якщо restartPolicy Podʼа дорівнює Never, і init-контейнер зазнає збою під час запуску цього Podʼа, Kubernetes вважає весь Pod невдалим.

Щоб вказати init-контейнер для Podʼа, додайте поле initContainers у специфікацію Podʼа, у вигляді масиву обʼєктів container (аналогічно полю containers застосунку та його вмісту). Дивіться Container в довідці API для отримання докладнішої інформації.

Статус init-контейнерів повертається у полі .status.initContainerStatuses у вигляді масиву статусів контейнерів (аналогічно полю .status.containerStatuses).

Відмінності від звичайних контейнерів

Init-контейнери підтримують всі поля та можливості контейнерів застосунків, включаючи обмеження ресурсів, томи та налаштування безпеки. Однак запити та обмеження ресурсів для init-контейнера обробляються по-іншому, як описано в розділі Спільне використання ресурсів всередині контейнерів.

Звичайні init-контейнери (іншими словами, виключаючи sidecar-контейнери) не підтримують поля lifecycle, livenessProbe, readinessProbe чи startupProbe. Init-контейнери повинні успішно завершити свою роботу перед тим, як Pod може бути готовий; sidecar-контейнери продовжують працювати протягом життєвого циклу Podʼа і підтримують деякі проби. Дивіться sidecar-контейнер для отримання додаткової інформації про ці контейнери.

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

Відмінності від sidecar-контейнерів

Init-контейнери запускаються і завершують свої завдання до того, як розпочнеться робота основного контейнера застосунку. На відміну від sidecar-контейнерів, init-контейнери не продовжують працювати паралельно з основними контейнерами.

Init-контейнери запускаються і завершують свою роботу послідовно, і основний контейнер не починає свою роботу, доки всі init-контейнери успішно не завершать свою роботу.

Init-контейнери не підтримують lifecycle, livenessProbe, readinessProbe чи startupProbe, у той час, як sidecar-контейнери підтримують всі ці проби, щоб керувати своїм життєвим циклом.

Init-контейнери використовують ті самі ресурси (CPU, памʼять, мережу), що й основні контейнери застосунків, але не взаємодіють з ними напряму. Однак вони можуть використовувати спільні томи для обміну даними.

Використання init-контейнерів

Оскільки init-контейнери мають образи, окремі від контейнерів застосунків, вони мають кілька переваг для коду, повʼязаного із запуском:

  • Init-контейнери можуть містити утиліти або власний код для налаштування, які відсутні в образі застосунку. Наприклад, немає потреби створювати образ FROM іншого образу лише для використання інструменту, такого як sed, awk, python чи dig під час налаштування.
  • Ролі створення та розгортання образу застосунку можуть працювати незалежно одна від одної без необхідності спільного створення єдиного образу застосунку.
  • Init-контейнери можуть працювати з іншим поданням файлової системи, ніж контейнери застосунків у тому самому Podʼі. Отже, їм можна надати доступ до Secrets, до яких контейнери застосунків не мають доступу.
  • Оскільки init-контейнери завершують свою роботу, перш ніж будь-які контейнери застосунків розпочнуть свою роботу, вони пропонують механізм блокування або затримки запуску контейнера застосунку до виконання певних умов. Після того, як умови виконані, всі контейнери застосунків у Podʼі можуть стартувати паралельно.
  • Init-контейнери можуть безпечно виконувати утиліти або власний код, який інакше зробив би образ контейнера застосунку менш безпечним. Відокремлюючи непотрібні інструменти, ви можете обмежити поверхню атаки вашого образу контейнера застосунку.

Приклади

Ось кілька ідей, як використовувати init-контейнери:

  • Очікування на створення Service, використовуючи команду оболонки у вигляді одного рядка, наприклад:

    for i in {1..100}; do sleep 1; if nslookup myservice; then exit 0; fi; done; exit 1
    
  • Реєстрація Podʼа на віддаленому сервері зі значеннями, отриманими з Downward API за допомогою команди, подібної цій:

    curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'
    
  • Очікування певного часу перед запуском контейнера застосунку за допомогою команди, подібної цій:

    sleep 60
    
  • Клонування репозиторію Git у том

  • Додавання значень у файл конфігурації та виклик інструменту шаблонування для динамічного створення файлу конфігурації для основного контейнера застосунку. Наприклад, додайте значення POD_IP у конфігурацію та створіть основний файл конфігурації застосунку за допомогою Jinja.

Init-контейнери в роботі

У цьому прикладі визначається простий Pod, який має два init-контейнери. Перший чекає на myservice, а другий — на mydb. Як тільки обидва init-контейнери завершаться, Pod запускає контейнер застосунку зі свого розділу spec.

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app.kubernetes.io/name: MyApp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]

Ви можете запустити цей Pod, виконавши:

kubectl apply -f myapp.yaml

Вивід буде подібний до цього:

pod/myapp-pod created

І перевірте його статус за допомогою:

kubectl get -f myapp.yaml

Вивід буде подібний до цього:

NAME        READY     STATUS     RESTARTS   AGE
myapp-pod   0/1       Init:0/2   0          6m

або докладніше:

kubectl describe -f myapp.yaml

Вивід буде подібний до цього:

Name:          myapp-pod
Namespace:     default
[...]
Labels:        app.kubernetes.io/name=MyApp
Status:        Pending
[...]
Init Containers:
  init-myservice:
[...]
    State:         Running
[...]
  init-mydb:
[...]
    State:         Waiting
      Reason:      PodInitializing
    Ready:         False
[...]
Containers:
  myapp-container:
[...]
    State:         Waiting
      Reason:      PodInitializing
    Ready:         False
[...]
Events:
  FirstSeen    LastSeen    Count    From                      SubObjectPath                           Type          Reason        Message
  ---------    --------    -----    ----                      -------------                           --------      ------        -------
  16s          16s         1        {default-scheduler }                                              Normal        Scheduled     Successfully assigned myapp-pod to 172.17.4.201
  16s          16s         1        {kubelet 172.17.4.201}    spec.initContainers{init-myservice}     Normal        Pulling       pulling image "busybox"
  13s          13s         1        {kubelet 172.17.4.201}    spec.initContainers{init-myservice}     Normal        Pulled        Successfully pulled image "busybox"
  13s          13s         1        {kubelet 172.17.4.201}    spec.initContainers{init-myservice}     Normal        Created       Created container init-myservice
  13s          13s         1        {kubelet 172.17.4.201}    spec.initContainers{init-myservice}     Normal        Started       Started container init-myservice

Щоб переглянути логи init-контейнерів у цьому Podʼі, виконайте:

kubectl logs myapp-pod -c init-myservice # Огляд першого init-контейнера
kubectl logs myapp-pod -c init-mydb      # Огляд другого init-контейнера

На цей момент ці init-контейнери будуть чекати виявлення Services з назвами mydb та myservice.

Ось конфігурація, яку ви можете використовувати для того, щоб ці Services зʼявилися:

---
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377

Щоб створити Services mydb та myservice:

kubectl apply -f services.yaml

Вивід буде подібний до цього:

service/myservice created
service/mydb created

Потім ви побачите, що ці init-контейнери завершаться, і Pod myapp-pod переходить у стан Running:

kubectl get -f myapp.yaml

Вивід буде подібний до цього:

NAME        READY     STATUS    RESTARTS   AGE
myapp-pod   1/1       Running   0          9m

Цей простий приклад повинен дати вам натхнення для створення ваших власних init-контейнерів. У розділі Що далі є посилання на більш детальний приклад.

Докладний опис поведінки

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

Кожен init-контейнер має успішно завершитися перед тим, як буде запущений наступний контейнер. Якщо контейнер не вдалося запустити через помилку середовища виконання або він завершується з помилкою, його перезапускають згідно з політикою перезапуску Podʼа (restartPolicy). Однак якщо політика перезапуску Podʼа (restartPolicy) встановлена на Always, init-контейнери використовують політику перезапуску OnFailure.

Pod не може бути Ready, поки всі init-контейнери не завершаться успішно. Порти init-контейнерів не агрегуються в Service. Pod, що ініціалізується, перебуває в стані Pending, але повинен мати умову Initialized, встановлену на false.

Якщо Pod перезапускається або був перезапущений, всі init-контейнери мають виконатися знову.

Зміни в специфікації init-контейнерів обмежуються полем образу контейнера. Безпосередня зміна поля image init-контейнера не призводить до перезапуску Podʼа або його перестворення. Якщо Pod ще не було запущено, ці зміни можуть вплинути на те, як він завантажиться.

Для шаблону Podʼа ви зазвичай можете змінити будь-яке поле init-контейнера; наслідки цієї зміни залежать від того, де використовується шаблон Podʼа.

Оскільки init-контейнери можуть бути перезапущені, повторно виконані або виконані заново, код init-контейнерів повинен бути ідемпотентним. Зокрема, код, що записує дані в будь-який том emptyDir, має бути підготовлений до того, що файл виводу вже може існувати.

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

Використовуйте activeDeadlineSeconds в Podʼі, щоб запобігти нескінченним збоям init-контейнерів. Активний крайній термін охоплює init-контейнери. Однак рекомендується використовувати activeDeadlineSeconds лише якщо команди розгортають свій застосунок як Job, оскільки activeDeadlineSeconds впливає навіть після завершення роботи init-контейнера. Pod, який вже працює правильно, буде завершено через activeDeadlineSeconds, якщо ви його налаштуєте.

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

Спільне використання ресурсів всередині контейнерів

З урахуванням порядку виконання init-контейнерів, sidecar-контейнерів і контейнерів застосунків застосовуються такі правила використання ресурсів:

  • Найвищий запит чи обмеження будь-якого конкретного ресурсу, визначеного у всіх init-контейнерах, вважається ефективним запитом/обмеженням ініціалізації. Якщо для будь-якого ресурсу не вказано обмеження, це вважається найвищим обмеженням.
  • Ефективний запит/обмеження Podʼа для ресурсу — це більше з:
    • суми запитів/обмежень усіх контейнерів застосунків для ресурсу
    • ефективного запиту/обмеження ініціалізації для ресурсу
  • Планування виконується на основі ефективних запитів/обмежень, що означає, що init-контейнери можуть резервувати ресурси для ініціалізації, які не використовуються протягом життя Podʼа.
  • Рівень якості обслуговування (QoS), ефективний рівень QoS Podʼа, — це рівень QoS як для init-контейнерів, так і для контейнерів застосунків.

Квоти та обмеження застосовуються на основі ефективного запиту та обмеження Podʼа.

Init-контейнери та cgroups Linux

У Linux розподіл ресурсів для контрольних груп (cgroups) рівня Podʼа ґрунтується на ефективному запиті та обмеженні Podʼа, так само як і для планувальника.

Причини перезапуску Podʼа

Pod може перезапускатися, що призводить до повторного виконання init-контейнерів, з таких причин:

  • Перезапускається контейнер інфраструктури Podʼа. Це трапляється рідко, і це мав би зробити хтось із root-доступом до вузлів.
  • Всі контейнери в Podʼі завершуються, коли restartPolicy встановлено в Always, що примушує до перезапуску, а запис про завершення init-контейнера було втрачено через збір сміття.

Pod не буде перезапущено, коли змінюється образ init-контейнера, або запис про завершення init-контейнера було втрачено через збір сміття. Це стосується Kubernetes v1.20 і пізніших версій. Якщо ви використовуєте старішу версію Kubernetes, ознайомтеся з документацією версії, яку ви використовуєте.

Що далі

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

4 - Ефемерні контейнери

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.25

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

Розуміння ефемерних контейнерів

Podʼи є фундаментальним елементом застосунків Kubernetes. Оскільки Podʼи призначені бути одноразовими та замінними, ви не можете додати контейнер до Podʼа після його створення. Замість цього ви зазвичай видаляєте та замінюєте Podʼи у контрольований спосіб, використовуючи Deployments.

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

Що таке ефемерний контейнер?

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

  • В ефемерних контейнерів не може бути портів, тому такі поля, як ports, livenessProbe, readinessProbe, заборонені.
  • Виділення ресурсів для Podʼа незмінне, тому встановлення resources заборонене.
  • Для повного списку дозволених полів дивіться довідкову документацію EphemeralContainer.

Ефемерні контейнери створюються за допомогою спеціального обробника ephemeralcontainers в API замість того, щоб додавати їх безпосередньо до pod.spec, тому не можна додати ефемерний контейнер за допомогою kubectl edit.

Як і звичайний контейнер, ефемерний контейнер не можна змінити або видалити після додавання до Podʼа.

Примітка:

Ефемерні контейнери не підтримуються статичними Podʼами.

Використання ефемерних контейнерів

Ефемерні контейнери корисні для інтерактивного усунення несправностей, коли kubectl exec недостатній, оскільки контейнер зазнав збою або образ контейнера не містить засобів налагодження.

Зокрема, образи distroless дозволяють вам розгортати мінімальні образи контейнерів, які зменшують поверхню атаки та вплив помилок і вразливостей. Оскільки образи distroless не включають оболонку або будь-які засоби налагодження, складно налагоджувати образи distroless, використовуючи лише kubectl exec.

Під час використання ефемерних контейнерів корисно увімкнути спільний простір імен процесів (process namespace sharing), щоб ви могли переглядати процеси в інших контейнерах.

Що далі

5 - Проби життєздатності, готовності та запуску

Kubernetes дозволяє визначати проби для безперервного моніторингу стану контейнерів у Podʼі. Проба — це діагностична перевірка контейнера, яку періодично виконує kubelet. Для виконання діагностики kubelet або виконує код всередині контейнера, або робить мережевий запит.

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

Типи проб

Kubelet може за потреби виконувати три види проб у запущених контейнерах і реагувати на їхні результати; кожна з них має власне призначення:

Проба запуску

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

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

Проба життєздатності

Проби життєздатності (Liveness) визначають, коли слід перезапустити контейнер. Наприклад, проби життєздатності можуть виявити ситуацію взаємного блокування, коли застосунок працює, але не може просуватися далі. Перезапуск контейнера в такому стані допомагає забезпечити більшу доступність застосунку, незважаючи на наявність помилок.

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

Увага:

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

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

Проба готовності

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

Якщо проба готовності повертає неуспішний стан, контролер EndpointSlice видаляє IP-адресу Podʼа з EndpointSlices усіх Services, що відповідають цьому Podʼу.

Проби готовності виконуються в контейнері протягом всього його життєвого циклу.

Примітка:

Якщо ви хочете мати можливість завершувати обробку запитів під час видалення Podʼа, вам не обовʼязково потрібна проба готовності; коли Pod видаляється, відповідна точка доступу в EndpointSlice оновить свої стани: стан готовності точки доступу буде встановлено на false, тому балансувальники навантаження не використовуватимуть Pod для звичайного трафіку. Дивіться Завершення роботи Podʼа для отримання додаткової інформації про те, як kubelet обробляє видалення Podʼа.

Коли використовувати кожну пробу

Коли слід використовувати пробу запуску?

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

Якщо ваш контейнер зазвичай запускається більше ніж \( initialDelaySeconds + failureThreshold \times periodSeconds \), слід вказати пробу запуску, яка перевіряє ту саму точку доступу, що й проба життєздатності. Стандартне значення для periodSeconds становить 10 секунд. Потім слід встановити failureThreshold достатньо високим, щоб дозволити контейнеру запуститися, не змінюючи стандартне значення для проби життєздатності. Це допомагає захиститися від взаємних блокувань.

Коли слід використовувати пробу життєздатності?

Якщо процес у вашому контейнері може самостійно аварійно завершуватися, щойно виникає проблема або він стає несправним, вам не обовʼязково потрібна проба життєздатності; kubelet автоматично виконає правильну дію відповідно до restartPolicy Podʼа.

Якщо ви хочете, щоб ваш контейнер був завершений і перезапущений у разі невдачі проби, тоді використовуйте пробу життєздатності та встановіть restartPolicy на Always або OnFailure.

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

Коли слід використовувати пробу готовності?

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

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

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

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

Механізми перевірки

Існує чотири різні способи перевірки контейнера за допомогою проб. Кожна проба повинна визначати точно один із цих чотирьох механізмів:

exec
Виконує вказану команду всередині контейнера. Діагностика вважається успішною, якщо команда завершується з кодом стану 0.
grpc
Виконує віддалений виклик процедури за допомогою gRPC. Цільовий обʼєкт повинен реалізовувати перевірки стану gRPC. Діагностика вважається успішною, якщо status відповіді дорівнює SERVING. Для отримання додаткової інформації див. gRPC-проби.
httpGet
Виконує запит HTTP GET до IP-адреси Podʼа на вказаному порту та шляху. Діагностика вважається успішною, якщо відповідь має код стану від 200 до 399 включно. Для отримання додаткової інформації див. HTTP-проби.
tcpSocket
Виконує перевірку TCP на IP-адресу Podʼа на вказаному порту. Діагностика вважається успішною, якщо порт відкритий. Якщо віддалена система (контейнер) закриває зʼєднання відразу після його відкриття, це також вважається справним станом. Для отримання додаткової інформації див. TCP-проби.

Увага:

На відміну від інших механізмів, реалізація проби exec передбачає створення/відгалуження кількох процесів під час кожного виконання. В результаті, у випадку кластерів з високою щільністю Podʼів, меншими інтервалами initialDelaySeconds, periodSeconds, налаштування будь-якої проби з механізмом exec може призвести до збільшення навантаження на CPU вузла. У таких сценаріях розгляньте можливість використання альтернативних механізмів проб, щоб уникнути цих накладних витрат.

Результати проб

Kubelet оцінює результат виконання кожної проби та діє відповідно. Кожна проба має один із трьох результатів:

Success
Контейнер пройшов діагностику.
Failure
Контейнер не пройшов діагностику. Для проб життєздатності та запуску kubelet завершує контейнер, і до нього застосовується його політика перезапуску. Для проб готовності kubelet позначає контейнер як неготовий, і Pod перестає отримувати трафік від відповідних Services.
Unknown
Діагностика не вдалася (жодних дій не слід виконувати, kubelet здійснить подальші перевірки).

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

Поля конфігурації

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

apiVersion: v1
kind: Pod
metadata:
  name: probe-example
spec:
  containers:
  - name: app
    image: registry.k8s.io/e2e-test-images/agnhost:2.40
    ports:
    - containerPort: 8080
    startupProbe:
      httpGet:
        path: /healthz
        port: 8080
      failureThreshold: 30
      periodSeconds: 10
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 10
      periodSeconds: 5
      timeoutSeconds: 3
      failureThreshold: 3
    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
      periodSeconds: 5
initialDelaySeconds
Кількість секунд після запуску контейнера, перш ніж будуть ініційовані проби запуску, життєздатності або готовності. Якщо визначена проба запуску, затримки проб життєздатності та готовності не починаються, поки проба запуску не буде успішною. У деяких старих версіях Kubernetes initialDelaySeconds може ігноруватися, якщо periodSeconds було встановлено на значення більше, ніж initialDelaySeconds. Однак у поточних версіях initialDelaySeconds завжди враховується, і проба не почнеться до закінчення цієї початкової затримки. Стандартне значення — 0 секунд. Мінімальне значення — 0.
periodSeconds
Як часто (у секундах) виконувати пробу. Стандартно — 10 секунд. Мінімальне значення — 1. Поки контейнер не готовий, проба готовності може виконуватися в інший час, ніж налаштований інтервал periodSeconds. Це робиться для того, щоб Pod став готовим швидше.
timeoutSeconds
Кількість секунд, після яких проба вважається такою, що перевищила час очікування. Стандартне значення — 1 секунда. Мінімальне значення — 1.
successThreshold
Мінімальна кількість послідовних успішних спроб, щоб проба вважалася успішною після невдачі. Стандартне значення — 1. Для проб життєздатності та запуску має бути 1. Мінімальне значення — 1.
failureThreshold
Після того, як проба не вдалася failureThreshold разів поспіль, Kubernetes вважає, що загальна перевірка не вдалася: контейнер не готовий/справний/живий. Стандартне значення — 3. Мінімальне значення — 1. У випадку проби запуску або життєздатності, якщо принаймні failureThreshold проб не вдалося, Kubernetes вважає контейнер несправним і запускає перезапуск для цього конкретного контейнера. Kubelet дотримується налаштування terminationGracePeriodSeconds для цього контейнера. Для невдалої проби готовності kubelet продовжує виконувати контейнер, який не пройшов перевірку, і також продовжує виконувати інші проби; оскільки перевірка не вдалася, kubelet встановлює стан Ready для Podʼа у значення false.
terminationGracePeriodSeconds
Налаштуйте період очікування для kubelet між ініціюванням завершення роботи несправного контейнера та примусовою зупинкою цього контейнера середовищем виконання контейнерів. Стандартно успадковується значення на рівні Podʼа для terminationGracePeriodSeconds (30 секунд, якщо не вказано), а мінімальне значення — 1. Див. terminationGracePeriodSeconds на рівні проби для детальнішої інформації.

Увага:

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

terminationGracePeriodSeconds на рівні проби

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.28

У версіях 1.25 і вище користувачі можуть вказати terminationGracePeriodSeconds на рівні проби як частину специфікації проби. Коли встановлені обидва значення terminationGracePeriodSeconds на рівні Podʼа і проби, kubelet використовує значення на рівні проби.

Під час встановлення terminationGracePeriodSeconds зверніть увагу на таке:

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

Наприклад:

spec:
  terminationGracePeriodSeconds: 3600  # рівень Podʼа
  containers:
  - name: test
    image: ...

    ports:
    - name: liveness-port
      containerPort: 8080

    livenessProbe:
      httpGet:
        path: /healthz
        port: liveness-port
      failureThreshold: 1
      periodSeconds: 60
      # Перевизначення значення terminationGracePeriodSeconds на рівні Podʼа
      terminationGracePeriodSeconds: 60

Значення terminationGracePeriodSeconds на рівні проби не може бути встановлено для проб готовності. Воно буде відхилено API-сервером.

Деталі механізму проб

HTTP-проби

HTTP-проби мають додаткові поля, які можна встановити в httpGet:

  • host: Імʼя хоста для підключення, стандартно IP-адреса Podʼа. Ймовірно, ви захочете встановити "Host" у httpHeaders замість цього.
  • scheme: Схема для підключення до хоста (HTTP або HTTPS). Стандартно "HTTP".
  • path: Шлях для доступу до HTTP-сервера. Стандартно "/".
  • httpHeaders: Власні заголовки для встановлення в запиті. HTTP дозволяє повторювані заголовки.
  • port: Назва або номер порту для доступу до контейнера. Номер повинен бути в діапазоні від 1 до 65535.
  • protocol: Протокол для використання в запиті проби. Стандартно HTTP1. Встановіть HTTP2, щоб виконувати пробу через HTTP/2 без шифрування (h2c). Вимагає увімкнення функціональної можливості H2CContainerProbe.

Для HTTP-проби kubelet надсилає HTTP-запит на вказаний порт і шлях для виконання перевірки. Kubelet надсилає пробу на IP-адресу Podʼа, якщо адреса не перевизначена за допомогою необовʼязкового поля host у httpGet. Якщо поле scheme встановлено в HTTPS, kubelet надсилає HTTPS-запит, пропускаючи перевірку сертифіката. У більшості сценаріїв ви не захочете встановлювати поле host. Ось один сценарій, де ви б його встановили. Припустимо, контейнер слухає на 127.0.0.1, а поле hostNetwork Podʼа встановлено в true. Тоді host у httpGet слід встановити на 127.0.0.1. Якщо ваш Pod покладається на віртуальні хости, що, ймовірно, є більш поширеним випадком, ви не повинні використовувати host, а натомість встановити заголовок Host у httpHeaders.

Для HTTP-проби kubelet надсилає два заголовки запиту на додачу до обовʼязкового заголовка Host:

  • User-Agent, який стандартно дорівнює kube-probe/1.37, де 1.37 — це версія kubelet.
  • Accept, який стандартно дорівнює */*.

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

livenessProbe:
  httpGet:
    httpHeaders:
      - name: Accept
        value: application/json

startupProbe:
  httpGet:
    httpHeaders:
      - name: User-Agent
        value: MyUserAgent

Ви також можете видалити ці два заголовки, визначивши їх з порожнім значенням.

livenessProbe:
  httpGet:
    httpHeaders:
      - name: Accept
        value: ""

startupProbe:
  httpGet:
    httpHeaders:
      - name: User-Agent
        value: ""
СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the H2CContainerProbe feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Ви можете налаштувати HTTP-пробу для використання HTTP/2 без шифрування (h2c), встановивши поле protocol на HTTP2. Коли protocol встановлено на HTTP2, kubelet використовує h2c (HTTP/2 через звичайний TCP) замість HTTP/1.1. Типове значення protocol — HTTP1. Встановлення protocol: HTTP2 вимагає scheme: HTTP (типове значення); API-сервер відхиляє комбінацію protocol: HTTP2 з scheme: HTTPS. Для отримання додаткових відомостей див. Використання HTTP/2 без шифрування (h2c) з HTTP-пробами.

Обробка перенаправлень

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

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

Якщо kubelet слідує за перенаправленням і отримує 11 або більше перенаправлень загалом, проба вважається успішною і записується подія ProbeWarning. Наприклад:

Events:
  Type     Reason        Age                     From               Message
  ----     ------        ----                    ----               -------
  Normal   Scheduled     29m                     default-scheduler  Successfully assigned default/httpbin-7b8bc9cb85-bjzwn to daocloud
  Normal   Pulling       29m                     kubelet            Pulling image "docker.io/kennethreitz/httpbin"
  Normal   Pulled        24m                     kubelet            Successfully pulled image "docker.io/kennethreitz/httpbin" in 5m12.402735213s
  Normal   Created       24m                     kubelet            Created container httpbin
  Normal   Started       24m                     kubelet            Started container httpbin
 Warning  ProbeWarning  4m11s (x1197 over 24m)  kubelet            Readiness probe warning: Probe terminated redirects

Увага:

Під час обробки проби httpGet kubelet припиняє читання тіла відповіді після 10KiB. Успішність проби визначається виключно кодом стану відповіді, який знаходиться в заголовках відповіді.

Якщо ви перевіряєте точку доступу, що повертає тіло відповіді більше ніж 10KiB, kubelet все одно позначить пробу як успішну на основі коду стану, але закриє зʼєднання після досягнення межі 10KiB. Це раптове закриття може спричинити появу в логах вашого застосунку помилок connection reset by peer або broken pipe errors, які важко відрізнити від реальних проблем мережі.

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

TCP-проби

Для TCP-проби kubelet встановлює зʼєднання проби на вузлі, а не в Podʼі, що означає, що ви не можете використовувати назву сервісу в параметрі host, оскільки kubelet не може її розвʼязати.

gRPC-проби

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.27

Якщо ваш застосунок реалізує Протокол перевірки стану gRPC, ви можете налаштувати Kubernetes для використання його для перевірки запуску, життєздатності або готовності застосунку.

Ось приклад маніфесту:

apiVersion: v1
kind: Pod
metadata:
  name: etcd-with-grpc
spec:
  containers:
  - name: etcd
    image: registry.k8s.io/etcd:3.5.1-0
    command: [ "/usr/local/bin/etcd", "--data-dir",  "/var/lib/etcd", "--listen-client-urls", "http://0.0.0.0:2379", "--advertise-client-urls", "http://127.0.0.1:2379", "--log-level", "debug"]
    ports:
    - containerPort: 2379
    livenessProbe:
      grpc:
        port: 2379
      initialDelaySeconds: 10

Для використання gRPC-проби необхідно налаштувати port. Якщо ви хочете розрізняти проби різних типів і проби для різних функцій, ви можете використовувати поле service. Ви можете встановити service зі значенням liveness і налаштувати вашу точку доступу gRPC Health Checking так, щоб вона відповідала на цей запит інакше, ніж коли service має значення readiness. Це дозволяє використовувати ту саму точку доступу для різних видів перевірки стану контейнера, замість того щоб слухати на двох різних портах. Якщо ви хочете вказати власну назву сервісу та також вказати тип проби, проєкт Kubernetes рекомендує використовувати назву, яка обʼєднує ці значення. Наприклад: myservice-liveness (використовуючи - як роздільник).

Примітка:

На відміну від HTTP або TCP-проб, ви не можете вказати порт перевірки стану за назвою, і ви не можете налаштувати власне імʼя хоста.

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

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the GRPCContainerProbeTLS feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Ви можете налаштувати gRPC-пробу для підключення через TLS, встановивши поле mode на TLS. Коли mode встановлено на TLS, kubelet використовує TLS з InsecureSkipVerify (він не перевіряє сертифікат сервера). Типове значення mode — Plaintext. Для отримання додаткових відомостей див. Використання TLS з gRPC-пробами.

Що далі

6 - Імʼя хоста Podʼа

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

Стандартне імʼя хоста Podʼа

Коли створюється Pod, імʼя його хоста (яке спостерігається зсередини Podʼа) походить від значення metadata.name Podʼа. І імʼя хоста, і відповідне повністю кваліфіковане доменне імʼя (FQDN) встановлюються у значення metadata.name (з точки зору Podʼа)

apiVersion: v1
kind: Pod
metadata:
  name: busybox-1
spec:
  containers:
  - image: busybox:1.28
    command:
      - sleep
      - "3600"
    name: busybox

Pod, створений цим маніфестом, матиме імʼя хоста та повністю кваліфіковане доменне імʼя (FQDN) встановлені як busybox-1.

Імʼя хоста з полями hostname та subdomain Podʼа

Специфікація Podʼа включає необовʼязкове поле hostname. Коли воно встановлене, це значення має пріоритет над metadata.name Podʼа як імʼя хоста (яке спостерігається зсередини Podʼа). Наприклад, Pod з spec.hostname встановленим як my-host матиме імʼя хоста встановлене як my-host.

Специфікація Podʼа також включає необовʼязкове поле subdomain, яке вказує, що Pod належить до піддомену в межах свого простору імен. Якщо Pod має spec.hostname встановлений як "foo" і spec.subdomain встановлений як "bar" у просторі імен my-namespace, імʼя його хоста стає foo, а його повністю кваліфіковане доменне імʼя (FQDN) стає foo.bar.my-namespace.svc.cluster-domain.example (спостерігається зсередини Podʼа).

Коли встановлені і hostname, і subdomain, DNS-сервер кластера створить записи A та/або AAAA на основі цих полів. Дивіться: Поля hostname та subdomain Podʼа.

Імʼя хоста з полем setHostnameAsFQDN Podʼа

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.22

Коли Pod налаштований на використання повністю кваліфікованого доменного імені (FQDN), його імʼя хоста є коротким імʼям хоста. Наприклад, якщо у вас є Pod з повністю кваліфікованим доменним імʼям busybox-1.busybox-subdomain.my-namespace.svc.cluster-domain.example, то стандартно команда hostname всередині цього Podʼа повертає busybox-1, а команда hostname --fqdn повертає FQDN.

Коли в специфікації Podʼа встановлено і setHostnameAsFQDN: true, і поле subdomain, kubelet записує FQDN Podʼа як імʼя хоста для простору імен цього Podʼа. У цьому випадку і hostname, і hostname --fqdn повертають FQDN Podʼа.

FQDN Podʼа будується так само, як було визначено раніше. Воно складається з поля spec.hostname Podʼа (якщо вказано) або поля metadata.name, spec.subdomain, назви простору імен та суфікса домену кластера.

Примітка:

У Linux поле імені хоста ядра (поле nodename структури utsname) обмежено 64 символами.

Якщо Pod вмикає цю функцію, а його FQDN довший за 64 символи, він не зможе запуститися. Pod залишатиметься в статусі Pending (відображається як ContainerCreating через kubectl), генеруючи події помилок, такі як "Failed to construct FQDN from Pod hostname and cluster domain".

Це означає, що під час використання цього поля ви повинні переконатися, що сумарна довжина полів metadata.name (або spec.hostname) та spec.subdomain Podʼа не призводить до появи FQDN, що перевищує 64 символи.

Імʼя хоста з полем hostnameOverride Podʼа

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.37; (стандартно увімкнено)
More information about this feature

This is a stable feature in Kubernetes, and has been since version 1.37. It was first available in the v1.34 release.

Встановлення значення для hostnameOverride в специфікації Podʼа змушує kubelet безумовно встановлювати як імʼя хоста, так і повністю кваліфіковане доменне імʼя (FQDN) Podʼа у значення hostnameOverride.

Поле hostnameOverride має обмеження довжини 64 символи і повинно відповідати стандарту імен піддоменів DNS, визначеному в RFC 1123.

Приклад:

apiVersion: v1
kind: Pod
metadata:
  name: busybox-2-busybox-example-domain
spec:
  hostnameOverride: busybox-2.busybox.example.domain
  containers:
  - image: busybox:1.28
    command:
      - sleep
      - "3600"
    name: busybox

Примітка:

Це впливає лише на імʼя хоста всередині Podʼа; це не впливає на записи A або AAAA Podʼа в DNS-сервері кластера.

Якщо hostnameOverride встановлено разом з полями hostname та subdomain:

  • Імʼя хоста всередині Podʼа перевизначається значенням hostnameOverride.

  • Записи A та/або AAAA Podʼа в DNS-сервері кластера все ще генеруються на основі полів hostname та subdomain.

Примітка: Якщо встановлено hostnameOverride, ви не можете одночасно встановлювати поля hostNetwork та setHostnameAsFQDN. API-сервер явно відхилить будь-який запит на створення, що намагається використати цю комбінацію.

Для деталей щодо поведінки, коли hostnameOverride встановлено в комбінації з іншими полями (hostname, subdomain, setHostnameAsFQDN, hostNetwork), див. таблицю в деталях проєкту KEP-4762.

7 - Група планування

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the GenericWorkload feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Ви можете повʼязати Pod з PodGroup, щоб вказати, що Pod належить до групи Pods, які плануються разом. Це дозволяє планувальнику застосовувати політики на рівні групи, такі як групове планування, замість того, щоб розглядати кожен Pod окремо.

Визначення групи планування

Коли увімкнено функціональну можливість GenericWorkload, ви можете встановити поле spec.schedulingGroup у маніфесті Pod. Це поле встановлює звʼязок із конкретним обʼєктом PodGroup у тому самому просторі імен за назвою.

apiVersion: v1
kind: Pod
metadata:
  name: worker-0
  namespace: some-ns
spec:
  schedulingGroup:
    podGroupName: training-worker-0
  containers:
  - name: ml-worker
    image: training:v1

Поле schedulingGroup є незмінним. Після встановлення Pod не можна перемістити до іншого PodGroup.

Поведінка

Коли ви встановлюєте spec.schedulingGroup, планувальник шукає вказаний PodGroup і застосовує визначену в ньому політику планування:

  • Якщо PodGroup використовує політику basic, кожен Pod планується незалежно, використовуючи стандартну поведінку Kubernetes. Групування використовується як мітка на рівні групи.
  • Якщо PodGroup використовує політику gang, Pod входить у життєвий цикл планування "все або нічого". Планувальник намагається розмістити принаймні minCount Pods у групі одночасно; жоден з них не привʼязується до вузлів, якщо мінімум не досягнуто.
СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the CompositePodGroup feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

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

Відсутні посилання на групи

Якщо Pod посилається на PodGroup, що ще не існує, Pod залишається в стані очікування. Аналогічно, якщо згаданий PodGroup вказує батьківський CompositePodGroup (через spec.parentCompositePodGroupName), який ще не створено, планування не починається, і Pod залишається в стані очікування, доки вся ієрархія груп не існуватиме в кластері.

Планувальник автоматично розглядає Pod повторно, щойно всі необхідні ресурси PodGroup та CompositePodGroup будуть існувати.

Що далі

8 - Статичні Podʼи

Статичні Podʼи (Static Pods) керуються безпосередньо демоном kubelet на конкретному вузлі, без спостереження за ними з боку API-сервера. На відміну від Podʼів, які керуються панеллю управління (наприклад, Deployment), kubelet стежить за кожним статичним Podʼом і перезапускає його у разі збою.

Статичні Podʼи завжди привʼязані до одного kubelet на конкретному вузлі.

Основне призначення статичних Podʼів — запуск самостійно розміщеної панелі управління: іншими словами, використання kubelet для контролю окремих компонентів панелі управління. Наприклад, kubeadm використовує статичні Podʼи для запуску kube-apiserver, kube-controller-manager, kube-scheduler та etcd на вузлах панелі управління.

Примітка:

Якщо ваш кластер запускає компоненти панелі управління як Podʼи, вони, ймовірно, є статичними Podʼами. Ви можете розпізнати їхні дзеркальні Podʼи в просторі імен kube-system за анотацією kubernetes.io/config.mirror.

Дзеркальні Podʼи

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

Kubelet передає мітки зі статичного Podʼа до дзеркального Podʼа. Ви можете використовувати ці мітки як зазвичай через селектори.

Якщо ви спробуєте використати kubectl для видалення дзеркального Podʼа з API-сервера, kubelet не видалить статичний Pod. Kubelet створить дзеркальний Pod заново.

Обмеження

Специфікація статичного Podʼа не може посилатися на інші обʼєкти API, такі як ServiceAccount, ConfigMap або Secret.

Статичні Podʼи не підтримують ефемерні контейнери.

Статичні Podʼи чи DaemonSets

Якщо ви запускаєте кластер Kubernetes і використовуєте статичні Podʼи для запуску Podʼів на кожному вузлі, вам, ймовірно, слід натомість використовувати DaemonSet.

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

Статичні Podʼи запускаються kubelet до того, як API-сервер стане доступним, що робить їх придатними для ініціалізації компонентів панелі управління. DaemonSets потребують запущеної панелі управління.

Що далі

9 - Простори імен користувачів

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.36
More information about this feature

This is a stable feature in Kubernetes, and has been since version v1.36. It was first available in the v1.28 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate UserNamespacesSupport, Kubernetes ignores it but does not report any error.

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

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

Ви можете використовувати цю функцію, щоб зменшити шкоду, яку скомпрометований контейнер може заподіяти хосту або іншим Podʼам на тому самому вузлі. Є кілька вразливостей безпеки, які оцінено як ВИСОКІ або КРИТИЧНІ, і які неможливо було використати, коли простори імен користувачів активні. Очікується, що простори імен користувачів також помʼякшуватимуть деякі майбутні вразливості.

Перш ніж ви розпочнете

Примітка: Цей розділ містить посилання на проєкти сторонніх розробників, які надають функціонал, необхідний для Kubernetes. Автори проєкту Kubernetes не несуть відповідальності за ці проєкти. Проєкти вказано в алфавітному порядку. Щоб додати проєкт до цього списку, ознайомтеся з посібником з контенту перед надсиланням змін. Докладніше.

Це функція, доступна лише для Linux, і потребує підтримки в Linux для монтування idmap на використовуваних файлових системах. Це означає:

  • На вузлі файлова система, яку ви використовуєте для /var/lib/kubelet/pods/, або власна тека, яку ви налаштовуєте для цього, повинна підтримувати монтування idmap.
  • Всі файлові системи, які використовуються в томах Podʼа, повинні підтримувати монтування idmap.

На практиці це означає, що вам потрібне ядро Linux принаймні версії 6.3, оскільки tmpfs почав підтримувати монтування idmap у цій версії. Це зазвичай потрібно, оскільки кілька функцій Kubernetes використовують tmpfs (токен ServiceAccount, який монтується стандартно, використовує tmpfs, Secrets також використовують tmpfs тощо).

Деякі популярні файлові системи, які підтримують монтування idmap в Linux 6.3, — це: btrfs, ext4, xfs, fat, tmpfs, overlayfs.

Крім того, середовище виконання контейнерів та його базове середовище виконання OCI повинні підтримувати простори імен користувачів. Підтримку надають такі середовища виконання OCI:

  • crun версії 1.9 або вище (рекомендована версія 1.13+).
  • runc версії 1.2 або вище.

Для використання просторів імен користувачів з Kubernetes також потрібне середовище виконання контейнерів CRI, щоб використовувати цю функцію з Podʼами Kubernetes:

  • containerd: версія 2.0 (і новіші) підтримує простори імен користувачів для контейнерів.
  • CRI-O: версія 1.25 (і новіші) підтримує простори імен користувачів для контейнерів.

Стан підтримки просторів імен користувачів в cri-dockerd відстежується у тікеті на GitHub.

Вступ

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

Pod може увімкнути використання просторів імен користувачів, встановивши поле pod.spec.hostUsers в false.

Kubelet вибере UID/GID хоста, на які зіставляється Pod, і зробить це так, щоб жодні два Podʼи на одному вузлі не використовували однакове зіставлення.

Поля runAsUser, runAsGroup, fsGroup тощо в pod.spec завжди посилаються на користувача всередині контейнера. Ці користувачі використовуватимуться для монтування томів (вказаних у pod.spec.volumes), і тому UID/GID хоста не матимуть жодного впливу на запис/читання з томів, які може монтувати Pod. Іншими словами, inode, створені/зчитані у томах, змонтованих Podʼом, будуть такими самими, як якби Pod не використовував простори імен користувачів.

Таким чином, Pod може легко вмикати та вимикати простори імен користувачів (не впливаючи на права власності на файли томів), а також надавати спільний доступ до томів з Podʼами без просторів імен користувачів, просто вказавши відповідних користувачів всередині контейнера (RunAsUser, RunAsGroup, fsGroup тощо). Це стосується будь-якого тому, який може бути змонтовано в Pod, включно з hostPath (якщо Podʼу дозволено монтувати томи hostPath).

Стандартно дійсні UID/GID, коли цю функцію активовано, лежать у діапазоні 0-65535. Це стосується файлів та процесів (runAsUser, runAsGroup тощо).

Файли з UID/GID за межами цього діапазону вважатимуться такими, що належать до overflow ID, зазвичай 65534 (налаштовано в /proc/sys/kernel/overflowuid та /proc/sys/kernel/overflowgid). Однак змінити ці файли неможливо, навіть якщо працювати як користувач/група 65534.

Якщо діапазон 0-65535 розширено за допомогою налаштування, вищезазначені обмеження застосовуються до розширеного діапазону.

Більшість застосунків, які потребують запуску з правами root, але не мають доступу до інших просторів імен хоста чи ресурсів, повинні продовжувати працювати без змін, якщо простори імен користувачів активовано.

Розуміння просторів імен користувачів для Podʼів

Кілька середовищ виконання контейнерів із їхньою типовою конфігурацією (таких як Docker Engine, containerd, CRI-O) використовують простори імен Linux для ізоляції. Існують інші технології, які також можна використовувати з цими середовищами (наприклад, Kata Containers використовує віртуальні машини замість просторів імен Linux). Ця сторінка стосується середовищ виконання контейнерів, які використовують простори імен Linux для ізоляції.

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

Це означає, що контейнери можуть працювати як root і зіставлятися з користувачем, який не є root, на хості. Всередині контейнера процес буде вважати себе root (і, отже, інструменти типу apt, dnf тощо працюватимуть нормально), тоді як насправді процес не має привілеїв на хості. Ви можете перевірити це, наприклад, дізнавшись, від імені якого користувача працює процес контейнера, виконавши ps aux на хості. Користувач, якого показує ps, не той самий, що і користувач, якого ви бачите, якщо ви виконаєте команду id всередині контейнера.

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

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

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

  • CAP_SYS_MODULE не має жодного ефекту, якщо його надано Podʼу, що використовує простори імен користувачів, Pod не може завантажити модулі ядра.
  • CAP_SYS_ADMIN обмежений простором імен користувачів Podʼа та є недійсним поза його межами.

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

Якщо ви хочете дізнатися більше подробиць про те, що змінюється під час використання просторів імен користувачів, дивіться man 7 user_namespaces.

Налаштування вузла для підтримки просторів імен користувачів

Типово kubelet призначає UID/GID Podʼам вище діапазону 0-65535, ґрунтуючись на припущенні, що файли та процеси хоста використовують UID/GID у цьому діапазоні, що є стандартним для більшості дистрибутивів Linux. Цей підхід запобігає будь-якому перетину між UID/GID хоста та UID/GID Podʼів.

Уникнення перетину є важливим для помʼякшення впливу вразливостей, таких як CVE-2021-25741, де потенційно Pod може читати довільні файли на хості. Якщо UID/GID Podʼа та хоста не перетинаються, те, що може робити Pod, обмежено: UID/GID Podʼа не буде відповідати власнику/групі файлів хоста.

Kubelet може використовувати власний діапазон ідентифікаторів користувачів та груп для Podʼів. Для налаштування власного діапазону вузол повинен мати:

  • Користувача kubelet в системі (ви не можете використовувати інше імʼя користувача тут)
  • Встановлений бінарний файл getsubids (частина shadow-utils), доступний у PATH для бінарного файлу kubelet.
  • Конфігурацію допоміжних UID/GID для користувача kubelet (див. man 5 subuid та man 5 subgid).

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

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

  • Допоміжний ідентифікатор користувача, який визначає початок діапазону UID для Podʼів, має бути кратним 65536 і також повинен бути більшим або рівним 65536. Іншими словами, ви не можете використовувати жодний ідентифікатор з діапазону 0-65535 для Podʼів; kubelet накладає це обмеження, щоб ускладнити створення ненавмисно незахищеної конфігурації.

  • Кількість допоміжних ID повинна бути кратною 65536.

  • Кількість допоміжних ID повинна бути щонайменше 65536 x <maxPods>, де <maxPods> — максимальна кількість Podʼів, які можуть запускатися на вузлі.

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

  • Жоден з призначених діапазонів не повинен перетинатися з жодним іншим призначенням.

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

Наприклад, ви можете визначити /etc/subuid та /etc/subgid, щоб обидва мали такі записи для користувача kubelet:

# Формат такий
#   імʼя:firstID:кількість ідентифікаторів
# де
# - firstID дорівнює 65536 (мінімальне можливе значення)
# - кількість ідентифікаторів дорівнює 110 * 65536
#   (110 — стандартне обмеження кількості Podʼів на вузлі)

kubelet:65536:7208960

Примітка, якщо ви переконфігуровуєте вузол

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

Конфігурацію слід змінювати, коли на вузлі не запущено жодного Podʼа, що використовує простори імен користувачів. Під час зміни на вузлі, де працюють будь-які Podʼи з просторами імен користувачів, вам потрібно спочатку очистити вузол перед застосуванням конфігурації та перезапуском kubelet. Під час очищення вузла памʼятайте, що Podʼи DaemonSet або інші Podʼи, що толерують taint unschedulable, не будуть виселені.

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

Кількість ID для кожного Podʼа

Починаючи з Kubernetes v1.33 можна встановити кількість ID для кожного Podʼа в KubeletConfiguration.

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
userNamespaces:
  idsPerPod: 1048576

Значення idsPerPod (uint32) має бути кратним 65536. Стандартне значення — 65536. Це значення застосовується лише до контейнерів, створених після запуску kubelet з цією KubeletConfiguration. На запущені контейнери ця конфігурація не впливає.

У версіях Kubernetes до v1.33 кількість ID для кожного Podʼа була жорстко встановлена на рівні 65536.

Інтеграція з перевіркою допуску безпеки Podʼів

Для Podʼів Linux, які увімкнули простори імен користувачів, Kubernetes послаблює застосування Стандартів безпеки Podʼа контрольованим способом.

Якщо ви створите Pod, який використовує простори імен користувачів, такі поля не будуть обмежені навіть у контекстах, які застосовують стандарт безпеки Podʼів Baseline чи Restricted. Це не становить проблему безпеки, оскільки root всередині Podʼа з просторами імен користувачів фактично посилається на користувача всередині контейнера, який ніколи не зіставляється з привілейованим користувачем на хості. Ось список полів, які не перевіряються для Podʼів в цих обставинах:

  • spec.securityContext.runAsNonRoot
  • spec.containers[*].securityContext.runAsNonRoot
  • spec.initContainers[*].securityContext.runAsNonRoot
  • spec.ephemeralContainers[*].securityContext.runAsNonRoot
  • spec.securityContext.runAsUser
  • spec.containers[*].securityContext.runAsUser
  • spec.initContainers[*].securityContext.runAsUser
  • spec.ephemeralContainers[*].securityContext.runAsUser

Крім того, якщо Pod перебуває в контексті зі стандартом безпеки Podʼів Baseline, перевірка таких полів також буде помʼякшена:

  • spec.containers[*].securityContext.procMount
  • spec.initContainers[*].securityContext.procMount
  • spec.ephemeralContainers[*].securityContext.procMount

Зі стандартом безпеки Podʼів Restricted Pod все одно повинен використовувати лише стандартний або порожній ProcMount.

Обмеження

Під час використання просторів імен користувачів для Podʼа заборонено використовувати інші простори імен хоста. Зокрема, якщо ви встановите hostUsers: false, ви не маєте права встановлювати жодне з такого:

  • hostNetwork: true
  • hostIPC: true
  • hostPID: true

Жоден контейнер також не може використовувати volumeDevices (блокові томи raw, такі як /dev/sda). Це стосується всіх масивів контейнерів у специфікації Podʼа:

  • containers
  • initContainers
  • ephemeralContainers

Підтримка файлової системи

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

Warning  Failed 1s kubelet Error: failed to create containerd task: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: failed to fulfil mount request: failed to set MOUNT_ATTR_IDMAP on ${your mount path} invalid argument (maybe the filesystem used doesn't support idmap mounts on this kernel?): unknown

Томи NFS не можуть бути змонтовані в Pod з простором імен користувачів, оскільки клієнт Linux NFS ще не підтримує монтування idmap. Для поточного списку підтримуваних файлових систем дивіться сторінку керівництва Linux mount_setattr(2).

Метрики та спостережуваність

Kubelet експортує дві метрики prometheus, специфічні для просторів імен користувачів:

  • started_user_namespaced_pods_total: лічильник, який відстежує кількість спроб створення Podʼів з просторами імен користувачів.
  • started_user_namespaced_pods_errors_total: лічильник, який відстежує кількість помилок під час створення Podʼів з просторами імен користувачів.

Що далі

10 - Downward API

Є два способи надати поля Podʼа та контейнера запущеному контейнеру: змінні середовища та файли, які заповнюються спеціальним типом тому. Разом ці два способи надання полів Podʼа та контейнера називають downward API.

Іноді корисно, щоб контейнер мав інформацію про себе, не перебуваючи занадто повʼязаним із Kubernetes. Downward API дозволяє контейнерам використовувати інформацію про себе чи кластер, не використовуючи клієнт Kubernetes або API-сервер.

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

У Kubernetes є два способи надати поля Podʼа та контейнера запущеному контейнеру:

Разом ці два способи надання полів Podʼа та контейнера називають downward API.

Доступні поля

Через downward API доступні лише деякі поля API Kubernetes. У цьому розділі перелічено поля, які ви можете зробити доступними.

Ви можете передавати інформацію з доступних полів рівня Podʼа, використовуючи fieldRef. На рівні API spec для Podʼа завжди визначає принаймні один Container. Ви можете передавати інформацію з доступних полів рівня Container, використовуючи resourceFieldRef.

Інформація, доступна за допомогою fieldRef

Деякі поля рівня Podʼа ви можете передати контейнеру як змінну середовища або через том downwardAPI. Через обидва механізми доступні такі поля:

metadata.name
назва Podʼа
metadata.namespace
простір імен Podʼа
metadata.uid
унікальний ідентифікатор Podʼа
metadata.annotations['<KEY>']
значення анотації Podʼа з назвою <KEY> (наприклад, metadata.annotations['myannotation'])
metadata.labels['<KEY>']
текстове значення мітки Podʼа з назвою <KEY> (наприклад, metadata.labels['mylabel'])

Така інформація доступна через змінні середовища, але не як поле fieldRef у томі downwardAPI:

spec.serviceAccountName
назва ServiceAccount Podʼа
spec.nodeName
назва вузла, на якому виконується Pod
status.hostIP
основна IP-адреса вузла, до якого призначено Pod
status.hostIPs
IP-адреси — це версія подвійного стека status.hostIP, перша завжди така сама, як і status.hostIP.
status.podIP
основна IP-адреса Podʼа (зазвичай, його IPv4-адреса)
status.podIPs
IP-адреси — це версія подвійного стека status.podIP, перша завжди така сама, як і status.podIP

Така інформація доступна через fieldRef тому downwardAPI, але не як змінні середовища:

metadata.labels
всі мітки Podʼа у форматі label-key="escaped-label-value" з однією міткою на рядок
metadata.annotations
всі анотації Podʼа у форматі annotation-key="escaped-annotation-value" з однією анотацією на рядок

Інформація, доступна за допомогою resourceFieldRef

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

Примітка:

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.35
More information about this feature

This is a stable feature in Kubernetes, and has been since version v1.35. It was first available in the v1.27 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate InPlacePodVerticalScaling, Kubernetes ignores it but does not report any error.

Ресурси CPU та памʼяті контейнера можуть бути змінені під час роботи контейнера. Якщо це станеться, буде оновлено том downward API, але змінні середовища не буде оновлено, доки контейнер не буде перезапущено. Докладніші відомості наведено у статті Зміна розміру ресурсів CPU та памʼяті, призначених контейнерам.

resource: limits.cpu
Обмеження CPU контейнера
resource: requests.cpu
Запит CPU контейнера
resource: limits.memory
Обмеження памʼяті контейнера
resource: requests.memory
Запит памʼяті контейнера
resource: limits.hugepages-*
Обмеження hugepages контейнера
resource: requests.hugepages-*
Запит hugepages контейнера
resource: limits.ephemeral-storage
Обмеження ефемерного сховища контейнера
resource: requests.ephemeral-storage
Запит ефемерного сховища контейнера

Резервна інформація для обмежень ресурсів

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

Що далі

Ви можете прочитати про томи downwardAPI.

Ви можете спробувати використовувати downward API щоб надати інформацію рівня контейнера чи Podʼа:

11 - Розширена конфігурація Podʼів

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

PriorityClasses

PriorityClasses дозволяють вам встановити важливість Podʼів відносно інших Podʼів. Якщо ви призначаєте клас пріоритету Podʼу, Kubernetes встановлює поле .spec.priority для цього Podʼа на основі PriorityClass, який ви вказали (ви не можете встановити .spec.priority безпосередньо). Якщо або коли Pod не може бути запланований, і проблема повʼязана з нестачею ресурсів, kube-scheduler намагається витіснити Podʼи з нижчим пріоритетом, щоб зробити можливим планування Podʼа з вищим пріоритетом.

PriorityClass — це обʼєкт API в межах кластера, який зіставляє назву класу пріоритету з цілочисельним значенням пріоритету. Більші числа вказують на вищий пріоритет.

Визначення PriorityClass

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 10000
globalDefault: false
description: "Клас пріоритету для робочих навантажень із високим пріоритетом"

Вказування пріоритету Podʼа за допомогою PriorityClass

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  priorityClassName: high-priority

Вбудовані PriorityClasses

Kubernetes надає два вбудовані PriorityClasses:

  • system-cluster-critical: для системних компонентів, які є критичними для кластера
  • system-node-critical: для системних компонентів, які є критичними для окремих вузлів. Це найвищий пріоритет, який можуть мати Podʼи в Kubernetes.

Для отримання додаткової інформації див. Пріоритет і витіснення Podʼів.

RuntimeClasses

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

Приклад Podʼа

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  runtimeClassName: myclass
  containers:
  - name: mycontainer
    image: nginx

RuntimeClass — це обʼєкт у межах кластера, який представляє середовище виконання контейнерів, доступне на деяких або всіх ваших вузлах.

Адміністратор кластера встановлює та налаштовує конкретні середовища виконання, що підтримують RuntimeClass.

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

Докладнішу інформацію див. у документації RuntimeClass.

Конфігурація контексту безпеки на рівні Podʼа та контейнера

Поле Security context у специфікації Podʼа забезпечує детальний контроль за налаштуваннями безпеки для Podʼів та контейнерів.

securityContext на рівні Podʼа

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

Ось приклад використання securityContext на рівні Podʼа:

Приклад Podʼа

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo
spec:
  securityContext:  # Це стосується всього Podʼа
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  containers:
  - name: sec-ctx-demo
    image: registry.k8s.io/e2e-test-images/agnhost:2.45
    command: ["sh", "-c", "sleep 1h"]

Контекст безпеки на рівні контейнера

Ви можете вказати контекст безпеки тільки для конкретного контейнера. Ось приклад:

Приклад Podʼа

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo-2
spec:
  containers:
  - name: sec-ctx-demo-2
    image: gcr.io/google-samples/node-hello:1.0
    securityContext:
      allowPrivilegeEscalation: false
      runAsNonRoot: true
      runAsUser: 1000
      capabilities:
        drop:
        - ALL
      seccompProfile:
        type: RuntimeDefault

Параметри контексту безпеки

  • Ідентифікатори користувачів та груп: контроль того, під яким користувачем/групою працює контейнер
  • Capabilities: додавання або видалення можливостей Linux
  • Профілі Seccomp: налаштування профілів обчислювальної безпеки
  • Параметри SELinux: налаштування контексту SELinux
  • AppArmor: налаштування профілів AppArmor для додаткового контролю доступу
  • Параметри Windows: налаштування параметрів безпеки, специфічних для Windows

Увага:

Ви також можете використовувати securityContext Podʼа, щоб дозволити привілейований режим у контейнерах Linux. Привілейований режим перевизначає багато інших налаштувань безпеки в securityContext. Уникайте використання цього параметра, якщо ви не можете надати еквівалентні дозволи за допомогою інших полів у securityContext. Ви можете запускати контейнери Windows у подібному привілейованому режимі, встановивши прапорець windowsOptions.hostProcess у контексті безпеки на рівні Podʼа. Детальні відомості та інструкції див. у розділі Створення Windows HostProcess Podʼа.

Для отримання додаткової інформації див. Налаштування контексту безпеки для Podʼа або контейнера.

Вплив на рішення щодо планування Podʼів

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

Селектори вузлів

Найпростіша форма обмеження вибору вузлів:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  nodeSelector:
    disktype: ssd

Спорідненість вузлів

Спорідненість вузлів дозволяє вам вказати правила, які обмежують, на яких вузлах може бути запланований ваш Pod. Ось приклад Podʼа, який віддає перевагу роботі на вузлах, позначених як такі, що розташовані на певному континенті, вибираючи на основі значення мітки topology.kubernetes.io/zone.

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: topology.kubernetes.io/zone
            operator: In
            values:
            - antarctica-east1
            - antarctica-west1
  containers:
  - name: with-node-affinity
    image: registry.k8s.io/pause:3.8

Спорідненість та антиспорідненість Podʼів

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

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - database
        topologyKey: topology.kubernetes.io/zone
  containers:
  - name: with-pod-affinity
    image: registry.k8s.io/pause:3.8

Tolerations

Tolerations дозволяють планувати Podʼи на вузли з відповідними taints:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: myapp
    image: nginx
  tolerations:
  - key: "key"
    operator: "Equal"
    value: "value"
    effect: "NoSchedule"

Для отримання додаткової інформації див. Призначення Podʼів до вузлів.

Накладні витрати на Pod

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

---
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: kvisor-runtime
handler: kvisor-runtime
overhead:
  podFixed:
    memory: "2Gi"
    cpu: "500m"
---
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  runtimeClassName: kvisor-runtime
  containers:
  - name: myapp
    image: nginx
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

Що далі