Server-Side Apply
Kubernetes v1.22 [stable]
(стандартно увімкнено: true)Kubernetes підтримує співпрацю кількох аплікаторів для керування полями одного обʼєкта.
Server-Side Apply (Серверне застосування) надає необовʼязковий механізм для контролера вашого кластера, щоб відстежувати зміни в полях обʼєкта. На рівні конкретного ресурсу, Server-Side Apply записує та відстежує інформацію про контроль над полями цього обʼєкта.
Server-Side Apply допомагає користувачам та контролерам керувати своїми ресурсами за допомогою декларативної конфігурації. Клієнти можуть створювати та змінювати обʼєкти декларативно, подаючи їх повністю визначений намір.
Повністю визначений намір — це частковий обʼєкт, який містить лише ті поля та значення, щодо яких у користувача є чітке уявлення. Цей намір або створює новий обʼєкт (використовуючи стандартні значення для невизначених полів), або обʼєднується з наявним обʼєктом через API сервер.
Порівняння з Client-Side Apply пояснює, як Server-Side Apply відрізняється від початкової реалізації kubectl apply
на стороні клієнта.
Управління полями
Kubernetes API сервер відстежує керовані поля для всіх новостворених обʼєктів.
При спробі застосувати обʼєкт, поля, які мають інше значення і належать іншому менеджеру, спричинять конфлікт. Це зроблено для того, щоб сигналізувати, що операція може скасувати зміни іншого спільника. Записи до обʼєктів з керованими полями можуть бути примусовими, в такому випадку значення будь-якого конфліктного поля буде перезаписане, а право власності передане.
Кожного разу, коли значення поля змінюється, право власності переходить від поточного менеджера до менеджера, що здійснює зміну.
Операція застосування перевіряє, чи є інші менеджери полів, які також володіють полем. Якщо поле не належить жодному іншому менеджеру полів, це поле встановлюється на стандартне значення (якщо таке є), або видаляється з обʼєкта. Те саме правило застосовується до полів, які є списками, асоціативними списками або map.
Для того, щоб користувач міг керувати полем в контексті Server-Side Apply, він повинен покладатися на те, що значення поля не зміниться. Користувач, який останнім висловив свою думку щодо значення поля, буде записаний як поточний менеджер поля. Це можна зробити, змінивши дані менеджера поля явним чином за допомогою HTTP POST
(створення), PUT
(оновлення), або не-застосувального PATCH
(патч). Ви також можете оголосити та записати менеджера поля, включивши значення для цього поля в операції Server-Side Apply.
Запит на патч в контексті Server-Side Apply вимагає від клієнта вказати свою ідентичність як менеджера поля. При використанні Server-Side Apply спроба змінити поле, що контролюється іншим менеджером, призведе до відхилення запиту, якщо клієнт не виконає примусове перевизначення. Для деталей щодо примусових перевизначень дивіться Конфлікти.
Коли два або більше аплікатора встановлюють поле на однакове значення, вони спільно володіють цим полем. Будь-яка спроба змінити значення спільного поля будь-ким з аплікаторів призведе до конфлікту. Спільні власники поля можуть відмовитися від права власності на поле, здійснивши запит на патч в контексті Server-Side Apply, який не включає це поле.
Деталі управління полями зберігаються в полі managedFields
, яке є частиною metadata
обʼєкта.
Якщо ви видалите поле з маніфесту і застосуєте цей маніфест, Server-Side Apply перевірить, чи є інші менеджери полів, які також володіють цим полем. Якщо поле не належить жодному іншому менеджеру полів, воно буде або видалене з поточного обʼєкта, або скинуте до стандартного значення, якщо таке є. Те саме правило застосовується до елементів асоціативного списку або map.
У порівнянні з (застарілою) kubectl.kubernetes.io/last-applied-configuration
анотацією, яка управляється kubectl
, Server-Side Apply використовує більш декларативний підхід, який відстежує управління полями користувача (або клієнта), а не останній застосований стан користувача. Побічним ефектом використання Server-Side Apply є також доступність інформації про те, який менеджер поля управляє кожним полем в обʼєкті.
Приклад
Простий приклад обʼєкта, створеного за допомогою Server-Side Apply, може виглядати так:
Примітка:
kubectl get
типово пропускає керовані поля. Додайте --show-managed-fields
щоб показати managedFields
у виводі в формаі json
або yaml
.---
apiVersion: v1
kind: ConfigMap
metadata:
name: test-cm
namespace: default
labels:
test-label: test
managedFields:
- manager: kubectl
operation: Apply # зверніть увагу на великі літери: "Apply" (або "Update")
apiVersion: v1
time: "2010-10-10T0:00:00Z"
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:labels:
f:test-label: {}
f:data:
f:key: {}
data:
key: some value
Цей приклад обʼєкта ConfigMap містить один запис про управління полями в .metadata.managedFields
. Запис управління полями складається з основної інформації про саму сутність, що виконує управління, а також з деталей про поля, якими управляють, та відповідну операцію (Apply
або Update
). Якщо запит, що останнім змінив це поле, був патчем Server-Side Apply, тоді значення operation
буде Apply
; в іншому випадку, це буде Update
.
Є ще один можливий результат. Клієнт може подати недійсний запит. Якщо повністю зазначений намір не створює дійсний обʼєкт, запит не вдасться виконати.
Однак, можливо змінити .metadata.managedFields
за допомогою операції оновлення або патчу, які не використовують Server-Side Apply. Це наполегливо не рекомендується, але може бути доцільно спробувати, якщо, наприклад, .metadata.managedFields
потрапить у неконсистентний стан (що не повинно відбуватися при нормальній роботі).
Формат managedFields
описаний у довіднику API Kubernetes.
Увага:
Поле.metadata.managedFields
керується API сервером. Ви повинні уникати його ручного оновлення.Конфлікти
Конфлікт — це спеціальна помилка статусу, яка виникає, коли операція Apply
намагається змінити поле, на яке інший менеджер також заявляє права на керування. Це запобігає ненавмисному перезапису значення, встановленого іншим користувачем. У разі конфлікту аплікатор має 3 варіанти для вирішення конфліктів:
Перезаписати значення, стати єдиним менеджером: Якщо перезапис значення був навмисним (або якщо аплікатор є автоматичним процесом, таким як контролер), аплікатор повинен встановити параметр запиту
force
вtrue
(дляkubectl apply
використовується параметр командного рядка--force-conflicts
) і повторити запит. Це змусить операцію завершитись успішно, змінить значення поля та видалить це поле з усіх інших записів менеджерів уmanagedFields
.Не перезаписувати значення, відмовитися від права управління: Якщо аплікатор більше не піклується про значення поля, він може видалити його зі своєї локальної моделі ресурсу і зробити новий запит, виключивши це конкретне поле. Це залишить значення незмінним і видалить поле із запису аплікатора у
managedFields
.Не перезаписувати значення, стати спільним менеджером: Якщо аплікатор все ще піклується про значення поля, але не хоче його перезаписувати, він може змінити значення цього поля у своїй локальній моделі ресурсу, щоб відповідати значенню обʼєкта на сервері, а потім зробити новий запит, враховуючи це локальне оновлення. Це залишить значення незмінним і зробить це поле керованим спільно аплікатором та всіма іншими менеджерами, які вже заявили про керування ним.
Менеджери полів
Менеджери визначають окремі робочі процеси, які змінюють обʼєкт (особливо корисно при конфліктах!), і можуть бути вказані через параметр запиту fieldManager
як частина запиту на зміни. Коли ви застосовуєте зміни до ресурсу, параметр fieldManager
є обовʼязковим. Для інших оновлень сервер API визначає ідентифікатор менеджера поля з заголовка HTTP "User-Agent:" (якщо він присутній).
Коли ви використовуєте інструмент kubectl
для виконання операції Server-Side Apply, kubectl
типово встановлює ідентифікатор менеджера в "kubectl"
.
Серіалізація
На рівні протоколу Kubernetes представляє тіла повідомлень Server-Side Apply у форматі YAML, з медіа типом application/apply-patch+yaml
.
Примітка:
Незалежно від того, чи ви подаєте дані у форматі JSON чи YAML, використовуйте application/apply-patch+yaml
як значення заголовка Content-Type
.
Усі документи JSON є дійсними документами YAML. Однак, у Kubernetes є помилка, яка полягає в тому, що він використовує парсер YAML, який не повністю реалізує специфікацію YAML. Деякі JSON екранування можуть не бути розпізнаними.
Серіалізація є такою ж, як для обʼєктів Kubernetes, за винятком того, що клієнти не зобовʼязані надсилати повний обʼєкт.
Ось приклад тіла повідомлення Server-Side Apply (повністю специфікований намір):
{
"apiVersion": "v1",
"kind": "ConfigMap"
}
(це зробить оновлення без змін, за умови, що це було надіслано як тіло patch запиту до дійсного ресурсу v1/configmaps
, з відповідним заголовком запиту Content-Type
).
Операції з області управління полями
Операції API Kubernetes, де враховується управління полями, включають:
- Server-Side Apply (HTTP
PATCH
, з типом контентуapplication/apply-patch+yaml
) - Заміна наявного обʼєкта (update для Kubernetes;
PUT
на рівні HTTP)
Обидві операції оновлюють .metadata.managedFields
, але поводяться трохи по-різному.
Якщо не вказано примусове перезаписування, операція apply, що зустрічає конфлікти на рівні полів, завжди зазнає невдачі; у противагу, якщо зміну здійснено за допомогою update, що впливає на кероване поле, конфлікт ніколи не призводить до невдачі операції.
Усі запити Server-Side Apply patch повинні ідентифікувати себе, надаючи параметр запиту fieldManager
, тоді як цей параметр запиту є необовʼязковим для операцій update. Нарешті, при використанні операції Apply
ви не можете визначати managedFields
у тілі запиту, який ви надсилаєте.
Приклад обʼєкта з декількома менеджерами може виглядати так:
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test-cm
namespace: default
labels:
test-label: test
managedFields:
- manager: kubectl
operation: Apply
time: '2019-03-30T15:00:00.000Z'
apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:labels:
f:test-label: {}
- manager: kube-controller-manager
operation: Update
apiVersion: v1
time: '2019-03-30T16:00:00.000Z'
fieldsType: FieldsV1
fieldsV1:
f:data:
f:key: {}
data:
key: new value
У цьому прикладі друга операція була виконана як update менеджером з назвою kube-controller-manager
. Запит на оновлення був успішним і змінив значення в полі даних, що призвело до зміни управління цим полем на kube-controller-manager
.
Якби була спроба застосувати це оновлення за допомогою Server-Side Apply, запит зазнав би невдачі через конфлікт управління.
Стратегія злиття
Стратегія злиття, реалізована в Server-Side Apply, забезпечує більш стабільний життєвий цикл обʼєкта. Server-Side Apply намагається обʼєднати поля на основі того, хто ними керує, замість того, щоб замінювати їх значення. Таким чином, кілька акторів можуть оновлювати один і той самий обʼєкт без несподіваних перешкод.
Коли користувач надсилає обʼєкт із повністю специфікованим наміром на точку доступу Server-Side Apply, сервер зʼєднує його з поточним обʼєктом, надаючи перевагу значенню з тіла запиту, якщо воно вказане в обох місцях. Якщо набір елементів, присутніх у застосованій конфігурації, не є надмножиною елементів, застосованих тим самим користувачем минулого разу, кожен відсутній елемент, яким не керують інші аплікатори, видаляється. Для отримання додаткової інформації про те, як схема обʼєкта використовується для прийняття рішень під час злиття, дивіться sigs.k8s.io/structured-merge-diff.
API Kubernetes (та код Go, який реалізує це API для Kubernetes) дозволяє визначати маркери стратегії злиття. Ці маркери описують підтримувану стратегію злиття для полів в обʼєктах Kubernetes. Для CustomResourceDefinition, ви можете встановити ці маркери під час визначення власного ресурсу.
Маркер Golang | Розширення OpenAPI | Можливі значення | Опис |
---|---|---|---|
//+listType | x-kubernetes-list-type | atomic /set /map | Застосовується до списків. set застосовується до списків, які включають лише скалярні елементи. Ці елементи повинні бути унікальними. map застосовується до списків вкладених типів. Значення ключів (див. listMapKey ) повинні бути унікальними в списку. atomic може застосовуватися до будь-якого списку. Якщо налаштовано як atomic , весь список замінюється під час злиття. У будь-який момент часу список належить одному менеджеру. Якщо set або map , різні менеджери можуть окремо керувати елементами. |
//+listMapKey | x-kubernetes-list-map-keys | Список імен полів, наприклад, ["port", "protocol"] | Застосовується лише при +listType=map . Список імен полів, значення яких унікально ідентифікують елементи у списку. Хоча ключів може бути багато, listMapKey є одниною, тому що ключі потрібно вказувати індивідуально в типі Go. Поля ключів повинні бути скалярами. |
//+mapType | x-kubernetes-map-type | atomic /granular | Застосовується до map. atomic означає, що map можна замінити повністю тільки одним менеджером. granular означає, що map підтримує окремих менеджерів, які оновлюють окремі поля. |
//+structType | x-kubernetes-map-type | atomic /granular | Застосовується до структур; інакше те ж використання та анотація OpenAPI, як //+mapType . |
Якщо listType
відсутній, сервер API інтерпретує patchStrategy=merge
як listType=map
і відповідний маркер patchMergeKey
як listMapKey
.
Тип списку atomic
є рекурсивним.
(У коді Go для Kubernetes, ці маркери вказуються як коментарі, і авторам коду не потрібно повторювати їх як теґи полів).
Власні ресурси та Серверне застосування
Стандартно, Server-Side Apply обробляє власні ресурси користувачів як неструктуровані дані. Усі ключі розглядаються як поля структури, а всі списки вважаються атомарними.
Якщо у визначенні CustomResourceDefinition міститься схема, яка містить анотації, визначені у попередньому розділі Стратегія злиття, ці анотації будуть використовуватись під час злиття обʼєктів цього типу.
Сумісність при зміні топології
У рідкісних випадках автор CustomResourceDefinition (CRD) або вбудованого ресурсу може захотіти змінити специфічну топологію поля у своєму ресурсі, не збільшуючи його версію API. Зміна топології типів шляхом оновлення кластера або CRD має різні наслідки при оновленні наявних обʼєктів. Є дві категорії змін: коли поле переходить від map
/set
/granular
до atomic
і навпаки.
Коли listType
, mapType
або structType
змінюються з map
/set
/granular
на atomic
, весь список, map або структура наявних обʼєктів будуть в підсумку належати акторам, які володіли елементом цих типів. Це означає, що будь-яка подальша зміна цих обʼєктів призведе до конфлікту.
Коли listType
, mapType
або structType
змінюються з atomic
на map
/set
/granular
, сервер API не може визначити нову власність цих полів. Через це конфлікти не виникатимуть під час оновлення обʼєктів із цими полями. Тому не рекомендується змінювати тип із atomic
на map
/set
/granular
.
Візьмемо, наприклад, власний ресурс користувача ресурс:
---
apiVersion: example.com/v1
kind: Foo
metadata:
name: foo-sample
managedFields:
- manager: "manager-one"
operation: Apply
apiVersion: example.com/v1
fieldsType: FieldsV1
fieldsV1:
f:spec:
f:data: {}
spec:
data:
key1: val1
key2: val2
До того, як spec.data
зміниться з atomic
на granular
, manager-one
володіє полем spec.data
і всіма полями в ньому (key1
та key2
). Коли CRD змінюється, щоб зробити spec.data
granular
, manager-one
продовжує володіти полем верхнього рівня spec.data
(що означає, що жоден інший менеджер не може видалити map data
без конфлікту), але він більше не володіє key1
та key2
, тому інший менеджер може змінити або видалити ці поля без конфлікту.
Використання Server-Side Apply в контролер
Як розробник контролера, ви можете використовувати Server-Side Apply як спосіб спростити логіку оновлення вашого контролера. Основні відмінності від кead-modify-write та/або patch наступні:
- застосований обʼєкт повинен містити всі поля, які цікавлять контролер.
- немає способу видалити поля, які не були застосовані контролером раніше (контролер все ще може надіслати patch або update для цих випадків використання).
- обʼєкт не обовʼязково має бути прочитаним перед тим;
resourceVersion
не потрібно вказувати.
Для контролерів рекомендується завжди застосовувати конфлікти на обʼєктах, якими вони володіють і керують, оскільки вони можуть не мати можливості розвʼязати або подіяти на ці конфлікти.
Передача власності
Окрім контролю конкурентності, забезпеченого вирішенням конфліктів, Server-Side Apply надає можливості для виконання координованих переходів власності полів від користувачів до контролерів.
Це найкраще пояснюється на прикладі. Розглянемо, як безпечно перевести власність поля replicas
від користувача до контролера, дозволяючи автоматичне горизонтальне масштабування для Deployment, використовуючи ресурс HorizontalPodAutoscaler та його супровідний контролер.
Скажімо, користувач визначив Deployment з replicas
, встановленим на бажане значення:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
І користувач створив Deployment, використовуючи Server-Side Apply, наступним чином:
kubectl apply -f https://k8s.io/examples/application/ssa/nginx-deployment.yaml --server-side
Пізніше автоматичне масштабування увімкнено для Deployment; наприклад:
kubectl autoscale deployment nginx-deployment --cpu-percent=50 --min=1 --max=10
Тепер користувач хоче видалити replicas
з конфігурації, щоб вони випадково не конфліктували з HorizontalPodAutoscaler (HPA) та його контролером. Однак виникають перегони: може пройти деякий час, перш ніж HPA вирішить змінити .spec.replicas
; якщо користувач видаляє .spec.replicas
перед тим, як HPA запише в поле і стане його власником, тоді API-сервер встановить .spec.replicas
на 1 (стандартна кількість реплік для Deployment). Це не те, що хоче користувач, ще й тимчасово — це може погіршити робоче навантаження.
Є два рішення:
(базовий) Залиште
replicas
в конфігурації; коли HPA нарешті запише в це поле, система сповістить користувачу про конфлікт при спробі зробити це. На цьому етапі безпечно видалити його з конфігурації.(більш розширений) Однак, якщо користувач не хоче чекати, наприклад, через те що вони хочуть, щоб кластер був зрозумілим для їх колег, тоді вони можуть виконати наступні кроки, щоб зробити видалення
replicas
з їх конфігурації безпечним:
Спочатку користувач визначає новий маніфест, що містить лише поле replicas
:
# Збережіть цей файл як 'nginx-deployment-replicas-only.yaml'.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
Примітка:
Файл YAML для SSA у цьому випадку містить лише поля, які ви хочете змінити. Вам не слід надавати повністю сумісний з Deployment маніфест, якщо ви хочете змінити лише полеspec.replicas
, використовуючи SSA.Користувач застосовує цей маніфест, використовуючи приватне імʼя менеджера полів. У цьому прикладі користувач вибрав handover-to-hpa
:
kubectl apply -f nginx-deployment-replicas-only.yaml \
--server-side --field-manager=handover-to-hpa \
--validate=false
Якщо застосування призводить до конфлікту з контролером HPA, тоді нічого не робіть. Конфлікт вказує на те, що контролер вже вимагає поле на цьому етапі.
На цьому етапі користувач може видалити поле replicas
з маніфесту:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
Зауважте, що кожного разу, коли контролер HPA встановлює значення поля replicas
на нове значення, тимчасовий менеджер полів більше не володіє жодними полями й буде автоматично видалений. Додаткового прибирання не потрібно.
Передача власності між менеджерами
Менеджери полів можуть передавати власність поля між собою, встановлюючи значення поля в тому самому значенні в обох їх застосованих конфігураціях, що призводить до того, що вони спільно володіють полем. Після цього менеджери можуть відмовитися від володіння полям та завершити передачу іншому менеджеру поля, видаливши поле з їх застосованої конфігурації.
Порівняння з Client-Side Apply
Server-Side Apply призначений як для заміни початкової реалізації команди kubectl apply
на стороні клієнта, так і для забезпечення простого та ефективного механізму для контролерів, щоб впроваджувати свої зміни.
Порівняно з анотацією last-applied
, якою керує kubectl
, Server-Side Apply використовує більш декларативний підхід, що відстежує управління полями обʼєкта, а не останній стан, застосований користувачем. Це означає, що як побічний ефект використання Server-Side Apply, стає доступною інформація про те, який менеджер полів керує кожним полем в обʼєкті.
Наслідком виявлення та вирішення конфліктів, реалізованих у Server-Side Apply, є те, що аплікатор завжди має актуальні значення полів у своєму локальному стані. Якщо ні, то він отримає конфлікт під час наступного застосування. Будь-який з трьох варіантів розвʼязання конфліктів призводить до того, що застосована конфігурація стає актуальною підмножиною полів обʼєкта на сервері.
Це відрізняється від Client-Side Apply, де застарілі значення, які були перезаписані іншими користувачами, залишаються в локальній конфігурації аплікатора. Ці значення стають точними лише тоді, коли користувач оновлює конкретне поле, якщо взагалі оновлює, і аплікатор не має способу дізнатися, чи наступне застосування перезапише зміни інших користувачів.
Ще однією відмінністю є те, що аплікатор, використовуючи Client-Side Apply, не може змінити версію API, яку він використовує, тоді як Server-Side Apply підтримує цей випадок використання.
Міграція між client-side і server-side apply
Перехід з client-side apply на server-side apply
Користувачі client-side apply, які керують ресурсом за допомогою kubectl apply
, можуть почати використовувати server-side apply з наступним прапорцем.
kubectl apply --server-side [--dry-run=server]
Стандартно, управління полями обʼєкта переходить з client-side apply на kubectl server-side apply без виникнення конфліктів.
Увага:
Тримайте анотацію last-applied-configuration
в актуальному стані. Анотація визначає поля, якими керує client-side apply. Будь-які поля, якими не керує client-side apply, викликають конфлікти.
Наприклад, якщо ви використовували kubectl scale
для оновлення поля replicas після client-side apply, тоді це поле не належить client-side apply і створює конфлікти при kubectl apply --server-side
.
Ця поведінка стосується server-side apply з менеджером полів kubectl
. Як виняток, ви можете відмовитися від цієї поведінки, вказавши іншого, не стандартного менеджера полів, як показано в наступному прикладі. Стандартним менеджером полів для kubectl server-side apply є kubectl
.
kubectl apply --server-side --field-manager=my-manager [--dry-run=server]
Повернення з server-side apply на client-side apply
Якщо ви керуєте ресурсом за допомогою kubectl apply --server-side
, ви можете перейти на client-side apply безпосередньо за допомогою kubectl apply
.
Повернення працює тому, що kubectl Server-Side Apply тримає анотацію last-applied-configuration
в актуальному стані, якщо ви використовуєте kubectl apply
.
Ця поведінка стосується Server-Side Apply з менеджером полів kubectl. Як виняток, ви можете відмовитися від цієї поведінки, вказавши іншого, не стандартного менеджера полів, як показано в наступному прикладі. Стандартним менеджером полів для kubectl server-side apply є kubectl
.
kubectl apply --server-side --field-manager=my-manager [--dry-run=server]
Реалізація API
Дієслово PATCH
для ресурсу, який підтримує Server-Side Apply, може приймати неофіційний тип контенту application/apply-patch+yaml
. Користувачі Server-Side Apply можуть надіслати частково специфіковані обʼєкти у вигляді YAML як тіло запиту PATCH
до URI ресурсу. При застосуванні конфігурації слід завжди включати всі поля, які є важливими для результату (наприклад, бажаний стан), який ви хочете визначити.
Усі повідомлення в форматі JSON є дійсним YAML. Деякі клієнти вказують запити Server-Side Apply, використовуючи тіла запитів у форматі YAML, які також є дійсним JSON.
Контроль доступу і дозволи
Оскільки Server-Side Apply є типом PATCH
, субʼєкт (такий як Роль для Kubernetes RBAC) потребує дозволу patch для редагування наявних ресурсів, а також дозволу на дієслово create для створення нових ресурсів за допомогою Server-Side Apply.
Очищення managedFields
Можливо видалити всі managedFields
з обʼєкта, переписавши їх за допомогою patch (JSON Merge Patch, Strategic Merge Patch, JSON Patch) або через update (HTTP PUT
); іншими словами, через будь-яку операцію запису, окрім apply. Це можна зробити, переписавши поле managedFields
порожнім записом. Два приклади:
PATCH /api/v1/namespaces/default/configmaps/example-cm
Accept: application/json
Content-Type: application/merge-patch+json
{
"metadata": {
"managedFields": [
{}
]
}
}
PATCH /api/v1/namespaces/default/configmaps/example-cm
Accept: application/json
Content-Type: application/json-patch+json
If-Match: 1234567890123456789
[{"op": "replace", "path": "/metadata/managedFields", "value": [{}]}]
Це перепише managedFields
списком, що містить один порожній запис, що в результаті повністю видалить managedFields
з обʼєкта. Зверніть увагу, що встановлення managedFields
як порожнього списку не скине це поле. Це зроблено спеціально, щоб managedFields
ніколи не видалялися клієнтами, які не знають про це поле.
У випадках, коли операція скидання комбінується зі змінами інших полів, крім managedFields
, це призведе до того, що спочатку managedFields
буде скинуто, а інші зміни будуть оброблені пізніше. У результаті аплікатор бере на себе відповідальність за будь-які поля, оновлені в тому ж запиті.
Примітка:
Server-Side Apply не правильно відстежує власність на субресурси, які не отримують тип обʼєкта ресурсу. Якщо ви використовуєте Server-Side Apply з таким субресурсом, змінені поля можуть не відслідковуватися.Що далі
Ви можете прочитати про managedFields
у довіднику API Kubernetes для верхнього рівня поля metadata
.