# Декларативне керування обʼєктами Kubernetes з використанням конфігураційних файлів

LLMS index: [llms.txt](/llms.txt)

---

<!-- overview -->

Обʼєкти Kubernetes можна створювати, оновлювати та видаляти, зберігаючи декілька файлів конфігурації обʼєктів у теці та використовувати `kubectl apply` для рекурсивного створення та оновлення цих обʼєктів за потреби. Цей метод зберігає записи, зроблені у поточних обʼєктах, без злиття змін до файлів конфігурації обʼєкта. За допомогою `kubectl diff` також можна переглянути зміни, які буде внесено командою `apply`.

## Перш ніж ви розпочнете

Встановіть [`kubectl`](/docs/tasks/tools/).

<p>Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою <a href="https://minikube.sigs.k8s.io/docs/tutorials/multi_node/">minikube</a> або використовувати одну з цих пісочниць:</p>
<ul>
<li><a href="https://labs.iximiuz.com/playgrounds?category=kubernetes&filter=all">iximiuz Labs</a></li>
<li><a href="https://killercoda.com/playgrounds/scenario/kubernetes">Killercoda</a></li>
<li><a href="https://kodekloud.com/public-playgrounds">KodeKloud</a></li>
</ul>
 
  <p>Для перевірки версії введіть  <code>kubectl version</code>.</p>


<!-- steps -->

## Компроміси {#trade-offs}

Інструмент `kubectl` підтримує три види управління обʼєктами:

* Імперативні команди
* Імперативне конфігурування обʼєктів
* Декларативне конфігурування обʼєктів

Див. [Управління обʼєктами Kubernetes](/docs/concepts/overview/working-with-objects/object-management/) для обговорення переваг та недоліків кожного виду управління обʼєктами.

## Огляд {#overview}

Декларативна конфігурація обʼєктів потребує чіткого розуміння визначень та конфігурації обʼєктів Kubernetes. Прочитайте наступні документи, якщо ви ще цього не зробили:

* [Управління обʼєктами Kubernetes за допомогою імперативних команд](/docs/tasks/manage-kubernetes-objects/imperative-command/)
* [Імперативне управління обʼєктами Kubernetes за допомогою файлів конфігурації](/docs/tasks/manage-kubernetes-objects/imperative-config/)

Нижче подано визначення термінів, використаних у цьому документі:

* *файл конфігурації обʼєкта / файл конфігурації*: Файл, який визначає конфігурацію для обʼєкта Kubernetes. Ця тема показує, як передавати файли конфігурації до `kubectl apply`. Файли конфігурації зазвичай зберігаються у системі контролю версій, такі як Git.
* *поточна конфігурація обʼєкта / поточна конфігурація*: Поточні значення конфігурації обʼєкта, які використовуються кластером Kubernetes. Їх зберігають у сховищі кластера Kubernetes, зазвичай etcd.
* *декларативний записувач конфігурації / декларативний письменник*: Особа або компонент програмного забезпечення, який вносить оновлення до поточного обʼєкта. Поточні записувачі, на які посилається ця тема, вносять зміни до файлів конфігурації обʼєктів та запускають `kubectl apply` для запису змін.

## Як створити обʼєкти {#how-to-create-objects}

Використовуйте `kubectl apply`, щоб створити всі обʼєкти, за винятком тих, що вже існують, які визначені у конфігураційних файлах у вказаній теці:

```shell
kubectl apply -f <тека>
```

Це встановлює анотацію `kubectl.kubernetes.io/last-applied-configuration: '{...}'` для кожного обʼєкта. Анотація містить вміст файлу конфігурації обʼєкта, який був використаний для створення обʼєкта.


<div class="alert alert-info" role="note"><h4 class="alert-heading">Примітка:</h4>Додайте прапорець <code>-R</code>, щоб рекурсивно обробляти теки.</div>


Ось приклад файлу конфігурації обʼєкта:


















<div class="highlight code-sample">
    <div class="copy-code-icon">
    <a href="https://raw.githubusercontent.com/kubernetes/website/main/content/uk/examples/application/simple_deployment.yaml" download="application/simple_deployment.yaml"><code>application/simple_deployment.yaml</code>
    </a><img src="/images/copycode.svg" class="icon-copycode" onclick="copyCode('application-simple-deployment-yaml')" title="Копіювати application/simple_deployment.yaml до буферу обміну"></img></div>
    <div class="includecode" id="application-simple-deployment-yaml"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apps/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Deployment</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">nginx-deployment</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">selector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">matchLabels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">minReadySeconds</span><span class="p">:</span><span class="w"> </span><span class="m">5</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">template</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">containers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">nginx:1.14.2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">ports</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="m">80</span><span class="w">
