Оновлення обʼєктів API на місці за допомогою kubectl patch

Використовуйте kubectl patch для оновлення обʼєктів Kubernetes API на місці. Виконайте стратегічний патч злиття або патч злиття JSON.

Це завдання показує, як використовувати 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, який ви можете встановити на одне з цих значень:

Значення параметраТип злиття
jsonJSON Patch, RFC 6902
mergeJSON 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, щоб змінити поточну конфігурацію обʼєкта Deployment. Ви не змінювали файл конфігурації, який ви спочатку використовували для створення обʼєкта Deployment. Інші команди для оновлення обʼєктів API включають kubectl annotate, kubectl edit, kubectl replace, kubectl scale, та kubectl apply.

Що далі

Змінено August 22, 2024 at 6:59 PM PST: upstream sync (b7f2b32b60)