Це багатосторінковий друкований вигляд цього розділу. Натисність щоб друкувати.
Керування обʼєктами Kubernetes
- 1: Декларативне керування обʼєктами Kubernetes з використанням конфігураційних файлів
- 2: Декларативне керування обʼєктами Kubernetes за допомогою Kustomize
- 3: Керування обʼєктами Kubernetes за допомогою імперативних команд
- 4: Імперативне керування обʼєктами Kubernetes за допомогою файлів конфігурації
- 5: Оновлення обʼєктів API на місці за допомогою kubectl patch
- 6: Міграція обʼєктів Kubernetes за допомогою міграції версій сховища
1 - Декларативне керування обʼєктами Kubernetes з використанням конфігураційних файлів
Обʼєкти Kubernetes можна створювати, оновлювати та видаляти, зберігаючи декілька файлів конфігурації обʼєктів у теці та використовувати kubectl apply
для рекурсивного створення та оновлення цих обʼєктів за потреби. Цей метод зберігає записи, зроблені у поточних обʼєктах, без злиття змін до файлів конфігурації обʼєкта. За допомогою kubectl diff
також можна переглянути зміни, які буде внесено командою apply
.
Перш ніж ви розпочнете
Встановіть kubectl
.
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Компроміси
Інструмент kubectl
підтримує три види управління обʼєктами:
- Імперативні команди
- Імперативне конфігурування обʼєктів
- Декларативне конфігурування обʼєктів
Див. Управління обʼєктами Kubernetes для обговорення переваг та недоліків кожного виду управління обʼєктами.
Огляд
Декларативна конфігурація обʼєктів потребує чіткого розуміння визначень та конфігурації обʼєктів Kubernetes. Прочитайте наступні документи, якщо ви ще цього не зробили:
- Управління обʼєктами Kubernetes за допомогою імперативних команд
- Імперативне управління обʼєктами Kubernetes за допомогою файлів конфігурації
Нижче подано визначення термінів, використаних у цьому документі:
- файл конфігурації обʼєкта / файл конфігурації: Файл, який визначає конфігурацію для обʼєкта Kubernetes. Ця тема показує, як передавати файли конфігурації до
kubectl apply
. Файли конфігурації зазвичай зберігаються у системі контролю версій, такі як Git. - поточна конфігурація обʼєкта / поточна конфігурація: Поточні значення конфігурації обʼєкта, які використовуються кластером Kubernetes. Їх зберігають у сховищі кластера Kubernetes, зазвичай etcd.
- декларативний записувач конфігурації / декларативний письменник: Особа або компонент програмного забезпечення, який вносить оновлення до поточного обʼєкта. Поточні записувачі, на які посилається ця тема, вносять зміни до файлів конфігурації обʼєктів та запускають
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.32, доступні два режими очищення в kubectl apply
:
- Очищення на основі allowlist: Цей режим існує з моменту kubectl v1.5, але все ще знаходиться на етапі альфа-тестування через проблеми з використанням, коректністю і продуктивністю його дизайну. Режим на основі ApplySet призначений для заміни його.
- Очищення на основі ApplySet: apply set — це обʼєкт на стороні сервера (типово, Secret), який kubectl може використовувати для точного та ефективного відстеження членства в наборі під час операцій apply. Цей режим був введений у альфа-версії в kubectl v1.27 як заміна очищенню на основі allowlist.
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, які охоплюють кілька просторів імен, повинні використовувати кластерний обʼєкт з кореневою текою. - Щоб безпечно використовувати очищення на основі ApplySet з декількома теками, використовуйте унікальне імʼя ApplySet для кожного.
Як переглянути обʼєкт
Ви можете використовувати kubectl get
з -o yaml
, щоб переглянути конфігурацію поточного обʼєкта:
kubectl get -f <filename|url> -o yaml
Як apply обчислює різницю та обʼєднує зміни
Увага:
Патч (накладання латок) — це операція оновлення, яка обмежена конкретними полями обʼєкта замість всього обʼєкта. Це дозволяє оновлювати лише певний набір полів обʼєкта без читання всього обʼєкта.Коли 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
, щоб вона відповідала значенню файлу конфігурації. - Обʼєднати результати з 1, 2, 3 у єдиний запит на патч до API-сервера.
Ось поточна конфігурація, яка є результатом злиття:
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
Поля primitive замінюються або очищаються.
Примітка:
-
використовується для "not applicable", оскільки значення не використовується.Поле в конфігураційному файлі обʼєкта | Поле в поточній конфігурації обʼєкта | Поле в останній застосованій конфігурації | Дія |
---|---|---|---|
Так | Так | - | Встановити поточне значення з конфігураційного файлу. |
Так | Ні | - | Встановити поточне значення з локального конфігураційного файлу. |
Ні | - | Так | Очистити з поточної конфігурації. |
Ні | - | Ні | Нічого не робити. Зберегти значення поточного обʼєкта. |
Злиття змін у полях типу map
Поля, які є map, зливаються шляхом порівняння кожного з підполів або елементів map:
Примітка:
-
використовується для "not applicable", оскільки значення не використовується.Ключ в конфігураційному файлі обʼєкта | Ключ у поточній конфігурації обʼєкта | Поле в останній застосованій конфігурації | Дія |
---|---|---|---|
Так | Так | - | Порівняти значення підполів. |
Так | Ні | - | Встановити поточне значення з локального конфігураційного файлу. |
Ні | - | Так | Видалити з поточної конфігурації. |
Ні | - | Ні | Нічого не робити. Зберігти значення поточного обʼєкта. |
Злиття змін для полів типу list
Злиття змін у list використовує одну з трьох стратегій:
- Заміна list, якщо всі його елементи є primitive.
- Злиття окремих елементів у списку комплексних елементів.
- Злиття list елементів primitive.
Вибір стратегії залежить від конкретного поля.
Заміна list, якщо всі його елементи є primitive
Такий список трактується так само як і поле 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
Пояснення:
- Контейнер з імʼям "nginx-helper-a" був видалений, оскільки жодного контейнера з іменем "nginx-helper-a" не знайдено у файлі конфігурації.
- Контейнер з імʼям "nginx-helper-b" зберіг зміни у
args
в поточній конфігурації.kubectl apply
зміг ідентифікувати, що "nginx-helper-b" у поточній конфігурації був тим самим "nginx-helper-b", що й у файлі конфігурації, навіть якщо їхні поля мали різні значення (немаєargs
у файлі конфігурації). Це тому, що значення поляpatchMergeKey
(name) було ідентичним у обох. - Контейнер з імʼям "nginx-helper-c" був доданий, оскільки жодного контейнера з таким імʼям не було у поточній конфігурації, але один з таким імʼям був у файлі конфігурації.
- Контейнер з імʼям "nginx-helper-d" був збережений, оскільки жодного елемента з таким імʼям не було в last-applied-configuration.
Злиття списку елементів типу primitive
Зараз, починаючи з 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
Пояснення:
- Користувач створює Deployment без визначення
strategy.type
. - Сервер встановлює станадартне значення для
strategy.type
наRollingUpdate
тв стандартне значення дляstrategy.rollingUpdate
. - Користувач змінює
strategy.type
наRecreate
. Значенняstrategy.rollingUpdate
залишаються стандартними значеннями, хоча сервер очікує, що вони будуть очищені. Якщо значенняstrategy.rollingUpdate
були визначені спочатку в файлі конфігурації, було б більш зрозуміло, що їх потрібно було б видалити. - Оновлення не вдається через те, що
strategy.rollingUpdate
не очищено. Полеstrategy.rollingupdate
не може бути визначено зstrategy.type
Recreate
.
Рекомендація: Ці поля слід явно визначити в файлі конфігурації обʼєкта:
- Селектори та мітки PodTemplate для робочих навантажень, таких як Deployment, StatefulSet, Job, DaemonSet, ReplicaSet та ReplicationController.
- Стратегія розгортання Deployment.
Як очистити стандартні поля встановлені сервером або поля, встановлені іншими записувачами
Поля, які не зʼявляються у файлі конфігурації, можна очистити, встановивши їх значення в 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
Попередження:
Рекомендується утриматися від оновлення селекторів на контролерах.Рекомендований підхід — це визначення єдиного, незмінного підпису PodTemplate, який використовується тільки селектором контролера без іншого семантичного значення.
Приклад:
selector:
matchLabels:
controller-selector: "apps/v1/deployment/nginx"
template:
metadata:
labels:
controller-selector: "apps/v1/deployment/nginx"
Що далі
2 - Декларативне керування обʼєктами Kubernetes за допомогою Kustomize
Kustomize — це окремий інструмент для налаштування обʼєктів Kubernetes за допомогою файлу кастомізації.
Починаючи з версії 1.14, Kubectl також підтримує керування обʼєктами Kubernetes за допомогою файлу кастомізації. Для перегляду ресурсів, знайдених у теці, що містить файл кастомізації, виконайте наступну команду:
kubectl kustomize <kustomization_directory>
Щоб застосувати ці ресурси, запустіть kubectl apply
з прапорцем --kustomize
або -k
:
kubectl apply -k <kustomization_directory>
Перш ніж ви розпочнете
Встановіть kubectl
.
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Огляд Kustomize
Kustomize — це інструмент для налаштування конфігурацій Kubernetes. Він має наступні функції для керування файлами конфігурації застосунків:
- генерація ресурсів з інших джерел
- встановлення наскрізних полів для ресурсів
- складання та налаштування колекцій ресурсів
Генерування ресурсів
ConfigMaps та Secrets зберігають конфігураційні або конфіденційні дані, які використовуються іншими обʼєктами Kubernetes, наприклад, Podʼами. Джерело істини для ConfigMaps або Secrets є зазвичай зовнішнім до кластера, наприклад як файл .properties
або файл ключів SSH. Kustomize має secretGenerator
та configMapGenerator
, які створюють Secret та ConfigMap з файлів або літералів.
configMapGenerator
Щоб створити ConfigMap з файлу, додайте запис до списку files
в configMapGenerator
. Ось приклад створення ConfigMap з елементом даних з файлу .properties
:
# Створіть файл application.properties
cat <<EOF >application.properties
FOO=Bar
EOF
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-1
files:
- application.properties
EOF
Згенерований ConfigMap можна переглянути за допомогою наступної команди:
kubectl kustomize ./
Згенерований ConfigMap виглядає так:
apiVersion: v1
data:
application.properties: |
FOO=Bar
kind: ConfigMap
metadata:
name: example-configmap-1-8mbdf7882g
Щоб створити ConfigMap з файлу оточення (env), додайте запис до списку envs
в configMapGenerator
. Ось приклад створення ConfigMap з елементом даних з файлу .env
:
# Створіть файл .env
cat <<EOF >.env
FOO=Bar
EOF
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-1
envs:
- .env
EOF
Згенерований ConfigMap можна переглянути за допомогою наступної команди:
kubectl kustomize ./
Згенерований ConfigMap виглядає так:
apiVersion: v1
data:
FOO: Bar
kind: ConfigMap
metadata:
name: example-configmap-1-42cfbf598f
Примітка:
Кожна змінна у файлі.env
стає окремим ключем в ConfigMap, який ви генеруєте. Це відрізняється від попереднього прикладу, в якому вбудовується файл з назвою application.properties
(та всі його записи) як значення для одного ключа.ConfigMaps також можна створювати з літеральних пар ключ-значення. Щоб створити ConfigMap з літеральною парою ключ-значення, додайте запис до списку literals
в configMapGenerator
. Ось приклад створення ConfigMap з елементом даних з пари ключ-значення:
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-2
literals:
- FOO=Bar
EOF
Згенерований ConfigMap можна перевірити за допомогою наступної команди:
kubectl kustomize ./
Згенерований ConfigMap виглядає так:
apiVersion: v1
data:
FOO: Bar
kind: ConfigMap
metadata:
name: example-configmap-2-g2hdhfc6tk
Щоб використовувати згенерований ConfigMap у Deployment, посилайтеся на нього за іменем configMapGenerator. Kustomize автоматично замінить це імʼя згенерованим.
Ось приклад Deployment, що використовує згенерований ConfigMap:
# Створіть файл application.properties
cat <<EOF >application.properties
FOO=Bar
EOF
cat <<EOF >deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: my-app
volumeMounts:
- name: config
mountPath: /config
volumes:
- name: config
configMap:
name: example-configmap-1
EOF
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
configMapGenerator:
- name: example-configmap-1
files:
- application.properties
EOF
Згенеруйте ConfigMap та Deployment:
kubectl kustomize ./
Згенерований Deployment буде посилатися на згенерований ConfigMap за іменем:
apiVersion: v1
data:
application.properties: |
FOO=Bar
kind: ConfigMap
metadata:
name: example-configmap-1-g4hk9g2ff8
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: my-app
name: my-app
spec:
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- image: my-app
name: app
volumeMounts:
- mountPath: /config
name: config
volumes:
- configMap:
name: example-configmap-1-g4hk9g2ff8
name: config
secretGenerator
Ви можете створювати Secrets з файлів або літеральних пар ключ-значення. Щоб створити Secret з файлу, додайте запис до списку files
в secretGenerator
. Ось приклад створення Secret з елементом даних з файлу:
# Створіть файл password.txt
cat <<EOF >./password.txt
username=admin
password=secret
EOF
cat <<EOF >./kustomization.yaml
secretGenerator:
- name: example-secret-1
files:
- password.txt
EOF
Згенерований Secret має наступний вигляд:
apiVersion: v1
data:
password.txt: dXNlcm5hbWU9YWRtaW4KcGFzc3dvcmQ9c2VjcmV0Cg==
kind: Secret
metadata:
name: example-secret-1-t2kt65hgtb
type: Opaque
Щоб створити Secret з літеральною парою ключ-значення, додайте запис до списку literals
в secretGenerator
. Ось приклад створення Secret з елементом даних з пари ключ-значення:
cat <<EOF >./kustomization.yaml
secretGenerator:
- name: example-secret-2
literals:
- username=admin
- password=secret
EOF
Згенерований Secret має наступний вигляд:
apiVersion: v1
data:
password: c2VjcmV0
username: YWRtaW4=
kind: Secret
metadata:
name: example-secret-2-t52t6g96d8
type: Opaque
Podʼібно до ConfigMaps, створені Secrets можна використовувати у Deployment, посилаючись на імʼя secretGenerator:
# Створіть файл password.txt
cat <<EOF >./password.txt
username=admin
password=secret
EOF
cat <<EOF >deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: my-app
volumeMounts:
- name: password
mountPath: /secrets
volumes:
- name: password
secret:
secretName: example-secret-1
EOF
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
secretGenerator:
- name: example-secret-1
files:
- password.txt
EOF
generatorOptions
Згенеровані ConfigMaps та Secrets мають суфікс хешу вмісту, що додається. Це забезпечує створення нового ConfigMap або Secret при зміні вмісту. Щоб вимкнути поведінку додавання суфікса, можна використовувати generatorOptions
. Крім того, також можливо вказати загальні опції для згенерованих ConfigMaps та Secrets.
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-3
literals:
- FOO=Bar
generatorOptions:
disableNameSuffixHash: true
labels:
type: generated
annotations:
note: generated
EOF
Виконайте kubectl kustomize ./
, щоб переглянути згенерований ConfigMap:
apiVersion: v1
data:
FOO: Bar
kind: ConfigMap
metadata:
annotations:
note: generated
labels:
type: generated
name: example-configmap-3
Встановлення загальних наскрізних полів
Досить поширене явище — встановлення загальних наскрізних полів для всіх ресурсів Kubernetes у проєкті. Деякі випадки встановлення загальних полів:
- встановлення одного й того ж простору імен для всіх ресурсів
- додавання одного й того ж префікса чи суфікса до імені
- додавання одного й того ж набору міток
- додавання одного й того ж набору анотацій
Ось приклад:
# Створіть deployment.yaml
cat <<EOF >./deployment.yaml
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
EOF
cat <<EOF >./kustomization.yaml
namespace: my-namespace
namePrefix: dev-
nameSuffix: "-001"
commonLabels:
app: bingo
commonAnnotations:
oncallPager: 800-555-1212
resources:
- deployment.yaml
EOF
Виконайте kubectl kustomize ./
, щоб переглянути, як ці поля встановлені у ресурсі Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
oncallPager: 800-555-1212
labels:
app: bingo
name: dev-nginx-deployment-001
namespace: my-namespace
spec:
selector:
matchLabels:
app: bingo
template:
metadata:
annotations:
oncallPager: 800-555-1212
labels:
app: bingo
spec:
containers:
- image: nginx
name: nginx
Компонування та кастомізація ресурсів
Часто в проєкті складають набір Ресурсів та керують ними всередині одного файлу чи теки. Kustomize пропонує компонування Ресурсів з різних файлів та застосування патчів чи інших налаштувань до них.
Компонування
Kustomize підтримує компонування різних ресурсів. Поле resources
у файлі kustomization.yaml
визначає список ресурсів, які слід включити в конфігурацію. Встановіть шлях до файлу конфігурації ресурсу у списку resources
. Ось приклад додавання до конфігурації застосунку NGINX, що складається з Deployment та Service:
# Створіть файл deployment.yaml
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
EOF
# Створіть файл service.yaml
cat <<EOF > service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx
EOF
# Створіть файл kustomization.yaml та скомпонуйте їх
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
- service.yaml
EOF
Ресурси з kubectl kustomize ./
містять обʼєкти як Deployment, так і Service.
Кастомізація
Патчі можуть бути використані для застосування різних кастомізацій до Ресурсів. Kustomize підтримує різні механізми патчінгу через patchesStrategicMerge
та patchesJson6902
. patchesStrategicMerge
— це список шляхів до файлів. Кожен файл повинен бути розвʼязаний до стратегічного обʼєднання патчів. Імена всередині патчів повинні відповідати іменам Ресурсів, які вже завантажені. Рекомендується використовувати невеликі патчі, які виконують одну задачу. Наприклад, створіть один патч для збільшення кількості реплік у Deployment та інший патч для встановлення обмеження памʼяті.
# Створіть файл deployment.yaml
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
EOF
# Створіть патч increase_replicas.yaml
cat <<EOF > increase_replicas.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 3
EOF
# Створіть інший патч set_memory.yaml
cat <<EOF > set_memory.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
template:
spec:
containers:
- name: my-nginx
resources:
limits:
memory: 512Mi
EOF
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
patchesStrategicMerge:
- increase_replicas.yaml
- set_memory.yaml
EOF
Виконайте kubectl kustomize ./
, щоб переглянути Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 3
selector:
matchLabels:
run: my-nginx
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- image: nginx
name: my-nginx
ports:
- containerPort: 80
resources:
limits:
memory: 512Mi
Не всі Ресурси чи поля підтримують стратегічні обʼєднувальні патчі. Для підтримки зміни довільних полів у довільних Ресурсах, Kustomize пропонує застосування JSON патчів через patchesJson6902
. Для знаходження правильного Ресурсу для Json патчу, потрібно вказати групу, версію, тип та імʼя цього Ресурсу у kustomization.yaml
. Наприклад, збільшення кількості реплік у обʼєкті Deployment також можна зробити через patchesJson6902
.
# Створіть файл deployment.yaml
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
EOF
# Створіть json патч
cat <<EOF > patch.yaml
- op: replace
path: /spec/replicas
value: 3
EOF
# Створіть kustomization.yaml
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
patchesJson6902:
- target:
group: apps
version: v1
kind: Deployment
name: my-nginx
path: patch.yaml
EOF
Виконайте kubectl kustomize ./
, щоб побачити, що поле replicas
оновлене:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 3
selector:
matchLabels:
run: my-nginx
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- image: nginx
name: my-nginx
ports:
- containerPort: 80
Крім патчів, Kustomize також пропонує налаштування контейнерних образів або введення значень полів з інших обʼєктів в контейнери без створення патчів. Наприклад, ви можете змінити використаний образ усередині контейнерів, вказавши новий образ у полі images
у kustomization.yaml
.
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
EOF
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
images:
- name: nginx
newName: my.image.registry/nginx
newTag: 1.4.0
EOF
Виконайте kubectl kustomize ./
, щоб переглянути, що використовується оновлений образ:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 2
selector:
matchLabels:
run: my-nginx
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- image: my.image.registry/nginx:1.4.0
name: my-nginx
ports:
- containerPort: 80
Іноді застосунок, що працює у Podʼі, може потребувати використання значень конфігурації з інших обʼєктів. Наприклад, Pod з обʼєкту Deployment повинен читати відповідне імʼя Service з Env або як аргумент команди. Оскільки імʼя Service може змінюватися через namePrefix
або nameSuffix
, додавання імені Service у командний аргумент не рекомендується. Для цього використовується Kustomize, що вводить імʼя Service в контейнери через vars
.
# Створіть файл deployment.yaml (взявши в лапки роздільник документа)
cat <<'EOF' > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
command: ["start", "--host", "$(MY_SERVICE_NAME)"]
EOF
# Створіть файл service.yaml
cat <<EOF > service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx
EOF
cat <<EOF >./kustomization.yaml
namePrefix: dev-
nameSuffix: "-001"
resources:
- deployment.yaml
- service.yaml
vars:
- name: MY_SERVICE_NAME
objref:
kind: Service
name: my-nginx
apiVersion: v1
EOF
Виконайте kubectl kustomize ./
, щоб побачити, що імʼя Service, введене у контейнери, — це dev-my-nginx-001
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: dev-my-nginx-001
spec:
replicas: 2
selector:
matchLabels:
run: my-nginx
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- command:
- start
- --host
- dev-my-nginx-001
image: nginx
name: my-nginx
Base та Overlay
У Kustomize існують концепції base та overlay. Base — це тека з файлом kustomization.yaml
, яка містить набір ресурсів та повʼязані налаштування. Base може бути як локальною текою, так і текою з віддаленого репозиторію, якщо присутній файл kustomization.yaml
. Overlay — це тека з файлом kustomization.yaml
, яка посилається на інші теки з налаштуваннями як на свої base
компоненти. Base не знає про overlay і може використовуватися в кількох overlay. Overlay може мати кілька base та компонувати всі ресурси з base, а також мати власні налаштування поверх.
Ось приклад base:
# Створіть теку для зберігання base
mkdir base
# Створіть файл base/deployment.yaml
cat <<EOF > base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
EOF
# Створіть файл base/service.yaml
cat <<EOF > base/service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx
EOF
# Створіть файл base/kustomization.yaml
cat <<EOF > base/kustomization.yaml
resources:
- deployment.yaml
- service.yaml
EOF
Цю базу можна використовувати в кількох overlay. Ви можете додавати різний namePrefix
або інші загальні поля у різних overlay. Ось два overlay, які використовують один і той же base.
mkdir dev
cat <<EOF > dev/kustomization.yaml
resources:
- ../base
namePrefix: dev-
EOF
mkdir prod
cat <<EOF > prod/kustomization.yaml
resources:
- ../base
namePrefix: prod-
EOF
Як застосувати/переглядати/видаляти обʼєкти використовуючи Kustomize
Використовуйте --kustomize
або -k
у командах kubectl
, щоб визначити Ресурси, які керуються kustomization.yaml
. Зверніть увагу, що -k
повинен посилатися на теку з налаштуваннями kustomization, наприклад,
kubectl apply -k <тека kustomization>/
Враховуючи наступний kustomization.yaml
,
# Створіть файл deployment.yaml
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
EOF
# Створіть файл kustomization.yaml
cat <<EOF >./kustomization.yaml
namePrefix: dev-
commonLabels:
app: my-nginx
resources:
- deployment.yaml
EOF
Виконайте наступну команду, щоб застосувати обʼєкт Deployment dev-my-nginx
:
> kubectl apply -k ./
deployment.apps/dev-my-nginx створено
Виконайте одну з наступних команд, щоб переглянути обʼєкт Deployment dev-my-nginx
:
kubectl get -k ./
kubectl describe -k ./
Виконайте наступну команду, щоб порівняти обʼєкт Deployment dev-my-nginx
зі станом, в якому буде кластер, якщо маніфест буде застосований:
kubectl diff -k ./
Виконайте наступну команду, щоб видалити обʼєкт Deployment dev-my-nginx
:
> kubectl delete -k ./
deployment.apps "dev-my-nginx" deleted
Перелік елементів Kustomize
Поле | Тип | Пояснення |
---|---|---|
namespace | string | додає простір імен до всіх ресурсів |
namePrefix | string | це значення додається до імен всіх ресурсів |
nameSuffix | string | це значення додається до кінця імен всіх ресурсів |
commonLabels | map[string]string | мітки, що додаються до всіх ресурсів і селекторів |
commonAnnotations | map[string]string | анотації, що додаються до всіх ресурсів |
resources | []string | кожний елемент цього списку повинен посилатися на наявний файл конфігурації ресурсів |
configMapGenerator | []ConfigMapArgs | Кожний елемент цього списку генерує ConfigMap |
secretGenerator | []SecretArgs | Кожний елемент цього списку генерує Secret |
generatorOptions | GeneratorOptions | Модифікує поведінку всіх генераторів ConfigMap і Secret |
bases | []string | Кожний елемент цього списку повинен посилатися на теку, що містить файл kustomization.yaml |
patchesStrategicMerge | []string | Кожний елемент цього списку повинен посилатися на стратегічне патч злиття обʼєкта Kubernetes |
patchesJson6902 | []Patch | Кожний елемент цього списку повинен посилатися на обʼєкт Kubernetes та Json Patch |
vars | []Var | Кожний елемент призначений для отримання тексту з поля одного ресурсу |
images | []Image | Кожний елемент призначений для зміни імені, тегів і/або дайджесту для одного образу без створення патчів |
configurations | []string | Кожний елемент цього списку повинен посилатися на файл, що містить конфігурації перетворювача Kustomize |
crds | []string | Кожний елемент цього списку повинен посилатися на файл визначення OpenAPI для типів Kubernetes |
Що далі
3 - Керування обʼєктами Kubernetes за допомогою імперативних команд
Обʼєкти Kubernetes можна швидко створювати, оновлювати та видаляти безпосередньо за допомогою імперативних команд, вбудованих в інструмент командного рядка kubectl
. Цей документ пояснює, як організовано ці команди та як їх використовувати для керування поточними обʼєктами.
Перш ніж ви розпочнете
Встановіть kubectl
.
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Компроміси
Інструмент kubectl
підтримує три види управління обʼєктами:
- Імперативні команди
- Імперативне конфігурування обʼєктів
- Декларативне конфігурування обʼєктів
Див. Управління обʼєктами Kubernetes для обговорення переваг та недоліків кожного виду управління обʼєктами.
Як створювати обʼєкти
Інструмент kubectl
підтримує команди, що базуються на дії, для створення деяких найпоширеніших типів обʼєктів. Команди названі так, щоб їх можна було впізнати користувачам, що не знайомі з типами обʼєктів Kubernetes.
run
: Створює новий Pod для запуску контейнера.expose
: Створює новий обʼєкт Service для балансування трафіку між Pod.autoscale
: Створює новий обʼєкт Autoscaler для автоматичного горизонтального масштабування контролера, наприклад, Deployment.
Інструмент kubectl
також підтримує команди створення, що базуються на типі обʼєкта. Ці команди підтримують більше типів обʼєктів і більш явно вказують на їх наміри, але вимагають, щоб користувачі знали типи обʼєктів, які вони мають намір створити.
create <типобʼєкта> [<підтип>] <імʼяекземпляра>
Деякі типи обʼєктів мають підтипи, які можна вказати в команді create
. Наприклад, обʼєкт Service має кілька підтипів, включаючи ClusterIP, LoadBalancer та NodePort. Ось приклад створення Service з підтипом NodePort:
kubectl create service nodeport <myservicename>
У попередньому прикладі команда create service nodeport
викликається як підкоманда команди create service
.
Ви можете використовувати прапорець -h
, щоб знайти аргументи та прапорці, які підтримуються підкомандою:
kubectl create service nodeport -h
Як оновлювати обʼєкти
Команда kubectl
підтримує команди, що базуються на дії, для деяких загальних операцій оновлення. Ці команди названі так, щоб користувачі, які не знайомі з обʼєктами Kubernetes, могли виконувати оновлення, не знаючи конкретних полів, які потрібно встановити:
scale
: Горизонтально масштабувати контролер для додавання або видалення Podʼів шляхом оновлення кількості реплік контролера.annotate
: Додати або видалити анотацію з обʼєкта.label
: Додати або видалити мітку з обʼєкта.
Команда kubectl
також підтримує команди оновлення, що базуються на аспекті обʼєкта. Встановлення цього аспекту може встановлювати різні поля для різних типів обʼєктів:
set
<поле>
: Встановити аспект обʼєкта.
Примітка:
У версії Kubernetes 1.5 не кожна команда, що базується на дії, має повʼязану команду, що базується на аспекті.Інструмент kubectl
підтримує ці додаткові способи оновлення поточного обʼєкта безпосередньо, однак вони вимагають кращого розуміння схеми обʼєктів Kubernetes.
edit
: Безпосередньо редагувати сирі конфігурації поточного обʼєкта, відкриваючи його конфігурацію в редакторі.patch
: Безпосередньо модифікувати конкретні поля поточного обʼєкта, використовуючи рядок патча. Докладніше про рядки патча див. розділ патча в Конвенціях API.
Як видаляти обʼєкти
Ви можете використовувати команду delete
, щоб видалити обʼєкт з кластера:
delete <тип>/<імʼя>
Примітка:
Ви можете використовуватиkubectl delete
як для імперативних команд, так і для імперативного конфігурування обʼєкта. Різниця полягає в аргументах, переданих команді. Щоб використовувати kubectl delete
як імперативну команду, передайте обʼєкт для видалення як аргумент. Ось приклад, який передає обʼєкт Deployment з іменем nginx:kubectl delete deployment/nginx
Як переглянути обʼєкт
Існують кілька команд для виведення інформації про обʼєкт:
get
: Виводить базову інформацію про відповідні обʼєкти. Використовуйтеget -h
, щоб побачити список опцій.describe
: Виводить агреговану детальну інформацію про відповідні обʼєкти.logs
: Виводить stdout та stderr для контейнера, що працює в Pod.
Використання команд set
для модифікації обʼєктів перед створенням
Є деякі поля обʼєктів, для яких не існує прапорця, який можна використовувати в команді create
. У деяких з цих випадків ви можете використовувати комбінацію set
та create
, щоб вказати значення для поля перед створенням обʼєкта. Це робиться за допомогою перенаправлення виводу команди create
на команду set
, а потім назад на команду create
. Ось приклад:
kubectl create service clusterip my-svc --clusterip="None" -o yaml --dry-run=client | kubectl set selector --local -f - 'environment=qa' -o yaml | kubectl create -f -
- Команда
kubectl create service -o yaml --dry-run=client
створює конфігурацію для Service, але виводить її на stdout у форматі YAML замість надсилання до сервера API Kubernetes. - Команда
kubectl set selector --local -f - -o yaml
читає конфігурацію з stdin і записує оновлену конфігурацію на stdout у форматі YAML. - Команда
kubectl create -f -
створює обʼєкт, використовуючи надану конфігурацію через stdin.
Використання --edit
для модифікації обʼєктів перед створенням
Можна використовувати kubectl create --edit
, щоб зробити довільні зміни обʼєкта перед його створенням. Ось приклад:
kubectl create service clusterip my-svc --clusterip="None" -o yaml --dry-run=client > /tmp/srv.yaml
kubectl create --edit -f /tmp/srv.yaml
- Команда
kubectl create service
створює конфігурацію для Service та зберігає її у/tmp/srv.yaml
. - Команда
kubectl create --edit
відкриває файл конфігурації для редагування перед створенням обʼєкта.
Що далі
4 - Імперативне керування обʼєктами Kubernetes за допомогою файлів конфігурації
Обʼєкти Kubernetes можна створювати, оновлювати та видаляти за допомогою інструменту командного рядка kubectl
разом із файлом конфігурації обʼєкта, написаним у форматі YAML або JSON. У цьому документі пояснюється, як визначати та керувати обʼєктами за допомогою файлів конфігурації.
Перш ніж ви розпочнете
Встановіть kubectl
.
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Компроміси
Інструмент kubectl
підтримує три види управління обʼєктами:
- Імперативні команди
- Імперативне конфігурування обʼєктів
- Декларативне конфігурування обʼєктів
Див. Управління обʼєктами Kubernetes для обговорення переваг та недоліків кожного виду управління обʼєктами.
Як створювати обʼєкти
Ви можете використовувати kubectl create -f
для створення обʼєкта з файлу конфігурації. Дивіться Довідник API Kubernetes для отримання деталей.
kubectl create -f <filename|url>
Як оновити обʼєкти
Попередження:
Оновлення обʼєктів за допомогою командиreplace
призводить до видалення всіх частин специфікації, які не вказані в файлі конфігурації. Це не слід використовувати з обʼєктами, чиї специфікації частково керуються кластером, наприклад, Service типу LoadBalancer
, де поле externalIPs
керується незалежно від файлу конфігурації. Поля, які керуються незалежно, повинні бути скопійовані в файл конфігурації, щоб уникнути їх втрати під час виконання replace
.Ви можете використовувати kubectl replace -f
для оновлення поточного обʼєкта згідно з файлом конфігурації.
kubectl replace -f <filename|url>
Як видалити обʼєкти
Ви можете використовувати kubectl delete -f
для видалення обʼєкта, який описаний у файлі конфігурації.
kubectl delete -f <filename|url>
Попередження:
Якщо файл конфігурації вказує поле generateName
в секції metadata
замість поля name
, ви не можете видалити обʼєкт, використовуючи kubectl delete -f <filename|url>
. Вам доведеться використовувати інші прапорці для видалення обʼєкта. Наприклад:
kubectl delete <тип> <імʼя>
kubectl delete <тип> -l <мітка>
Як переглянути обʼєкт
Ви можете використовувати kubectl get -f
, щоб переглянути інформацію про обʼєкт, що описаний у файлі конфігурації.
kubectl get -f <filename|url> -o yaml
Прапорець -o yaml
вказує, що повна конфігурація обʼєкта виводиться. Використовуйте kubectl get -h
, щоб побачити список опцій.
Обмеження
Команди create
, replace
та delete
працюють добре, коли кожна конфігурація обʼєкта повністю визначена і записана у своєму файлі конфігурації. Однак, коли поточний обʼєкт оновлюється, і оновлення не обʼєднуються в його файл конфігурації, оновлення будуть втрачені після наступного виконання replace
. Це може статися, якщо контролер, такий як HorizontalPodAutoscaler, вносить оновлення безпосередньо до поточного обʼєкта. Ось приклад:
- Ви створюєте обʼєкт з файлу конфігурації.
- Інше джерело оновлює обʼєкт, змінюючи якесь поле.
- Ви замінюєте обʼєкт з файлу конфігурації. Зміни, внесені іншим джерелом на кроці 2, втрачені.
Якщо вам потрібна підтримка кількох записувачів для одного обʼєкта, ви можете використовувати kubectl apply
для керування обʼєктом.
Створення та редагування обʼєкта за URL без зберігання конфігурації
Припустимо, що у вас є URL файлу конфігурації обʼєкта. Ви можете використовувати kubectl create --edit
для внесення змін до конфігурації перед створенням обʼєкта. Це особливо корисно для підручників та завдань, які вказують на файл конфігурації, який може бути змінений читачем.
kubectl create -f <url> --edit
Міграція від імперативних команд до імперативного конфігурування обʼєктів
Міграція від імперативних команд до імперативної конфігурації обʼєктів включає декілька кроків, які потрібно виконати вручну.
Експортуйте поточний обʼєкт у локальний файл конфігурації обʼєкта:
kubectl get <kind>/<name> -o yaml > <kind>_<name>.yaml
Ручне видалення поля стану з файлу конфігурації обʼєкта.
Для подальшого керування обʼєктом виключно використовуйте
replace
.kubectl replace -f <kind>_<name>.yaml
Визначення селекторів контролерів та міток PodTemplate
Попередження:
Оновлення селекторів на контролерах наполегливо не рекомендується.Рекомендований підхід — визначити одну незмінну мітку PodTemplate, яка використовується тільки селектором контролера без іншого семантичного значення.
Приклад мітки:
selector:
matchLabels:
controller-selector: "apps/v1/deployment/nginx"
template:
metadata:
labels:
controller-selector: "apps/v1/deployment/nginx"
Що далі
5 - Оновлення обʼєктів API на місці за допомогою kubectl patch
Це завдання показує, як використовувати kubectl patch
для оновлення обʼєкта API на місці. Вправи в цьому завданні демонструють стратегічний патч злиття та патч злиття JSON.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Використання стратегічного патчу злиття для оновлення Deployment
Ось файл конфігурації для Deployment, що має дві репліки. Кожна репліка є Podʼом, який має один контейнер:
apiVersion: apps/v1
kind: Deployment
metadata:
name: patch-demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: patch-demo-ctr
image: nginx
tolerations:
- effect: NoSchedule
key: dedicated
value: test-team
Створіть Deployment:
kubectl apply -f https://k8s.io/examples/application/deployment-patch.yaml
Перегляньте Podʼи, повʼязані з вашим Deployment:
kubectl get pods
Вивід показує, що Deployment має два Podʼи. 1/1
вказує на те, що кожен Pod має один контейнер:
NAME READY STATUS RESTARTS AGE
patch-demo-28633765-670qr 1/1 Running 0 23s
patch-demo-28633765-j5qs3 1/1 Running 0 23s
Зробіть позначку про імена працюючих Podʼів. Пізніше ви побачите, що ці Podʼи будуть завершені та замінені новими.
На цей момент кожен Pod має один контейнер, який запускає образ nginx. Тепер, здавалося б, вам потрібно, щоб кожен Pod мав два контейнери: один, який запускає nginx, і один, який запускає redis.
Створіть файл з іменем patch-file.yaml
, який має такий вміст:
spec:
template:
spec:
containers:
- name: patch-demo-ctr-2
image: redis
Застосуйте патч до вашого Deployment:
kubectl patch deployment patch-demo --patch-file patch-file.yaml
Перегляньте Deployment після накладання патчу:
kubectl get deployment patch-demo --output yaml
Вивід показує, що PodSpec у Deployment має ддва контейнери
containers:
- image: redis
imagePullPolicy: Always
name: patch-demo-ctr-2
...
- image: nginx
imagePullPolicy: Always
name: patch-demo-ctr
...
Перегляньте Podʼи, повʼязані з вашим Deployment після накладання патчу:
kubectl get pods
Вивід показує, що працюючі Podʼи мають різні імена Podʼів, у порівнняні з тими що працювали раніше. Deployment припинив роботу старих Podʼів та створив два нові Podʼи, які відповідають оновленій специфікації Deployment. 2/2
вказує на те, що кожен Pod має два контейнера:
NAME READY STATUS RESTARTS AGE
patch-demo-1081991389-2wrn5 2/2 Running 0 1m
patch-demo-1081991389-jmg7b 2/2 Running 0 1m
Придивіться уважніше до одного з Podʼів patch-demo:
kubectl get pod <your-pod-name> --output yaml
Вивід показує, що Pod має два контейнери: один, який запускає nginx, і один, який запускає redis:
containers:
- image: redis
...
- image: nginx
...
Примітки щодо стратегічного патчу злиття
Патч, який ви виконали у попередній вправі, називається стратегічним патчем злиття. Зверніть увагу, що патч не замінив список containers
. Замість цього він додав новий контейнер до списку. Іншими словами, список у патчі був обʼєднаний з поточним списком. Це не завжди трапляється, коли ви використовуєте стратегічний патч злиття для списку. У деяких випадках список замінюється, а не обʼєднується.
За допомогою стратегічних патчів злиття список або замінюється, або обʼєднується залежно від його стратегії патча. Стратегія патча вказується значенням ключа patchStrategy
у мітці поля в вихідному коді Kubernetes. Наприклад, поле Containers
структури PodSpec
має patchStrategy
рівне merge
:
type PodSpec struct {
...
Containers []Container `json:"containers" patchStrategy:"merge" patchMergeKey:"name" ...`
...
}
Ви також можете побачити стратегію патча в специфікації OpenApi:
"io.k8s.api.core.v1.PodSpec": {
...,
"containers": {
"description": "List of containers belonging to the pod. ...."
},
"x-kubernetes-patch-merge-key": "name",
"x-kubernetes-patch-strategy": "merge"
}
І ви можете побачити стратегію патча в документації Kubernetes API.
Створіть файл з іменем patch-file-tolerations.yaml
із таким вмістом:
spec:
template:
spec:
tolerations:
- effect: NoSchedule
key: disktype
value: ssd
Застосуйте патч до вашого Deployment:
kubectl patch deployment patch-demo --patch-file patch-file-tolerations.yaml
Перегляньте Deployment після накладання патчу:
kubectl get deployment patch-demo --output yaml
Відвід показує, що у PodSpec у Deployment є лише один Toleration:
tolerations:
- effect: NoSchedule
key: disktype
value: ssd
Зверніть увагу, що список tolerations
в PodSpec був замінений, а не обʼєднаний. Це тому, що поле Tolerations структури PodSpec не має ключа patchStrategy
у своїй мітці поля. Тому стратегія патча, що використовується стандартно, дорівнює replace
.
type PodSpec struct {
...
Tolerations []Toleration `json:"tolerations,omitempty" protobuf:"bytes,22,opt,name=tolerations"`
...
}
Використання патчу злиття JSON для оновлення Deployment
Стратегічне патч злиття відрізняється від JSON merge patch. З JSON merge patch, якщо вам потрібно оновити список, вам потрібно вказати цілий новий список. І новий список повністю замінює поточний список.
Команда kubectl patch
має параметр type
, який ви можете встановити на одне з цих значень:
Значення параметра | Тип злиття |
---|---|
json | JSON Patch, RFC 6902 |
merge | JSON Merge Patch, RFC 7386 |
strategic | Стратегічне патч злиття |
Для порівняння JSON patch та JSON merge patch, див. JSON Patch та JSON Merge Patch.
Стандартне значення для параметра type
є strategic
. Таким чином, у попередній вправі ви виконали стратегічний патч злиття.
Далі виконайте JSON merge patch на вашому Deployment. Створіть файл з іменем patch-file-2.yaml
із таким вмістом:
spec:
template:
spec:
containers:
- name: patch-demo-ctr-3
image: gcr.io/google-samples/hello-app:2.0
У вашій команді патча встановіть type
на merge
:
kubectl patch deployment patch-demo --type merge --patch-file patch-file-2.yaml
Перегляньте Deployment після накладання патчу:
kubectl get deployment patch-demo --output yaml
Список containers
, який ви вказали у патчі, має лише один контейнер. Вивід показує, що ваш список з одним контейнером замінив наявний список containers
.
spec:
containers:
- image: gcr.io/google-samples/hello-app:2.0
...
name: patch-demo-ctr-3
Перегляньте Podʼи:
kubectl get pods
У виводі ви можете побачити, що наявні Podʼи були завершені, а нові Podʼи — створені. 1/1
вказує на те, що кожен новий Pod працює лише з одним контейнером.
NAME READY STATUS RESTARTS AGE
patch-demo-1307768864-69308 1/1 Running 0 1m
patch-demo-1307768864-c86dc 1/1 Running 0 1m
Використання стратегічного патча злиття для оновлення Deployment з використанням стратегії retainKeys
Ось файл конфігурації для Deployment, що використовує стратегію RollingUpdate
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: retainkeys-demo
spec:
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 30%
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: retainkeys-demo-ctr
image: nginx
Створіть Deployment:
kubectl apply -f https://k8s.io/examples/application/deployment-retainkeys.yaml
На цей момент Deployment створено і використовує стратегію RollingUpdate
.
Створіть файл з іменем patch-file-no-retainkeys.yaml
з таким вмістом:
spec:
strategy:
type: Recreate
Застосуйте патч до вашого Deployment:
kubectl patch deployment retainkeys-demo --type strategic --patch-file patch-file-no-retainkeys.yaml
У виводі ви побачите, що неможливо встановити type
як Recreate
, коли значення визначено для spec.strategy.rollingUpdate
:
The Deployment "retainkeys-demo" is invalid: spec.strategy.rollingUpdate: Forbidden: may not be specified when strategy `type` is 'Recreate'
Способом видалити значення для spec.strategy.rollingUpdate
під час оновлення значення для type
є використання стратегії retainKeys для стратегічного злиття.
Створіть ще один файл з іменем patch-file-retainkeys.yaml
з таким вмістом:
spec:
strategy:
$retainKeys:
- type
type: Recreate
З цим патчем ми вказуємо, що ми хочемо зберегти лише ключ type
обʼєкта strategy
. Таким чином, під час операції патча значення rollingUpdate
буде видалено.
Знову застосуйте патч до вашого Deployment з цим новим патчем:
kubectl patch deployment retainkeys-demo --type strategic --patch-file patch-file-retainkeys.yaml
Дослідіть вміст Deployment:
kubectl get deployment retainkeys-demo --output yaml
У виводі показано, що обʼєкт стратегії в Deployment більше не містить ключа rollingUpdate
:
spec:
strategy:
type: Recreate
template:
Примітки щодо стратегічного патчу злиття з використанням стратегії retainKeys
Патч, який ви виконали в попередній вправі, називається стратегічним патчем злиття з використанням стратегії retainKeys. Цей метод вводить нову директиву $retainKeys
, яка має наступні стратегії:
- Вона містить список рядків.
- Усі поля, які потрібно зберегти, повинні бути присутні в списку
$retainKeys
. - Поля, які присутні, будуть обʼєднані з поточним обʼєктом.
- Всі відсутні поля будуть очищені під час застосування патча.
- Усі поля у списку
$retainKeys
повинні бути надмножиною або такими ж, як і поля, що присутні в патчі.
Стратегія retainKeys
не працює для всіх обʼєктів. Вона працює лише тоді, коли значення ключа patchStrategy
у мітці поля в вихідному коді Kubernetes містить retainKeys
. Наприклад, поле Strategy
структури DeploymentSpec
має patchStrategy
рівне retainKeys
:
type DeploymentSpec struct {
...
// +patchStrategy=retainKeys
Strategy DeploymentStrategy `json:"strategy,omitempty" patchStrategy:"retainKeys" ...`
...
}
Ви також можете побачити стратегію retainKeys
в специфікації OpenApi:
"io.k8s.api.apps.v1.DeploymentSpec": {
...,
"strategy": {
"$ref": "#/definitions/io.k8s.api.apps.v1.DeploymentStrategy",
"description": "The deployment strategy to use to replace existing pods with new ones.",
"x-kubernetes-patch-strategy": "retainKeys"
},
....
}
І ви можете дізнатись більше про стратегію retainKeys
в документації Kubernetes API.
Альтернативні форми команди kubectl patch
Команда kubectl patch
приймає YAML або JSON. Вона може приймати патч як файл або безпосередньо в командному рядку.
Створіть файл з іменем patch-file.json
з таким вмістом:
{
"spec": {
"template": {
"spec": {
"containers": [
{
"name": "patch-demo-ctr-2",
"image": "redis"
}
]
}
}
}
}
Наступні команди є еквівалентними:
kubectl patch deployment patch-demo --patch-file patch-file.yaml
kubectl patch deployment patch-demo --patch 'spec:\n template:\n spec:\n containers:\n - name: patch-demo-ctr-2\n image: redis'
kubectl patch deployment patch-demo --patch-file patch-file.json
kubectl patch deployment patch-demo --patch '{"spec": {"template": {"spec": {"containers": [{"name": "patch-demo-ctr-2","image": "redis"}]}}}}'
Оновлення кількості реплік обʼєкта за допомогою kubectl patch
з --subresource
Kubernetes v1.24 [alpha]
Прапорець --subresource=[імʼя-субресурсу]
використовується з командами kubectl, такими як get, patch, edit і replace, для отримання та оновлення субресурсів status
та scale
ресурсів
(застосовується для версії kubectl v1.24 або новішої). Цей прапорець використовується з усіма ресурсами API (вбудованими та CR), які мають субресурси status
або scale
. Deployment — один з прикладів, які підтримують ці субресурси.
Ось маніфест для Deployment, що має дві репліки:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # вказує Deployment запустити 2 Podʼи, що відповідають шаблону
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
Створіть Deployment:
kubectl apply -f https://k8s.io/examples/application/deployment.yaml
Перегляньте Podʼи, повʼязані з вашим Deployment:
kubectl get pods -l app=nginx
У виводі ви можете побачити, що у Deployment є дві Podʼи. Наприклад:
NAME READY STATUS RESTARTS AGE
nginx-deployment-7fb96c846b-22567 1/1 Running 0 47s
nginx-deployment-7fb96c846b-mlgns 1/1 Running 0 47s
Тепер застосуйте патч до Deployment з прапорцем --subresource=[імʼя-субресурсу]
:
kubectl patch deployment nginx-deployment --subresource='scale' --type='merge' -p '{"spec":{"replicas":3}}'
Вивід:
scale.autoscaling/nginx-deployment patched
Перегляньте Podʼи, повʼязані з вашим Deployment після патчу:
kubectl get pods -l app=nginx
У виводі ви можете побачити, що було створено один новий Pod, тепер у вас є 3 запущені Podʼи.
NAME READY STATUS RESTARTS AGE
nginx-deployment-7fb96c846b-22567 1/1 Running 0 107s
nginx-deployment-7fb96c846b-lxfr2 1/1 Running 0 14s
nginx-deployment-7fb96c846b-mlgns 1/1 Running 0 107s
Перегляньте Deployment після патчу:
kubectl get deployment nginx-deployment -o yaml
...
spec:
replicas: 3
...
status:
...
availableReplicas: 3
readyReplicas: 3
replicas: 3
Примітка:
Якщо ви запускаєтеkubectl patch
і вказуєте прапорець --subresource
для ресурсу, який не підтримує цей конкретний субресурс, сервер API повертає помилку 404 Not Found.Підсумки
У цій вправі ви використали kubectl patch
, щоб змінити поточну конфігурацію обʼєкта Deployment. Ви не змінювали файл конфігурації, який ви спочатку використовували для створення обʼєкта Deployment. Інші команди для оновлення обʼєктів API включають kubectl annotate, kubectl edit, kubectl replace, kubectl scale, та kubectl apply.
Примітка:
Стратегічний патч злиття не підтримується для власних ресурсів.Що далі
6 - Міграція обʼєктів Kubernetes за допомогою міграції версій сховища
Kubernetes v1.30 [alpha]
(стандартно увімкнено: false)Kubernetes покладається на активне переписування даних API, щоб підтримувати деякі дії обслуговування, повʼязані зі збереженням у спокої. Два видатні приклади цього — це версійна схема збережених ресурсів (тобто зміна перевіреної схеми збереження від v1 до v2 для певного ресурсу) та шифрування у спокої (тобто перезапис старих даних на основі зміни у способі шифрування даних).
Перш ніж ви розпочнете
Встановіть kubectl
.
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Версія вашого Kubernetes сервера має бути не старішою ніж v1.30. Для перевірки версії введітьkubectl version
.Переконайтеся, що у вашому кластері увімкнено функціональні можливості StorageVersionMigrator
та InformerResourceVersion
. Для внесення цих змін вам знадобиться доступ адміністратора панелі управління.
Увімкніть REST API для міграції версій сховища, встановивши параметр конфігурації storagemigration.k8s.io/v1alpha1
на true
для API-сервера. Для отримання додаткової інформації про те, як це зробити, прочитайте увімкнення або вимкнення API Kubernetes.
Перешифрування Secret Kubernetes за допомогою міграції версій сховища
Для початку, налаштуйте постачальника KMS для шифрування даних у спокої в etcd, використовуючи наступну конфігурацію шифрування.
kind: EncryptionConfiguration apiVersion: apiserver.config.k8s.io/v1 resources: - resources: - secrets providers: - aescbc: keys: - name: key1 secret: c2VjcmV0IGlzIHNlY3VyZQ==
Переконайтеся, що автоматичне перезавантаження конфігурації шифрування встановлено на значення true, встановивши
--encryption-provider-config-automatic-reload
.Створіть Secret за допомогою kubectl.
kubectl create secret generic my-secret --from-literal=key1=supersecret
Перевірте серіалізовані дані для цього обʼєкта Secret, що починаються з
k8s:enc:aescbc:v1:key1
.Оновіть файл конфігурації шифрування наступним чином, щоб виконати ротацію ключа шифрування.
kind: EncryptionConfiguration apiVersion: apiserver.config.k8s.io/v1 resources: - resources: - secrets providers: - aescbc: keys: - name: key2 secret: c2VjcmV0IGlzIHNlY3VyZSwgaXMgaXQ/ - aescbc: keys: - name: key1 secret: c2VjcmV0IGlzIHNlY3VyZQ==
Щоб переконатися, що раніше створений секрет
my-secret
зашифровано новим ключемkey2
, ви будете використовувати Storage Version Migration.Створіть маніфест StorageVersionMigration з назвою
migrate-secret.yaml
, наступного змісту:kind: StorageVersionMigration apiVersion: storagemigration.k8s.io/v1alpha1 metadata: name: secrets-migration spec: resource: group: "" version: v1 resource: secrets
Створіть обʼєкт за допомогою kubectl наступним чином:
kubectl apply -f migrate-secret.yaml
Спостерігайте за міграцією Secret, перевіряючи
.status
обʼєкта StorageVersionMigration. Успішна міграція повинна мати умовуSucceeded
встановлену на true. Отримайте обʼєкт StorageVersionMigration наступним чином:kubectl get storageversionmigration.storagemigration.k8s.io/secrets-migration -o yaml
Вивід буде подібним до:
kind: StorageVersionMigration apiVersion: storagemigration.k8s.io/v1alpha1 metadata: name: secrets-migration uid: 628f6922-a9cb-4514-b076-12d3c178967c resourceVersion: "90" creationTimestamp: "2024-03-12T20:29:45Z" spec: resource: group: "" version: v1 resource: secrets status: conditions: - type: Running status: "False" lastUpdateTime: "2024-03-12T20:29:46Z" reason: StorageVersionMigrationInProgress - type: Succeeded status: "True" lastUpdateTime: "2024-03-12T20:29:46Z" reason: StorageVersionMigrationSucceeded resourceVersion: "84"
Перевірте збережений Secret тепер починається з
k8s:enc:aescbc:v1:key2
.
Оновлення бажаної схеми зберігання CRD
Розгляньте сценарій, де створено CustomResourceDefinition (CRD), щоб обслуговувати власні ресурси (CR), і встановлено як бажана схема сховища. Коли настане час ввести v2 CRD, його можна додати для обслуговування лише з вебхуком. Це дозволяє плавний перехід, де користувачі можуть створювати CR за допомогою схеми v1 або v2, з вкбхуком, що виконує необхідну конвертацію схеми між ними. Перш ніж встановити v2 як бажану версію схеми сховища, важливо переконатися, що всі наявні CR, збережені як v1, мігрували на v2. Ця міграція може бути досягнута через Storage Version Migration для міграції всіх CR від v1 до v2.
Створіть маніфест для CRD з назвою
test-crd.yaml
, наступного змісту:apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: selfierequests.stable.example.com spec: group: stable.example.com names: plural: SelfieRequests singular: SelfieRequest kind: SelfieRequest listKind: SelfieRequestList scope: Namespaced versions: - name: v1 served: true storage: true schema: openAPIV3Schema: type: object properties: hostPort: type: string conversion: strategy: Webhook webhook: clientConfig: url: "https://127.0.0.1:9443/crdconvert" caBundle: <Інформація про CA Bundle> conversionReviewVersions: - v1 - v2
Створіть CRD за допомогою kubectl:
kubectl apply -f test-crd.yaml
Створіть маніфест для прикладу testcrd. Назва маніфесту —
cr1.yaml
, з наступним змістом:apiVersion: stable.example.com/v1 kind: SelfieRequest metadata: name: cr1 namespace: default
Створіть CR за допомогою kubectl:
kubectl apply -f cr1.yaml
Перевірте, що CR записано і збережено як v1, отримавши обʼєкт з etcd.
ETCDCTL_API=3 etcdctl get /kubernetes.io/stable.example.com/testcrds/default/cr1 [...] | hexdump -C
де
[...]
містить додаткові аргументи для підключення до сервера etcd.Оновіть CRD
test-crd.yaml
, щоб додати версію v2 для обслуговування і сховища, а також v1 як обслуговування тільки, наступним чином:apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: selfierequests.stable.example.com spec: group: stable.example.com names: plural: SelfieRequests singular: SelfieRequest kind: SelfieRequest listKind: SelfieRequestList scope: Namespaced versions: - name: v2 served: true storage: true schema: openAPIV3Schema: type: object properties: host: type: string port: type: string - name: v1 served: true storage: false schema: openAPIV3Schema: type: object properties: hostPort: type: string conversion: strategy: Webhook webhook: clientConfig: url: "https://127.0.0.1:9443/crdconvert" caBundle: <Інформація про CA Bundle> conversionReviewVersions: - v1 - v2
Оновіть CRD за допомогою kubectl:
kubectl apply -f test-crd.yaml
Створіть файл ресурсу CR з назвою
cr2.yaml
наступного змісту:apiVersion: stable.example.com/v2 kind: SelfieRequest metadata: name: cr2 namespace: default
Створіть CR за допомогою kubectl:
kubectl apply -f cr2.yaml
Перевірте, що CR записано і збережено як v2, отримавши обʼєкт з etcd.
ETCDCTL_API=3 etcdctl get /kubernetes.io/stable.example.com/testcrds/default/cr2 [...] | hexdump -C
де
[...]
містить додаткові аргументи для підключення до сервера etcd.Створіть маніфест міграції версії сховища з назвою
migrate-crd.yaml
, з наступним
змістом:
kind: StorageVersionMigration
apiVersion: storagemigration.k8s.io/v1alpha1
metadata:
name: crdsvm
spec:
resource:
group: stable.example.com
version: v1
resource: SelfieRequest
Створіть обʼєкт за допомогою kubectl наступним чином:
kubectl apply -f migrate-crd.yaml
Спостерігайте за міграцією Secretʼів, використовуючи статус. Успішна міграція повинна мати умову
Succeeded
, встановлену на "True" у полі статусу. Отримайте ресурс міграції наступним чином:kubectl get storageversionmigration.storagemigration.k8s.io/crdsvm -o yaml
Виведення буде подібним до:
kind: StorageVersionMigration apiVersion: storagemigration.k8s.io/v1alpha1 metadata: name: crdsvm uid: 13062fe4-32d7-47cc-9528-5067fa0c6ac8 resourceVersion: "111" creationTimestamp: "2024-03-12T22:40:01Z" spec: resource: group: stable.example.com version: v1 resource: testcrds status: conditions: - type: Running status: "False" lastUpdateTime: "2024-03-12T22:40:03Z" reason: StorageVersionMigrationInProgress - type: Succeeded status: "True" lastUpdateTime: "2024-03-12T22:40:03Z" reason: StorageVersionMigrationSucceeded resourceVersion: "106"
Перевірте, що раніше створений cr1 тепер записано і збережено як v2, отримавши обʼєкт з etcd.
ETCDCTL_API=3 etcdctl get /kubernetes.io/stable.example.com/testcrds/default/cr1 [...] | hexdump -C
де
[...]
містить додаткові аргументи для підключення до сервера etcd.