</span></span></span></code></pre></div></div>
</div>

Запустіть `kubectl diff`, щоб показати обʼєкт, який буде створено:

```shell
kubectl diff -f https://k8s.io/examples/application/simple_deployment.yaml
```


<div class="alert alert-info" role="note"><h4 class="alert-heading">Примітка:</h4><p><code>diff</code> використовує <a href="/uk/docs/reference/using-api/api-concepts/#dry-run">запуск без внесення змін на сервері (dry-run)</a>, таку можливість потрібно ввімкнути на <code>kube-apiserver</code>.</p>
<p>Оскільки <code>diff</code> виконує запит на стороні сервера для застосування в режимі без внесення змін, для його роботи потрібно дозволити дії <code>PATCH</code>, <code>CREATE</code> та <code>UPDATE</code>. Детальніше див. <a href="/uk/docs/reference/using-api/api-concepts/#dry-run-authorization">Авторизація запуску dry-run</a>.</p>
</div>


Створіть обʼєкт за допомогою `kubectl apply`:

```shell
kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml
```

Виведіть поточну конфігурацію за допомогою `kubectl get`:

```shell
kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml
```

Вивід показує, що анотація `kubectl.kubernetes.io/last-applied-configuration` була записана до поточної конфігурації та відповідає конфігураційному файлу:

```yaml
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
        # ...
      # ...
    # ...
  # ...
```

## Як оновити обʼєкти {#how-to-update-objects}

Ви також можете використовувати `kubectl apply`, щоб оновити всі обʼєкти, визначені у теці, навіть якщо ці обʼєкти вже існують. Цей підхід виконує наступне:

1. Встановлює поля, що зʼявляються у файлі конфігурації, у поточній конфігурації.
2. Очищає поля, які були видалені з файлу конфігурації, у поточній конфігурації.

```shell
kubectl diff -f <тека>
kubectl apply -f <тека>
```


<div class="alert alert-info" role="note"><h4 class="alert-heading">Примітка:</h4>Додайте прапорець <code>-R</code>, щоб рекурсивно обробляти теки.</div>


Ось приклад конфігураційного файлу:


















<div class="highlight code-sample">
    <div class="copy-code-icon">
    <a href="https://raw.githubusercontent.com/kubernetes/website/main/content/uk/examples/application/simple_deployment.yaml" download="application/simple_deployment.yaml"><code>application/simple_deployment.yaml</code>
    </a><img src="/images/copycode.svg" class="icon-copycode" onclick="copyCode('application-simple-deployment-yaml')" title="Копіювати application/simple_deployment.yaml до буферу обміну"></img></div>
    <div class="includecode" id="application-simple-deployment-yaml"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apps/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Deployment</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">nginx-deployment</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">selector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">matchLabels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">minReadySeconds</span><span class="p">:</span><span class="w"> </span><span class="m">5</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">template</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">containers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">nginx:1.14.2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">ports</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="m">80</span><span class="w">
</span></span></span></code></pre></div></div>
</div>

Створіть обʼєкт за допомогою `kubectl apply`:

```shell
kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml
```


<div class="alert alert-info" role="note"><h4 class="alert-heading">Примітка:</h4>З метою ілюстрації, попередня команда посилається на один конфігураційний файл замість теки.</div>


Виведіть поточну конфігурацію за допомогою `kubectl get`:

```shell
kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml
```

Вивід показує, що анотація `kubectl.kubernetes.io/last-applied-configuration` була записана до поточної конфігурації та відповідає конфігураційному файлу:

```yaml
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`:

```shell
kubectl scale deployment/nginx-deployment --replicas=2
```

Виведіть поточну конфігурацію за допомогою `kubectl get`:

```shell
kubectl get deployment nginx-deployment -o yaml
```

Вивід показує, що поле `replicas` встановлено на 2, і анотація `last-applied-configuration`
не містить поле `replicas`:

```yaml
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`:


















<div class="highlight code-sample">
    <div class="copy-code-icon">
    <a href="https://raw.githubusercontent.com/kubernetes/website/main/content/uk/examples/application/update_deployment.yaml" download="application/update_deployment.yaml"><code>application/update_deployment.yaml</code>
    </a><img src="/images/copycode.svg" class="icon-copycode" onclick="copyCode('application-update-deployment-yaml')" title="Копіювати application/update_deployment.yaml до буферу обміну"></img></div>
    <div class="includecode" id="application-update-deployment-yaml"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apps/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Deployment</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">nginx-deployment</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">selector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">matchLabels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">template</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">containers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">nginx:1.16.1</span><span class="w"> </span><span class="c"># оновіть образ</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">ports</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="m">80</span><span class="w">
