Концепції API Kubernetes
API Kubernetes — це програмний інтерфейс на основі ресурсів (RESTful), який надається через HTTP. Він підтримує отримання, створення, оновлення та видалення основних ресурсів за допомогою стандартних HTTP-дієслів (POST, PUT, PATCH, DELETE, GET).
Для деяких ресурсів API включає додаткові субресурси, що дозволяють детальніше налаштовувати авторизацію (наприклад, окремі представлення для деталей Pod та отримання логів), і може приймати та надавати ці ресурси в різних форматах для зручності або ефективності.
Kubernetes підтримує ефективні сповіщення про зміни ресурсів за допомогою watches.
В API Kubernetes, watch це дієслово, яке використовується для відстеження змін обʼєкта в Kubernetes у вигляді потоку. Використовується для ефективного виявлення змін.
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
— повертає колекцію всіх екземплярів вказаного типу ресурсу в просторі імен NAMESPACEGET /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 для отримання додаткової інформації. Немає можливості отримати доступ до субресурсів через декілька ресурсів — зазвичай використовується новий віртуальний тип ресурсу, якщо це стає необхідним.
HTTP медіа-типи
Kubernetes підтримує кодування JSON та Protobuf для передачі даних по HTTP.
Стандартно, Kubernetes повертає серіалізовані об’єкти JSON, використовуючи медіа-тип application/json
. Хоча JSON є стандартним типом, клієнти можуть запитувати відповідь у форматі YAML, або більш ефективне двійкове подання у вигляді Protobuf для кращої продуктивності.
Kubernetes API реалізує стандартне узгодження типів вмісту HTTP: передача заголовка Accept
у запиті GET
вказує серверу спробувати повернути відповідь у бажаному медіа-типі. Якщо ви хочете надіслати об’єкт у форматі Protobuf на сервер для запиту PUT
або POST
, вам необхідно відповідно встановити заголовок запиту Content-Type
.
Якщо ви запитуєте доступні медіа-типи, API-сервер повертає відповідь з відповідним заголовком Content-Type
; якщо жоден із запитаних медіа-типів не підтримується, API-сервер поверне повідомлення про помилку 406 Not acceptable
. Усі вбудовані типи ресурсів підтримують медіа-тип application/json
.
Кодування ресурсів у форматі JSON
API Kubernetes стандартно використовує JSON для кодування тіла HTTP повідомлень.
Наприклад:
Вивести список усіх Podʼів в кластері без вказування бажаного формату
GET /api/v1/pods
200 OK Content-Type: application/json … Колекція Pod, закодована у форматі JSON (обʼєкт PodList)
Створити Pod, відправивши JSON на сервер та запросивши відповідь у форматі JSON.
POST /api/v1/namespaces/test/pods Content-Type: application/json Accept: application/json … Обʼєкт Pod, закодований у форматі JSON
200 OK Content-Type: application/json { "kind": "Pod", "apiVersion": "v1", … }
Кодування ресурсів у YAML
Kubernetes також підтримує медіатип application/yaml
для запитів та відповідей. YAML
може використовуватись для визначення маніфестів Kubernetes та взаємодії з API.
Наприклад:
Отримати список усіх podʼів у кластері у форматі YAML
GET /api/v1/pods Accept: application/yaml
200 OK Content-Type: application/yaml … YAML-кодована колекція Podʼів (обʼєкт PodList)
Створити pod, надіславши дані у форматі YAML на сервер і запросивши відповідь у форматі YAML:
POST /api/v1/namespaces/test/pods Content-Type: application/yaml Accept: application/yaml … YAML-кодований об'єкт Pod
200 OK Content-Type: application/yaml apiVersion: v1 kind: Pod metadata: name: my-pod …
Кодування Kubernetes Protobuf
Kubernetes використовує обгортку-конверт для кодування відповідей у форматі Protobuf. Ця обгортка починається з 4 байтів магічного числа, щоб допомогти ідентифікувати вміст на диску або в etcd як Protobuf (на відміну від JSON). Дані з магічним числом (4 байти) слідують за повідомленням, закодованим у форматі Protobuf, яке описує кодування та тип основного об’єкта. Усередині повідомлення Protobuf дані внутрішнього об’єкта записуються за допомогою поля raw
Unknown (дивіться IDL для докладної інформації).
Наприклад:
Вивести список усіх Pod в кластері у форматі Protobuf.
GET /api/v1/pods Accept: application/vnd.kubernetes.protobuf
200 OK Content-Type: application/vnd.kubernetes.protobuf … Колекція Pod, закодована у форматі JSON (об'єкт PodList)
Створити Pod, відправивши дані, закодовані у форматі Protobuf на сервер, але запросити відповідь у форматі JSON.
POST /api/v1/namespaces/test/pods Content-Type: application/vnd.kubernetes.protobuf Accept: application/json … двійково закодований обʼєкт Pod --- 200 OK Content-Type: application/json { "kind": "Pod", "apiVersion": "v1", ... }
Ви можете використовувати обидві техніки разом і взаємодіяти з API Kubernetes, яке підтримує кодування Protobuf, для читання та запису даних. Лише деякі типи ресурсів API є сумісними з Protobuf.
Формат обгортки:
Чотирибайтовий префікс магічного числа:
Байти 0-3: "k8s\x00" [0x6b, 0x38, 0x73, 0x00]
Закодоване повідомлення Protobuf з наступним IDL:
message Unknown {
// typeMeta повинне містити значення рядків для "kind" та "apiVersion", як встановлено в обʼєкті
JSON optional TypeMeta typeMeta = 1;
// raw містить повний серіалізований обʼєкт у форматі protobuf.
// Дивіться визначення protobuf у клієнтських бібліотеках для конкретного виду.
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;
}
Примітка:
Клієнти, які отримують відповідь у форматіapplication/vnd.kubernetes.protobuf
, що не відповідає очікуваному префіксу, повинні відхилити відповідь, оскільки майбутні версії можуть змінити формат серіалізації на несумісний спосіб, і це буде зроблено шляхом зміни префіксу.Сумісність із Kubernetes Protobuf
Не всі типи ресурсів API підтримують кодування Kubernetes у форматі Protobuf; зокрема, Protobuf не доступний для ресурсів, які визначені як CustomResourceDefinitions або надаються через шар агрегації.
Як клієнт, якщо вам може знадобитися працювати з розширеними типами, слід вказати кілька типів контенту в заголовку Accept
запиту для підтримки резервного переходу на JSON. Наприклад:
Accept: application/vnd.kubernetes.protobuf, application/json
Кодування ресурсів CBOR
Kubernetes v1.32 [alpha]
(стандартно увімкнено: false)З увімкненою функціональною можливістю CBORServingAndStorage
тіла запитів і відповідей для всіх вбудованих типів ресурсів і всіх ресурсів, визначених CustomResourceDefinition, можуть бути закодовані у двійковий формат даних CBOR. CBOR також підтримується на рівні aggregation layer, якщо він увімкнений на окремих агрегованих серверах API.
Клієнти повинні вказувати медіа-тип IANA application/cbor
в заголовку HTTP-запиту Content-Type
, коли тіло запиту містить один CBOR закодований елемент даних, і в заголовку HTTP-запиту Accept
, коли вони готові прийняти CBOR-кодований елемент даних у відповіді. Сервери API будуть використовувати application/cbor
в заголовку Content-Type
HTTP-відповіді, коли тіло відповіді містить об'єкт, закодований CBOR.
Якщо сервер API кодує свою відповідь на watch request за допомогою CBOR, тіло відповіді буде CBOR Sequence, а в заголовку Content-Type
HTTP-відповіді буде використано медіа-тип IANA application/cbor-seq
. Кожен елемент послідовності (якщо такий є) є окремою подією спостереження, закодованою CBOR.
На додаток до існуючого типу даних application/apply-patch+yaml
для YAML-кодованих [конфігурацій додатків на стороні сервера] (#patch-and-apply), сервери API, які підтримують CBOR, прийматимуть тип даних application/apply-patch+cbor
для конфігурацій додатків на стороні сервера, закодованих CBOR. Для application/json-patch+json
або application/merge-patch+json
, або application/strategic-merge-patch+json
не підтримується еквівалент CBOR.
Ефективне виявлення змін
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 і розпочати знову. Див. Семантика версій ресурсів для отримання детальнішої інформації.
Наприклад:
Отримання списку всіх Podʼів у вказаному просторі імен.
GET /api/v1/namespaces/test/pods --- 200 OK Content-Type: application/json { "kind": "PodList", "apiVersion": "v1", "metadata": {"resourceVersion":"10245"}, "items": [...] }
Починаючи з версії ресурсу 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.32 [beta]
(стандартно увімкнено: true)У великих кластерах отримання колекції деяких типів ресурсів може призвести до значного збільшення використання ресурсів (переважно RAM) панелі управління. Щоб зменшити вплив та спростити користування шаблоном list + watch у Kubernetes v1.32 переведено у бета-версію функцію, яка дозволяє запитувати початковий стан (який раніше запитувався за допомогою запиту list) як частину запиту watch.
На стороні клієнта початковий стан можна запросити, вказавши 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]
(стандартно увімкнено: true)Опція 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]
(стандартно увімкнено: true)У великих кластерах отримання колекції деяких типів ресурсів може призвести до дуже великих відповідей, що може вплинути на сервер та клієнта. Наприклад, у кластері може бути десятки тисяч 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ʼів за раз, запитуйте ці частини наступним чином:
Отримати всі 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 }
Продовжити попередній запит, отримуючи наступний набір з 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 }
Продовжити попередній запит, отримуючи останні 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
Примітка:
Памʼятайте, що API Kubernetes не має kind
з іменем List
.
kind: List
є клієнтським внутрішнім деталям реалізації для обробки колекцій, які можуть бути різними типами обʼєктів. Уникайте залежності від kind: List
в автоматизації або іншому коді.
Отримання ресурсів у вигляді таблиць
Коли ви запускаєте 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
Видалення ресурсів
Коли ви видаляєте ресурс, цей процес проходить у два етапи:
- Завершення (finalization)
- Видалення (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.
Примусове видалення
Kubernetes v1.32 [alpha]
(стандартно увімкнено: false)Увага:
Це може порушити робоче навантаження, повʼязане з примусовим видаленням ресурсу, якщо воно покладається на звичайний потік видалення, що може призвести до руйнування кластера.Увімкнувши опцію видалення ignoreStoreReadErrorWithClusterBreakingPotential
, користувач може виконати небезпечну операцію примусового видалення нерозшифрованого/пошкодженого ресурсу. Ця опція знаходиться за функціональною можоивістю ALPHA, і стандартно вона вимкнена. Щоб скористатися цією опцією, оператор кластера повинен увімкнути її за допомогою параметра командного рядка --feature-gates=AllowUnsafeMalformedObjectDeletion=true
.
Примітка:
Користувач, який виконує операцію примусового видалення, повинен мати привілеї на виконання обох дієслів delete і unsafe-delete-ignore-read-errors на даному ресурсі.Ресурс вважається пошкодженим, якщо він не може бути успішно вилучений зі сховища через а) помилку перетворення (наприклад, помилку розшифрування), або б) обʼєкт не вдалося декодувати. Сервер API спочатку намагається виконати звичайне видалення, і якщо це не вдається з помилкою corrupt resource, він запускає операцію примусового видалення. Операція примусового видалення є небезпечною, оскільки вона ігнорує обмеження фіналізатора і пропускає перевірку передумов.
Стандартне значення для цієї опції — false
, це забезпечує зворотну сумісність. Для запиту delete з параметром ignoreStoreReadErrorWithClusterBreakingPotential
, встановленим у значення true
, поля dryRun
, gracePeriodSeconds
, orphanDependents
, preconditions
і propagationPolicy
слід залишити не встановленими.
Примітка:
Якщо користувач надсилає запит delete зі значеннямignoreStoreReadErrorWithClusterBreakingPotential
, встановленим у true
для ресурсу, який інакше можна прочитати, сервер API перериває запит з помилкою.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-запиті.
Ці ситуації такі:
- Поле не розпізнається, оскільки воно не входить до схеми OpenAPI ресурсу. (Одним винятком є CRDs, які явно обирають не обрізати невідомі поля через
x-kubernetes-preserve-unknown-fields
). - Поле дублюється в обʼєкті.
Валідація для нерозпізнаних або дубльованих полів
Kubernetes v1.27 [stable]
(стандартно увімкнено: true)З версії 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
.
Примітка:
Якщо ви надсилаєте запит, що вказує на нерозпізнане поле, яке також є недійсним з іншої причини (наприклад, запит надає рядкове значення, де API очікує цілого числа для відомого поля), тоді сервер API відповідає з помилкою 400 Bad Request, але не надасть жодної інформації про невідомі або дубльовані поля (тільки про ту фатальну помилку, яку він виявив першою).
У цьому випадку ви завжди отримаєте відповідь про помилку, незалежно від того, який рівень валідації полів ви запросили.
Інструменти, які надсилають запити на сервер (такі як kubectl
), можуть встановлювати свої власні типові значення, які відрізняються від рівня валідації Warn
, що стандартно використовується сервером API.
Інструмент kubectl
використовує прапорець --validate
для встановлення рівня валідації полів. Він приймає значення ignore
, warn
та strict
, а також приймає значення true
(еквівалентно strict
) і false
(еквівалентно ignore
). Станадртне налаштування валідації для kubectl — це --validate=true
, що означає сувору валідацію полів на стороні сервера.
Коли kubectl не може підключитися до сервера API з валідацією полів (сервери API до Kubernetes 1.27), він повернеться до використання валідації на стороні клієнта. Валідація на стороні клієнта буде повністю видалена у майбутній версії kubectl.
Примітка:
До Kubernetes 1.25 прапорецьkubectl --validate
використовувався для перемикання валідації на стороні клієнта увімквимкання/вимиканнямнено булевого прапореця.Dry-run
Kubernetes v1.19 [stable]
(стандартно увімкнено: true)При використанні 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
.
Примітка:
Якщо вебхук дійсно має побічні ефекти, то полеsideEffects
має бути встановлено на "NoneOnDryRun". Ця зміна є доречною за умови, що вебхук також модифіковано щоб він розумів поле DryRun
у AdmissionReview і для запобігання побічним ефектам на будь-який запит, позначений як dry run.Приклад 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 замінив Strategic Merge Patch.
Функція Серверного застосування 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 | Параметри розбиття на сторінки | 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=Exact | limit не встановлено | Недійсний | Недійсний | Exact |
resourceVersionMatch=Exact | limit=<n>, continue не встановлено | Недійсний | Недійсний | Exact |
resourceVersionMatch=NotOlderThan | limit не встановлено | Недійсний | Any | NotOlderThan |
resourceVersionMatch=NotOlderThan | limit=<n>, continue не встановлено | Недійсний | Any | NotOlderThan |
Примітка:
Якщо сервер API вашого кластера не враховує параметрresourceVersionMatch
, поведінка буде такою самою, як і якщо ви його не встановили.Сенс семантики операцій get та list такий:
- Any
- Повернути дані на будь-якій версії ресурсу. Вибирається найновіша доступна версія ресурсу, але не потрібна сильна консистентність; дані на будь-якій версії ресурсу можуть бути обслуговані. Є можливість отримати дані на значно старішій версії ресурсу, яку клієнт раніше спостерігав, особливо в конфігураціях високої доступності через розділи або застарілі кеші. Клієнти, які не можуть терпіти це, не повинні використовувати цю семантику.
- Найновіший
- Повернути дані на найновішій версії ресурсу. Повернені дані повинні бути консистентними (детально: обслуговуються з etcd за допомогою кворумного читання). Для etcd версій v3.4.31+ та v3.5.13+ Kubernetes 1.32 обслуговує "найсвіжіші" читання з watch cache: внутрішнього, вбудованого в памʼять сховища всередині API сервера, що кешує та відображає стан даних, збережених у etcd. Kubernetes запитує сповіщення про прогрес, щоб підтримувати консистентність кешу з шаром збереження даних (persistence layer) у etcd. Версії Kubernetes з v1.28 до v1.30 також підтримували цю функцію, але як Alpha, вона не рекомендувалася для використання в операційному середовищі і не була стандартно увімкненою до випуску v1.31.
- 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.
Примітка:
Коли ви перелічцєте (list) ресурси та отримуєте відповідь у вигляді колекції, відповідь містить метадані списку колекції, а також метадані обʼєктів для кожного елемента у цій колекції. Для окремих обʼєктів, знайдених у відповіді колекції,.metadata.resourceVersion
відстежує, коли цей обʼєкт був останній раз оновлений, а не те, наскільки актуальний обʼєкт, коли він обслуговується.При використанні resourceVersionMatch=Не старше
та встановленому ліміті клієнти мають обробляти відповіді HTTP 410 "Gone". Наприклад, клієнт може повторно спробувати з новішою resourceVersion
або використовувати resourceVersion=""
.
При використанні resourceVersionMatch=Точно
та не встановленому ліміті, клієнти мають перевірити, що .metadata.resourceVersion
колекції співпадає з запитаною resourceVersion
, і обробити випадок, коли це не так. Наприклад, клієнт може використовувати запит з встановленим лімітом.
Семантика для операції watch
Для операцій watch, семантика параметра resourceVersion
така:
watch:
resourceVersion невстановлено | resourceVersion="0" | resourceVersion="{значення, відмінне від 0}" |
---|---|---|
Отримати стан і почати з найновішого | Отримати стан і почати з будь-якого | Почати точно з |
Сенс цієї семантики для watch такий:
- Отримати стан і почати з будь-якого
- Почати watch на будь-якій версії ресурсу; найбільш нова доступна версія є переважною, але не обовʼязковою. Дозволено будь-яку початкову версію ресурсу. Можливо, що watch почнеться на набагато старішій версії ресурсу, яку клієнт раніше спостерігав, особливо в конфігураціях високої доступності через розділи або застарілі кеші. Клієнти, які не можуть терпіти таке відмотування назад, не повинні починати watch з цією семантикою. Для встановлення початкового стану, watch починається з синтетичних подій "Added" для всіх екземплярів ресурсів, які існують на початковій версії ресурсу. Усі наступні події watch стосуються всіх змін, що сталися після початкової версії ресурсу, з якої почався 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-сервер може чекати невизначений час (до тайм-ауту запиту), поки версія ресурсу не стане доступною.
Ідемпотентність означає, що ви можете повторно виконати операцію без змін у стані системи. https://uk.wikipedia.org/wiki/Ідемпотентність ↩︎