Оновлення обʼєктів 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.