</span></span></span></code></pre></div></div>
</div>

Застосуйте зміни, внесені до конфігураційного файлу:

```shell
kubectl diff -f https://k8s.io/examples/application/update_deployment.yaml
kubectl apply -f https://k8s.io/examples/application/update_deployment.yaml
```

Виведіть поточну конфігурацію за допомогою `kubectl get`:

```shell
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`.

```yaml
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
      # ...
    # ...
  # ...
```

<div class="alert alert-danger" role="note"><h4 class="alert-heading">Попередження:</h4>Змішування <code>kubectl apply</code> з імперативними командами конфігурації обʼєктів <code>create</code> та <code>replace</code> не підтримується. Це через те, що <code>create</code> та <code>replace</code> не зберігають анотацію <code>kubectl.kubernetes.io/last-applied-configuration</code>, яку використовує <code>kubectl apply</code> для обробки оновлень.</div>


## Як видалити обʼєкти {#how-to-delete-objects}

Існують два підходи до видалення обʼєктів, керованих за допомогою `kubectl apply`.

### Рекомендований: `kubectl delete -f <filename>` {#recommended-kubectl-delete-f-filename}

Ручне видалення обʼєктів за допомогою імперативної команди є рекомендованим підходом, оскільки він більш явно вказує на те, що видаляється, і менш ймовірно призводить до випадкового видалення чогось:

```shell
kubectl delete -f <filename>
```

### Альтернатива: `kubectl apply -f <directory> --prune` {#alternative-kubectl-apply-f-directory-prune}

Як альтернативу `kubectl delete`, ви можете використовувати `kubectl apply` для ідентифікації обʼєктів, які мають бути видалені після видалення їх маніфестів з теки у локальній файловій системі.

У Kubernetes 1.36, доступні два режими очищення в `kubectl apply`:

* Очищення на основі allowlist: Цей режим існує з моменту kubectl v1.5, але все ще знаходиться на етапі альфа-тестування через проблеми з використанням, коректністю і продуктивністю його дизайну. Режим на основі ApplySet призначений для заміни його.
* Очищення на основі ApplySet: _apply set_ — це обʼєкт на стороні сервера (типово, Secret), який kubectl може використовувати для точного та ефективного відстеження членства в наборі під час операцій **apply**. Цей режим був введений у альфа-версії в kubectl v1.27 як заміна очищенню на основі allowlist.

<ul class="nav nav-tabs" id="tabs-kubectl-apply-prune" role="tablist"><li class="nav-item"><a data-bs-toggle="tab" class="nav-link active" href="#tabs-kubectl-apply-prune-0" role="tab" aria-controls="tabs-kubectl-apply-prune-0" aria-selected="true">Allow list</a></li>
	  
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-kubectl-apply-prune-1" role="tab" aria-controls="tabs-kubectl-apply-prune-1">Apply set</a></li></ul>

<div class="tab-content" id="tabs-kubectl-apply-prune-content"><div class="tab-body tab-pane fadeshow active"
        id="tabs-kubectl-apply-prune-0" role="tabpanel" aria-labelledby="tabs-kubectl-apply-prune-0-tab" tabindex="kubectl-apply-prune">  <div class="feature-state-notice feature-alpha">
      <span class="feature-state-name">СТАН ФУНКЦІОНАЛУ:</span>
      <code>Kubernetes v1.5 [alpha]</code>
    </div>
