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

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

Огляд API

Цей розділ містить довідкову інформацію про API Kubernetes.

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

Довідник API Kubernetes містить список API для версії Kubernetes v1.30.

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

Версіювання API

Схеми серіалізації JSON та Protobuf слідують однаковими принципами для змін схеми. Наступні описи стосуються обох форматів.

Версіювання API та версіювання програмного забезпечення непрямо повʼязані. Пропозиція з версіювання API та релізів описує відносини між версіюванням API та версіюванням програмного забезпечення.

Різні версії API вказують на різні рівні стабільності та підтримки. Докладнішу інформацію про критерії кожного рівня можна знайти в документації API Changes.

Ось короткий огляд кожного рівня:

  • Alpha:

    • Назви версій містять alpha (наприклад, v1alpha1).
    • Вбудовані версії API рівня alpha типово вимкнені та повинні бути явно увімкнені в конфігурації kube-apiserver для використання.
    • Програмне забезпечення може містити помилки. Увімкнення функції може виявити помилки.
    • Підтримка alpha API може бути відключена в будь-який момент без попередження.
    • API може змінитися несумісним чином у подальших версіях програмного забезпечення без попередження.
    • Рекомендується використовувати програмне забезпечення тільки в тестових кластерах для короткочасного тестування через збільшений ризик помилок та відсутність довгострокової підтримки.
  • Beta:

    • Назви версій містять beta (наприклад, v2beta3).

    • Вбудовані версії API рівня beta типово вимкнені та повинні бути явно увімкнені в конфігурації kube-apiserver для використання (за винятком бета-версій API, представлених до Kubernetes 1.22, які були типово увімкнені).

    • Вбудовані версії API рівня beta мають максимальний термін служби 9 місяців або 3 мінорні випуски (в залежності, що довше), починаючи від введення до застаріння, і 9 місяців або 3 мінорні випуски (в залежності, що довше) від застаріння до вилучення.

    • Програмне забезпечення добре протестоване. Увімкнення функції вважається безпечним.

    • Підтримка функції не буде відключена, хоча можуть змінитися деталі.

    • Схема та/або семантика обʼєктів може змінюватися несумісним чином у подальших версіях API рівня beta або стабільного. Коли це відбувається, надаються інструкції з міграції. Адаптація до наступної версії API рівня beta або стабільного може вимагати редагування чи повторного створення обʼєктів API, і це може бути не простим. Міграція може вимагати перерви у роботі застосунків, які покладаються на цю функцію.

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

  • Stable:

    • Назва версії — vX, де X – це ціле число.
    • Стабільні версії API залишаються доступними для всіх майбутніх випусків в межах основної версії Kubernetes, і немає поточних планів щодо ревізії основної версії Kubernetes, що вилучає стабільні API.

Групи API

Групи API спрощують розширення API Kubernetes. Група API вказується в REST-шляху та в полі apiVersion серіалізованого обʼєкта.

У Kubernetes існує кілька груп API:

  • core (також називається legacy) група знаходиться за REST-шляхом /api/v1. Основна група не вказується як частина поля apiVersion, наприклад, apiVersion: v1.
  • Названі групи знаходяться за REST-шляхом /apis/$GROUP_NAME/$VERSION та використовують apiVersion: $GROUP_NAME/$VERSION (наприклад, apiVersion: batch/v1). Повний список підтримуваних груп API можна знайти в довіднику API Kubernetes.

Увімкнення чи вимкнення груп API

Деякі ресурси та групи API типово увімкнені. Ви можете увімкнути чи вимкнути їх, встановивши --runtime-config на API-сервері. Прапорець --runtime-config приймає розділені комами пари <key>[=<value>], що описують конфігурацію запуску API-сервера. Якщо частина =<value> пропущена, вона розглядається так, ніби вказано =true. Наприклад:

  • для вимкнення batch/v1 встановіть --runtime-config=batch/v1=false
  • для увімкнення batch/v2alpha1 встановіть --runtime-config=batch/v2alpha1
  • для увімкнення конкретної версії API, наприклад, storage.k8s.io/v1beta1/csistoragecapacities, встановіть --runtime-config=storage.k8s.io/v1beta1/csistoragecapacities

Збереження

Kubernetes зберігає свій серіалізований стан у термінах ресурсів API, записуючи їх в etcd.

Що далі

1 - Концепції API Kubernetes

API Kubernetes — це програмний інтерфейс на основі ресурсів (RESTful), який надається через HTTP. Він підтримує отримання, створення, оновлення та видалення основних ресурсів за допомогою стандартних HTTP-дієслів (POST, PUT, PATCH, DELETE, GET).

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

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

Ви можете переглянути Довідник API онлайн або прочитати далі, щоб дізнатися про API загалом.

Терміни API Kubernetes

Kubernetes зазвичай використовує загальноприйняту термінологію RESTful для опису концепцій API:

  • Тип ресурсу — це назва, що використовується в URL (pods, namespaces, services)
  • Усі типи ресурсів мають конкретне представлення (їх схему обʼєкта), яке називається kind
  • Список екземплярів типу ресурсу називається колекцією
  • Окремий екземпляр типу ресурсу називається ресурсом і зазвичай представляє обʼєкт
  • Для деяких типів ресурсів API включає один або більше субресурсів, які представлені як URI-шляхи після назви ресурсу

Більшість типів ресурсів API Kubernetes є обʼєктами — вони представляють конкретний екземпляр концепції у кластері, як-от pod або namespace. Невелика кількість типів ресурсів API є віртуальними, оскільки вони часто представляють операції над обʼєктами, а не самі обʼєкти, такі як перевірка дозволів (використання POST із JSON-кодованим тілом SubjectAccessReview для ресурсу subjectaccessreviews), або субресурс eviction у Pod (використовується для запуску виселення, ініційованого API).

Імена обʼєктів

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

Дієслова API

Майже всі типи ресурсів підтримують стандартні HTTP-дієслова — GET, POST, PUT, PATCH, та DELETE. Kubernetes також використовує власні дієслова, які часто пишуться малими літерами, щоб відрізняти їх від HTTP-дієслів.

Kubernetes використовує термін list для опису отримання колекції ресурсів, щоб відрізняти його від отримання одного ресурсу, яке зазвичай називається get. Якщо ви надішлете HTTP-запит GET із параметром ?watch, Kubernetes називає це watch, а не get (див. Ефективне виявлення змін для деталей).

Для запитів PUT Kubernetes внутрішньо класифікує їх як create або update залежно від стану наявного обʼєкта. Update відрізняється від patch; HTTP-дієслово для patch - PATCH.

URI ресурсів

