API Kubernetes — це програмний інтерфейс на основі ресурсів (RESTful), який надається через HTTP. Він підтримує отримання, створення, оновлення та видалення основних ресурсів за допомогою стандартних HTTP-дієслів (POST, PUT, PATCH, DELETE, GET).
Для деяких ресурсів API включає додаткові субресурси, що дозволяють детальніше налаштовувати авторизацію (наприклад, окремі представлення для деталей Pod та отримання логів), і може приймати та надавати ці ресурси в різних форматах для зручності або ефективності.
В API Kubernetes, watch це дієслово, яке використовується для відстеження змін обʼєкта в Kubernetes у вигляді потоку. Використовується для ефективного виявлення змін.
Kubernetes також забезпечує послідовні операції зі списками, щоб клієнти API могли ефективно кешувати, відстежувати та синхронізувати стан ресурсів.
Kubernetes зазвичай використовує загальноприйняту термінологію RESTful для опису концепцій API:
Майже всі типи ресурсів підтримують стандартні HTTP-дієслова — GET, POST, PUT, PATCH, та DELETE. Kubernetes також використовує власні дієслова, які часто пишуться малими літерами, щоб відрізняти їх від HTTP-дієслів.
Ви також можете отримати доступ до колекцій ресурсів (наприклад, переліку усіх Nodes). Наступні шляхи використовуються для отримання колекцій та ресурсів:
Оскільки простір імен є ресурсом кластерного рівня, ви можете отримати перелік ("колекцію") всіх просторів імен за допомогою GET /api/v1/namespaces
та деталі про конкретний простір імен за допомогою GET /api/v1/namespaces/NAME
.
Підтримувані дієслова для кожного субресурсу будуть відрізнятися залежно від обʼєкта — див. Довідник API для отримання додаткової інформації. Немає можливості отримати доступ до субресурсів через декілька ресурсів — зазвичай використовується новий віртуальний тип ресурсу, якщо це стає необхідним.
Kubernetes підтримує кодування JSON та Protobuf для передачі даних по HTTP.
Kubernetes API реалізує стандартне узгодження типів вмісту HTTP: передача заголовка Accept
у запиті GET
вказує серверу спробувати повернути відповідь у бажаному медіа-типі. Якщо ви хочете надіслати об’єкт у форматі Protobuf на сервер для запиту PUT
або POST
, вам необхідно відповідно встановити заголовок запиту Content-Type
.
Якщо ви запитуєте доступні медіа-типи, API-сервер повертає відповідь з відповідним заголовком Content-Type
; якщо жоден із запитаних медіа-типів не підтримується, API-сервер поверне повідомлення про помилку 406 Not acceptable
. Усі вбудовані типи ресурсів підтримують медіа-тип application/json
.
Kubernetes використовує обгортку-конверт для кодування відповідей у форматі Protobuf. Ця обгортка починається з 4 байтів магічного числа, щоб допомогти ідентифікувати вміст на диску або в etcd як Protobuf (на відміну від JSON). Дані з магічним числом (4 байти) слідують за повідомленням, закодованим у форматі Protobuf, яке описує кодування та тип основного об’єкта. Усередині повідомлення Protobuf дані внутрішнього об’єкта записуються за допомогою поля raw
Unknown (дивіться IDL для докладної інформації).
Ви можете використовувати обидві техніки разом і взаємодіяти з 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
Ефективне виявлення змін
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.27 [alpha]
(стандартно увімкнено: false)
У великих кластерах отримання колекції деяких типів ресурсів може призвести до значного збільшення використання ресурсів (переважно 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]
(стандартно увімкнено: 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.
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-клієнти можуть порівнювати лише дві версії ресурсів на рівність (це означає, що ви не можете порівнювати версії ресурсів за відносними значеннями "більше" або "менше").
Клієнти знаходять версії ресурсів в ресурсах, включаючи ресурси з потоку відповіді під час спостереження (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:
Сервери не зобовʼязані зберігати всі старі версії ресурсів і можуть повернути код HTTP 410 (Gone)
, якщо клієнт запитує resourceVersion
, який старіший, ніж версія, збережена сервером. Клієнти повинні бути готові обробляти відповіді 410 (Gone)
. Дивіться розділ Ефективне виявлення змін для отримання додаткової інформації про те, як обробляти відповіді 410 (Gone)
при спостереженні за ресурсами.
Сервери не зобовʼязані обслуговувати нерозпізнані версії ресурсів. Якщо ви запитуєте list або get для версії ресурсу, яку API-сервер не розпізнає, то API-сервер може або:
Якщо ви запитуєте версію ресурсу, яку API-сервер не розпізнає, kube-apiserver додатково ідентифікує свої відповіді на помилки повідомленням "Too large resource version".