<div class="alert alert-danger" role="note"><h4 class="alert-heading">Попередження:</h4>Будьте обережні при використанні <code>--prune</code> з <code>kubectl apply</code> в режимі allow list. Те, які обʼєкти очищаються, залежить від значень прапорців <code>--prune-allowlist</code>, <code>--selector</code> та <code>--namespace</code>, і ґрунтується на динамічному виявленні обʼєктів, що підпадають під область застосування. Особливо, якщо значення прапорців змінюються між викликами, це може призвести до неочікуваного видалення або збереження обʼєктів.</div>
<p>Щоб використовувати очищення на основі allowlist, додайте наступні прапорці до свого виклику <code>kubectl apply</code>:</p>
<ul>
<li><code>--prune</code>: Видалити попередньо застосовані обʼєкти, які не є у наборі, що передані поточному виклику.</li>
<li><code>--prune-allowlist</code>: Список груп-версій-типів (GVK, group-version-kind), які розглядаються для очищення. Цей прапорець є необовʼязковим, але наполегливо рекомендується, оскільки його стандартне значення є частковим списком обʼєктів з просторами імен та областями застосування, що може призвести до несподіваних результатів.</li>
<li><code>--selector/-l</code>: Використовуйте селектор міток для обмеження набору обʼєктів, обраних для очищення. Цей прапорець є необовʼязковим, але наполегливо рекомендується.</li>
<li><code>--all</code>: використовуйте замість <code>--selector/-l</code>, щоб явно вибрати всі попередньо застосовані обʼєкти відповідних типів, які знаходяться у списку дозволених.</li>
</ul>
<p>Очищення на основі allowlist запитує API-сервер щодо всіх обʼєктів затверджених GVK, які відповідають заданим міткам (якщо є), і намагається зіставити конфігурації активних обʼєктів, отриманих в результаті, з файлами маніфестів обʼєктів. Якщо обʼєкт відповідає запиту і він не має маніфесту в теці, і має анотацію <code>kubectl.kubernetes.io/last-applied-configuration</code>, він видаляється.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">kubectl apply -f &lt;directory&gt; --prune -l &lt;labels&gt; --prune-allowlist<span class="o">=</span>&lt;gvk-list&gt;
</span></span></code></pre></div><div class="alert alert-danger" role="note"><h4 class="alert-heading">Попередження:</h4>Очищення з використанням <code>--prune</code> повинне бути виконане тільки для кореневої теки, що містить маніфести обʼєктів. Виконання для підтек може призвести до неочікуваного видалення обʼєктів, які раніше були застосовані, мають задані мітки (якщо є) і не зʼявляються у підтеці.</div>
</div><div class="tab-body tab-pane fade"
        id="tabs-kubectl-apply-prune-1" role="tabpanel" aria-labelledby="tabs-kubectl-apply-prune-1-tab" tabindex="kubectl-apply-prune">  <div class="feature-state-notice feature-alpha">
      <span class="feature-state-name">СТАН ФУНКЦІОНАЛУ:</span>
      <code>Kubernetes v1.27 [alpha]</code>
    </div>
<div class="alert alert-caution" role="note"><h4 class="alert-heading">Увага:</h4><code>kubectl apply --prune --applyset</code> знаходиться на етапі альфа-тестування, і в майбутніх випусках можуть бути внесені зміни, що несумісні з попередніми версіями.</div>
<p>Для використання очищення на основі ApplySet встановіть змінну середовища <code>KUBECTL_APPLYSET=true</code>, і додайте наступні прапорці до свого виклику <code>kubectl apply</code>:</p>
<ul>
<li><code>--prune</code>: Видалити попередньо застосовані обʼєкти, які не є у наборі, що передані поточному виклику.</li>
<li><code>--applyset</code>: Назва обʼєкта, який kubectl може використовувати для точного та ефективного відстеження членства в наборі під час операцій <strong>apply</strong>.</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nv">KUBECTL_APPLYSET</span><span class="o">=</span><span class="nb">true</span> kubectl apply -f &lt;directory&gt; --prune --applyset<span class="o">=</span>&lt;name&gt;
</span></span></code></pre></div><p>Типово тип батьківського обʼєкта ApplySet, що використовується, — Secret. Однак також можуть бути використані ConfigMaps у форматі: <code>--applyset=configmaps/&lt;name&gt;</code>. При використанні Secret або ConfigMap, kubectl створить обʼєкт, якщо він ще не існує.</p>
<p>Також можливе використання власних ресурсів як батьківських обʼєктів ApplySet. Для цього позначте міткою Custom Resource Definition (CRD), що визначає ресурс, який ви хочете використовувати з наступним: <code>applyset.kubernetes.io/is-parent-type: true</code>. Потім створіть обʼєкт, який ви хочете використовувати як батьківський обʼєкт ApplySet (kubectl цього не робить автоматично для Custom Resource). Нарешті, посилайтеся на цей обʼєкт у прапорці applyset таким чином: <code>--applyset=&lt;resource&gt;.&lt;group&gt;/&lt;name&gt;</code> (наприклад, <code>widgets.custom.example.com/widget-name</code>).</p>
<p>Під час очищення на основі ApplySet kubectl додає мітку <code>applyset.kubernetes.io/part-of=&lt;parentID&gt;</code> до кожного обʼєкта в наборі, перш ніж вони будуть надіслані на сервер. З метою продуктивності він також збирає список типів ресурсів і просторів імен, які включаються у набір, і додає ці дані в анотації поточного батьківського обʼєкта. В кінеці операції apply, він запитує API-сервер щодо обʼєктів цих типів в цих просторах імен (або в областях кластера, якщо це доречно), які належать до набору, визначеного міткою <code>applyset.kubernetes.io/part-of=&lt;parentID&gt;</code>.</p>
<p>Застереження та обмеження:</p>
<ul>
<li>Кожен обʼєкт може бути членом не більше одного набору.</li>
<li>Прапорець <code>--namespace</code> є обовʼязковим при використанні будь-якого обʼєкта з простором імен, включаючи типово Secret. Це означає, що ApplySets, які охоплюють кілька просторів імен, повинні використовувати кластерний обʼєкт з кореневою текою.</li>
<li>Щоб безпечно використовувати очищення на основі ApplySet з декількома теками, використовуйте унікальне імʼя ApplySet для кожного.</li>
</ul>
</div></div>