Усі типи ресурсів або належать кластеру (/apis/GROUP/VERSION/*), або простору імен (/apis/GROUP/VERSION/namespaces/NAMESPACE/*). Тип ресурсу, що належить простору імен, буде видалений при видаленні простору імен, і доступ до цього типу ресурсу контролюється перевірками авторизації в межах простору імен.

Примітка: основні ресурси використовують /api замість /apis і пропускають сегмент GROUP.

Приклади:

  • /api/v1/namespaces
  • /api/v1/pods
  • /api/v1/namespaces/my-namespace/pods
  • /apis/apps/v1/deployments
  • /apis/apps/v1/namespaces/my-namespace/deployments
  • /apis/apps/v1/namespaces/my-namespace/deployments/my-deployment

Ви також можете отримати доступ до колекцій ресурсів (наприклад, переліку усіх Nodes). Наступні шляхи використовуються для отримання колекцій та ресурсів:

  • Ресурси кластерного рівня:

    • GET /apis/GROUP/VERSION/RESOURCETYPE — повертає колекцію ресурсів вказаного типу ресурсу
    • GET /apis/GROUP/VERSION/RESOURCETYPE/NAME — повертає ресурс з імʼям NAME вказаного типу ресурсу
  • Ресурси рівня простору імен:

    • GET /apis/GROUP/VERSION/RESOURCETYPE — повертає колекцію всіх екземплярів вказаного типу ресурсу в усіх просторах імен
    • GET /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE — повертає колекцію всіх екземплярів вказаного типу ресурсу в просторі імен NAMESPACE
    • GET /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME — повертає екземпляр вказаного типу ресурсу з імʼям NAME в просторі імен NAMESPACE

Оскільки простір імен є ресурсом кластерного рівня, ви можете отримати перелік (“колекцію”) всіх просторів імен за допомогою GET /api/v1/namespaces та деталі про конкретний простір імен за допомогою GET /api/v1/namespaces/NAME.

  • Субресурс кластерного рівня: GET /apis/GROUP/VERSION/RESOURCETYPE/NAME/SUBRESOURCE
  • Субресурс рівня простору імен: GET /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME/SUBRESOURCE

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

Ефективне виявлення змін

API Kubernetes дозволяє клієнтам зробити початковий запит на обʼєкт або колекцію, а потім відстежувати зміни з моменту цього запиту: це watch. Клієнти можуть відправити list або get і потім зробити наступний запит watch.

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

Коли ви надсилаєте запит watch, сервер API відповідає потоком змін. Ці зміни перераховують результати операцій (таких як create, delete, та update), що відбулись після resourceVersion, значення якого було вказане як параметр до запиту watch. Загальний механізм watch дозволяє клієнту отримати поточний стан і потім підписатися на подальші зміни, не пропускаючи жодної події.

Якщо клієнт watch відʼєднується, тоді цей клієнт може розпочати новий сеанс watch з останнього повернутого resourceVersion; клієнт також може виконати новий запити get/list і розпочати знову. Див. Семантика версій ресурсів для отримання детальнішої інформації.

Наприклад:

  1. Отримання списку всіх Podʼів у вказаному просторі імен.

    GET /api/v1/namespaces/test/pods
    ---
    200 OK
    Content-Type: application/json
    
    {
      "kind": "PodList",
      "apiVersion": "v1",
      "metadata": {"resourceVersion":"10245"},
      "items": [...]
    }
    
  2. Починаючи з версії ресурсу 10245, отримуйте сповіщення про будь-які операції API (такі як create, delete, patch або update), що впливають на Podʼи у просторі імен test. Кожне сповіщення про зміну — це документ JSON. Тіло відповіді HTTP (надається як application/json) складається із серії документів JSON.

    GET /api/v1/namespaces/test/pods?watch=1&resourceVersion=10245
    ---
    200 OK
    Transfer-Encoding: chunked
    Content-Type: application/json
    
    {
      "type": "ADDED",
      "object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "10596", ...}, ...}
    }
    {
      "type": "MODIFIED",
      "object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "11020", ...}, ...}
    }
    ...
    

Сервер Kubernetes буде зберігати історичний запис змін лише протягом обмеженого часу. Кластери, що використовують etcd 3, стандартно зберігають зміни за останні 5 хвилин. Коли запитувані операції watch не вдаються через недоступність історичної версії цього ресурсу, клієнти повинні обробляти цей випадок, розпізнаючи код статусу 410 Gone, очищаючи свій локальний кеш, виконуючи новий get або list запит, і починаючи watch з resourceVersion, яке було повернуто.

Для підписки на колекції бібліотеки клієнтів Kubernetes зазвичай пропонують певну форму стандартного інструменту для логіки list-потім-watch. (У бібліотеці клієнтів Go це називається Reflector і знаходиться в пакеті k8s.io/client-go/tools/cache).

Закладки для Watch

Щоб зменшити вплив короткого вікна історії, API Kubernetes надає подію спостереження під назвою BOOKMARK. Це особливий вид події, що позначає, що всі зміни до вказаної клієнтом resourceVersion вже були надіслані. Документ, що представляє подію BOOKMARK, має тип який отримується запитом, але включає лише поле .metadata.resourceVersion. Наприклад:

GET /api/v1/namespaces/test/pods?watch=1&resourceVersion=10245&allowWatchBookmarks=true
---
200 OK
Transfer-Encoding: chunked
Content-Type: application/json

{
  "type": "ADDED",
  "object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "10596", ...}, ...}
}
...
{
  "type": "BOOKMARK",
  "object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "12746"} }
}

Як клієнт, ви можете запитувати події BOOKMARK, встановлюючи параметр запиту allowWatchBookmarks=true у запиті watch, але не слід припускати, що закладки будуть повертатися з певним інтервалом, і клієнти не можуть очікувати, що сервер API надішле будь-яку подію BOOKMARK, навіть якщо її було запитано.

Потокові списки

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

У великих кластерах отримання колекції деяких типів ресурсів може призвести до значного збільшення використання ресурсів (переважно RAM) панелі управління. Щоб зменшити цей вплив та спростити користування шаблоном list + watch, Kubernetes v1.27 вводить альфа-функцію підтримки запиту початкового стану (раніше запитуваного через запит list) як частини запиту watch.

За умови, що ввімкнено функціонал WatchList, це можна зробити, вказавши sendInitialEvents=true як параметр рядка запиту у запиті watch. Якщо встановлено, сервер API починає потік спостереження з синтетичних початкових подій (типу ADDED) для побудови всього стану всіх наявних обʼєктів, після чого йде подія BOOKMARK (якщо запитано через параметр allowWatchBookmarks=true). Подія закладки включає версію ресурсу, до якої його було синхронізовано. Після надсилання події закладки сервер API продовжує роботу як для будь-якого іншого запиту watch.

Коли ви встановлюєте sendInitialEvents=true у рядку запиту, Kubernetes також вимагає, щоб ви встановили resourceVersionMatch до значення NotOlderThan. Якщо ви вказали resourceVersion у рядку запиту без значення або не вказали його взагалі, це інтерпретується як запит на узгоджене читання (consistent read); подія закладки надсилається, коли стан синхронізовано щонайменше до моменту узгодженого читання з моменту, коли запит почав оброблятися. Якщо ви вказуєте resourceVersion (у рядку запиту), подія закладки надсилається, коли стан синхронізовано щонайменше до вказаної версії ресурсу.

Приклад

Приклад: ви хочете спостерігати за колекцією Podʼів. Для цієї колекції поточна версія ресурсу становить 10245, і є два Podʼи: foo та bar. Надсилання наступного запиту (який явно запитує узгоджене читання, встановлюючи порожню версію ресурсу за допомогою resourceVersion=) може призвести до наступної послідовності подій:

GET /api/v1/namespaces/test/pods?watch=1&sendInitialEvents=true&allowWatchBookmarks=true&resourceVersion=&resourceVersionMatch=NotOlderThan
---
200 OK
Transfer-Encoding: chunked
Content-Type: application/json

{
  "type": "ADDED",
  "object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "8467", "name": "foo"}, ...}
}
{
  "type": "ADDED",
  "object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "5726", "name": "bar"}, ...}
}
{
  "type": "BOOKMARK",
  "object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "10245"} }
}
...
<далі йде звичайний потік спостереження, починаючи з resourceVersion="10245">

Стиснення відповідей

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

Опція APIResponseCompression дозволяє серверу API стискати відповіді на запити get та list, зменшуючи використання мережевої пропускної здатності та покращуючи продуктивність у великих кластерах. Її стандартно увімкнено з Kubernetes 1.16 і її можна вимкнути додаванням APIResponseCompression=false у прапорець --feature-gates на сервері API.

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

Щоб перевірити, чи працює APIResponseCompression, ви можете надіслати запит get або list на сервер API з заголовком Accept-Encoding та перевірити розмір відповіді та заголовки. Наприклад:

GET /api/v1/pods
Accept-Encoding: gzip
---
200 OK
Content-Type: application/json
content-encoding: gzip
...

Заголовок content-encoding вказує, що відповідь стиснута за допомогою gzip.

Отримання великих наборів результатів частинами

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

У великих кластерах отримання колекції деяких типів ресурсів може призвести до дуже великих відповідей, що може вплинути на сервер та клієнта. Наприклад, у кластері може бути десятки тисяч Podʼів, кожен з яких еквівалентний приблизно 2 КіБ у форматі JSON. Отримання всіх Podʼів через всі простори імен може призвести до дуже великої відповіді (10-20 МБ) та спожити багато ресурсів сервера.

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

Ви можете запитувати сервер API для обробки list запиту, використовуючи сторінки (які Kubernetes називає chunks). Щоб отримати одну колекцію частинами, підтримуються два параметри запиту limit та continue у запитах до колекцій, і поле відповіді continue повертається з усіх операцій list у полі metadata колекції. Клієнт повинен вказати максимальну кількість результатів, яку він бажає отримати у кожній частині за допомогою limit, і сервер поверне кількість ресурсів у результаті не більше limit та включить значення continue, якщо у колекції є більше ресурсів.

Як клієнт API, ви можете передати це значення continue серверу API у наступному запиті, щоб вказати серверу повернути наступну сторінку (chunk) результатів. Продовжуючи до тих пір, поки сервер не поверне порожнє значення continue, ви можете отримати всю колекцію.

Як і у випадку з операцією watch, токен continue закінчується через короткий проміжок часу (стандартно 5 хвилин) і повертає 410 Gone, якщо більше результатів не може бути повернуто. У цьому випадку клієнт повинен буде почати з початку або опустити параметр limit.

Наприклад, якщо у кластері є 1,253 Podʼів і ви хочете отримувати частини по 500 Podʼів за раз, запитуйте ці частини наступним чином:

  1. Отримати всі Podʼи в кластері, отримуючи до 500 Podʼів за раз.

    GET /api/v1/pods?limit=500
    ---
    200 OK
    Content-Type: application/json
    
    {
      "kind": "PodList",
      "apiVersion": "v1",
      "metadata": {
        "resourceVersion":"10245",
        "continue": "ENCODED_CONTINUE_TOKEN",
        "remainingItemCount": 753,
        ...
      },
      "items": [...] // повертає Podʼи 1-500
    }
    
  2. Продовжити попередній запит, отримуючи наступний набір з 500 Podʼів.

    GET /api/v1/pods?limit=500&continue=ENCODED_CONTINUE_TOKEN
    ---
    200 OK
    Content-Type: application/json
    
    {
      "kind": "PodList",
      "apiVersion": "v1",
      "metadata": {
        "resourceVersion":"10245",
        "continue": "ENCODED_CONTINUE_TOKEN_2",
        "remainingItemCount": 253,
        ...
      },
      "items": [...] // повертає Podʼи 501-1000
    }
    
  3. Продовжити попередній запит, отримуючи останні 253 Podʼів.

    GET /api/v1/pods?limit=500&continue=ENCODED_CONTINUE_TOKEN_2
    ---
    200 OK
    Content-Type: application/json
    
    {
      "kind": "PodList",
      "apiVersion": "v1",
      "metadata": {
        "resourceVersion":"10245",
        "continue": "", // токен continue порожній, тому що ми досягли кінця списку
        ...
      },
      "items": [...] // повертає Podʼи 1001-1253
    }
    

Зверніть увагу, що resourceVersion колекції залишається постійним в кожному запиті, що вказує на те, що сервер показує вам узгоджену копію Podʼів. Podʼи, що створюються, оновлюються або видаляються після версії 10245, не будуть показані, якщо ви не зробите окремий запит list без токена continue. Це дозволяє вам розбивати великі запити на менші частини, а потім виконувати операцію watch на повному наборі, не пропускаючи жодного оновлення.

Поле remainingItemCount вказує кількість наступних елементів у колекції, які не включені у цю відповідь. Якщо запит list містив мітки або поля селектори, тоді кількість залишкових елементів невідома, і сервер API не включає поле remainingItemCount у свою відповідь. Якщо list запит завершено (або тому, що він не розбивається на частини, або тому, що це остання частина), то більше немає залишкових елементів, і сервер API не включає поле remainingItemCount у свою відповідь. Очікуване використання `remainingItemCount — оцінка розміру колекції.

Колекції

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

Коли ви надсилаєте запит API для певного типу, всі елементи, повернуті цим запитом, є цього типу. Наприклад, коли ви надсилаєте list Services, відповідь колекції має kind, встановлений на ServiceList; кожен елемент у цій колекції представляє один Service. Наприклад:

GET /api/v1/services
{
  "kind": "ServiceList",
  "apiVersion": "v1",
  "metadata": {
    "resourceVersion": "2947301"
  },
  "items": [
    {
      "metadata": {
        "name": "kubernetes",
        "namespace": "default",
...
      "metadata": {
        "name": "kube-dns",
        "namespace": "kube-system",
...

Є десятки типів колекцій (таких як PodList, ServiceList та NodeList), визначених в API Kubernetes. Ви можете отримати більше інформації про кожен тип колекції з довідника Kubernetes API.

Деякі інструменти, такі як kubectl, представляють механізм колекцій Kubernetes трохи інакше, ніж сам API Kubernetes. Оскільки вихідні дані kubectl можуть включати відповідь з декількох операцій list на рівні API, kubectl представляє список елементів, використовуючи kind: List. Наприклад:

kubectl get services -A -o yaml
apiVersion: v1
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""
items:
- apiVersion: v1
  kind: Service
  metadata:
    creationTimestamp: "2021-06-03T14:54:12Z"
    labels:
      component: apiserver
      provider: kubernetes
    name: kubernetes
    namespace: default
...
- apiVersion: v1
  kind: Service
  metadata:
    annotations:
      prometheus.io/port: "9153"
      prometheus.io/scrape: "true"
    creationTimestamp: "2021-06-03T14:54:14Z"
    labels:
      k8s-app: kube-dns
      kubernetes.io/cluster-service: "true"
      kubernetes.io/name: CoreDNS
    name: kube-dns
    namespace: kube-system

Отримання ресурсів у вигляді таблиць

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

Щоб уникнути можливих обмежень, описаних вище, клієнти можуть запитувати табличну репрезентацію обʼєктів, делегуючи серверу специфічні деталі виводу. API Kubernetes реалізує стандартні HTTP-узгодження щодо типу контенту: передача заголовка Accept, що містить значення application/json;as=Table;g=meta.k8s.io;v=v1 з запитом GET попросить сервер повернути обʼєкти у форматі таблиці.

Наприклад, список усіх Podʼів у кластері у форматі таблиці.

GET /api/v1/pods
Accept: application/json;as=Table;g=meta.k8s.io;v=v1
---
200 OK
Content-Type: application/json

{
    "kind": "Table",
    "apiVersion": "meta.k8s.io/v1",
    ...
    "columnDefinitions": [
        ...
    ]
}

Для типів ресурсів API, які не мають табличного визначення, відомого панелі управління, сервер API повертає стандартну таблицю, яка складається з полів name та creationTimestamp ресурсу.

GET /apis/crd.example.com/v1alpha1/namespaces/default/resources
---
200 OK
Content-Type: application/json
...

{
    "kind": "Table",
    "apiVersion": "meta.k8s.io/v1",
    ...
    "columnDefinitions": [
        {
            "name": "Name",
            "type": "string",
            ...
        },
        {
            "name": "Created At",
            "type": "date",
            ...
        }
    ]
}

Не всі типи ресурсів API підтримують табличну відповідь; наприклад, CustomResourceDefinitions можуть не визначати відповідність полів таблиці, а APIService, що розширює основний API Kubernetes може взагалі не обслуговувати табличні відповіді. Якщо ви створюєте клієнта, що використовує інформацію з таблиці та який повинен працювати з усіма типами ресурсів, включаючи розширення, ви повинні робити запити, які вказують кілька типів контенту у заголовку Accept. Наприклад:

Accept: application/json;as=Table;g=meta.k8s.io;v=v1, application/json

Альтернативні представлення ресурсів

Типово Kubernetes повертає обʼєкти, серіалізовані у форматі JSON з типом контенту application/json. Це станадртний формат серіалізації для API. Однак клієнти можуть запросити більш ефективне представлення у форматі Protobuf цих обʼєктів для покращення продуктивності в масштабі. API Kubernetes реалізує стандартні HTTP-узгодження щодо типу контенту: передача заголовка Accept з викликом GET запросить сервер повернути відповідь у вашому бажаному медіа-типі, тоді як надсилання обʼєкта у форматі Protobuf на сервер для виклику PUT або POST означає, що ви повинні відповідним чином встановити заголовок Content-Type.

Сервер поверне відповідь з заголовком Content-Type, якщо запитаний формат підтримується, або помилку 406 Not acceptable, якщо жоден з медіа-типів, які ви запросили, не підтримується. Усі вбудовані типи ресурсів підтримують медіа-тип application/json.

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

Наприклад:

  1. Список всіх Podʼів у кластері у форматі Protobuf.

    GET /api/v1/pods
    Accept: application/vnd.kubernetes.protobuf
    ---
    200 OK
    Content-Type: application/vnd.kubernetes.protobuf
    
    ... binary encoded PodList object
    
  2. Створення Podʼа, надсиланням даних у форматі Protobuf на сервер, але із запитом відповідіу форматі JSON.

    POST /api/v1/namespaces/test/pods
    Content-Type: application/vnd.kubernetes.protobuf
    Accept: application/json
    ... binary encoded Pod object
    ---
    200 OK
    Content-Type: application/json
    
    {
      "kind": "Pod",
      "apiVersion": "v1",
      ...
    }
    

Не всі типи ресурсів API підтримують Protobuf; зокрема, Protobuf недоступний для ресурсів, визначених як CustomResourceDefinitions або обслуговуються через шар агрегації. Як клієнт, який може працювати з розширеними типами, ви повинні вказати кілька типів контенту у заголовку запиту Accept для підтримки відкату до JSON. Наприклад:

Accept: application/vnd.kubernetes.protobuf, application/json

Кодування Protobuf у Kubernetes

Kubernetes використовує обгортку для кодування відповідей Protobuf. Ця обгортка починається з 4-байтового магічного числа для ідентифікації контенту на диску або в etcd як Protobuf (на відміну від JSON), а потім слідує Protobuf-кодована обгортка повідомлення, яка описує кодування і тип основного обʼєкта, а потім містить сам обʼєкт.

Формат обгортки виглядає так:

Чотирибайтовий префікс магічного числа:
  Байти 0-3: "k8s\x00" [0x6b, 0x38, 0x73, 0x00]

Кодоване повідомлення Protobuf з наступним IDL:
  message Unknown {
    // typeMeta повинен мати рядкові значення для "kind" та "apiVersion", встановлені на обʼєкті JSON
    optional TypeMeta typeMeta = 1;

    // raw буде містити повністю серіалізований обʼєкт у форматі Protobuf. Дивіться визначення Protobuf у клієнтських бібліотеках для певного kind.
    optional bytes raw = 2;

    // contentEncoding — це кодування, що використовується для raw даних. Відсутність означає відсутність кодування.
    optional string contentEncoding = 3;

    // contentType — це метод серіалізації, використаний для серіалізації 'raw'. Відсутність означає application/vnd.kubernetes.protobuf
    // і зазвичай опускається.
    optional string contentType = 4;
  }

  message TypeMeta {
    // apiVersion — це група/версія для цього типу
    optional string apiVersion = 1;
    // kind — це назва схеми обʼєкта. Визначення Protobuf повинно існувати для цього обʼєкта.
    optional string kind = 2;
  }

Видалення ресурсів

Коли ви видаляєте ресурс, цей процес проходить у два етапи:

  1. Завершення (finalization)
  2. Видалення (removal)
{
  "kind": "ConfigMap",
  "apiVersion": "v1",
  "metadata": {
    "finalizers": ["url.io/neat-finalization", "other-url.io/my-finalizer"],
    "deletionTimestamp": null,
  }
}

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

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

Поле .metadata.finalizers є спільним: будь-який áктор з дозволом може змінювати його порядок. Якби список завершувачів оброблявся по порядку, це могло б призвести до ситуації, коли компонент, відповідальний за перший завершувач у списку, чекає на якийсь сигнал (значення поля, зовнішню систему або інше), що створюється компонентом, відповідальним за завершувач пізніше у списку, що призводить до застярягання всього списку.

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

Після видалення останнього завершувача ресурс фактично видаляється з etcd.

API для одного ресурсу

API Kubernetes з дієсловами get, create, update, patch, delete та proxy підтримують тільки одиничні ресурси. Ці дієслова з підтримкою одиничного ресурсу не підтримують надсилання кількох ресурсів разом в упорядкованому або неупорядкованому списку чи транзакції.

Коли клієнти (включаючи kubectl) виконують дії з набором ресурсів, клієнт робить серію одиничних API запитів до ресурсу, а потім, за потреби, агрегує відповіді.

На відміну від цього, API Kubernetes з дієсловами list і watch дозволяють отримувати кілька ресурсів, а deletecollection дозволяє видаляти кілька ресурсів.

Валідація полів

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

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

Типово, сервер API видаляє поля, які він не розпізнає, з вхідних даних, які він отримує (наприклад, тіло JSON запиту PUT).

Є дві ситуації, коли сервер API видаляє поля, які ви надали у HTTP-запиті.

Ці ситуації такі:

  1. Поле не розпізнається, оскільки воно не входить до схеми OpenAPI ресурсу. (Одним винятком є CRDs, які явно обирають не обрізати невідомі поля через x-kubernetes-preserve-unknown-fields).
  2. Поле дублюється в обʼєкті.

Валідація для нерозпізнаних або дубльованих полів

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

З версії 1.25 і далі, нерозпізнані або дубльовані поля в обʼєкті виявляються через валідацію на сервері при використанні HTTP-дієслів, які можуть надсилати дані (POST, PUT та PATCH). Можливі рівні валідації: Ignore, Warn (стандартно) та Strict.

Ignore
Сервер API успішно обробляє запит так, ніби у ньому немає неправильних полів, відкидаючи всі невідомі та дубльовані поля та не повідомляючи про це.
Warn
(Стандартно) Сервер API успішно обробляє запит і надсилає клієнту попередження. Попередження надсилається за допомогою заголовка відповіді Warning:, додаючи один елемент попередження для кожного невідомого або дубльованого поля. Для отримання додаткової інформації про попередження та API Kubernetes дивіться статтю блогу Warning: Helpful Warnings Ahead.
Strict
Сервер API відхиляє запит з помилкою 400 Bad Request, коли виявляє будь-які невідомі або дубльовані поля. Повідомлення відповіді від сервера API вказує всі невідомі або дубльовані поля, які сервер API виявив.

Рівень валідації полів встановлюється параметром запиту fieldValidation.

Інструменти, які надсилають запити на сервер (такі як kubectl), можуть встановлювати свої власні типові значення, які відрізняються від рівня валідації Warn, що стандартно використовується сервером API.

Інструмент kubectl використовує прапорець --validate для встановлення рівня валідації полів. Він приймає значення ignore, warn та strict, а також приймає значення true (еквівалентно strict) і false (еквівалентно ignore). Станадртне налаштування валідації для kubectl — це --validate=true, що означає сувору валідацію полів на стороні сервера.

Коли kubectl не може підключитися до сервера API з валідацією полів (сервери API до Kubernetes 1.27), він повернеться до використання валідації на стороні клієнта. Валідація на стороні клієнта буде повністю видалена у майбутній версії kubectl.

Dry-run

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

При використанні HTTP-дієслів, які можуть змінювати ресурси (POST, PUT, PATCH і DELETE), ви можете надіслати свій запит у режимі dry run. Режим dry run допомагає оцінити запит через типові етапи обробки запиту (ланцюг допумків, валідацію, конфлікти злиття) аж до збереження обʼєктів у сховищі. Тіло відповіді на запит є максимально наближеним до відповіді у режимі non-dry-run. Kubernetes гарантує, що dry-run запити не будуть збережені в сховищі і не матимуть жодних інших побічних ефектів.

Виконання dry-run запиту

Dry-run активується встановленням параметра запиту dryRun. Цей параметр є рядковим, діє як перерахування, і єдині прийнятні значення:

[без значення]
Дозволити побічні ефекти. Ви запитуєте це за допомогою рядка запиту типу ?dryRun або ?dryRun&pretty=true. Відповідь є остаточним обʼєктом, який був би збережений, або помилкою, якщо запит не може бути виконаний.
All
Кожен етап виконується як зазвичай, за винятком кінцевого етапу збереження, де побічні ефекти запобігаються.

Коли ви встановлюєте ?dryRun=All, усі відповідні контролерів допуску виконуються, перевіряючи запит після зміни, злиття виконується для PATCH, поля заповнюються станадартними значеннями, і проводиться валідація схеми. Зміни не зберігаються в базовому сховищі, але остаточний обʼєкт, який був би збережений, все ще повертається користувачеві разом із звичайним кодом статусу.

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

Приклад dry-run запиту, який використовує ?dryRun=All:

POST /api/v1/namespaces/test/pods?dryRun=All
Content-Type: application/json
Accept: application/json

Відповідь буде виглядати так само, як для запиту без dry-run, але значення деяких згенерованих полів можуть відрізнятися.

Згенеровані значення

Деякі значення обʼєкта зазвичай генеруються перед його збереженням. Важливо не покладатися на значення цих полів, встановлених dry-run запитом, оскільки ці значення, ймовірно, будуть відрізнятися в dry-run режимі від реального запиту. Деякі з цих полів:

  • name: якщо встановлено generateName, name матиме унікальне випадкове імʼя
  • creationTimestamp / deletionTimestamp: фіксує час створення/видалення
  • UID: унікально ідентифікує обʼєкт і генерується випадково (недетерміновано)
  • resourceVersion: відстежує збережену версію обʼєкта
  • Будь-яке поле, встановлене мутаційним контролером допуску
  • Для ресурсу Service: Порти або IP-адреси, які kube-apiserver надає обʼєктам Service

Авторизація dry-run

Авторизація для dry-run і non-dry-run запитів ідентична. Таким чином, щоб виконати dry-run запит, ви повинні мати дозвіл на виконання non-dry-run запиту.

Наприклад, щоб виконати dry-run patch для Deployment, ви повинні мати дозвіл на виконання цього patch. Ось приклад правила для Kubernetes RBAC, що дозволяє робити patch для Deployment:

rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["patch"]

Дивіться Огляд авторизації.

Оновлення наявних ресурсів

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

Ви можете перезаписати (оновити) наявний ресурс, наприклад, ConfigMap, використовуючи HTTP PUT. Для запиту PUT відповідальність за вказання resourceVersion (отриманого з обʼєкта, що оновлюється) лежить на клієнті. Kubernetes використовує інформацію resourceVersion, щоб сервер API міг виявити втрачені оновлення і відхилити запити від клієнта, який не актуальний для кластера. У разі зміни ресурсу (коли resourceVersion, надана клієнтом, застаріла), сервер API повертає відповідь з помилкою 409 Conflict.

Замість надсилання запиту PUT клієнт може надіслати інструкцію серверу API для накладання патчу до наявного ресурсу. Патч зазвичай підходить, якщо зміна, яку клієнт хоче внести, не залежить від наявних даних. Клієнти, яким потрібне ефективне виявлення втрачених оновлень, повинні розглянути можливість зробити свій запит умовним до існуючого resourceVersion (або HTTP PUT, або HTTP PATCH), а потім обробити будь-які повтори, які можуть знадобитися у разі конфлікту.

API Kubernetes підтримує чотири різні операції PATCH, які визначаються відповідним заголовком HTTP Content-Type:

application/apply-patch+yaml
Серверне застосування YAML (специфічне розширення Kubernetes, засноване на YAML). Всі документи JSON є дійсними в YAML, тому ви також можете надавати JSON, використовуючи цей тип медіа. Дивіться серіалізація для серверного застосування для отримання додаткової інформації. Для Kubernetes це операція створення, якщо обʼєкт не існує, або операція накладання патчу, якщо обʼєкт вже існує.
application/json-patch+json
JSON Patch, як визначено в RFC6902. JSON патч — це послідовність операцій, які виконуються з ресурсом; наприклад, {"op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ]}. Для Kubernetes це операція накладання патчу. Патч з використанням application/json-patch+json може включати умови для перевірки консистентності, дозволяючи операції зазнати невдачі, якщо ці умови не виконуються (наприклад, щоб уникнути втрати оновлення).
application/merge-patch+json
JSON Merge Patch, як визначено в RFC7386. JSON Merge Patch фактично є частковим представленням ресурсу. Поданий JSON комбінується з поточним ресурсом для створення нового, а потім новий зберігається. Для Kubernetes це операція накладання патчу.
application/strategic-merge-patch+json
Strategic Merge Patch (специфічне розширення Kubernetes на основі JSON). Strategic Merge Patch — це власна реалізація JSON Merge Patch. Ви можете використовувати Strategic Merge Patch лише з вбудованими API або з агрегованими серверами API, які мають спеціальну підтримку для цього. Ви не можете використовувати application/strategic-merge-patch+json з будь-яким API, визначеним за допомогою CustomResourceDefinition.

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

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

Дивіться Серверне застосування для отримання додаткової інформації.

Вибір механізму оновлення

HTTP PUT для заміни наявного ресурсу

Операція оновлення (HTTP PUT) проста у виконанні та гнучка, але має недоліки:

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

HTTP PATCH з використанням JSON Patch

Оновлення патчем корисне через такі причини:

  • Оскільки ви надсилаєте лише різницю, ви маєте менше даних для надсилання у запиті PATCH.
  • Ви можете робити зміни, які ґрунтуються на наявних значеннях, наприклад, копіювати значення певного поля в анотацію.
  • На відміну від оновлення (HTTP PUT), ваші зміни можуть відбуватися відразу навіть при частих змінах не повʼязаних полів: зазвичай вам не потрібно повторювати спроби.
    • Вам все ще може знадобитися вказати resourceVersion (щоб відповідати існуючому обʼєкту), якщо ви хочете бути особливо обережними, щоб уникнути втрати оновлень.
    • Все ж це хороша практика написати деяку логіку повторної спроби у випадку помилок.
  • Ви можете використовувати тестові умови для обережного створення конкретних умов оновлення. Наприклад, ви можете збільшити лічильник без його читання, якщо існуюче значення відповідає вашим очікуванням. Ви можете це зробити без ризику втрати оновлення, навіть якщо обʼєкт змінився іншим чином з моменту вашого останнього запису до нього. (Якщо тестова умова не виконається, ви можете використовувати поточне значення і потім записати змінене число).

Проте:

  • Вам потрібна більша локальна (клієнтська) логіка для створення патчу; дуже корисно мати реалізацію бібліотеки JSON Patch або навіть створення JSON Patch специально для Kubernetes.
  • Як автору клієнтського програмного забезпечення, вам потрібно бути обережним при створенні патчу (тіла запиту HTTP), щоб не видаляти поля (порядок операцій має значення).

HTTP PATCH з використанням Server-Side Apply

Серверне застосування має чіткі переваги:

  • Одноразовий прохід веред-назад: зазвичай спочатку не потребує виконання GET запиту.
    • і ви все ще можете виявляти конфлікти для неочікуваних змін
    • у вас є можливість примусово перезаписати конфлікт, якщо це доцільно
  • Реалізація клієнта легка для створення
  • Ви отримуєте атомарну операцію створення або оновлення без додаткових зусиль (аналогічно UPSERT у деяких діалектах SQL).

Проте:

  • Серверне застосування зовсім не працює для змін полів, які залежать від поточного значення обʼєкта.
  • Ви можете застосовувати оновлення лише до обʼєктів. Деякі ресурси в HTTP API Kubernetes не є обʼєктами (вони не мають поля .metadata), а серверне застосування стосується лише обʼєктів Kubernetes.

Версії ресурсів

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

Не слід припускати, що версії ресурсів є числовими або можуть бути впорядковані. API-клієнти можуть порівнювати лише дві версії ресурсів на рівність (це означає, що ви не можете порівнювати версії ресурсів за відносними значеннями "більше" або "менше").

Поля resourceVersion в метаданих

Клієнти знаходять версії ресурсів в ресурсах, включаючи ресурси з потоку відповіді під час спостереження (watch) або при отримані переліку (list) ресурсів.

v1.meta/ObjectMeta — metadata.resourceVersion екземпляра ресурсу ідентифікує версію ресурсу, на якій останній раз він був змінений.

v1.meta/ListMeta — metadata.resourceVersion колекції ресурсів (відповідь на перелік (list)) ідентифікує версію ресурсу, на якій була створена колекція.

Параметри resourceVersion у рядках запитів

Операції отримання (get), переліку (list) та спостереження (watch) підтримують параметр resourceVersion. Починаючи з версії v1.19, сервери API Kubernetes також підтримують параметр resourceVersionMatch у запитах list.

Сервер API інтерпретує параметр resourceVersion по-різному, залежно від операції, яку ви запитуєте, та від значення resourceVersion. Якщо ви встановлюєте resourceVersionMatch, то це також впливає на спосіб порівняння.

Семантика для операцій get та list

Для операцій get та list, семантика параметра resourceVersion така:

get:

resourceVersion невстановленоresourceVersion="0"resourceVersion="{значення, відмінне від 0}"
НайновішийБудь-якеНе старше

list:

Починаючи з версії v1.19, сервери API Kubernetes підтримують параметр resourceVersionMatch у запитах list. Якщо ви встановлюєте як resourceVersion, так і resourceVersionMatch, то параметр resourceVersionMatch визначає, як сервер API інтерпретує resourceVersion.

Вам завжди слід встановлювати параметр resourceVersionMatch, коли ви встановлюєте resourceVersion у запиті list. Однак будьте готові обробляти випадок, де сервер API, що відповідає, не підтримує resourceVersionMatch та ігнорує його.

Крім випадків сильних вимог до консистентності, використання resourceVersionMatch=NotOlderThan та відомої resourceVersion є бажаним, оскільки це може забезпечити кращу продуктивність та масштабованість вашого кластеру, ніж залишати resourceVersion і resourceVersionMatch невстановленими, що вимагає отримання кворуму для обслуговування.

Встановлення параметра resourceVersionMatch без встановлення resourceVersion є недійсним.

Ця таблиця пояснює поведінку запитів list з різними комбінаціями resourceVersion та resourceVersionMatch:

Параметри resourceVersionMatch та розбиття на сторінки для list
Параметр resourceVersionMatchПараметри розбиття на сторінкиresourceVersion не встановленоresourceVersion="0"resourceVersion="{значення, відмінне від 0}"
не встановленоlimit не встановленоНайновішийAnyНе старше
не встановленоlimit=<n>, continue не встановленоНайновішийAnyТочно
не встановленоlimit=<n>, continue=<токен>Continue Token, ExactНедійсний, розглядається як Continue Token, ExactНедійсний, HTTP 400 Bad Request
resourceVersionMatch=Exactlimit не встановленоНедійснийНедійснийExact
resourceVersionMatch=Exactlimit=<n>, continue не встановленоНедійснийНедійснийExact
resourceVersionMatch=NotOlderThanlimit не встановленоНедійснийAnyNotOlderThan
resourceVersionMatch=NotOlderThanlimit=<n>, continue не встановленоНедійснийAnyNotOlderThan

Сенс семантики операцій get та list такий:

Any
Повернути дані на будь-якій версії ресурсу. Вибирається найновіша доступна версія ресурсу, але не потрібна сильна консистентність; дані на будь-якій версії ресурсу можуть бути обслуговані. Є можливість отримати дані на значно старішій версії ресурсу, яку клієнт раніше спостерігав, особливо в конфігураціях високої доступності через розділи або застарілі кеші. Клієнти, які не можуть терпіти це, не повинні використовувати цю семантику.
Найновіший
Повернути дані на найновішій версії ресурсу. Повернені дані повинні бути консистентними (детально: обслуговуються з etcd за допомогою кворумного читання).
NotOlderThan
Повернути дані, які є принаймні так новими, як наданий resourceVersion. Вибирається найновіша доступна інформація, але будь-яка інформація, яка не старше наданої resourceVersion, може бути обслугована. Для запитів list до серверів, які підтримують параметр resourceVersionMatch, це гарантує, що .metadata.resourceVersion колекції не старше вказаної resourceVersion, але не надає гарантії щодо .metadata.resourceVersion будь-яких елементів у цій колекції.
Exact
Повернути дані на точній версії ресурсу, яка надана. Якщо надана resourceVersion недоступна, сервер відповідає HTTP 410 "Відсутній". Для запитів list до серверів, які підтримують параметр resourceVersionMatch, це гарантує, що .metadata.resourceVersion колекції співпадає з resourceVersion, яку ви запросили у рядку запиту. Ця гарантія не поширюється на .metadata.resourceVersion будь-яких елементів у цій колекції.
Continue Token, Exact
Повернути дані на версії ресурсу початкового виклику list розділеного на сторінки. Повернені продовження токенів відповідальні за відстеження початково наданої версії ресурсу для всіх викликів list розділених на сторінки після початкового виклику list.

При використанні resourceVersionMatch=Не старше та встановленому ліміті клієнти мають обробляти відповіді HTTP 410 "Gone". Наприклад, клієнт може повторно спробувати з новішою resourceVersion або використовувати resourceVersion="".

При використанні resourceVersionMatch=Точно та не встановленому ліміті, клієнти мають перевірити, що .metadata.resourceVersion колекції співпадає з запитаною resourceVersion, і обробити випадок, коли це не так. Наприклад, клієнт може використовувати запит з встановленим лімітом.

Семантика для операції watch

Для операцій watch, семантика параметра resourceVersion така:

watch:

resourceVersion для watch
resourceVersion невстановленоresourceVersion="0"resourceVersion="{значення, відмінне від 0}"
Отримати стан і почати з найновішогоОтримати стан і почати з будь-якогоПочати точно з

Сенс цієї семантики для watch такий:

Отримати стан і почати з будь-якого
Почати watch на будь-якій версії ресурсу; найбільш нова доступна версія є переважною, але не обовʼязковою. Дозволено будь-яку початкову версію ресурсу. Можливо, що watch почнеться на набагато старішій версії ресурсу, яку клієнт раніше спостерігав, особливо в конфігураціях високої доступності через розділи або застарілі кеші. Клієнти, які не можуть терпіти таке відмотування назад, не повинні починати watch з цією семантикою. Для встановлення початкового стану, watch починається з синтетичних подій "Added" для всіх екземплярів ресурсів, які існують на початковій версії ресурсу. Усі наступні події watch стосуються всіх змін, що сталися після початкової версії ресурсу, з якої почався watch.
Отримати стан і почати з найновішого
Почати watch на найбільш новій версії ресурсу, яка повинна бути консистентною (детально: обслуговується з etcd за допомогою отримання кворуму). Для встановлення початкового стану watch починається з синтетичних подій "Added" для всіх екземплярів ресурсів, які існують на початковій версії ресурсу. Усі наступні події watch стосуються всіх змін, що сталися після початкової версії ресурсу, з якої почався watch.
Почати точно з
Почати watch на точній версії ресурсу. Події watch стосуються всіх змін після наданої версії ресурсу. На відміну від "Отримати стан і почати з найновішого" та "Отримати стан і почати з будь-якого", watch не починається з синтетичних подій "Added" для наданої версії ресурсу. Вважається, що клієнт вже має початковий стан на стартовій версії ресурсу, оскільки клієнт надав цю версію ресурсу.

Відповіді "410 Gone"

Сервери не зобовʼязані зберігати всі старі версії ресурсів і можуть повернути код HTTP 410 (Gone), якщо клієнт запитує resourceVersion, який старіший, ніж версія, збережена сервером. Клієнти повинні бути готові обробляти відповіді 410 (Gone). Дивіться розділ Ефективне виявлення змін для отримання додаткової інформації про те, як обробляти відповіді 410 (Gone) при спостереженні за ресурсами.

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

Недоступні версії ресурсів

Сервери не зобовʼязані обслуговувати нерозпізнані версії ресурсів. Якщо ви запитуєте list або get для версії ресурсу, яку API-сервер не розпізнає, то API-сервер може або:

  • почекати трохи, поки версія ресурсу не стане доступною, а потім завершити з тайм-аутом і відповіддю 504 (Gateway Timeout), якщо надана версія ресурсу не стане доступною в розумний термін;
  • відповісти заголовком Retry-After, вказуючи, через скільки секунд клієнт повинен повторити запит.

Якщо ви запитуєте версію ресурсу, яку API-сервер не розпізнає, kube-apiserver додатково ідентифікує свої відповіді на помилки повідомленням "Too large resource version".

Якщо ви робите запит watch для нерозпізнаної версії ресурсу, API-сервер може чекати невизначений час (до тайм-ауту запиту), поки версія ресурсу не стане доступною.


  1. Ідемпотентність означає, що ви можете повторно виконати операцію без змін у стані системи. https://uk.wikipedia.org/wiki/Ідемпотентність ↩︎

2 - Server-Side Apply

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

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

Server-Side Apply (Серверне застосування) надає необовʼязковий механізм для контролера вашого кластера, щоб відстежувати зміни в полях обʼєкта. На рівні конкретного ресурсу, Server-Side Apply записує та відстежує інформацію про контроль над полями цього обʼєкта.

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

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

Порівняння з Client-Side Apply пояснює, як Server-Side Apply відрізняється від початкової реалізації kubectl apply на стороні клієнта.

Управління полями

Kubernetes API сервер відстежує керовані поля для всіх новостворених обʼєктів.

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

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

Операція застосування перевіряє, чи є інші менеджери полів, які також володіють полем. Якщо поле не належить жодному іншому менеджеру полів, це поле встановлюється на стандартне значення (якщо таке є), або видаляється з обʼєкта. Те саме правило застосовується до полів, які є списками, асоціативними списками або map.

Для того, щоб користувач міг керувати полем в контексті Server-Side Apply, він повинен покладатися на те, що значення поля не зміниться. Користувач, який останнім висловив свою думку щодо значення поля, буде записаний як поточний менеджер поля. Це можна зробити, змінивши дані менеджера поля явним чином за допомогою HTTP POST (створення), PUT (оновлення), або не-застосувального PATCH (патч). Ви також можете оголосити та записати менеджера поля, включивши значення для цього поля в операції Server-Side Apply.

Запит на патч в контексті Server-Side Apply вимагає від клієнта вказати свою ідентичність як менеджера поля. При використанні Server-Side Apply спроба змінити поле, що контролюється іншим менеджером, призведе до відхилення запиту, якщо клієнт не виконає примусове перевизначення. Для деталей щодо примусових перевизначень дивіться Конфлікти.

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

Деталі управління полями зберігаються в полі managedFields, яке є частиною metadata обʼєкта.

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

У порівнянні з (застарілою) kubectl.kubernetes.io/last-applied-configuration анотацією, яка управляється kubectl, Server-Side Apply використовує більш декларативний підхід, який відстежує управління полями користувача (або клієнта), а не останній застосований стан користувача. Побічним ефектом використання Server-Side Apply є також доступність інформації про те, який менеджер поля управляє кожним полем в обʼєкті.

Приклад

Простий приклад обʼєкта, створеного за допомогою Server-Side Apply, може виглядати так:

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: test-cm
  namespace: default
  labels:
    test-label: test
  managedFields:
  - manager: kubectl
    operation: Apply # зверніть увагу на великі літери: "Apply" (або "Update")
    apiVersion: v1
    time: "2010-10-10T0:00:00Z"
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:labels:
          f:test-label: {}
      f:data:
        f:key: {}
data:
  key: some value

Цей приклад обʼєкта ConfigMap містить один запис про управління полями в .metadata.managedFields. Запис управління полями складається з основної інформації про саму сутність, що виконує управління, а також з деталей про поля, якими управляють, та відповідну операцію (Apply або Update). Якщо запит, що останнім змінив це поле, був патчем Server-Side Apply, тоді значення operation буде Apply; в іншому випадку, це буде Update.

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

Однак, можливо змінити .metadata.managedFields за допомогою операції оновлення або патчу, які не використовують Server-Side Apply. Це наполегливо не рекомендується, але може бути доцільно спробувати, якщо, наприклад, .metadata.managedFields потрапить у неконсистентний стан (що не повинно відбуватися при нормальній роботі).

Формат managedFields описаний у довіднику API Kubernetes.

Конфлікти

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

  • Перезаписати значення, стати єдиним менеджером: Якщо перезапис значення був навмисним (або якщо аплікатор є автоматичним процесом, таким як контролер), аплікатор повинен встановити параметр запиту force в true (для kubectl apply використовується параметр командного рядка --force-conflicts) і повторити запит. Це змусить операцію завершитись успішно, змінить значення поля та видалить це поле з усіх інших записів менеджерів у managedFields.

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

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

Менеджери полів

Менеджери визначають окремі робочі процеси, які змінюють обʼєкт (особливо корисно при конфліктах!), і можуть бути вказані через параметр запиту fieldManager як частина запиту на зміни. Коли ви застосовуєте зміни до ресурсу, параметр fieldManager є обовʼязковим. Для інших оновлень сервер API визначає ідентифікатор менеджера поля з заголовка HTTP "User-Agent:" (якщо він присутній).

Коли ви використовуєте інструмент kubectl для виконання операції Server-Side Apply, kubectl типово встановлює ідентифікатор менеджера в "kubectl".

Серіалізація

На рівні протоколу Kubernetes представляє тіла повідомлень Server-Side Apply у форматі YAML, з медіа типом application/apply-patch+yaml.

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

Ось приклад тіла повідомлення Server-Side Apply (повністю специфікований намір):

{
  "apiVersion": "v1",
  "kind": "ConfigMap"
}

(це зробить оновлення без змін, за умови, що це було надіслано як тіло patch запиту до дійсного ресурсу v1/configmaps, з відповідним заголовком запиту Content-Type).

Операції з області управління полями

Операції API Kubernetes, де враховується управління полями, включають:

  1. Server-Side Apply (HTTP PATCH, з типом контенту application/apply-patch+yaml)
  2. Заміна наявного обʼєкта (update для Kubernetes; PUT на рівні HTTP)

Обидві операції оновлюють .metadata.managedFields, але поводяться трохи по-різному.

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

Усі запити Server-Side Apply patch повинні ідентифікувати себе, надаючи параметр запиту fieldManager, тоді як цей параметр запиту є необовʼязковим для операцій update. Нарешті, при використанні операції Apply ви не можете визначати managedFields у тілі запиту, який ви надсилаєте.

Приклад обʼєкта з декількома менеджерами може виглядати так:

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: test-cm
  namespace: default
  labels:
    test-label: test
  managedFields:
  - manager: kubectl
    operation: Apply
    apiVersion: v1
    fields:
      f:metadata:
        f:labels:
          f:test-label: {}
  - manager: kube-controller-manager
    operation: Update
    apiVersion: v1
    time: '2019-03-30T16:00:00.000Z'
    fields:
      f:data:
        f:key: {}
data:
  key: new value

У цьому прикладі друга операція була виконана як update менеджером з назвою kube-controller-manager. Запит на оновлення був успішним і змінив значення в полі даних, що призвело до зміни управління цим полем на kube-controller-manager.

Якби була спроба застосувати це оновлення за допомогою Server-Side Apply, запит зазнав би невдачі через конфлікт управління.

Стратегія злиття

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

Коли користувач надсилає обʼєкт із повністю специфікованим наміром на точку доступу Server-Side Apply, сервер зʼєднує його з поточним обʼєктом, надаючи перевагу значенню з тіла запиту, якщо воно вказане в обох місцях. Якщо набір елементів, присутніх у застосованій конфігурації, не є надмножиною елементів, застосованих тим самим користувачем минулого разу, кожен відсутній елемент, яким не керують інші аплікатори, видаляється. Для отримання додаткової інформації про те, як схема обʼєкта використовується для прийняття рішень під час злиття, дивіться sigs.k8s.io/structured-merge-diff.

API Kubernetes (та код Go, який реалізує це API для Kubernetes) дозволяє визначати маркери стратегії злиття. Ці маркери описують підтримувану стратегію злиття для полів в обʼєктах Kubernetes. Для CustomResourceDefinition, ви можете встановити ці маркери під час визначення власного ресурсу.

Маркер GolangРозширення OpenAPIМожливі значенняОпис
//+listTypex-kubernetes-list-typeatomic/set/mapЗастосовується до списків. set застосовується до списків, які включають лише скалярні елементи. Ці елементи повинні бути унікальними. map застосовується до списків вкладених типів. Значення ключів (див. listMapKey) повинні бути унікальними в списку. atomic може застосовуватися до будь-якого списку. Якщо налаштовано як atomic, весь список замінюється під час злиття. У будь-який момент часу список належить одному менеджеру. Якщо set або map, різні менеджери можуть окремо керувати елементами.
//+listMapKeyx-kubernetes-list-map-keysСписок імен полів, наприклад, ["port", "protocol"]Застосовується лише при +listType=map. Список імен полів, значення яких унікально ідентифікують елементи у списку. Хоча ключів може бути багато, listMapKey є одниною, тому що ключі потрібно вказувати індивідуально в типі Go. Поля ключів повинні бути скалярами.
//+mapTypex-kubernetes-map-typeatomic/granularЗастосовується до map. atomic означає, що map можна замінити повністю тільки одним менеджером. granular означає, що map підтримує окремих менеджерів, які оновлюють окремі поля.
//+structTypex-kubernetes-map-typeatomic/granularЗастосовується до структур; інакше те ж використання та анотація OpenAPI, як //+mapType.

Якщо listType відсутній, сервер API інтерпретує patchStrategy=merge як listType=map і відповідний маркер patchMergeKey як listMapKey.

Тип списку atomic є рекурсивним.

(У коді Go для Kubernetes, ці маркери вказуються як коментарі, і авторам коду не потрібно повторювати їх як теґи полів).

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

Стандартно, Server-Side Apply обробляє власні ресурси користувачів як неструктуровані дані. Усі ключі розглядаються як поля структури, а всі списки вважаються атомарними.

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

Сумісність при зміні топології

У рідкісних випадках автор CustomResourceDefinition (CRD) або вбудованого ресурсу може захотіти змінити специфічну топологію поля у своєму ресурсі, не збільшуючи його версію API. Зміна топології типів шляхом оновлення кластера або CRD має різні наслідки при оновленні наявних обʼєктів. Є дві категорії змін: коли поле переходить від map/set/granular до atomic і навпаки.

Коли listType, mapType або structType змінюються з map/set/granular на atomic, весь список, map або структура наявних обʼєктів будуть в підсумку належати акторам, які володіли елементом цих типів. Це означає, що будь-яка подальша зміна цих обʼєктів призведе до конфлікту.

Коли listType, mapType або structType змінюються з atomic на map/set/granular, сервер API не може визначити нову власність цих полів. Через це конфлікти не виникатимуть під час оновлення обʼєктів із цими полями. Тому не рекомендується змінювати тип із atomic на map/set/granular.

Візьмемо, наприклад, власний ресурс користувача ресурс:

---
apiVersion: example.com/v1
kind: Foo
metadata:
  name: foo-sample
  managedFields:
  - manager: "manager-one"
    operation: Apply
    apiVersion: example.com/v1
    fields:
      f:spec:
        f:data: {}
spec:
  data:
    key1: val1
    key2: val2

До того, як spec.data зміниться з atomic на granular, manager-one володіє полем spec.data і всіма полями в ньому (key1 та key2). Коли CRD змінюється, щоб зробити spec.data granular, manager-one продовжує володіти полем верхнього рівня spec.data (що означає, що жоден інший менеджер не може видалити map data без конфлікту), але він більше не володіє key1 та key2, тому інший менеджер може змінити або видалити ці поля без конфлікту.

Використання Server-Side Apply в контролер

Як розробник контролера, ви можете використовувати Server-Side Apply як спосіб спростити логіку оновлення вашого контролера. Основні відмінності від кead-modify-write та/або patch наступні:

  • застосований обʼєкт повинен містити всі поля, які цікавлять контролер.
  • немає способу видалити поля, які не були застосовані контролером раніше (контролер все ще може надіслати patch або update для цих випадків використання).
  • обʼєкт не обовʼязково має бути прочитаним перед тим; resourceVersion не потрібно вказувати.

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

Передача власності

Окрім контролю конкурентності, забезпеченого вирішенням конфліктів, Server-Side Apply надає можливості для виконання координованих переходів власності полів від користувачів до контролерів.

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

Скажімо, користувач визначив Deployment з replicas, встановленим на бажане значення:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2

І користувач створив Deployment, використовуючи Server-Side Apply, наступним чином:

kubectl apply -f https://k8s.io/examples/application/ssa/nginx-deployment.yaml --server-side

Пізніше автоматичне масштабування увімкнено для Deployment; наприклад:

kubectl autoscale deployment nginx-deployment --cpu-percent=50 --min=1 --max=10

Тепер користувач хоче видалити replicas з конфігурації, щоб вони випадково не конфліктували з HorizontalPodAutoscaler (HPA) та його контролером. Однак виникають перегони: може пройти деякий час, перш ніж HPA вирішить змінити .spec.replicas; якщо користувач видаляє .spec.replicas перед тим, як HPA запише в поле і стане його власником, тоді API-сервер встановить .spec.replicas на 1 (стандартна кількість реплік для Deployment). Це не те, що хоче користувач, ще й тимчасово — це може погіршити робоче навантаження.

Є два рішення:

  • (базовий) Залиште replicas в конфігурації; коли HPA нарешті запише в це поле, система сповістить користувачу про конфлікт при спробі зробити це. На цьому етапі безпечно видалити його з конфігурації.

  • (більш розширений) Однак, якщо користувач не хоче чекати, наприклад, через те що вони хочуть, щоб кластер був зрозумілим для їх колег, тоді вони можуть виконати наступні кроки, щоб зробити видалення replicas з їх конфігурації безпечним:

Спочатку користувач визначає новий маніфест, що містить лише поле replicas:

# Збережіть цей файл як 'nginx-deployment-replicas-only.yaml'.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3

Користувач застосовує цей маніфест, використовуючи приватне імʼя менеджера полів. У цьому прикладі користувач вибрав handover-to-hpa:

kubectl apply -f nginx-deployment-replicas-only.yaml \
  --server-side --field-manager=handover-to-hpa \
  --validate=false

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

На цьому етапі користувач може видалити поле replicas з маніфесту:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2

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

Передача власності між менеджерами

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

Порівняння з Client-Side Apply

Server-Side Apply призначений як для заміни початкової реалізації команди kubectl apply на стороні клієнта, так і для забезпечення простого та ефективного механізму для контролерів, щоб впроваджувати свої зміни.

Порівняно з анотацією last-applied, якою керує kubectl, Server-Side Apply використовує більш декларативний підхід, що відстежує управління полями обʼєкта, а не останній стан, застосований користувачем. Це означає, що як побічний ефект використання Server-Side Apply, стає доступною інформація про те, який менеджер полів керує кожним полем в обʼєкті.

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

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

Ще однією відмінністю є те, що аплікатор, використовуючи Client-Side Apply, не може змінити версію API, яку він використовує, тоді як Server-Side Apply підтримує цей випадок використання.

Міграція між client-side і server-side apply

Перехід з client-side apply на server-side apply

Користувачі client-side apply, які керують ресурсом за допомогою kubectl apply, можуть почати використовувати server-side apply з наступним прапорцем.

kubectl apply --server-side [--dry-run=server]

Стандартно, управління полями обʼєкта переходить з client-side apply на kubectl server-side apply без виникнення конфліктів.

Ця поведінка стосується server-side apply з менеджером полів kubectl. Як виняток, ви можете відмовитися від цієї поведінки, вказавши іншого, не стандартного менеджера полів, як показано в наступному прикладі. Стандартним менеджером полів для kubectl server-side apply є kubectl.

kubectl apply --server-side --field-manager=my-manager [--dry-run=server]

Повернення з server-side apply на client-side apply

Якщо ви керуєте ресурсом за допомогою kubectl apply --server-side, ви можете перейти на client-side apply безпосередньо за допомогою kubectl apply.

Повернення працює тому, що kubectl Server-Side Apply тримає анотацію last-applied-configuration в актуальному стані, якщо ви використовуєте kubectl apply.

Ця поведінка стосується Server-Side Apply з менеджером полів kubectl. Як виняток, ви можете відмовитися від цієї поведінки, вказавши іншого, не стандартного менеджера полів, як показано в наступному прикладі. Стандартним менеджером полів для kubectl server-side apply є kubectl.

kubectl apply --server-side --field-manager=my-manager [--dry-run=server]

Реалізація API

Дієслово PATCH для ресурсу, який підтримує Server-Side Apply, може приймати неофіційний тип контенту application/apply-patch+yaml. Користувачі Server-Side Apply можуть надіслати частково специфіковані обʼєкти у вигляді YAML як тіло запиту PATCH до URI ресурсу. При застосуванні конфігурації слід завжди включати всі поля, які є важливими для результату (наприклад, бажаний стан), який ви хочете визначити.

Усі повідомлення в форматі JSON є дійсним YAML. Деякі клієнти вказують запити Server-Side Apply, використовуючи тіла запитів у форматі YAML, які також є дійсним JSON.

Контроль доступу і дозволи

Оскільки Server-Side Apply є типом PATCH, субʼєкт (такий як Роль для Kubernetes RBAC) потребує дозволу patch для редагування наявних ресурсів, а також дозволу на дієслово create для створення нових ресурсів за допомогою Server-Side Apply.

Очищення managedFields

Можливо видалити всі managedFields з обʼєкта, переписавши їх за допомогою patch (JSON Merge Patch, Strategic Merge Patch, JSON Patch) або через update (HTTP PUT); іншими словами, через будь-яку операцію запису, окрім apply. Це можна зробити, переписавши поле managedFields порожнім записом. Два приклади:

PATCH /api/v1/namespaces/default/configmaps/example-cm
Accept: application/json
Content-Type: application/merge-patch+json

{
  "metadata": {
    "managedFields": [
      {}
    ]
  }
}
PATCH /api/v1/namespaces/default/configmaps/example-cm
Accept: application/json
Content-Type: application/json-patch+json
If-Match: 1234567890123456789

[{"op": "replace", "path": "/metadata/managedFields", "value": [{}]}]

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

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

Що далі

Ви можете прочитати про managedFields у довіднику API Kubernetes для верхнього рівня поля metadata.

3 - Бібліотеки клієнтів

Ця сторінка містить огляд бібліотек клієнтів для використання Kubernetes API різними мовами програмування.

Для написання застосунків, що використовують Kubernetes REST API, вам не потрібно самостійно реалізовувати виклики API та типи запитів/відповідей. Ви можете використовувати бібліотеку клієнтів для мови програмування, яку ви використовуєте.

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

Офіційно підтримувані бібліотеки клієнтів Kubernetes

Наступні бібліотеки клієнтів офіційно підтримуються Kubernetes SIG API Machinery.

МоваБібліотека клієнтівПриклад програм
Cgithub.com/kubernetes-client/cпереглянути
dotnetgithub.com/kubernetes-client/csharpпереглянути
Gogithub.com/kubernetes/client-go/переглянути
Haskellgithub.com/kubernetes-client/haskellпереглянути
Javagithub.com/kubernetes-client/javaпереглянути
JavaScriptgithub.com/kubernetes-client/javascriptпереглянути
Perlgithub.com/kubernetes-client/perl/переглянути
Pythongithub.com/kubernetes-client/python/переглянути
Rubygithub.com/kubernetes-client/ruby/переглянути

Бібліотеки клієнтів, що підтримуються спільнотою

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

МоваБібліотека клієнтів
Clojuregithub.com/yanatan16/clj-kubernetes-api
DotNetgithub.com/tonnyeremin/kubernetes_gen
DotNet (RestSharp)github.com/masroorhasan/Kubernetes.DotNet
Elixirgithub.com/obmarg/kazan
Elixirgithub.com/coryodaniel/k8s
Java (OSGi)bitbucket.org/amdatulabs/amdatu-kubernetes
Java (Fabric8, OSGi)github.com/fabric8io/kubernetes-client
Javagithub.com/manusa/yakc
Lispgithub.com/brendandburns/cl-k8s
Lispgithub.com/xh4/cube
Node.js (TypeScript)github.com/Goyoo/node-k8s-client
Node.jsgithub.com/ajpauwels/easy-k8s
Node.jsgithub.com/godaddy/kubernetes-client
Node.jsgithub.com/tenxcloud/node-kubernetes-client
Perlmetacpan.org/pod/Net::Kubernetes
PHPgithub.com/allansun/kubernetes-php-client
PHPgithub.com/maclof/kubernetes-client
PHPgithub.com/travisghansen/kubernetes-client-php
PHPgithub.com/renoki-co/php-k8s
Pythongithub.com/fiaas/k8s
Pythongithub.com/gtsystem/lightkube
Pythongithub.com/kr8s-org/kr8s
Pythongithub.com/mnubo/kubernetes-py
Pythongithub.com/tomplus/kubernetes_asyncio
Pythongithub.com/Frankkkkk/pykorm
Rubygithub.com/abonas/kubeclient
Rubygithub.com/k8s-ruby/k8s-ruby
Rubygithub.com/kontena/k8s-client
Rustgithub.com/kube-rs/kube
Rustgithub.com/ynqa/kubernetes-rust
Scalagithub.com/hagay3/skuber
Scalagithub.com/hnaderi/scala-k8s
Scalagithub.com/joan38/kubernetes-client
Swiftgithub.com/swiftkube/client

4 - Загальна мова виразів у Kubernetes

Загальна мова виразів (Common Expression Language, CEL) використовується в API Kubernetes для оголошення правил валідації, політик та інших обмежень чи умов.

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

Огляд мови

Мова CEL має простий синтаксис, який схожий на вирази в C, C++, Java, JavaScript і Go.

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

Вхідні дані для програми CEL — це "змінні". Кожне поле API Kubernetes, яке містить CEL, декларує в документації API, які змінні доступні для використання для цього поля. Наприклад, у полі x-kubernetes-validations[i].rules у CustomResourceDefinitions доступні змінні self і oldSelf, що відносяться до попереднього та поточного стану даних власного ресурсу користувача, які потрібно перевірити за допомогою виразу CEL. Інші поля API Kubernetes можуть оголошувати різні змінні. Дивіться документацію API для полів API, щоб дізнатися, які змінні доступні для цього поля.

Приклади виразів CEL:

Приклади виразів CEL та їх призначення
ПравилоПризначення
self.minReplicas <= self.replicas && self.replicas <= self.maxReplicasПеревірити, що три поля, що визначають репліки, розташовані в правильному порядку
'Available' in self.stateCountsПеревірити, що в map існує запис з ключем 'Available'
(self.list1.size() == 0) != (self.list2.size() == 0)Перевірити, що один із двох списків не порожній, але не обидва одночасно
self.envars.filter(e, e.name = 'MY_ENV').all(e, e.value.matches('^[a-zA-Z]*$')Перевірити поле 'value' у запису listMap, де поле ключа 'name' дорівнює 'MY_ENV'
has(self.expired) && self.created + self.ttl < self.expiredПеревірити, що дата 'expired' є пізніше дати 'created' плюс тривалість 'ttl'
self.health.startsWith('ok')Перевірити, що строкове поле 'health' має префікс 'ok'
self.widgets.exists(w, w.key == 'x' && w.foo < 10)Перевірити, що властивість 'foo' елемента listMap з ключем 'x' менше 10
type(self) == string ? self == '99%' : self == 42Перевірити поле типу int-або-string для обох випадків: int та string
self.metadata.name == 'singleton'Перевірити, що імʼя обʼєкта відповідає конкретному значенню (робить його унікальним)
self.set1.all(e, !(e in self.set2))Перевірити, що два списки (listSets) не перетинаються
self.names.size() == self.details.size() && self.names.all(n, n in self.details)Перевірити, що map 'details' має ключі, які відповідають елементам у списку 'names'
self.details.all(key, key.matches('^[a-zA-Z]*$'))Перевірити ключі map 'details'
self.details.all(key, self.details[key].matches('^[a-zA-Z]*$'))Перевірити значення map 'details'

Опції CEL, особливості мови та бібліотеки

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

Опція, бібліотека або особливість мови CELВключеноДоступність
Стандартні макросиhas, all, exists, exists_one, map, filterУсі версії Kubernetes
Стандартні функціїДивіться офіційний список стандартних визначеньУсі версії Kubernetes
Однорідні агрегаційні літералиУсі версії Kubernetes
Часовий пояс UTC за замовчуваннямУсі версії Kubernetes
Рання перевірка деклараційУсі версії Kubernetes
бібліотека розширених рядків, Версія 1charAt, indexOf, lastIndexOf, lowerAscii, upperAscii, replace, split, join, substring, trimУсі версії Kubernetes
Бібліотека списків KubernetesДивіться бібліотеку списків KubernetesУсі версії Kubernetes
Бібліотека регулярних виразів KubernetesДивіться бібліотеку регулярних виразів KubernetesУсі версії Kubernetes
Бібліотека URL KubernetesДивіться бібліотеку URL KubernetesУсі версії Kubernetes
Бібліотека авторизації KubernetesДивіться бібліотеку авторизації KubernetesУсі версії Kubernetes
Бібліотека кількостей KubernetesДивіться бібліотеку кількостей KubernetesВерсії Kubernetes 1.29+
Опційні типи CELДивіться опційні типи CELВерсії Kubernetes 1.29+
Порівняння чисел різних типів CELДивіться порівняння чисел різних типів CELВерсії Kubernetes 1.29+

Функції CEL, особливості та налаштування мови підтримують відкат панелі управління Kubernetes. Наприклад, опційні значення CEL були введені у Kubernetes 1.29, і лише сервери API цієї версії або новіші прийматимуть запити на запис виразів CEL, які використовують опційні значення CEL. Однак, коли кластер відкочується до версії Kubernetes 1.28, вирази CEL, що використовують "опційні значення CEL", які вже збережені в ресурсах API, продовжуватимуть правильно оцінюватись.

Бібліотеки CEL Kubernetes

Крім спільнотних бібліотек CEL, Kubernetes включає бібліотеки CEL, які доступні у всіх місцях використання CEL в Kubernetes.

Бібліотека списків Kubernetes

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

Бібліотека списків також включає min, max та sum. Сума підтримується для всіх типів чисел, а також для типу тривалості. Мінімум та максимум підтримуються для всіх типів, що можна порівняти.

Також надається функція isSorted для зручності та підтримується для всіх типів, які можна порівняти.

Приклади:

Приклади виразів CEL, що використовують функції бібліотеки списків
Вираз CELПризначення
names.isSorted()Перевірити, що список імен зберігається в алфавітному порядку
items.map(x, x.weight).sum() == 1.0Перевірити, що "ваги" списку обʼєктів дорівнюють 1.0
lowPriorities.map(x, x.priority).max() < highPriorities.map(x, x.priority).min()Перевірити, що два набори пріоритетів не перекриваються
names.indexOf('should-be-first') == 1Вимагати, щоб перше імʼя у списку було певним значенням

Для отримання додаткової інформації дивіться бібліотеку списків Kubernetes godoc.

Бібліотека регулярних виразів Kubernetes

Крім функції matches, наданої стандартною бібліотекою CEL, бібліотека регулярних виразів надає функції find та findAll, що дозволяють виконувати ширший спектр операцій з регулярними виразами.

Приклади:

Приклади виразів CEL, що використовують функції бібліотеки регулярних виразів
Вираз CELПризначення
"abc 123".find('[0-9]+')Знайти перше число у рядку
"1, 2, 3, 4".findAll('[0-9]+').map(x, int(x)).sum() < 100Перевірити, що сума чисел у рядку менше 100

Для отримання додаткової інформації дивіться бібліотеку регулярних виразів Kubernetes godoc.

Бібліотека URL Kubernetes

Для спрощення та безпечної обробки URL надані наступні функції:

  • isURL(string) перевіряє, чи є рядок рядком дійсним URL з пакетом Go net/url. Рядок повинен бути абсолютним URL.
  • url(string) URL конвертує рядок в URL або викликає помилку, якщо рядок не є дійсним URL.

Після розбору за допомогою функції url, отриманий обʼєкт URL має наступні методи доступу: getScheme, getHost, getHostname, getPort, getEscapedPath та getQuery.

Приклади:

Приклади виразів CEL, що використовують функції бібліотеки URL
Вираз CELПризначення
url('https://example.com:80/').getHost()Отримати частину хосту 'example.com:80' URL.
url('https://example.com/path with spaces/').getEscapedPath()Повертає '/path%20with%20spaces/'

Для отримання додаткової інформації дивіться бібліотеку URL Kubernetes godoc.

Бібліотека авторизатора Kubernetes

Для виразів CEL в API, де доступна змінна типу Authorizer, авторизатор може використовуватися для виконання перевірок авторизації для принципала (автентифікованого користувача) запиту.

Перевірки ресурсів API виконуються наступним чином:

  1. Вкажіть групу та ресурс для перевірки: Authorizer.group(string).resource(string) ResourceCheck.

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

    • ResourceCheck.subresource(string) ResourceCheck
    • ResourceCheck.namespace(string) ResourceCheck
    • ResourceCheck.name(string) ResourceCheck
  3. Викличте ResourceCheck.check(verb string) Decision, щоб виконати перевірку авторизації.

  4. Викличте allowed() bool або reason() string, щоб переглянути результат перевірки авторизації.

Не-ресурсна авторизація виконується так:

  1. Вкажіть лише шлях: Authorizer.path(string) PathCheck.
  2. Викличте PathCheck.check(httpVerb string) Decision, щоб виконати перевірку авторизації.
  3. Викличте allowed() bool або reason() string, щоб переглянути результат перевірки авторизації.

Для виконання перевірки авторизації для службового облікового запису:

  • Authorizer.serviceAccount(namespace string, name string) Authorizer
Приклади виразів CEL, що використовують функції бібліотеки авторизатора
Вираз CELПризначення
authorizer.group('').resource('pods').namespace('default').check('create').allowed()Повертає true, якщо принципалу (користувачу або службовому обліковому запису) дозволено створювати Podʼи у просторі імен 'default'.
authorizer.path('/healthz').check('get').allowed()Перевіряє, чи авторизований принципал (користувач або службовий обліковий запис) виконує HTTP GET-запити до шляху API /healthz.
authorizer.serviceAccount('default', 'myserviceaccount').resource('deployments').check('delete').allowed()Перевіряє, чи службовий обліковий запис має дозвіл на видалення deployments.

Для отримання додаткової інформації дивіться бібліотеку авторизатора Kubernetes godoc.

Бібліотека кількості Kubernetes

У Kubernetes 1.28 додана підтримка обробки рядків кількості (наприклад, 1,5G, 512k, 20Mi).

  • isQuantity(string) перевіряє, чи є рядок дійсною кількістю відповідно до Кількості ресурсів Kubernetes.
  • quantity(string) Quantity конвертує рядок у кількість або викликає помилку, якщо рядок не є дійсною кількістю.

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

Набір доступних методів для кількості
МетодПовертає типОпис
isInteger()boolПовертає true, якщо asInteger може бути викликано без помилки.
asInteger()intПовертає представлення поточного значення як int64, якщо це можливо, або викликає помилку, якщо конвертація призводить до переповнення або втрати точності.
asApproximateFloat()floatПовертає представлення кількості як float64, що може втратити точність.
sign()intПовертає 1, якщо кількість додатня, -1, якщо вона відʼємна, або 0, якщо вона нуль.
add(<Quantity>)QuantityПовертає суму двох кількостей.
add(<int>)QuantityПовертає суму кількості та цілого числа.
sub(<Quantity>)QuantityПовертає різницю між двома кількостями.
sub(<int>)QuantityПовертає різницю між кількістю та цілим числом.
isLessThan(<Quantity>)boolПовертає true, якщо отримувач менше операнта.
isGreaterThan(<Quantity>)boolПовертає true, якщо отримувач більше операнта.
compareTo(<Quantity>)intПорівнює отримувача з операндом та повертає 0, якщо вони рівні, 1, якщо отримувач більший або -1, якщо отримувач менший за операнд.

Приклади:

Приклади виразів CEL, що використовують функції бібліотеки кількості
Вираз CELПризначення
quantity("500000G").isInteger()Перевірка, чи конвертація в ціле число викликає помилку.
quantity("50k").asInteger()Точна конвертація в ціле число.
quantity("9999999999999999999999999999999999999G").asApproximateFloat()Втратна конвертація в плаваючий рядок.
quantity("50k").add(quantity("20k"))Додати дві кількості.
quantity("50k").sub(20000)Відняти ціле число від кількості.
quantity("50k").add(20).sub(quantity("100k")).sub(-50000)Ланцюгове додавання та віднімання цілих чисел та кількостей.
quantity("200M").compareTo(quantity("0.2G"))Порівняти дві кількості.
quantity("150Mi").isGreaterThan(quantity("100Mi"))Перевірити, чи кількість більша за отримувача.
quantity("50M").isLessThan(quantity("100M"))Перевірити, чи кількість менша за отримувача.

Перевірка типів

CEL — це поступово типізована мова.

Деякі поля API Kubernetes містять повністю перевірені типи CEL-виразів. Наприклад, Правила валідації власних ресурсів повністю перевірені за типом.

Деякі поля API Kubernetes містять частково перевірені типи CEL-виразів. Частково перевірений вираз — це вираз, в якому деякі змінні статично типізовані, а інші — динамічно типізовані. Наприклад, в CEL-виразах ValidatingAdmissionPolicies, змінна request має тип, але змінна object динамічно типізована. У звʼязку з цим вираз, що містить request.namex, не пройде перевірку типів, оскільки поле namex не визначене. Однак object.namex пройде перевірку типів навіть тоді, коли поле namex не визначене для типів ресурсів, на які посилається object, оскільки object динамічно типізований.

Макрос has() в CEL можна використовувати у виразах CEL для перевірки доступності поля динамічно типізованої змінної перед спробою доступу до значення поля. Наприклад:

has(object.namex) ? object.namex == 'special' : request.name == 'special'

Інтеграція системи типів

Таблиця, що показує взаємозвʼязок між типами OpenAPIv3 та CEL
Тип OpenAPIv3Тип CEL
'object' з Propertiesobject / "тип повідомлення" (type(<object>) обчислюється як selfType<uniqueNumber>.path.to.object.from.self
'object' з AdditionalPropertiesmap
'object' з x-kubernetes-embedded-typeobject / "тип повідомлення", 'apiVersion', 'kind', 'metadata.name' і 'metadata.generateName' включені в схему
'object' з x-kubernetes-preserve-unknown-fieldsobject / "тип повідомлення", невідомі поля НЕ доступні у виразі CEL
x-kubernetes-int-or-stringоб'єднання int або string, self.intOrString < 100 || self.intOrString == '50%' обчислюється як true для 50 і "50%"
'array'list
'array' з x-kubernetes-list-type=maplist з базованими на map рівноправністю та унікальними ключами
'array' з x-kubernetes-list-type=setlist з базованими на set рівноправністю та унікальними елементами
'boolean'boolean
'number' (усі формати)double
'integer' (усі формати)int (64)
немає еквівалентаuint (64)
'null'null_type
'string'string
'string' з format=byte (base64 encoded)bytes
'string' з format=datetimestamp (google.protobuf.Timestamp)
'string' з format=datetimetimestamp (google.protobuf.Timestamp)
'string' з format=durationduration (google.protobuf.Duration)

Також дивіться: Типи CEL, Типи OpenAPI, Структурні схеми Kubernetes.

Порівняння рівності для масивів з x-kubernetes-list-type типу set або map ігнорує порядок елементів. Наприклад, [1, 2] == [2, 1] якщо масиви представляють значення Kubernetes set.

Конкатенація для масивів з x-kubernetes-list-type використовує семантику типу списку:

  • set: X + Y виконує об'єднання, де позиції елементів у X зберігаються, а не перетинаючі елементи у Y додаються, зберігаючи їх частковий порядок.
  • map: X + Y виконує об'єднання, де позиції ключів у X зберігаються, але значення перезаписуються значеннями у Y, коли ключові множини X і Y перетинаються. Елементи у Y з неперетинаючими ключами додаються, зберігаючи їх частковий порядок.

Екранування

Тільки імена властивостей ресурсів Kubernetes форми [a-zA-Z_.-/][a-zA-Z0-9_.-/]* доступні з CEL. Доступні імена властивостей екрануються згідно з наступними правилами при доступі у виразі:

Таблиця правил екранування ідентифікаторів CEL
екрануюча послідовністьеквівалент імені властивості
__underscores____
__dot__.
__dash__-
__slash__/
__{keyword}__ЗАРЕЗЕРВОВАНЕ ключове слово CEL

Коли ви екрануєте будь-яке з ЗАРЕЗЕРВОВАНИХ ключових слів CEL, збіг повинен точно відповідати імені властивості та використовувати екранування з підкресленням (наприклад, int у слові sprint не буде екрановано, і це не буде необхідно).

Приклади екранування:

Приклади екранованих ідентифікаторів CEL
імʼя властивостіправило з екранованим імʼям властивості
namespaceself.__namespace__ > 0
x-propself.x__dash__prop > 0
redact__dself.redact__underscores__d > 0
stringself.startsWith('kube')

Обмеження ресурсів

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

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

Багато з основних операцій CEL мають фіксовані витрати. Найпростіші операції, такі як порівняння (наприклад, <), мають вартість 1. Деякі мають вищу фіксовану вартість, наприклад, оголошення літералів списку мають фіксовану базову вартість 40 одиниць вартості.

Виклики функцій, реалізованих у рідному коді, оцінюються на основі часової складності операції. Наприклад, операції, що використовують регулярні вирази, такі як match та find, оцінюються з використанням приблизної вартості length(regexString)*length(inputString). Приблизна вартість відображає найгірший випадок часової складності реалізації RE2 в Go.

Бюджет вартості під час виконання

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

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

Оцінювані обмеження вартості

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

5 - Політика застарівання Kubernetes

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

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

Застарівання частин API

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

ПрикладТрек
v1GA (загальнодоступна, стабільна)
v1beta1Beta (попередній випуск, перед GA)
v1alpha1Alpha (експериментальна)

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

Наступні правила регулюють застарівання елементів API. Це включає:

  • Ресурси REST (також відомі як обʼєкти API)
  • Поля ресурсів REST
  • Анотації на ресурсах REST, включаючи "бета" анотації, але не включаючи "альфа" анотації
  • Перелічувані або постійні значення
  • Структури конфігурації компонентів

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

Правило №1: Елементи API можуть бути видалені лише шляхом інкрементування версії групи API.

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

Правило №2: Обʼєкти API повинні мати можливість переходу між версіями API в даному випуску без втрати інформації, за винятком випадків, коли цілі ресурси REST не існують у деяких версіях.

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

Правило №3: Версія API в даному треку не може бути застарілою на користь менш стабільної версії API.

  • GA версії API можуть замінювати бета та альфа версії API.
  • Бета версії API можуть замінювати попередні бета та альфа версії API, але не можуть замінювати GA версії API.
  • Альфа версії API можуть замінювати попередні альфа версії API, але не можуть замінювати GA або бета версії API.

Правило №4а: Тривалість життя API визначається рівнем стабільності API

  • GA версії API можуть бути позначені як застарілі, але не можуть бути видалені в межах основної версії Kubernetes
  • Бета версії API застарівають не раніше ніж через 9 місяців або 3 мінорних випуски після впровадження (що довше), і більше не обслуговуються через 9 місяців або 3 мінорних випуски після застарівання (що довше)
  • Альфа версії API можуть бути видалені в будь-якому випуску без попереднього повідомлення про застарівання

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

Правило №4б: "Бажана" версія API та "версія зберігання" для даної групи можуть не просуватися до того, як буде зроблено випуск, що підтримує як нову версію, так і попередню версію.

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

Все це найкраще ілюструється прикладами. Уявіть собі випуск Kubernetes, версія X, який вводить нову групу API. Новий випуск Kubernetes виходить приблизно кожні 4 місяці (3 на рік). Наступна таблиця описує, які версії API підтримуються в ряді наступних випусків.

ВипускВерсії APIБажана/Версія зберіганняПримітки
Xv1alpha1v1alpha1
X+1v1alpha2v1alpha2
  • v1alpha1 видалено, "необхідна дія" інформація про випуск
X+2v1beta1v1beta1
  • v1alpha2 видалено, "необхідна дія" інформація про випуск
X+3v1beta2, v1beta1 (застар

іла)

v1beta1
  • v1beta1 застаріла, "необхідна дія" інформація про випуск
X+4v1beta2, v1beta1 (застаріла)v1beta2
X+5v1, v1beta1 (застаріла), v1beta2 (застаріла)v1beta2
  • v1beta2 застаріла, "необхідна дія" інформація про випуск
X+6v1, v1beta2 (застаріла)v1
  • v1beta1 видалено, "необхідна дія" інформація про випуск
X+7v1, v1beta2 (застаріла)v1
X+8v2alpha1, v1v1
  • v1beta2 видалено, "необхідна дія" інформація про випуск
X+9v2alpha2, v1v1
  • v2alpha1 видалено, "необхідна дія" інформація про випуск
X+10v2beta1, v1v1
  • v2alpha2 видалено, "необхідна дія" інформація про випуск
X+11v2beta2, v2beta1 (застаріла), v1v1
  • v2beta1 застаріла, "необхідна дія" інформація про випуск
X+12v2, v2beta2 (застаріла), v2beta1 (застаріла), v1 (застаріла)v1
  • v2beta2 застаріла, "необхідна дія" інформація про випуск
  • v1 застаріла на користь v2, але не буде видалена
X+13v2, v2beta1 (застаріла), v2beta2 (застаріла), v1 (застаріла)v2
X+14v2, v2beta2 (застаріла), v1 (застаріла)v2
  • v2beta1 видалено, "необхідна дія" інформація про випуск
X+15v2, v1 (застаріла)v2
  • v2beta2 видалено, "необхідна дія" інформація про випуск

REST ресурси (або обʼєкти API)

Розглянемо гіпотетичний REST ресурс з назвою Widget, який був присутній у версії API v1 у наведеній вище хронології і який потрібно визнати застарілим. Ми документуємо та оголошуємо про його застарівання синхронно з випуском X+1. Ресурс Widget все ще існує у версії API v1 (застарілий), але не у v2alpha1. Ресурс Widget продовжує існувати та функціонувати у випусках до, та включно з, X+8. Лише у випуску X+9, коли API v1 виходить з використання, ресурс Widget перестає існувати та його віповідна поведінка видаляється.

Починаючи з Kubernetes v1.19, виконання запиту до застарілої точки доступу REST API:

  1. Повертає заголовок Warning (як визначено у RFC7234, Розділ 5.5) у відповіді API.

  2. Додає "k8s.io/deprecated":"true" анотацію до події аудиту, зареєстрованої для запиту.

  3. Встановлює метрику apiserver_requested_deprecated_apis gauge у значення 1 у процесі kube-apiserver. Метрика має мітки group, version, resource, subresource, які можна поєднати з метрикою apiserver_request_total, і мітку removed_release, яка вказує випуск Kubernetes, в якому API більше не буде обслуговуватися. Наступний запит Prometheus повертає інформацію про запити, зроблені до застарілих API, які будуть видалені у версії v1.22:

    apiserver_requested_deprecated_apis{removed_release="1.22"} * on(group,version,resource,subresource) group_right() apiserver_request_total
    

Поля REST ресурсів

Як і REST ресурси в цілому, так і окреме поле, яке було присутнє у версії API v1, має існувати та функціонувати до видалення API v1. На відміну від ресурсів в цілому, API v2 можуть вибрати інше представлення для поля, допоки є можливість виконувати перехід між версіями в обидва боки. Наприклад, поле v1 з назвою "magnitude", яке було застарілим, може називатися "deprecatedMagnitude" в API v2. Коли v1 врешті буде видалено, застаріле поле може бути видалене з v2.

Перераховані або константні значення

Як і для REST ресурсу в цілому, так і його полів, константне значення, яке підтримувалося в API v1, має існувати та функціонувати до видалення API v1.

Структури конфігурацій компонентів

Конфігурації компонентів версіонуються та керуються аналогічно до REST ресурсів.

Майбутні роботи

З часом Kubernetes запровадить більш детальні версії API, і тоді ці правила будуть скориговані за потреби.

Застарівання прапорця або CLI

Система Kubernetes складається з кількох різних програм, які співпрацюють між собою. Іноді випуск Kubernetes може видаляти прапорці або команди CLI (загалом "елементи CLI") у цих програмах. Програми природно діляться на дві основні групи — програми для користувачів і програми для адміністраторів, які трохи відрізняються своїми політиками застарівання. Якщо прапорець явно не позначено або задокументовано як "alpha" або "beta", він вважається стабільним (GA).

Елементи CLI фактично є частиною API до системи, але оскільки вони не версіонуються так само, як REST API, правила застарівання наступні:

Правило №5а: Елементи CLI компонентів для користувачів (наприклад, kubectl) повинні функціонувати після оголошення їх застарівання не менше ніж:

  • GA: 12 місяців або 2 випуски (залежно від того, що довше)
  • Beta: 3 місяці або 1 випуск (залежно від того, що довше)
  • Alpha: 0 випусків

Правило №5б: Елементи CLI компонентів для адміністраторів (наприклад, kubelet) повинні функціонувати після оголошення їх застарівання не менше ніж:

  • GA: 6 місяців або 1 випуск (залежно від того, що довше)
  • Beta: 3 місяці або 1 випуск (залежно від того, що довше)
  • Alpha: 0 випусків

Правило №5в: Елементи командного інтерфейсу (CLI) не можуть бути застарілими на користь менш стабільних елементів CLI.

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

Правило №6: Застарілі елементи CLI повинні видавати попередження (можливо, такі, що відключаються) при використанні.

Застарівання функціонала або поведінки

Час від часу випуск Kubernetes потребує визнання застарілим певного функціонала або поведінки системи, яка не контролюється API або CLI. У цьому випадку правила застарівання такі:

Правило №7: Застарілі функції повинні функціонувати не менше 1 року після оголошеного застарівання.

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

Правило №8: Функцію або поведінку не можна визнати застарілою на користь альтернативної реалізації, яка менш стабільна.

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

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

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

Виняток з вищезазначеного правила  — це функціональні можливості. Функціональні можливості — це пари ключ=значення, які дозволяють користувачам увімкнути/вимкнути експериментальні функції.

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

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

  • Alpha: функціональні можливості стандартно вимкнені та можуть бути увімкнені користувачем.
  • Beta: функціональні можливості стандартно увімкнені та можуть бути вимкнені користувачем.
  • GA: функціональні можливості застарілі (див. "Застарівання") і стають нечинними.
  • GA, вікно застарівання завершено: функціональні можливості видаляються, і виклики до них більше не приймаються.

Застарівання

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

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

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

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

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

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

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

  • Від бета-функції до GA: 6 місяців або 2 випуски (залежно від того, що довше)
  • Від бета-функції до EOL: 3 місяці або 1 випуск (залежно від того, що довше)
  • Від альфа-функції до EOL: 0 випусків

Правило №10: Застарілі функціональні можливості повинні відповідати попередженням при використанні. Коли функціональні можливості застарівають, вони повинні бути задокументовані як в примітках про випуски, так і в відповідній довідці CLI. Як попередження, так і документація повинні вказувати, чи є функціональні можливості нечинними.

Застарівання метрики

Кожен компонент панелі управління Kubernetes використовує метрики (зазвичай за допомогою точки доступу /metrics), які зазвичай обробляються адміністраторами кластера. Не всі метрики однакові: деякі метрики широко використовуються як показники рівня сервісу (SLI) або для визначення SLO, тому вони мають більшу важливість. Інші метрики мають більш експериментальний характер або використовуються переважно у процесі розробки Kubernetes.

Відповідно, метрики поділяються на три класи стабільності (ALPHA, BETA, STABLE); це впливає на видалення метрики під час випуску Kubernetes. Ці класи визначаються важливістю метрики. Правила для застарівання та видалення метрики такі:

Правило №11а: Метрики для відповідного класу стабільності повинні функціонувати не менше ніж:

  • STABLE: 4 випуски або 12 місяців (що довше)
  • BETA: 2 випуски або 8 місяців (що довше)
  • ALPHA: 0 випусків

Правило №11б: Метрики, після їх оголошеного застарівання, повинні функціонувати не менше ніж:

  • STABLE: 3 випуски або 9 місяців (що довше)
  • BETA: 1 випуск або 4 місяці (що довше)
  • ALPHA: 0 випусків

Застарілі метрики будуть мати текст опису, у якому буде префікс з повідомленням про застарівання '(Застаріло з x.y)', і під час реєстрації метрики буде запис в лог з попередженням. Подібно до їх стабільних незастарілих аналогів, застарілі метрики будуть автоматично зареєстровані в точці доступу метрик і, отже, будуть видимими.

У наступному випуску (коли deprecatedVersion метрики дорівнює current_kubernetes_version - 3)), застаріла метрика стане прихованою метрикою. На відміну від їх застарілих аналогів, приховані метрики більше не будуть автоматично реєструватися в точці доступу метрик (таким чином, вони будуть приховані). Однак їх можна буде явно увімкнути через прапорець командного рядка (--show-hidden-metrics-for-version=). Це надає адміністраторам кластера можливість виходу зі складностей з міграцією від застарілої метрики, якщо вони не змогли відреагувати на раніше надані попередження щодо застарівання. Приховані метрики повинні бути видалені після одного випуску.

Винятки

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

6 - Посібник з міграції від застарілих API

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

Вилучені API в розрізі версій

v1.32

У випуску v1.32 перестануть обслуговуватися наступні застарілі версії API:

Ресурси контролю потоку

Версія API flowcontrol.apiserver.k8s.io/v1beta3 FlowSchema та PriorityLevelConfiguration більше не буде обслуговуватися у v1.32.

  • Перенесіть маніфести та клієнти API на використання версії API flowcontrol.apiserver.k8s.io/v1, доступної з версії v1.29.
  • Усі наявні збережені обʼєкти доступні через новий API
  • Значні зміни у flowcontrol.apiserver.k8s.io/v1:
    • Поле spec.limited.nominalConcurrencyShares PriorityLevelConfiguration має стандартне значення 30, коли не вказане, і явне значення 0 не змінюється на 30.

v1.29

У випуску v1.29 перестали обслуговуватися наступні застарілі версії API:

Ресурси контролю потоку

Версія API flowcontrol.apiserver.k8s.io/v1beta2 FlowSchema та PriorityLevelConfiguration більше не обслуговується з версії v1.29.

  • Перенесіть маніфести та клієнти API на використання версії API flowcontrol.apiserver.k8s.io/v1, доступної з версії v1.29, або версії API flowcontrol.apiserver.k8s.io/v1beta3, доступної з версії v1.26.
  • Усі наявні збережені обʼєкти доступні через новий API
  • Значні зміни в flowcontrol.apiserver.k8s.io/v1:
    • Поле spec.limited.assuredConcurrencyShares PriorityLevelConfiguration перейменоване на spec.limited.nominalConcurrencyShares і має стандартне значення 30, коли не вказане, і явне значення 0 не змінюється на 30.
  • Значні зміни в flowcontrol.apiserver.k8s.io/v1beta3:
    • Поле spec.limited.assuredConcurrencyShares PriorityLevelConfiguration перейменоване на spec.limited.nominalConcurrencyShares

v1.27

Випуск v1.27 припинив обслуговування наступних застарілих версій API:

CSIStorageCapacity

Версія API CSIStorageCapacity storage.k8s.io/v1beta1 більше не обслуговується з версії v1.27.

  • Перенесіть маніфести та клієнти API на версію API storage.k8s.io/v1, доступну з версії v1.24.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API
  • Немає помітних змін

v1.26

Випуск v1.26 припинив обслуговування наступних застарілих версій API:

Ресурси керування потоком

Версія API FlowSchema та PriorityLevelConfiguration flowcontrol.apiserver.k8s.io/v1beta1 більше не обслуговується з версії v1.26.

  • Перенесіть маніфести та клієнти API на версію API flowcontrol.apiserver.k8s.io/v1beta2.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API
  • Немає помітних змін

HorizontalPodAutoscaler

Версія API HorizontalPodAutoscaler autoscaling/v2beta2 більше не обслуговується з версії v1.26.

v1.25

Випуск v1.25 припинив обслуговування наступних застарілих версій API:

CronJob

Версія API CronJob batch/v1beta1 більше не обслуговується з версії v1.25.

  • Перенесіть маніфести та клієнти API на версію API batch/v1, доступну з версії v1.21.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API
  • Немає помітних змін

EndpointSlice

Версія API EndpointSlice discovery.k8s.io/v1beta1 більше не обслуговується з версії v1.25.

  • Перенесіть маніфести та клієнти API на версію API discovery.k8s.io/v1, доступну з версії v1.21.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API
  • Помітні зміни в discovery.k8s.io/v1:
    • використовуйте поле nodeName для кожного Endpoint замість застарілого поля topology["kubernetes.io/hostname"]
    • використовуйте поле zone для кожного Endpoint замість застарілого поля topology["topology.kubernetes.io/zone"]
    • topology замінено полем deprecatedTopology, яке не доступне для запису у v1

Event

Версія API Event events.k8s.io/v1beta1 більше не обслуговується з версії v1.25.

  • Перенесіть маніфести та клієнти API на версію API events.k8s.io/v1, доступну з версії v1.19.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API
  • Помітні зміни в events.k8s.io/v1:
    • type обмежено до Normal та Warning
    • involvedObject перейменовано в regarding
    • action, reason, reportingController та reportingInstance є обовʼязковими при створенні нових events.k8s.io/v1 Events
    • використовуйте eventTime замість застарілого поля firstTimestamp (яке перейменовано в deprecatedFirstTimestamp та не допускається в нових events.k8s.io/v1 Events)
    • використовуйте series.lastObservedTime замість застарілого поля lastTimestamp (яке перейменовано в deprecatedLastTimestamp та не допускається в нових **events.k8ерсіях API events.k8s.io/v1 Events)
    • використовуйте series.count замість застарілого поля count (яке перейменовано в deprecatedCount та не допускається в нових events.k8s.io/v1 Events)
    • використовуйте reportingController замість застарілого поля source.component (яке перейменовано в deprecatedSource.component та не допускається в нових events.k8s.io/v1 Events)
    • використовуйте reportingInstance замість застарілого поля source.host (яке перейменовано в deprecatedSource.host та не допускається в нових events.k8s.io/v1 Events)

HorizontalPodAutoscaler

Версія API HorizontalPodAutoscaler autoscaling/v2beta1 більше не обслуговується з версії v1.25.

PodDisruptionBudget

Версія API PodDisruptionBudget policy/v1beta1 більше не обслуговується з версії v1.25.

  • Перенесіть маніфести та клієнти API на версію API policy/v1, доступну з версії v1.21.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API
  • Помітні зміни в policy/v1:
    • пустий spec.selector ({}), записаний до policy/v1 PodDisruptionBudget, вибирає всі теки в просторі імен (у policy/v1beta1 пустий spec.selector не вибирав жодні теки). Неустановлений spec.selector вибирає жодні теки в обох версіях API.

PodSecurityPolicy

PodSecurityPolicy в версії API policy/v1beta1 більше не обслуговується з версії v1.25, і контролер допуску PodSecurityPolicy буде видалено.

Перейдіть до Pod Security Admission або виклику стороннього вебхуку допуску. Для настанов з міграції, див. Міграція з PodSecurityPolicy до вбудованого контролера допуску PodSecurity Admission Controller. Для отримання додаткової інформації про застарілість, див. ВPodSecurityPolicy Deprecation: Past, Present, and Future.

RuntimeClass

RuntimeClass в версії API node.k8s.io/v1beta1 більше не обслуговується з версії v1.25.

  • Перенесіть маніфести та клієнти API на версію API node.k8s.io/v1, доступну з версії v1.20.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API
  • Немає помітних змін

v1.22

Випуск v1.22 припинив обслуговування наступних застарілих версій API:

Ресурси вебхуків

Версія API admissionregistration.k8s.io/v1beta1 для MutatingWebhookConfiguration та ValidatingWebhookConfiguration більше не обслуговується з версії v1.22.

  • Перенесіть маніфести та клієнти API на версію API admissionregistration.k8s.io/v1, доступну з версії v1.16.
  • Усі наявні обʼєкти, які зберігаються, доступні через нові API
  • Помітні зміни:
    • стандартно webhooks[*].failurePolicy змінено з Ignore на Fail для v1
    • стандартно webhooks[*].matchPolicy змінено з Exact на Equivalent для v1
    • стандартно webhooks[*].timeoutSeconds змінено з 30s на 10s для v1
    • поле webhooks[*].sideEffects стандартно видалено, і тепер воно обовʼязкове, і дозволяється лише None та NoneOnDryRun для v1
    • стандартно видалено значення поля webhooks[*].admissionReviewVersions та робиться обовʼязковим для v1 (підтримувані версії для AdmissionReview - v1 та v1beta1)
    • поле webhooks[*].name повинно бути унікальним в списку для обʼєктів, створених через admissionregistration.k8s.io/v1

CustomResourceDefinition

Версія API apiextensions.k8s.io/v1beta1 для CustomResourceDefinition більше не обслуговується з версії v1.22.

  • Перенесіть маніфести та клієнти API на версію API apiextensions.k8s.io/v1, доступну з версії v1.16.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API
  • Помітні зміни:
    • поле spec.scope тепер не має станадртного значення Namespaced і повинно бути явно вказано
    • поле spec.version вилучено в v1; використовуйте замість цього spec.versions
    • поле spec.validation вилучено в v1; використовуйте замість цього spec.versions[*].schema
    • поле spec.subresources вилучено в v1; використовуйте замість цього spec.versions[*].subresources
    • поле spec.additionalPrinterColumns вилучено в v1; використовуйте замість цього spec.versions[*].additionalPrinterColumns
    • spec.conversion.webhookClientConfig переміщено в spec.conversion.webhook.clientConfig в v1
    • spec.conversion.conversionReviewVersions переміщено в spec.conversion.webhook.conversionReviewVersions в v1
    • поле spec.versions[*].schema.openAPIV3Schema тепер обовʼязкове при створенні обʼєктів CustomResourceDefinition для v1, і повинно бути структурною схемою
    • spec.preserveUnknownFields: true заборонено при створенні обʼєктів CustomResourceDefinition для v1; воно повинно бути вказано у визначеннях схем як x-kubernetes-preserve-unknown-fields: true
    • В елементах additionalPrinterColumns поле JSONPath перейменовано в jsonPath в v1 (виправлення #66531)

APIService

Версія API apiregistration.k8s.io/v1beta1 для APIService більше не обслуговується з версії v1.22.

  • Перенесіть маніфести та клієнти API на версію API apiregistration.k8s.io/v1, доступну з версії v1.10.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API
  • Немає помітних змін

TokenReview

Версія API authentication.k8s.io/v1beta1 для TokenReview більше не обслуговується з версії v1.22.

  • Перенесіть маніфести та клієнти API на версію API authentication.k8s.io/v1, доступну з версії v1.6.
  • Немає помітних змін

Ресурси SubjectAccessReview

Версія API authorization.k8s.io/v1beta1 для LocalSubjectAccessReview, SelfSubjectAccessReview, SubjectAccessReview та SelfSubjectRulesReview більше не обслуговується з версії v1.22.

  • Перенесіть маніфести та клієнти API на версію API authorization.k8s.io/v1, доступну з версії v1.6.
  • Помітні зміни:
    • Поле spec.group перейменовано на spec.groups в v1 (виправляє #32709)

CertificateSigningRequest

Версія API certificates.k8s.io/v1beta1 для CertificateSigningRequest більше не обслуговується з версії v1.22.

  • Перенесіть маніфести та клієнти API на версію API certificates.k8s.io/v1, доступну з версії v1.19.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API
  • Помітні зміни в certificates.k8s.io/v1:
    • Для API-клієнтів, що запитують сертифікати:
      • Поле spec.signerName тепер обовʼязкове (див. відомі підписувачи Kubernetes), і запити на kubernetes.io/legacy-unknown не дозволяються бути створеними через API certificates.k8s.io/v1
      • Поле spec.usages тепер обовʼязкове, не може містити дубльованих значень та повинно містити лише відомі використання
    • Для API-клієнтів, що схвалюють або підписують сертифікати:
      • status.conditions не може містити дублюються типи
      • status.conditions[*].status тепер обовʼязкове
      • status.certificate повинно бути в кодуванні PEM та містити лише блоки CERTIFICATE

Lease

Версія API coordination.k8s.io/v1beta1 для Lease більше не обслуговується з версії v1.22.

  • Перенесіть маніфести та клієнти API на версію API coordination.k8s.io/v1, доступну з версії v1.14.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API
  • Немає помітних змін

Ingress

Версії API extensions/v1beta1 та networking.k8s.io/v1beta1 для Ingress більше не обслуговуються з версії v1.22.

  • Перенесіть маніфести та клієнти API на версію API networking.k8s.io/v1, доступну з версії v1.19.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API
  • Помітні зміни:
    • Поле spec.backend перейменовано на spec.defaultBackend
    • Поле serviceName бекенду перейменовано на service.name
    • Числові поля servicePort бекенду перейменовані на service.port.number
    • Рядкові поля servicePort бекенду перейменовані на service.port.name
    • pathType тепер обовʼязковий для кожного вказаного шляху. Варіанти — Prefix, Exact, та ImplementationSpecific. Для відповідності невизначеній поведінці v1beta1 використовуйте ImplementationSpecific.

IngressClass

Версія API networking.k8s.io/v1beta1 для IngressClass більше не обслуговується з версії v1.22.

  • Перенесіть маніфести та клієнти API на версію API networking.k8s.io/v1, доступну з версії v1.19.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API
  • Немає помітних змін

Ресурси RBAC

Версія API rbac.authorization.k8s.io/v1beta1 для ClusterRole, ClusterRoleBinding, Role та RoleBinding більше не обслуговується з версії v1.22.

  • Перенесіть маніфести та клієнти API на версію API rbac.authorization.k8s.io/v1, доступну з версії v1.8.
  • Усі наявні обʼєкти, які зберігаються, доступні через нові API
  • Немає помітних змін

PriorityClass

Версія API scheduling.k8s.io/v1beta1 для PriorityClass більше не обслуговується з версії v1.22.

  • Перенесіть маніфести та клієнти API на версію API scheduling.k8s.io/v1, доступну з версії v1.14.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API.
  • Немає помітних змін.

Ресурси зберігання

Версія API storage.k8s.io/v1beta1 для CSIDriver, CSINode, StorageClass та VolumeAttachment більше не обслуговується з версії v1.22.

  • Перенесіть маніфести та клієнти API на версію API storage.k8s.io/v1
    • CSIDriver доступний у storage.k8s.io/v1 починаючи з версії v1.19.
    • CSINode доступний у storage.k8s.io/v1 починаючи з версії v1.17.
    • StorageClass доступний у storage.k8s.io/v1 починаючи з версії v1.6.
    • VolumeAttachment доступний у storage.k8s.io/v1 з версії v1.13.
  • Усі наявні обʼєкти, які зберігаються, доступні через нові API.
  • Немає помітних змін.

v1.16

Випуск v1.16 припинив обслуговування наступних застарілих версій API:

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

Версія API extensions/v1beta1 для NetworkPolicy більше не обслуговується з версії v1.16.

  • Перенесіть маніфести та клієнти API на версію API networking.k8s.io/v1, доступну з версії v1.8.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API.

DaemonSet

Версії API extensions/v1beta1 та apps/v1beta2 для DaemonSet більше не обслуговуються з версії v1.16.

  • Перенесіть маніфести та клієнти API на версію API apps/v1, доступну з версії v1.9.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API.
  • Помітні зміни:
    • spec.templateGeneration видалено.
    • spec.selector тепер є обовʼязковим і незмінним після створення; використовуйте наявні мітки шаблону як селектор для безшовного оновлення.
    • spec.updateStrategy.type тепер стандартно встановлено на RollingUpdate (стандартно в extensions/v1beta1 було OnDelete).

Deployment

Версії API extensions/v1beta1, apps/v1beta1 та apps/v1beta2 для Deployment більше не обслуговуються з версії v1.16.

  • Перенесіть маніфести та клієнти API на версію API apps/v1, доступну з версії v1.9.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API.
  • Помітні зміни:
    • spec.rollbackTo видалено.
    • spec.selector тепер є обовʼязковим і незмінним після створення; використовуйте наявні мітки шаблону як селектор для безшовного оновлення.
    • spec.progressDeadlineSeconds тепер стандартно встановлено на 600 секунд (стандартно в extensions/v1beta1 було без крайнього терміну).
    • spec.revisionHistoryLimit тепер стандартно встановлено на 10 (стандартно в apps/v1beta1 було 2, стандартно в extensions/v1beta1 було зберігати всі).
    • maxSurge та maxUnavailable тепер стандартно встановлено на 25% (стандартно в extensions/v1beta1 було 1).

StatefulSet

Версії API apps/v1beta1 та apps/v1beta2 для StatefulSet більше не обслуговуються з версії v1.16.

  • Перенесіть маніфести та клієнти API на версію API apps/v1, доступну з версії v1.9.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API.
  • Помітні зміни:
    • spec.selector тепер є обовʼязковим і незмінним після створення; використовуйте наявні мітки шаблону як селектор для безшовного оновлення.
    • spec.updateStrategy.type тепер за замовчуванням встановлено на RollingUpdate (стандартно в apps/v1beta1 було OnDelete).

ReplicaSet

Версії API extensions/v1beta1, apps/v1beta1 та apps/v1beta2 для ReplicaSet більше не обслуговуються з версії v1.16.

  • Перенесіть маніфести та клієнти API на версію API apps/v1, доступну з версії v1.9.
  • Усі наявні обʼєкти, які зберігаються, доступні через новий API.
  • Помітні зміни:
    • spec.selector тепер є обовʼязковим і незмінним після створення; використовуйте наявні мітки шаблону як селектор для безшовного оновлення.

PodSecurityPolicy

Версія API extensions/v1beta1 для PodSecurityPolicy більше не обслуговується з версії v1.16.

  • Перенесіть маніфести та клієнти API на версію API policy/v1beta1, доступну з версії v1.10.
  • Зауважте, що версія API policy/v1beta1 для PodSecurityPolicy буде видалена у версії v1.25.

Що робити

Тестування з вимкненими застарілими API

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

--runtime-config=<group>/<version>=false

Наприклад:

--runtime-config=admissionregistration.k8s.io/v1beta1=false,apiextensions.k8s.io/v1beta1,...

Пошук використання застарілих API

Використовуйте попередження клієнтів, метрики та інформацію аудиту, доступні в версії 1.19+ для визначення використання застарілих API.

Перехід на незастарілі API

  • Оновіть власні інтеграції та контролери, щоб викликати незастарілі API.

  • Змініть YAML файли, щоб вони посилалися на незастарілі API.

    Ви можете використовувати команду kubectl convert для автоматичного перетворення наявного обʼєкта:

    kubectl convert -f <file> --output-version <group>/<version>.

    Наприклад, щоб перетворити старий Deployment на apps/v1, ви можете виконати:

    kubectl convert -f ./my-deployment.yaml --output-version apps/v1

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

7 - Точки доступу для моніторингу стану API Kubernetes

API сервер Kubernetes надає точки доступу API для індикації поточного стану API сервера. Ця сторінка описує ці точки доступу API та пояснює, як ви можете їх використовувати.

Точки доступу API для моніторингу стану

API сервер Kubernetes надає 3 точки доступу API (healthz, livez і readyz) для індикації поточного стану API сервера. Точка доступу healthz є застарілою (з Kubernetes v1.16), і ви повинні використовувати більш конкретні точки доступу livez та readyz. Точку доступу livez можна використовувати з прапорцем --livez-grace-period, щоб вказати тривалість запуску. Для належного завершення роботи ви можете вказати прапорець --shutdown-delay-duration з точкою доступу /readyz. Машини, що перевіряють healthz/livez/readyz API сервера, повинні покладатися на HTTP-код статусу. Код статусу 200 вказує, що API сервер є healthy/live/ready, залежно від викликаної точки доступу. Більш докладні опції, показані нижче, призначені для використання людьми-операторами для налагодження їх кластера або розуміння стану API сервера.

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

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

curl -k https://localhost:6443/livez?verbose

або з віддаленого хосту з автентифікацією:

kubectl get --raw='/readyz?verbose'

Вивід буде виглядати наступним чином:

[+]ping ok
[+]log ok
[+]etcd ok
[+]poststarthook/start-kube-apiserver-admission-initializer ok
[+]poststarthook/generic-apiserver-start-informers ok
[+]poststarthook/start-apiextensions-informers ok
[+]poststarthook/start-apiextensions-controllers ok
[+]poststarthook/crd-informer-synced ok
[+]poststarthook/bootstrap-controller ok
[+]poststarthook/rbac/bootstrap-roles ok
[+]poststarthook/scheduling/bootstrap-system-priority-classes ok
[+]poststarthook/start-cluster-authentication-info-controller ok
[+]poststarthook/start-kube-aggregator-informers ok
[+]poststarthook/apiservice-registration-controller ok
[+]poststarthook/apiservice-status-available-controller ok
[+]poststarthook/kube-apiserver-autoregistration ok
[+]autoregister-completion ok
[+]poststarthook/apiservice-openapi-controller ok
healthz check passed

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

curl -k 'https://localhost:6443/readyz?verbose&exclude=etcd'

Вивід показує, що перевірка etcd виключено:

[+]ping ok
[+]log ok
[+]etcd excluded: ok
[+]poststarthook/start-kube-apiserver-admission-initializer ok
[+]poststarthook/generic-apiserver-start-informers ok
[+]poststarthook/start-apiextensions-informers ok
[+]poststarthook/start-apiextensions-controllers ok
[+]poststarthook/crd-informer-synced ok
[+]poststarthook/bootstrap-controller ok
[+]poststarthook/rbac/bootstrap-roles ok
[+]poststarthook/scheduling/bootstrap-system-priority-classes ok
[+]poststarthook/start-cluster-authentication-info-controller ok
[+]poststarthook/start-kube-aggregator-informers ok
[+]poststarthook/apiservice-registration-controller ok
[+]poststarthook/apiservice-status-available-controller ok
[+]poststarthook/kube-apiserver-autoregistration ok
[+]autoregister-completion ok
[+]poststarthook/apiservice-openapi-controller ok
[+]shutdown ok
healthz check passed

Індивідуальні перевірки стану

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

Кожна індивідуальна перевірка стану надає HTTP точку доступу і може бути перевірена індивідуально. Схема для індивідуальних перевірок стану — /livez/<healthcheck-name> або /readyz/<healthcheck-name>, де livez і readyz можуть бути використані для індикації, чи ви хочете перевірити liveness або readiness API сервера відповідно. Шлях <healthcheck-name> можна знайти, використовуючи прапорець verbose вище та шлях між [+] та ok. Ці індивідуальні перевірки стану не повинні використовуватися машинами, але можуть бути корисні для оператора-людини для налагодження системи:

curl -k https://localhost:6443/livez/etcd