Обʼєкти Kubernetes можна створювати, оновлювати та видаляти, зберігаючи декілька файлів конфігурації обʼєктів у теці та використовувати kubectl apply для рекурсивного створення та оновлення цих обʼєктів за потреби. Цей метод зберігає записи, зроблені у поточних обʼєктах, без злиття змін до файлів конфігурації обʼєкта. За допомогою kubectl diff також можна переглянути зміни, які буде внесено командою apply.
Встановіть kubectl.
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введіть kubectl version.
Інструмент kubectl підтримує три види управління обʼєктами:
Див. Управління обʼєктами Kubernetes для обговорення переваг та недоліків кожного виду управління обʼєктами.
Декларативна конфігурація обʼєктів потребує чіткого розуміння визначень та конфігурації обʼєктів Kubernetes. Прочитайте наступні документи, якщо ви ще цього не зробили:
Нижче подано визначення термінів, використаних у цьому документі:
kubectl apply. Файли конфігурації зазвичай зберігаються у системі контролю версій, такі як Git.kubectl apply для запису змін.Використовуйте kubectl apply, щоб створити всі обʼєкти, за винятком тих, що вже існують, які визначені у конфігураційних файлах у вказаній теці:
kubectl apply -f <тека>
Це встановлює анотацію kubectl.kubernetes.io/last-applied-configuration: '{...}' для кожного обʼєкта. Анотація містить вміст файлу конфігурації обʼєкта, який був використаний для створення обʼєкта.
-R, щоб рекурсивно обробляти теки.Ось приклад файлу конфігурації обʼєкта:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
minReadySeconds: 5
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
Запустіть kubectl diff, щоб показати обʼєкт, який буде створено:
kubectl diff -f https://k8s.io/examples/application/simple_deployment.yaml
diff використовує запуск без внесення змін на сервері (dry-run), таку можливість потрібно ввімкнути на kube-apiserver.
Оскільки diff виконує запит на стороні сервера для застосування в режимі без внесення змін, для його роботи потрібно дозволити дії PATCH, CREATE та UPDATE. Детальніше див. Авторизація запуску dry-run.
Створіть обʼєкт за допомогою kubectl apply:
kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml
Виведіть поточну конфігурацію за допомогою kubectl get:
kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml
Вивід показує, що анотація kubectl.kubernetes.io/last-applied-configuration була записана до поточної конфігурації та відповідає конфігураційному файлу:
kind: Deployment
metadata:
annotations:
# ...
# Це json-представлення simple_deployment.yaml
# Воно було створено за допомогою kubectl apply під час створення обʼєкта
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment",
"metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
"spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
"spec":{"containers":[{"image":"nginx:1.14.2","name":"nginx",
"ports":[{"containerPort":80}]}]}}}}
# ...
spec:
# ...
minReadySeconds: 5
selector:
matchLabels:
# ...
app: nginx
template:
metadata:
# ...
labels:
app: nginx
spec:
containers:
- image: nginx:1.14.2
# ...
name: nginx
ports:
- containerPort: 80
# ...
# ...
# ...
# ...
Ви також можете використовувати kubectl apply, щоб оновити всі обʼєкти, визначені у теці, навіть якщо ці обʼєкти вже існують. Цей підхід виконує наступне:
kubectl diff -f <тека>
kubectl apply -f <тека>
-R, щоб рекурсивно обробляти теки.Ось приклад конфігураційного файлу:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
minReadySeconds: 5
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
Створіть обʼєкт за допомогою kubectl apply:
kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml
Виведіть поточну конфігурацію за допомогою kubectl get:
kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml
Вивід показує, що анотація kubectl.kubernetes.io/last-applied-configuration була записана до поточної конфігурації та відповідає конфігураційному файлу:
kind: Deployment
metadata:
annotations:
# ...
# Це json-представлення simple_deployment.yaml
# Воно було створено за допомогою kubectl apply під час створення обʼєкта
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment",
"metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
"spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
"spec":{"containers":[{"image":"nginx:1.14.2","name":"nginx",
"ports":[{"containerPort":80}]}]}}}}
# ...
spec:
# ...
minReadySeconds: 5
selector:
matchLabels:
# ...
app: nginx
template:
metadata:
# ...
labels:
app: nginx
spec:
containers:
- image: nginx:1.14.2
# ...
name: nginx
ports:
- containerPort: 80
# ...
# ...
# ...
# ...
Напряму оновіть поле replicas у поточній конфігурації за допомогою kubectl scale. Для цього не використовується kubectl apply:
kubectl scale deployment/nginx-deployment --replicas=2
Виведіть поточну конфігурацію за допомогою kubectl get:
kubectl get deployment nginx-deployment -o yaml
Вивід показує, що поле replicas встановлено на 2, і анотація last-applied-configuration
не містить поле replicas:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
# ...
# Зверніть увагу, що анотація не містить replicas
# тому що воно не було оновлено через apply
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment",
"metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
"spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
"spec":{"containers":[{"image":"nginx:1.14.2","name":"nginx",
"ports":[{"containerPort":80}]}]}}}}
# ...
spec:
replicas: 2 # Встановлено за допомогою `kubectl scale`. Ігнорується `kubectl apply`.
# ...
minReadySeconds: 5
selector:
matchLabels:
# ...
app: nginx
template:
metadata:
# ...
labels:
app: nginx
spec:
containers:
- image: nginx:1.14.2 # Встановлено за допомогою `kubectl apply`
# ...
name: nginx
ports:
- containerPort: 80
# ...
# ...
# ...
Оновіть конфігураційний файл simple_deployment.yaml, щоб змінити образ з nginx:1.14.2 на nginx:1.16.1 та видалити поле minReadySeconds:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.16.1 # оновіть образ
ports:
- containerPort: 80
Застосуйте зміни, внесені до конфігураційного файлу:
kubectl diff -f https://k8s.io/examples/application/update_deployment.yaml
kubectl apply -f https://k8s.io/examples/application/update_deployment.yaml
Виведіть поточну конфігурацію за допомогою kubectl get:
kubectl get -f https://k8s.io/examples/application/update_deployment.yaml -o yaml
Вивід показує наступні зміни в поточній конфігурації:
replicas зберігає значення 2, встановлене за допомогою kubectl scale. Це можливо через його відсутність у конфігураційному файлі.image було оновлено на nginx:1.16.1 з nginx:1.14.2.last-applied-configuration була оновлена новим образом.minReadySeconds було очищено.last-applied-configuration більше не містить поле minReadySeconds.apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
# ...
# Анотація містить оновлений образ nginx 1.16.1,
# але не містить оновлення копій на 2
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment",
"metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
"spec":{"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
"spec":{"containers":[{"image":"nginx:1.16.1","name":"nginx",
"ports":[{"containerPort":80}]}]}}}}
# ...
spec:
replicas: 2 # Встановлено за допомогою `kubectl scale`. Ігнорується `kubectl apply`.
# minReadySeconds очищено за допомогою `kubectl apply`
# ...
selector:
matchLabels:
# ...
app: nginx
template:
metadata:
# ...
labels:
app: nginx
spec:
containers:
- image: nginx:1.16.1 # Встановлено за допомогою `kubectl apply`
# ...
name: nginx
ports:
- containerPort: 80
# ...
# ...
# ...
kubectl apply з імперативними командами конфігурації обʼєктів create та replace не підтримується. Це через те, що create та replace не зберігають анотацію kubectl.kubernetes.io/last-applied-configuration, яку використовує kubectl apply для обробки оновлень.Існують два підходи до видалення обʼєктів, керованих за допомогою kubectl apply.
kubectl delete -f <filename>Ручне видалення обʼєктів за допомогою імперативної команди є рекомендованим підходом, оскільки він більш явно вказує на те, що видаляється, і менш ймовірно призводить до випадкового видалення чогось:
kubectl delete -f <filename>
kubectl apply -f <directory> --pruneЯк альтернативу kubectl delete, ви можете використовувати kubectl apply для ідентифікації обʼєктів, які мають бути видалені після видалення їх маніфестів з теки у локальній файловій системі.
У Kubernetes 1.35, доступні два режими очищення в kubectl apply:
Kubernetes v1.5 [alpha]
--prune з kubectl apply в режимі allow list. Те, які обʼєкти очищаються, залежить від значень прапорців --prune-allowlist, --selector та --namespace, і ґрунтується на динамічному виявленні обʼєктів, що підпадають під область застосування. Особливо, якщо значення прапорців змінюються між викликами, це може призвести до неочікуваного видалення або збереження обʼєктів.Щоб використовувати очищення на основі allowlist, додайте наступні прапорці до свого виклику kubectl apply:
--prune: Видалити попередньо застосовані обʼєкти, які не є у наборі, що передані поточному виклику.--prune-allowlist: Список груп-версій-типів (GVK, group-version-kind), які розглядаються для очищення. Цей прапорець є необовʼязковим, але наполегливо рекомендується, оскільки його стандартне значення є частковим списком обʼєктів з просторами імен та областями застосування, що може призвести до несподіваних результатів.--selector/-l: Використовуйте селектор міток для обмеження набору обʼєктів, обраних для очищення. Цей прапорець є необовʼязковим, але наполегливо рекомендується.--all: використовуйте замість --selector/-l, щоб явно вибрати всі попередньо застосовані обʼєкти відповідних типів, які знаходяться у списку дозволених.Очищення на основі allowlist запитує API-сервер щодо всіх обʼєктів затверджених GVK, які відповідають заданим міткам (якщо є), і намагається зіставити конфігурації активних обʼєктів, отриманих в результаті, з файлами маніфестів обʼєктів. Якщо обʼєкт відповідає запиту і він не має маніфесту в теці, і має анотацію kubectl.kubernetes.io/last-applied-configuration, він видаляється.
kubectl apply -f <directory> --prune -l <labels> --prune-allowlist=<gvk-list>
--prune повинне бути виконане тільки для кореневої теки, що містить маніфести обʼєктів. Виконання для підтек може призвести до неочікуваного видалення обʼєктів, які раніше були застосовані, мають задані мітки (якщо є) і не зʼявляються у підтеці.
Kubernetes v1.27 [alpha]
kubectl apply --prune --applyset знаходиться на етапі альфа-тестування, і в майбутніх випусках можуть бути внесені зміни, що несумісні з попередніми версіями.Для використання очищення на основі ApplySet встановіть змінну середовища KUBECTL_APPLYSET=true, і додайте наступні прапорці до свого виклику kubectl apply:
--prune: Видалити попередньо застосовані обʼєкти, які не є у наборі, що передані поточному виклику.--applyset: Назва обʼєкта, який kubectl може використовувати для точного та ефективного відстеження членства в наборі під час операцій apply.KUBECTL_APPLYSET=true kubectl apply -f <directory> --prune --applyset=<name>
Типово тип батьківського обʼєкта ApplySet, що використовується, — Secret. Однак також можуть бути використані ConfigMaps у форматі: --applyset=configmaps/<name>. При використанні Secret або ConfigMap, kubectl створить обʼєкт, якщо він ще не існує.
Також можливе використання власних ресурсів як батьківських обʼєктів ApplySet. Для цього позначте міткою Custom Resource Definition (CRD), що визначає ресурс, який ви хочете використовувати з наступним: applyset.kubernetes.io/is-parent-type: true. Потім створіть обʼєкт, який ви хочете використовувати як батьківський обʼєкт ApplySet (kubectl цього не робить автоматично для Custom Resource). Нарешті, посилайтеся на цей обʼєкт у прапорці applyset таким чином: --applyset=<resource>.<group>/<name> (наприклад, widgets.custom.example.com/widget-name).
Під час очищення на основі ApplySet kubectl додає мітку applyset.kubernetes.io/part-of=<parentID> до кожного обʼєкта в наборі, перш ніж вони будуть надіслані на сервер. З метою продуктивності він також збирає список типів ресурсів і просторів імен, які включаються у набір, і додає ці дані в анотації поточного батьківського обʼєкта. В кінеці операції apply, він запитує API-сервер щодо обʼєктів цих типів в цих просторах імен (або в областях кластера, якщо це доречно), які належать до набору, визначеного міткою applyset.kubernetes.io/part-of=<parentID>.
Застереження та обмеження:
--namespace є обовʼязковим при використанні будь-якого обʼєкта з простором імен, включаючи типово Secret. Це означає, що ApplySets, які охоплюють кілька просторів імен, повинні використовувати кластерний обʼєкт з кореневою текою.Ви можете використовувати kubectl get з -o yaml, щоб переглянути конфігурацію поточного обʼєкта:
kubectl get -f <filename|url> -o yaml
Коли kubectl apply оновлює поточну конфігурацію обʼєкта, він робить це, надсилаючи запит на патч до API-сервера. Патч визначає оновлення для конкретних полів конфігурації живого обʼєкта. Команда kubectl apply обчислює цей запит на патч за допомогою файлу конфігурації, поточної конфігурації та анотації last-applied-configuration, збереженої в поточній конфігурації.
Команда kubectl apply записує вміст файлу конфігурації до анотації kubectl.kubernetes.io/last-applied-configuration. Вона використовується для ідентифікації полів, які були видалені з файлу конфігурації та які потрібно видалити з поточної конфігурації. Ось кроки, які використовуються для обчислення того, які поля потрібно видалити або встановити:
last-applied-configuration та відсутні в файлі конфігурації.Ось приклад. Припустимо, що це файл конфігурації для обʼєкта типу Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.16.1 # оновіть образ
ports:
- containerPort: 80
Також, припустимо, що це поточна конфігурація для того самого обʼєкта типу Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
# ...
# Зауважте, що анотація не містить поля replicas,
# оскільки воно не було оновлено через apply
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment",
"metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
"spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
"spec":{"containers":[{"image":"nginx:1.14.2","name":"nginx",
"ports":[{"containerPort":80}]}]}}}}
# ...
spec:
replicas: 2 # вказано через scale
# ...
minReadySeconds: 5
selector:
matchLabels:
# ...
app: nginx
template:
metadata:
# ...
labels:
app: nginx
spec:
containers:
- image: nginx:1.14.2
# ...
name: nginx
ports:
- containerPort: 80
# ...
Ось обчислення злиття, які виконає kubectl apply:
last-applied-configuration і порівнюючи їх зі значеннями у файлі конфігурації. Очищення полів, які явно встановлені на null у локальному файлі конфігурації обʼєкта, незалежно від того, чи вони зʼявляються в анотації last-applied-configuration. У цьому прикладі minReadySeconds зʼявляється в анотації last-applied-configuration, але не зʼявляється у файлі конфігурації. Дія: Прибрати minReadySeconds з поточної конфігурації.image у файлі конфігурації не відповідає значенню у поточній конфігурації. Дія: Встановити значення image у поточній конфігурації.last-applied-configuration, щоб вона відповідала значенню файлу конфігурації.Ось поточна конфігурація, яка є результатом злиття:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
# ...
# Анотація містить оновлений образ nginx 1.16.1,
# але не містить оновлення реплік до 2
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment",
"metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
"spec":{"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
"spec":{"containers":[{"image":"nginx:1.16.1","name":"nginx",
"ports":[{"containerPort":80}]}]}}}}
# ...
spec:
selector:
matchLabels:
# ...
app: nginx
replicas: 2 # Встановлено за допомогою `kubectl scale`. Ігнорується `kubectl apply`.
# minReadySeconds очищено за допомогою `kubectl apply`
# ...
template:
metadata:
# ...
labels:
app: nginx
spec:
containers:
- image: nginx:1.16.1 # Встановлено за допомогою `kubectl apply`
# ...
name: nginx
ports:
- containerPort: 80
# ...
# ...
# ...
# ...
Як певне поле в конфігураційному файлі зливається з поточною конфігурацією залежить від типу поля. Існують кілька типів полів:
primitive: Поле типу рядок, ціле число або логічне значення. Наприклад, image та replicas є полями примітивів. Дія: Замінити.
map, також відомий як object: Поле типу map або комплексний тип, який містить підполя. Наприклад, labels, annotations, spec та metadata — це всі map. Дія: Злити елементи або підполя.
list: Поле, яке містить список елементів, які можуть бути або типами primitive, або map. Наприклад, containers, ports та args є списками. Дія: Варіюється.
Коли kubectl apply оновлює map або list, він зазвичай не замінює все поле цілком, а замість цього оновлює окремі піделементи. Наприклад, при злитті spec в Deployment, весь spec не
замінюється. Замість цього порівнюються та зливаються підполя spec, такі як replicas.
Поля primitive замінюються або очищаються.
- використовується для "not applicable", оскільки значення не використовується.| Поле в конфігураційному файлі обʼєкта | Поле в поточній конфігурації обʼєкта | Поле в останній застосованій конфігурації | Дія |
|---|---|---|---|
| Так | Так | - | Встановити поточне значення з конфігураційного файлу. |
| Так | Ні | - | Встановити поточне значення з локального конфігураційного файлу. |
| Ні | - | Так | Очистити з поточної конфігурації. |
| Ні | - | Ні | Нічого не робити. Зберегти значення поточного обʼєкта. |
Поля, які є map, зливаються шляхом порівняння кожного з підполів або елементів map:
- використовується для "not applicable", оскільки значення не використовується.| Ключ в конфігураційному файлі обʼєкта | Ключ у поточній конфігурації обʼєкта | Поле в останній застосованій конфігурації | Дія |
|---|---|---|---|
| Так | Так | - | Порівняти значення підполів. |
| Так | Ні | - | Встановити поточне значення з локального конфігураційного файлу. |
| Ні | - | Так | Видалити з поточної конфігурації. |
| Ні | - | Ні | Нічого не робити. Зберігти значення поточного обʼєкта. |
Злиття змін у list використовує одну з трьох стратегій:
Вибір стратегії залежить від конкретного поля.
Такий список трактується так само як і поле primitive. Замініть або видаліть весь список. Це зберігає порядок.
Приклад: Використовуйте kubectl apply, щоб оновити поле args контейнера в Podʼі. Це встановлює значення args в поточній конфігурації на значення у файлі конфігурації. Будь-які елементи args, які раніше були додані до поточної конфігурації, втрачаються. Порядок елементів args, визначених у файлі конфігурації, зберігається у поточній конфігурації.
# Значення last-applied-configuration
args: ["a", "b"]
# Значення файлу конфігурації
args: ["a", "c"]
# Поточна конфігурація
args: ["a", "b", "d"]
# Результат після злиття
args: ["a", "c"]
Пояснення: Злиття використовує значення файлу конфігурації як нове значення списку.
Трактуйте список як map, а конкретне поле кожного елемента як ключ. Додавайте, видаляйте або оновлюйте окремі елементи. Це не зберігає порядок.
Ця стратегія злиття використовує спеціальний теґ на кожному полі, який називається patchMergeKey. patchMergeKey визначено для кожного поля в коді Kubernetes: types.go При злитті списку map, поле, вказане як patchMergeKey для певного елемента, використовується як ключ map для цього елемента.
Приклад: Використайте kubectl apply, щоб оновити поле containers у PodSpec. Це злиття списку, ніби він був map, де кожен елемент має ключ name.
# Значення last-applied-configuration
containers:
- name: nginx
image: nginx:1.16
- name: nginx-helper-a # ключ: nginx-helper-a; буде видалено у результаті
image: helper:1.3
- name: nginx-helper-b # ключ: nginx-helper-b; буде збережено
image: helper:1.3
# Значення файлу конфігурації
containers:
- name: nginx
image: nginx:1.16
- name: nginx-helper-b
image: helper:1.3
- name: nginx-helper-c # ключ: nginx-helper-c; буде додано у результаті
image: helper:1.3
# Поточна конфігурація
containers:
- name: nginx
image: nginx:1.16
- name: nginx-helper-a
image: helper:1.3
- name: nginx-helper-b
image: helper:1.3
args: ["run"] # Поле буде збережено
- name: nginx-helper-d # ключ: nginx-helper-d; буде збережено
image: helper:1.3
# Результат після злиття
containers:
- name: nginx
image: nginx:1.16
# Елемент nginx-helper-a був видалений
- name: nginx-helper-b
image: helper:1.3
args: ["run"] # Поле було збережено
- name: nginx-helper-c # Елемент був доданий
image: helper:1.3
- name: nginx-helper-d # Елемент був ігнорований
image: helper:1.3
Пояснення:
args в поточній конфігурації. kubectl apply зміг ідентифікувати, що "nginx-helper-b" у поточній конфігурації був тим самим "nginx-helper-b", що й у файлі конфігурації, навіть якщо їхні поля мали різні значення (немає args у файлі конфігурації). Це тому, що значення поля patchMergeKey (name) було ідентичним у обох.Зараз, починаючи з Kubernetes 1.5, злиття списків елементів типу primitive не підтримується.
patchStrategy у types.go. Якщо для поля типу списку не вказано patchStrategy, тоді список замінюється.Сервер API встановлює в певні поля станадартні значення у поточній конфігурації, якщо вони не вказані при створенні обʼєкта.
Ось файл конфігурації для обʼєкта Deployment. У файлі не вказано strategy:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
minReadySeconds: 5
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
Створіть обʼєкт, використовуючи kubectl apply:
kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml
Виведіть поточну конфігурацію, використовуючи kubectl get:
kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml
Вивід показує, що сервер API встановив в деякі поля стандартні значення у поточній конфігурації. Ці поля не були вказані в файлі конфігурації.
apiVersion: apps/v1
kind: Deployment
# ...
spec:
selector:
matchLabels:
app: nginx
minReadySeconds: 5
replicas: 1 # станадратне значення додане apiserver
strategy:
rollingUpdate: # станадратне значення додане apiserver - походить з strategy.type
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate # станадратне значення додане apiserver
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx:1.14.2
imagePullPolicy: IfNotPresent # станадратне значення додане apiserver
name: nginx
ports:
- containerPort: 80
protocol: TCP # станадратне значення додане apiserver
resources: {} # станадратне значення додане apiserver
terminationMessagePath: /dev/termination-log # станадратне значення додане apiserver
dnsPolicy: ClusterFirst # станадратне значення додане apiserver
restartPolicy: Always # станадратне значення додане apiserver
securityContext: {} # станадратне значення додане apiserver
terminationGracePeriodSeconds: 30 # станадратне значення додане apiserver
# ...
У запиті на патч, поля, які мають станаддартні значення, не перезаписуються, якщо вони явно не очищені як частина запиту на патч. Це може призвести до неочікуваної поведінки для полів, які мають стнадартні значення на основі значень інших полів. Після зміни інших полів значення, які мають стандартні значення з них, не будуть оновлені, якщо їх не явно очищено.
З цієї причини рекомендується, щоб певні поля, стандартні значення яких встановлює сервер, були явно визначені в файлі конфігурації обʼєкта, навіть якщо бажані значення відповідають станадартним значенням сервера. Це полегшить розпізнавання суперечливих значень, які не будуть перезаписані сервером на станадартні значення.
Приклад:
# last-applied-configuration
spec:
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
# конфігураційний файл
spec:
strategy:
type: Recreate # оновленне значення
template:
metadata:
labels:
app:
nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
# поточна конфігурація
spec:
strategy:
type: RollingUpdate # встановлене типове значення
rollingUpdate: # встановлене типове значення отримане з type
maxSurge : 1
maxUnavailable: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
# результат після злиття - ПОМИЛКА!
spec:
strategy:
type: Recreate # оновленне значення: несумісне з rollingUpdate
rollingUpdate: # встановлене типове значення: несумісне з "type: Recreate"
maxSurge : 1
maxUnavailable: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
Пояснення:
strategy.type.strategy.type на RollingUpdate тв стандартне значення для strategy.rollingUpdate.strategy.type на Recreate. Значення strategy.rollingUpdate залишаються стандартними значеннями, хоча сервер очікує, що вони будуть очищені. Якщо значення strategy.rollingUpdate були визначені спочатку в файлі конфігурації, було б більш зрозуміло, що їх потрібно було б видалити.strategy.rollingUpdate не очищено. Поле strategy.rollingupdate не може бути визначено з strategy.type Recreate.Рекомендація: Ці поля слід явно визначити в файлі конфігурації обʼєкта:
Поля, які не зʼявляються у файлі конфігурації, можна очистити, встановивши їх значення в null, а потім застосувати файл конфігурації. Для полів, стандартні значення яких встановлено сервером, це спричинить перезапис цих значень.
Ці методи — єдиний вірний спосіб змінювати окреме поле обʼєкта:
kubectl apply.kubectl scale.Додайте поле до файлу конфігурації. Для цього поля припиніть прямі оновлення поточної конфігурації, які не проходять через kubectl apply.
Починаючи з Kubernetes 1.5, зміна власника поля з файлу конфігурації на імперативного запусувача вимагає виконання наступних кроків:
kubectl.kubernetes.io/last-applied-configuration на поточному обʼєкті.Обʼєктами Kubernetes слід керувати за допомогою лише одного методу одночасно. Перехід з одного методу на інший можливий, але це вимагає ручної обробки.
Міграція з управління імперативними командами до декларативної конфігурації обʼєктів включає кілька ручних кроків:
Експортуйте поточний обʼєкт у локальний файл конфігурації:
kubectl get <kind>/<name> -o yaml > <kind>_<name>.yaml
Видаліть вручну поле status з файлу конфігурації.
kubectl apply не оновлює поле статусу, навіть якщо воно присутнє у файлі конфігурації.Встановіть анотацію kubectl.kubernetes.io/last-applied-configuration на обʼєкті:
kubectl replace --save-config -f <kind>_<name>.yaml
Змініть процеси так, щоб вони використовували виключно kubectl apply для керування обʼєктом.
Встановіть анотацію kubectl.kubernetes.io/last-applied-configuration на обʼєкті:
kubectl replace --save-config -f <kind>_<name>.yaml
Змініть процеси так, щоб використовували kubectl apply виключно для керування обʼєктом.
Рекомендований підхід — це визначення єдиного, незмінного підпису PodTemplate, який використовується тільки селектором контролера без іншого семантичного значення.
Приклад:
selector:
matchLabels:
controller-selector: "apps/v1/deployment/nginx"
template:
metadata:
labels:
controller-selector: "apps/v1/deployment/nginx"