## Як переглянути обʼєкт {#how-to-view-objects}

Ви можете використовувати `kubectl get` з `-o yaml`, щоб переглянути конфігурацію поточного обʼєкта:

```shell
kubectl get -f <filename|url> -o yaml
```

## Як apply обчислює різницю та обʼєднує зміни {#how-apply-calculates-differences-and-merges-changes}

<div class="alert alert-caution" role="note"><h4 class="alert-heading">Увага:</h4><em>Патч (накладання латок)</em> — це операція оновлення, яка обмежена конкретними полями обʼєкта замість всього обʼєкта. Це дозволяє оновлювати лише певний набір полів обʼєкта без читання всього обʼєкта.</div>


Коли `kubectl apply` оновлює поточну конфігурацію обʼєкта, він робить це, надсилаючи запит на патч до API-сервера. Патч визначає оновлення для конкретних полів конфігурації живого обʼєкта. Команда `kubectl apply` обчислює цей запит на патч за допомогою файлу конфігурації, поточної конфігурації та анотації `last-applied-configuration`, збереженої в поточній конфігурації.

### Обчислення злиття патчів {#calculating-patch-merges}

Команда `kubectl apply` записує вміст файлу конфігурації до анотації `kubectl.kubernetes.io/last-applied-configuration`. Вона використовується для ідентифікації полів, які були видалені з файлу конфігурації та які потрібно видалити з поточної конфігурації. Ось кроки, які використовуються для обчислення того, які поля потрібно видалити або встановити:

1. Обчислити поля для видалення. Це поля, які присутні в `last-applied-configuration` та відсутні в файлі конфігурації.
2. Обчислити поля для додавання або встановлення. Це поля, які присутні в файлі конфігурації, значення яких не відповідають поточній конфігурації.

Ось приклад. Припустимо, що це файл конфігурації для обʼєкта типу Deployment:


















<div class="highlight code-sample">
    <div class="copy-code-icon">
    <a href="https://raw.githubusercontent.com/kubernetes/website/main/content/uk/examples/application/update_deployment.yaml" download="application/update_deployment.yaml"><code>application/update_deployment.yaml</code>
    </a><img src="/images/copycode.svg" class="icon-copycode" onclick="copyCode('application-update-deployment-yaml')" title="Копіювати application/update_deployment.yaml до буферу обміну"></img></div>
    <div class="includecode" id="application-update-deployment-yaml"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apps/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Deployment</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">nginx-deployment</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">selector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">matchLabels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">template</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">containers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">nginx:1.16.1</span><span class="w"> </span><span class="c"># оновіть образ</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">ports</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="m">80</span><span class="w">
</span></span></span></code></pre></div></div>
</div>

Також, припустимо, що це поточна конфігурація для того самого обʼєкта типу Deployment:

```yaml
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`:

1. Обчислення полів для видалення, отримуючи значення з `last-applied-configuration` і порівнюючи їх зі значеннями у файлі конфігурації. Очищення полів, які явно встановлені ​​на null у локальному файлі конфігурації обʼєкта, незалежно від того, чи вони зʼявляються в анотації `last-applied-configuration`. У цьому прикладі `minReadySeconds` зʼявляється в анотації `last-applied-configuration`, але не зʼявляється у файлі конфігурації. **Дія:** Прибрати `minReadySeconds` з поточної конфігурації.
2. Обчислення полів для встановлення, отримуючи значення з файлу конфігурації та порівнюючи їх зі значеннями у поточній конфігурації. У цьому прикладі значення `image` у файлі конфігурації не відповідає значенню у поточній конфігурації. **Дія:** Встановити значення `image` у поточній конфігурації.
3. Встановити анотацію `last-applied-configuration`, щоб вона відповідала значенню файлу конфігурації.
4. Обʼєднати результати з 1, 2, 3 у єдиний запит на патч до API-сервера.

Ось поточна конфігурація, яка є результатом злиття:

```yaml
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
        # ...
      # ...
    # ...
  # ...
```

### Як зливаються поля різних типів {#how-different-types-of-fields-are-merged}

Як певне поле в конфігураційному файлі зливається з поточною конфігурацією залежить від типу поля. Існують кілька типів полів:

* *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 {#merging-changes-to-primitive-fields}

Поля primitive замінюються або очищаються.


<div class="alert alert-info" role="note"><h4 class="alert-heading">Примітка:</h4><code>-</code> використовується для &quot;not applicable&quot;, оскільки значення не використовується.</div>


| Поле в конфігураційному файлі обʼєкта | Поле в поточній конфігурації обʼєкта | Поле в останній застосованій конфігурації | Дія                                          |
|----------------------------------------|-----------------------------------|-----------------------------------------|---------------------------------------------|
| Так                                    | Так                               | -                                       | Встановити поточне значення з конфігураційного файлу.  |
| Так                                    | Ні                                | -                                       | Встановити поточне значення з локального конфігураційного файлу. |
| Ні                                     | -                                 | Так                                     | Очистити з поточної конфігурації.             |
| Ні                                     | -                                 | Ні                                      | Нічого не робити. Зберегти значення поточного обʼєкта.   |

### Злиття змін у полях типу map {#merging-changes-to-map-fields}

Поля, які є map, зливаються шляхом порівняння кожного з підполів або елементів map:


<div class="alert alert-info" role="note"><h4 class="alert-heading">Примітка:</h4><code>-</code> використовується для &quot;not applicable&quot;, оскільки значення не використовується.</div>


| Ключ в конфігураційному файлі обʼєкта | Ключ у поточній конфігурації обʼєкта | Поле в останній застосованій конфігурації | Дія                                     |
|----------------------------------------|------------------------------------|--------------------------------------------|----------------------------------------|
| Так                                    | Так                                | -                                          | Порівняти значення підполів.          |
| Так                                    | Ні                                 | -                                          | Встановити поточне значення з локального конфігураційного файлу. |
| Ні                                     | -                                  | Так                                        | Видалити з поточної конфігурації.       |
| Ні                                     | -                                  | Ні                                         | Нічого не робити. Зберігти значення поточного обʼєкта. |

### Злиття змін для полів типу list {#merging-changes-for-fields-of-type-list}

Злиття змін у list використовує одну з трьох стратегій:

* Заміна list, якщо всі його елементи є primitive.
* Злиття окремих елементів у списку комплексних елементів.
* Злиття list елементів primitive.

Вибір стратегії залежить від конкретного поля.

#### Заміна list, якщо всі його елементи є primitive {#replace-the-list-if-all-its-elements-are-primitive}

Такий список трактується так само як і поле primitive. Замініть або видаліть
весь список. Це зберігає порядок.

**Приклад:** Використовуйте `kubectl apply`, щоб оновити поле `args` контейнера в Podʼі. Це встановлює значення `args` в поточній конфігурації на значення у файлі конфігурації. Будь-які елементи `args`, які раніше були додані до поточної конфігурації, втрачаються. Порядок елементів `args`, визначених у файлі конфігурації, зберігається у поточній конфігурації.

```yaml
# Значення last-applied-configuration
    args: ["a", "b"]

# Значення файлу конфігурації
    args: ["a", "c"]

# Поточна конфігурація
    args: ["a", "b", "d"]

# Результат після злиття
    args: ["a", "c"]
```

**Пояснення:** Злиття використовує значення файлу конфігурації як нове значення списку.

#### Злиття окремих елементів списку комлексних елементів: {#merging-individual-elements-of-a-list-of-complex-elements}

Трактуйте список як map, а конкретне поле кожного елемента як ключ. Додавайте, видаляйте або оновлюйте окремі елементи. Це не зберігає порядок.

Ця стратегія злиття використовує спеціальний теґ на кожному полі, який називається `patchMergeKey`. `patchMergeKey` визначено для кожного поля в коді Kubernetes: [types.go](https://github.com/kubernetes/api/blob/d04500c8c3dda9c980b668c57abc2ca61efcf5c4/core/v1/types.go#L2747) При злитті списку map, поле, вказане як `patchMergeKey` для певного елемента, використовується як ключ map для цього елемента.

**Приклад:** Використайте `kubectl apply`, щоб оновити поле `containers` у PodSpec. Це злиття списку, ніби він був map, де кожен елемент має ключ `name`.

```yaml
# Значення 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 {#merging-a-list-of-primitive-elements}

Зараз, починаючи з Kubernetes 1.5, злиття списків елементів типу primitive не підтримується.


<div class="alert alert-info" role="note"><h4 class="alert-heading">Примітка:</h4>Яка зі стратегій вище вибирається для певного поля контролюється теґом <code>patchStrategy</code> у <a href="https://github.com/kubernetes/api/blob/d04500c8c3dda9c980b668c57abc2ca61efcf5c4/core/v1/types.go#L2748">types.go</a>. Якщо для поля типу списку не вказано <code>patchStrategy</code>, тоді список замінюється.</div>




## Стандартні значення полів {#default-field-values}

Сервер API встановлює в певні поля стандартні значення у поточній конфігурації, якщо вони не вказані при створенні обʼєкта.

Ось файл конфігурації для обʼєкта Deployment. У файлі не вказано `strategy`:


















<div class="highlight code-sample">
    <div class="copy-code-icon">
    <a href="https://raw.githubusercontent.com/kubernetes/website/main/content/uk/examples/application/simple_deployment.yaml" download="application/simple_deployment.yaml"><code>application/simple_deployment.yaml</code>
    </a><img src="/images/copycode.svg" class="icon-copycode" onclick="copyCode('application-simple-deployment-yaml')" title="Копіювати application/simple_deployment.yaml до буферу обміну"></img></div>
    <div class="includecode" id="application-simple-deployment-yaml"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apps/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Deployment</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">nginx-deployment</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">selector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">matchLabels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">minReadySeconds</span><span class="p">:</span><span class="w"> </span><span class="m">5</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">template</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">containers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">nginx:1.14.2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">ports</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="m">80</span><span class="w">
</span></span></span></code></pre></div></div>
</div>

Створіть обʼєкт, використовуючи `kubectl apply`:

```shell
kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml
```

Виведіть поточну конфігурацію, використовуючи `kubectl get`:

```shell
kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml
```

Вивід показує, що сервер API встановив в деякі поля стандартні значення у поточній конфігурації. Ці поля не були вказані в файлі конфігурації.

```yaml
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
# ...
```

У запиті на патч, поля, які мають стандартні значення, не перезаписуються, якщо вони явно не очищені як частина запиту на патч. Це може призвести до неочікуваної поведінки для полів, які мають стандартні значення на основі значень інших полів. Після зміни інших полів значення, які мають стандартні значення з них, не будуть оновлені, якщо їх не явно очищено.

З цієї причини рекомендується, щоб певні поля, стандартні значення яких встановлює сервер, були явно визначені в файлі конфігурації обʼєкта, навіть якщо бажані значення відповідають стандартним значенням сервера. Це полегшить розпізнавання суперечливих значень, які не будуть перезаписані сервером на стандартні значення.

**Приклад:**

```yaml
# 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
```

**Пояснення:**

1. Користувач створює Deployment без визначення `strategy.type`.
2. Сервер встановлює стандартне значення для `strategy.type` на `RollingUpdate` та стандартне значення для `strategy.rollingUpdate`.
3. Користувач змінює `strategy.type` на `Recreate`. Значення `strategy.rollingUpdate` залишаються стандартними значеннями, хоча сервер очікує, що вони будуть очищені. Якщо значення `strategy.rollingUpdate` були визначені спочатку в файлі конфігурації, було б більш зрозуміло, що їх потрібно було б видалити.
4. Оновлення не вдається через те, що `strategy.rollingUpdate` не очищено. Поле `strategy.rollingupdate` не може бути визначено з `strategy.type` `Recreate`.

Рекомендація: Ці поля слід явно визначити в файлі конфігурації обʼєкта:

* Селектори та мітки PodTemplate для робочих навантажень, таких як Deployment, StatefulSet, Job, DaemonSet, ReplicaSet та ReplicationController.
* Стратегія розгортання Deployment.

### Як очистити стандартні поля встановлені сервером або поля, встановлені іншими записувачами {#how-to-clear-server-defaulted-fields-or-fields-set-by-other-writers}

Поля, які не зʼявляються у файлі конфігурації, можна очистити, встановивши їх значення в `null`, а потім застосувати файл конфігурації. Для полів, стандартні значення яких встановлено сервером, це спричинить перезапис цих значень.

## Як змінити власника поля між файлом конфігурації та прямими імперативними записувачами {#how-to-change-ownership-of-a-field-between-the-configuration-file-and-direct-imperative-writers}

Ці методи — єдиний вірний спосіб змінювати окреме поле обʼєкта:

* Використовуйте `kubectl apply`.
* Пишіть безпосередньо в поточну конфігурацію без змін файлу конфігурації: наприклад, використовуйте `kubectl scale`.

### Зміна власника з прямого імперативного записувача на файл конфігурації {#changing-the-owner-from-direct-imperative-writer-to-a-configuration-file}

Додайте поле до файлу конфігурації. Для цього поля припиніть прямі оновлення поточної конфігурації, які не проходять через `kubectl apply`.

### Зміна власника з файлу конфігурації на безпосереднього імперативного записувача {#changing-the-owner-from-a-configuration-file-to-a-direct-imperative-writer}

Починаючи з Kubernetes 1.5, зміна власника поля з файлу конфігурації на імперативного запусувача вимагає виконання наступних кроків:

* Видаліть поле з файлу конфігурації.
* Видаліть поле з анотації `kubectl.kubernetes.io/last-applied-configuration` на поточному обʼєкті.

## Зміна методів управління {#changing-management-methods}

Обʼєктами Kubernetes слід керувати за допомогою лише одного методу одночасно. Перехід з одного методу на інший можливий, але це вимагає ручної обробки.


<div class="alert alert-info" role="note"><h4 class="alert-heading">Примітка:</h4>Використання імперативного видалення з декларативним управлінням є прийнятним.</div>




### Міграція з управління імперативними командами до декларативної конфігурації обʼєктів {#migrating-from-imperative-command-management-to-declarative-object-configuration}

Міграція з управління імперативними командами до декларативної конфігурації обʼєктів включає кілька ручних кроків:

1. Експортуйте поточний обʼєкт у локальний файл конфігурації:

   ```shell
   kubectl get <kind>/<name> -o yaml > <kind>_<name>.yaml
   ```

1. Видаліть вручну поле `status` з файлу конфігурації.

   
<div class="alert alert-info" role="note"><h4 class="alert-heading">Примітка:</h4>Цей крок є необовʼязковим, оскільки <code>kubectl apply</code> не оновлює поле статусу, навіть якщо воно присутнє у файлі конфігурації.</div>


1. Встановіть анотацію `kubectl.kubernetes.io/last-applied-configuration` на обʼєкті:

   ```shell
   kubectl replace --save-config -f <kind>_<name>.yaml
   ```

1. Змініть процеси так, щоб вони використовували виключно `kubectl apply` для керування обʼєктом.



### Міграція з імперативної конфігурації обʼєктів до декларативної конфігурації обʼєктів {#migrating-from-imperative-object-configuration-to-declarative-object-configuration}

1. Встановіть анотацію `kubectl.kubernetes.io/last-applied-configuration` на обʼєкті:

   ```shell
   kubectl replace --save-config -f <kind>_<name>.yaml
   ```

1. Змініть процеси так, щоб використовували `kubectl apply` виключно для керування обʼєктом.

## Визначення селекторів контролера та міток PodTemplate {#defining-controller-selectors-and-podtemplate-labels}

<div class="alert alert-danger" role="note"><h4 class="alert-heading">Попередження:</h4>Рекомендується утриматися від оновлення селекторів на контролерах.</div>


Рекомендований підхід — це визначення єдиного, незмінного підпису PodTemplate, який використовується тільки селектором контролера без іншого семантичного значення.

**Приклад:**

```yaml
selector:
  matchLabels:
      controller-selector: "apps/v1/deployment/nginx"
template:
  metadata:
    labels:
      controller-selector: "apps/v1/deployment/nginx"
```

## Що далі

* [Керування обʼєктами Kubernetes за допомогою імперативних команд](/docs/tasks/manage-kubernetes-objects/imperative-command/)
* [Імперативне керування обʼєктами Kubernetes за допомогою конфігураційних файлів](/docs/tasks/manage-kubernetes-objects/imperative-config/)
* [Довідник команд kubectl](/docs/reference/generated/kubectl/kubectl-commands/)
* [Довідник API Kubernetes](/docs/reference/generated/kubernetes-api/v1.36/)
