# Шифрування конфіденційних даних у спокої

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

---

<!-- overview -->

Усі API в Kubernetes, які дозволяють записувати постійні дані ресурсів API, підтримують шифрування у спокої. Наприклад, ви можете увімкнути шифрування у спокої для <a class='glossary-tooltip' title='Зберігає конфіденційну інформацію, таку як паролі, токени OAuth та ключі SSH.' data-bs-toggle='tooltip' data-bs-placement='top' href='/uk/docs/concepts/configuration/secret/' target='_blank' aria-label='Secret'>Secret</a>. Це шифрування у спокої є додатковим до будь-якого шифрування на рівні системи для кластера etcd або для файлових систем на вузлах, де ви запускаєте kube-apiserver.

На цій сторінці показано, як увімкнути та налаштувати шифрування даних API у спокої.


<div class="alert alert-info" role="note"><h4 class="alert-heading">Примітка:</h4><p>Це завдання охоплює шифрування даних ресурсів, збережених за допомогою <a class='glossary-tooltip' title='Застосунок, який обслуговує функціонал Kubernetes через RESTful інтерфейс та зберігає стан кластера.' data-bs-toggle='tooltip' data-bs-placement='top' href='/uk/docs/concepts/overview/kubernetes-api/' target='_blank' aria-label='Kubernetes API'>Kubernetes API</a>. Наприклад, ви можете шифрувати обʼєкти Secret, включаючи дані у формі ключ-значення.</p>
<p>Якщо ви хочете зашифрувати дані в файлових системах, які підключаються до контейнерів, вам замість цього потрібно або:</p>
<ul>
<li>використовуйте інтеграцію зберігання, яка забезпечує шифровані <a class='glossary-tooltip' title='Тека, що містить дані та доступна для контейнерів у Podʼі.' data-bs-toggle='tooltip' data-bs-placement='top' href='/uk/docs/concepts/storage/volumes/' target='_blank' aria-label='томи'>томи</a></li>
<li>шифрувати дані всередині вашого власного застосунку</li>
</ul>
</div>


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

- <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>


- Це завдання передбачає, що ви запускаєте сервер API Kubernetes як <a class='glossary-tooltip' title='Pod, яким управляє безпосередньо демон kubelet на певному вузлі.' data-bs-toggle='tooltip' data-bs-placement='top' href='/uk/docs/tasks/configure-pod-container/static-pod/' target='_blank' aria-label='статичний Pod'>статичний Pod</a> на кожному вузлі панелі управління.

- Панель управління кластера **обовʼязково** має використовувати etcd версії 3.x (головна версія 3, будь-яка мінорна версія).

- Для шифрування власного ресурсу ваш кластер повинен працювати на Kubernetes v1.26 або новіше.

- Щоб використовувати символ підстановки для відповідності ресурсів, ваш кластер повинен працювати на Kubernetes v1.27 або новіше.


 <p>Для перевірки версії введіть  <code>kubectl version</code>.</p>


<!-- steps -->

## Визначте, чи вже увімкнено шифрування у спокої {#determining-whether-encryption-at-rest-is-already-enabled}

Стандартно, сервер API зберігає текстові представлення ресурсів у etcd без шифрування у спокої.

Процес `kube-apiserver` приймає аргумент `--encryption-provider-config`, який вказує шлях до конфігураційного файлу. Зміст цього файлу, якщо ви його вказали, контролює спосіб шифрування даних API Kubernetes у etcd. Якщо ви запускаєте kube-apiserver без аргументу командного рядка `--encryption-provider-config`, то у вас немає увімкненого шифрування у спокої. Якщо ви запускаєте kube-apiserver з аргументом командного рядка `--encryption-provider-config`, і файл, на який він посилається, вказує на постачальника шифрування `identity` як першого постачальника шифрування у списку, то у вас немає увімкненого шифрування у спокої (**типовий постачальник `identity` не надає захисту конфіденційності.**)

Якщо ви запускаєте kube-apiserver з аргументом командного рядка `--encryption-provider-config`, і файл, на який він посилається, вказує на іншого постачальника, а не `identity`, як першого постачальника шифрування у списку, то ви вже маєте увімкнене шифрування у спокої. Однак ця перевірка не показує, чи вдалася попередня міграція до зашифрованого сховища. Якщо ви не впевнені, [переконайтеся, що всі відповідні дані зашифровані](#ensure-all-secrets-are-encrypted).

## Розуміння конфігурації шифрування у спокої {#understanding-the-encryption-at-rest-configuration}

<!-- note to localizers: the highlight is to make the initial comment obvious -->
<!-- you can use as many lines as makes sense for your target localization    -->

<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="c">#</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="c"># УВАГА: це приклад конфігурації.</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="c"># Не використовуйте його для вашого кластера!</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="c">#</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apiserver.config.k8s.io/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">EncryptionConfiguration</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">resources</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">resources</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">secrets</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">configmaps</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">pandas.awesome.bears.example</span><span class="w"> </span><span class="c"># a custom resource API</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">providers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><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="c"># налаштований постачальник вказує механізм &#34;identity&#34;, який</span><span class="w">
</span></span></span><span class="line"><span class="cl"><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="c">#</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">identity</span><span class="p">:</span><span class="w"> </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">aesgcm</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">keys</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">key1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">secret</span><span class="p">:</span><span class="w"> </span><span class="l">c2VjcmV0IGlzIHNlY3VyZQ==</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">key2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">secret</span><span class="p">:</span><span class="w"> </span><span class="l">dGhpcyBpcyBwYXNzd29yZA==</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">aescbc</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">keys</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">key1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">secret</span><span class="p">:</span><span class="w"> </span><span class="l">c2VjcmV0IGlzIHNlY3VyZQ==</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">key2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">secret</span><span class="p">:</span><span class="w"> </span><span class="l">dGhpcyBpcyBwYXNzd29yZA==</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">secretbox</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">keys</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">key1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">secret</span><span class="p">:</span><span class="w"> </span><span class="l">YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">resources</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">events</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">providers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">identity</span><span class="p">:</span><span class="w"> </span>{}<span class="w"> </span><span class="c"># не шифрувати Events навіть якщо *.* вказаний нижче</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">resources</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s1">&#39;*.apps&#39;</span><span class="w"> </span><span class="c"># використання символу підстановки потребує Kubernetes 1.27 або пізніше</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">providers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">aescbc</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">keys</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">key2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">secret</span><span class="p">:</span><span class="w"> </span><span class="l">c2VjcmV0IGlzIHNlY3VyZSwgb3IgaXMgaXQ/Cg==</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">resources</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s1">&#39;*.*&#39;</span><span class="w"> </span><span class="c"># використання символу підстановки потребує Kubernetes 1.27 або пізніше</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">providers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">aescbc</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">keys</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">key3</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">secret</span><span class="p">:</span><span class="w"> </span><span class="l">c2VjcmV0IGlzIHNlY3VyZSwgSSB0aGluaw==</span></span></span></code></pre></div>

Кожен елемент масиву `resources` — це окрема конфігурація і містить повну конфігурацію. Поле `resources.resources` — це масив імен ресурсів Kubernetes (`resource` або `resource.group`), які мають бути зашифровані, наприклад, Secrets, ConfigMaps або інші ресурси.

Якщо ви додаєте власні ресурси до `EncryptionConfiguration`, і версія кластера — 1.26 або новіша, то будь-які нові створені власні ресурси, зазначені в `EncryptionConfiguration`, будуть зашифровані. Будь-які власні ресурси, які існували в etcd до цієї версії та конфігурації, залишаться незашифрованими до тих пір, поки вони наступного разу не будуть записані у сховище. Така ж поведінка застосовується й до вбудованих ресурсів. Дивіться розділ [Переконайтеся, що всі секрети зашифровані](#ensure-all-secrets-are-encrypted).

Масив `providers` — це упорядкований список можливих постачальників шифрування, які можна використовувати для перелічених вами API. Кожен постачальник підтримує кілька ключів — ключі перевіряються по черзі для розшифрування, і якщо постачальник є першим, перший ключ використовується для шифрування.

Для кожного елементу може бути вказано лише один тип постачальника (`identity` або `aescbc` може бути наданий, але не обидва в одному елементі). Перший постачальник у списку використовується для шифрування ресурсів, записаних у сховище. При читанні ресурсів зі сховища кожен постачальник, який відповідає збереженим даним, намагається по черзі розшифрувати дані. Якщо жоден постачальник не може прочитати збережені дані через несумісність формату або секретного ключа, повертається помилка, яка перешкоджає клієнтам отримати доступ до цього ресурсу.

`EncryptionConfiguration` підтримує використання символів підстановки для вказівки ресурсів, які мають бути зашифровані. Використовуйте '`*.<group>`', щоб зашифрувати всі ресурси у групі (наприклад, '`*.apps`' у вищезазначеному прикладі) або '`*.*`' для шифрування всіх ресурсів. '`*.`' може бути використаний для шифрування всіх ресурсів у групі ядра. '`*.*`' зашифрує всі ресурси, навіть власні ресурси, які додаються після запуску сервера API.


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


Якщо у вас є символ підстановки, який охоплює ресурси, і ви хочете відмовитися від шифрування у спокої певного типу ресурсу, ви можете досягати цього, додавши окремий елемент масиву `resources` з іменем ресурсу, який ви хочете виключити, за яким слідує елемент масиву `providers`, де ви вказуєте постачальника `identity`. Ви додаєте цей елемент до списку так, щоб він зʼявився раніше, ніж конфігурація, де ви вказуєте шифрування (постачальник, який не є `identity`).

Наприклад, якщо ввімкнено '`*.*`', і ви хочете відмовитися від шифрування для Events та ConfigMaps, додайте новий **раніший** елемент до `resources`, за яким слідує елемент масиву постачальників з `identity` як постачальник. Більш конкретний запис повинен зʼявитися перед записом з символом підстановки.

Новий елемент буде схожий на:

```yaml
  ...
  - resources:
      - configmaps. # спеціально з ядра API групи,
                    # через крапку в кінці
      - events
    providers:
      - identity: {}
  # а потім інші записи в resources
```

Переконайтеся, що виключення перераховане _до_ позначки символу підстановки '`*.*`' в масиві ресурсів, щоб надати йому пріоритет.

Для отримання більш детальної інформації про структуру `EncryptionConfiguration`, зверніться до [API конфігурації шифрування](/docs/reference/config-api/apiserver-config.v1/).

<div class="alert alert-caution" role="note"><h4 class="alert-heading">Увага:</h4><p>Якщо будь-який ресурс не може бути прочитаний через конфігурацію шифрування (через зміну ключів) та ви не можете відновити робочу конфігурацію, єдиним виходом буде видалити цей ключ безпосередньо з підтримуваного etcd.</p>
<p>Будь-які виклики до API Kubernetes, які намагаються прочитати цей ресурс, завершаться невдачею, поки він не буде видалений або надано дійсний ключ для розшифрування.</p>
</div>


### Доступні постачальники {#providers}

Перш ніж налаштувати шифрування у спокої для даних у Kubernetes API вашого кластера, вам потрібно вибрати, які постачальники ви будете використовувати.

Наступна таблиця описує кожного доступного постачальника.

<table class="complex-layout">
<caption style="display: none;">Постачальники для шифрування у спокої Kubernetes</caption>
<thead>
  <tr>
  <th>Назва</th>
  <th>Шифрування</th>
  <th>Стійкість</th>
  <th>Швидкість</th>
  <th>Довжина ключа</th>
  </tr>
</thead>
<tbody id="encryption-providers-identity">
  <!-- list identity first, even when the remaining rows are sorted alphabetically -->
  <tr>
  <th rowspan="2" scope="row"><tt>identity</tt></th>
  <td><strong>Відсутнє</strong></td>
  <td>Н/Д</td>
  <td>Н/Д</td>
  <td>Н/Д</td>
  </tr>
  <tr>
  <td colspan="4">Ресурси зберігаються як є без шифрування. Коли встановлено як перший постачальник, ресурс буде розшифрований при записі нових значень. Існуючі зашифровані ресурси автоматично <strong>не</strong> перезаписуються даними у відкритому тексті. Постачальник `identity` є типовим, якщо ви не вказали інше.</td>
  </tr>
</tbody>
<tbody id="encryption-providers-that-encrypt">
  <tr>
  <th rowspan="2" scope="row"><tt>aescbc</tt></th>
  <td>AES-CBC з використанням <a href="https://datatracker.ietf.org/doc/html/rfc2315">padding PKCS#7</a></td>
  <td>Слабка</td>
  <td>Швидка</td>
  <td>16, 24 або 32 байти</td>
  </tr>
  <tr>
  <td colspan="4">Не рекомендується через вразливість CBC до атаки padding oracle attacks. Вміст ключа доступний з хоста панелі управління.</td>
  </tr>
  <tr>
  <th rowspan="2" scope="row"><tt>aesgcm</tt></th>
  <td>AES-GCM з випадковим нонсом</td>
  <td>Потрібно оновлювати через кожні 200,000 записів</td>
  <td>Найшвидший</td>
  <td>16, 24 або 32 байти</td>
  </tr>
  <tr>
  <td colspan="4">Не рекомендується для використання, крім як у випадку, коли реалізована автоматизована схема оновлення ключів. Вміст ключа доступний з хоста панелі управління.</td>
  </tr>
  <tr>
  <th rowspan="2" scope="row"><tt>kms</tt> v1 <em>(застарілий з Kubernetes v1.28)</em></th>
  <td>Використовує схему шифрування конвертів із DEK для кожного ресурсу.</td>
  <td>Найміцніший</td>
  <td>Повільний (<em>порівняно з <tt>kms</tt> версією 2</em>)</td>
  <td>32 байти</td>
  </tr>
  <tr>
  <td colspan="4">
    Дані шифруються за допомогою ключів шифрування даних (DEK) з використанням AES-GCM;
    DEK шифруються ключами шифрування ключів (KEKs) згідно з
    конфігурацією в Службі управління ключами (KMS).
    Просте оновлення ключа, з новим DEK, що генерується для кожного шифрування, та
    оновлення KEK, контрольоване користувачем.
    <br />
    Прочитайте, як <a href="/uk/docs/tasks/administer-cluster/kms-provider#configuring-the-kms-provider-kms-v1">налаштувати постачальника KMS V1</a>.
    </td>
  </tr>
  <tr>
  <th rowspan="2" scope="row"><tt>kms</tt> v2 </th>
  <td>Використовує схему шифрування конвертів із DEK для кожного сервера API.</td>
  <td>Найміцніший</td>
  <td>Швидкий</td>
  <td>32 байти</td>
  </tr>
  <tr>
  <td colspan="4">
    Дані шифруються за допомогою ключів шифрування даних (DEKs) з використанням AES-GCM; DEKs
    шифруються ключами шифрування ключів (KEKs) згідно з конфігурацією
    в Службі управління ключами (KMS).
    Kubernetes генерує новий DEK для кожного шифрування з секретного насіння.
    Насіння змінюється кожного разу, коли змінюється KEK.<br/>
    Добрий вибір, якщо використовується сторонній інструмент для управління ключами.
    Доступний як стабільний з Kubernetes v1.29.
    <br />
    Прочитайте, як <a href="/uk/docs/tasks/administer-cluster/kms-provider#configuring-the-kms-provider-kms-v2">налаштувати постачальника KMS V2</a>.
    </td>
  </tr>
  <tr>
  <th rowspan="2" scope="row"><tt>secretbox</tt></th>
  <td>XSalsa20 і Poly1305</td>
  <td>Найміцніший</td>
  <td>Швидший</td>
  <td>32 байти</td>
  </tr>
  <tr>
  <td colspan="4">Використовує відносно нові технології шифрування, які можуть не бути прийнятними в середовищах, які вимагають високого рівня перегляду. Вміст ключа доступний з хоста панелі управління.</td>
  </tr>
</tbody>
</table>

Постачальник `identity` є типовим, якщо ви не вказали інше. **Постачальник `identity` не шифрує збережені дані та не надає _жодного_ додаткового захисту конфіденційності.**

### Зберігання ключів {#key-storage}

#### Локальне зберігання ключів {#local-key-storage}

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

#### Зберігання ключів сервісом KMS {#kms-key-storage}

Постачальник KMS використовує _шифрування конвертів_: Kubernetes шифрує ресурси за допомогою ключа даних, а потім шифрує цей ключ даних за допомогою служби керування шифруванням. Kubernetes генерує унікальний ключ даних для кожного ресурсу. API-сервер зберігає зашифровану версію ключа даних в etcd поряд із шифротекстом; при читанні ресурсу API-сервер викликає служби керування шифруванням і надає як шифротекст, так і (зашифрований) ключ даних. У межах служби керування шифруванням, постачальник використовує _ключ шифрування ключа_, щоб розшифрувати ключ даних, розшифровує ключ даних і, нарешті, відновлює звичайний текст. Комунікація між панеллю управління та KMS вимагає захисту під час передачі, такого як TLS.

Використання шифрування конвертів створює залежність від ключа шифрування ключа, який не зберігається в Kubernetes. У випадку KMS зловмиснику, який намагається отримати несанкціонований доступ до значень у відкритому тексті, необхідно скомпрометувати etcd **та** стороннього постачальника KMS.

### Захист для ключів шифрування {#protecting-encryption-keys}

Вам слід прийняти належні заходи для захисту конфіденційної інформації, що дозволяє розшифрування, чи то це локальний ключ шифрування, чи то токен автентифікації, який дозволяє API-серверу викликати KMS.

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

### Зашифруйте ваші дані {#encrypting-your-data}

### Згенеруйте ключ шифрування {#generate-key-no-kms}

Наступні кроки передбачають, що ви не використовуєте KMS, тому кроки також передбачають, що вам потрібно згенерувати ключ шифрування. Якщо у вас вже є ключ шифрування, перейдіть до [Написання файлу конфігурації шифрування](#write-an-encryption-configuration-file).

<div class="alert alert-caution" role="note"><h4 class="alert-heading">Увага:</h4><p>Зберігання сирого ключа шифрування у конфігурації шифрування забезпечує помірний рівень безпеки, порівняно з відсутністю шифрування.</p>
<p>Для додаткової секретності розгляньте використання постачальника <code>kms</code>, оскільки це ґрунтується на ключах, що зберігаються поза вашим кластером Kubernetes. Реалізації <code>kms</code> можуть працювати з модулями апаратного забезпечення для збереження ключів або з службами шифрування, які керуються вашим постачальником хмарних послуг.</p>
<p>Щоб дізнатися, як налаштувати шифрування в стані спокою з використанням KMS, див. <a href="/uk/docs/tasks/administer-cluster/kms-provider/">Використання постачальника KMS для шифрування даних</a>. Втулок постачальника KMS, який ви використовуєте, також може постачатися з додатковою конкретною документацією.</p>
</div>


Розпочніть з генерації нового ключа шифрування, а потім закодуйте його за допомогою base64:

<ul class="nav nav-tabs" id="tabs-generate-encryption-key" role="tablist"><li class="nav-item"><a data-bs-toggle="tab" class="nav-link active" href="#tabs-generate-encryption-key-0" role="tab" aria-controls="tabs-generate-encryption-key-0" aria-selected="true">Linux</a></li>
	  
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-generate-encryption-key-1" role="tab" aria-controls="tabs-generate-encryption-key-1">macOS</a></li>
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-generate-encryption-key-2" role="tab" aria-controls="tabs-generate-encryption-key-2">Windows</a></li></ul>

<div class="tab-content" id="tabs-generate-encryption-key-content"><div class="tab-body tab-pane fadeshow active"
        id="tabs-generate-encryption-key-0" role="tabpanel" aria-labelledby="tabs-generate-encryption-key-0-tab" tabindex="generate-encryption-key"><p>Згенеруйте випадковий ключ з 32 байтів і закодуйте його у форматі base64. Ви можете використовувати цю команду:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">head -c <span class="m">32</span> /dev/urandom <span class="p">|</span> base64
</span></span></code></pre></div><p>Ви можете використовувати <code>/dev/hwrng</code> замість <code>/dev/urandom</code>, якщо ви хочете використовувати вбудований апаратний генератор ентропії вашого ПК. Не всі пристрої з Linux надають апаратний генератор випадкових чисел.</p>
</div><div class="tab-body tab-pane fade"
        id="tabs-generate-encryption-key-1" role="tabpanel" aria-labelledby="tabs-generate-encryption-key-1-tab" tabindex="generate-encryption-key"><!-- localization note: this is similar to the Linux tab and the wording
should match wherever the English text does -->
<p>Згенеруйте випадковий ключ з 32 байтів і закодуйте його у форматі base64. Ви можете використовувати цю команду:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">head -c <span class="m">32</span> /dev/urandom <span class="p">|</span> base64
</span></span></code></pre></div></div><div class="tab-body tab-pane fade"
        id="tabs-generate-encryption-key-2" role="tabpanel" aria-labelledby="tabs-generate-encryption-key-2-tab" tabindex="generate-encryption-key"><p>Згенеруйте випадковий ключ з 32 байтів і закодуйте його у форматі base64. Ви можете використовувати цю команду:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># Не запускайте це в сесії, де ви встановили насіння генератора випадкових чисел.</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="no">Convert</span><span class="p">]::</span><span class="n">ToBase64String</span><span class="p">((</span><span class="mf">1</span><span class="p">.</span><span class="mf">.32</span><span class="p">|%{[</span><span class="no">byte</span><span class="p">](</span><span class="nb">Get-Random</span> <span class="n">-Max</span> <span class="mf">256</span><span class="p">)}))</span>
</span></span></code></pre></div></div></div>



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


### Реплікація ключа шифрування {#replicate-the-encryption-key}

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

Як мінімум використовуйте шифрування під час передачі даних — наприклад, захищену оболонку (SSH). Для більшої безпеки використовуйте асиметричне шифрування між вузлами або змініть підхід, який ви використовуєте, щоб ви покладалися на шифрування KMS.

### Створіть файл конфігурації шифрування {#write-an-encryption-configuration-file}

<div class="alert alert-caution" role="note"><h4 class="alert-heading">Увага:</h4>Файл конфігурації шифрування може містити ключі, які можуть розшифрувати вміст в etcd. Якщо файл конфігурації містить будь-який вміст ключа, вам слід належним чином обмежити дозволи на всіх ваших вузлах керування так, щоб лише користувач, який запускає kube-apiserver, міг читати цю конфігурацію.</div>


Створіть новий файл конфігурації шифрування. Зміст повинен бути подібним до:

```yaml
---
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
      - configmaps
      - pandas.awesome.bears.example
    providers:
      - aescbc:
          keys:
            - name: key1
              # Див. наступний текст для отримання додаткової інформації про секретне значення
              secret: <BASE 64 ENCODED SECRET>
      - identity: {} # цей резервний варіант дозволяє читати незашифровані секрети;
                     # наприклад, під час початкової міграції
```

Щоб створити новий ключ шифрування (який не використовує KMS), див. [Згенеруйте ключ шифрування](#generate-key-no-kms).

### Використовуйте новий файл конфігурації шифрування {#use-the-new-encryption-configuration-file}

Вам потрібно буде приєднати новий файл конфігурації шифрування до статичного Podʼа `kube-apiserver`. Ось приклад того, як це зробити:

1. Збережіть новий файл конфігурації шифрування у `/etc/kubernetes/enc/enc.yaml` на вузлі панелі управління.
1. Відредагуйте маніфест для статичного Podʼа `kube-apiserver`: `/etc/kubernetes/manifests/kube-apiserver.yaml`, щоб він був подібний до:

   ```yaml
   ---
   #
   # Це фрагмент маніфеста для статичного Podʼа.
   # Перевірте, чи це правильно для вашого кластера та для вашого API-сервера.
   #
   apiVersion: v1
   kind: Pod
   metadata:
     annotations:
       kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 10.20.30.40:443
     creationTimestamp: null
     labels:
       app.kubernetes.io/component: kube-apiserver
       tier: control-plane
     name: kube-apiserver
     namespace: kube-system
   spec:
     containers:
     - command:
       - kube-apiserver
       ...
       - --encryption-provider-config=/etc/kubernetes/enc/enc.yaml  # додайте цей рядок
       volumeMounts:
       ...
       - name: enc                           # додайте цей рядок
         mountPath: /etc/kubernetes/enc      # додайте цей рядок
         readOnly: true                      # додайте цей рядок
       ...
     volumes:
     ...
     - name: enc                             # додайте цей рядок
       hostPath:                             # додайте цей рядок
         path: /etc/kubernetes/enc           # додайте цей рядок
         type: DirectoryOrCreate             # додайте цей рядок
     ...
   ```

1. Перезапустіть свій API-сервер.

<div class="alert alert-caution" role="note"><h4 class="alert-heading">Увага:</h4>Ваш файл конфігурації містить ключі, які можуть розшифрувати вміст в etcd, тому вам слід належним чином обмежити дозволи на вузлах керування так, щоб лише користувач, який запускає <code>kube-apiserver</code>, міг читати його.</div>


Тепер у вас є шифрування для **одного** вузла панелі управління. У типовому кластері Kubernetes є кілька вузлів керування, тому зробіть це на інших вузлах.

### Переконфігуруйте інші вузли керування {#api-server-config-update-more}

Якщо у вашому кластері є кілька API-серверів, вам слід розгорнути зміни по черзі на кожному API-сервері.

<div class="alert alert-caution" role="note"><h4 class="alert-heading">Увага:</h4><p>Для конфігурацій кластеру з двома або більше вузлами панелі управління, конфігурація шифрування повинна бути ідентичною на кожному вузлі панелі управління.</p>
<p>Якщо існує різниця в конфігурації постачальника шифрування між вузлами панелі управління, ця різниця може означати, що kube-apiserver не може розшифрувати дані.</p>
</div>


Коли ви плануєте оновлення конфігурації шифрування вашого кластера, сплануйте це так, щоб API-сервери у вашій панелі управління завжди могли розшифрувати збережені дані (навіть під час часткового впровадження змін).

Переконайтеся, що ви використовуєте **однакову** конфігурацію шифрування на кожному вузлі керування.

### Перевірте, що нові дані записані зашифровано {#verifying-that-data-is-encrypted}

Дані зашифровуються під час запису в etcd. Після перезапуску вашого `kube-apiserver` будь-який новий створений або оновлений Secret (або інші види ресурсів, налаштовані в `EncryptionConfiguration`), повинні бути зашифровані при зберіганні.

Щоб перевірити це, ви можете використовувати інтерфейс командного рядка `etcdctl`, щоб отримати вміст вашого секретного ключа.

Цей приклад показує, як це перевірити для шифрування Secret API.

1. Створіть новий Secret під назвою `secret1` у просторі імен `default`:

   ```shell
   kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
   ```

2. Використовуючи інтерфейс командного рядка `etcdctl`, прочитайте цей Секрет з etcd:

   ```none
   ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C
   ```

   де `[...]` повинно бути додатковими аргументами для приєднання до сервера etcd.

   Наприклад:

   ```shell
   ETCDCTL_API=3 etcdctl \
      --cacert=/etc/kubernetes/pki/etcd/ca.crt   \
      --cert=/etc/kubernetes/pki/etcd/server.crt \
      --key=/etc/kubernetes/pki/etcd/server.key  \
      get /registry/secrets/default/secret1 | hexdump -C
   ```

   Вивід подібний до цього (скорочено):

   ```hexdump
   00000000  2f 72 65 67 69 73 74 72  79 2f 73 65 63 72 65 74  |/registry/secret|
   00000010  73 2f 64 65 66 61 75 6c  74 2f 73 65 63 72 65 74  |s/default/secret|
   00000020  31 0a 6b 38 73 3a 65 6e  63 3a 61 65 73 63 62 63  |1.k8s:enc:aescbc|
   00000030  3a 76 31 3a 6b 65 79 31  3a c7 6c e7 d3 09 bc 06  |:v1:key1:.l.....|
   00000040  25 51 91 e4 e0 6c e5 b1  4d 7a 8b 3d b9 c2 7c 6e  |%Q...l..Mz.=..|n|
   00000050  b4 79 df 05 28 ae 0d 8e  5f 35 13 2c c0 18 99 3e  |.y..(..._5.,...>|
   [...]
   00000110  23 3a 0d fc 28 ca 48 2d  6b 2d 46 cc 72 0b 70 4c  |#:..(.H-k-F.r.pL|
   00000120  a5 fc 35 43 12 4e 60 ef  bf 6f fe cf df 0b ad 1f  |..5C.N`..o......|
   00000130  82 c4 88 53 02 da 3e 66  ff 0a                    |...S..>f..|
   0000013a
   ```

3. Перевірте, що збережений Secret має префікс `k8s:enc:aescbc:v1:`, що вказує на те, що провайдер `aescbc` зашифрував результати. Переконайтеся, що імʼя ключа, вказане в `etcd`, відповідає імені ключа, вказаному в `EncryptionConfiguration` вище. У цьому прикладі ви бачите, що ключ шифрування під назвою `key1` використовується в `etcd` і в `EncryptionConfiguration`.

4. Перевірте, що Secret правильно розшифровується під час отримання через API:

   ```shell
   kubectl get secret secret1 -n default -o yaml
   ```

   Вивід повинен містити `mykey: bXlkYXRh`, з вмістом `mydata`, закодованим за допомогою base64; прочитайте [декодування Secret](/docs/tasks/configmap-secret/managing-secret-using-kubectl/#decoding-secret), щоб дізнатися, як повністю декодувати Secret.

### Забезпечте шифрування всіх відповідних даних {#ensure-all-secrets-are-encrypted}

Часто недостатньо лише переконатися, що нові обʼєкти зашифровані: ви також хочете, щоб шифрування застосовувалося до обʼєктів, які вже збережені.

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

Ви можете виконати цю зміну для всіх Secret у вашому кластері:

```shell
# Виконайте це в якості адміністратора, який може читати і записувати всі Secret
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
```

Команда вище зчитує всі Secret, а потім оновлює їх з тими самими даними, щоб застосувати шифрування на стороні сервера.


<div class="alert alert-info" role="note"><h4 class="alert-heading">Примітка:</h4><p>Якщо виникає помилка через конфлікт запису, повторіть команду. Це безпечно виконати цю команду більше одного разу.</p>
<p>Для великих кластерів ви можете бажати розділити Secret за просторами імен або сценарію оновлення.</p>
</div>


## Запобігання отриманню відкритого тексту {#cleanup-all-secrets-encrypted}

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

<div class="alert alert-danger" role="note"><h4 class="alert-heading">Попередження:</h4><p>Ця зміна заважає API-серверу отримувати ресурси, які позначені як зашифровані в спокої, але насправді зберігаються у відкритому вигляді.</p>
<p>Коли ви налаштували шифрування у спокої для API (наприклад: вид API <code>Secret</code>, який представляє ресурси <code>secrets</code> в основній групі API), <strong>вам необхідно</strong> переконатися, що всі ці ресурси у цьому кластері дійсно зашифровані у спокої. Перевірте це, перш ніж продовжувати з наступними кроками.</p>
</div>


Після того, як всі Secret у вашому кластері зашифровані, ви можете видалити `identity` частину конфігурації шифрування. Наприклад:

<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apiserver.config.k8s.io/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">EncryptionConfiguration</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">resources</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">resources</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">secrets</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">providers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">aescbc</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">keys</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">key1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">secret</span><span class="p">:</span><span class="w"> </span><span class="l">&lt;BASE 64 ENCODED SECRET&gt;</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w">      </span>- <span class="nt">identity</span><span class="p">:</span><span class="w"> </span>{}<span class="w"> </span><span class="c"># ВИДАЛІТЬ ЦЮ СТРОКУ</span></span></span></code></pre></div>

… а потім перезапустіть кожен API-сервер по черзі. Ця зміна запобігає API-серверу отримувати доступ до Secret у відкритому текстовому форматі, навіть випадково.

## Ротація ключа розшифрування {#rotating-a-decryption-key}

Зміна ключа шифрування для Kubernetes без простою вимагає багатокрокової операції, особливо в умовах високодоступного розгортання, де працюють кілька процесів `kube-apiserver`.

1. Згенеруйте новий ключ і додайте його як другий запис ключа для поточного провайдера на всіх вузлах панелі управління.
2. Перезапустіть **усі** процеси `kube-apiserver`, щоб кожен сервер міг розшифрувати будь-які дані, які зашифровані новим ключем.
3. Зробіть безпечне резервне копіювання нового ключа шифрування. Якщо ви втратите всі копії цього ключа, вам доведеться видалити всі ресурси, які були зашифровані втраченим ключем, і робочі навантаження можуть не працювати як очікується протягом часу, коли шифровання у спокої зламане.
4. Зробіть новий ключ першим записом у масиві `keys`, щоб він використовувався для шифрування у спокої для нових записів.
5. Перезапустіть всі процеси `kube-apiserver`, щоб кожен хост панелі управління тепер шифрував за допомогою нового ключа.
6. Як привілейований користувач виконайте команду `kubectl get secrets --all-namespaces -o json | kubectl replace -f -`, щоб зашифрувати всі наявні секрети новим ключем.
7. Після того, як ви оновили всі наявні секрети, щоб вони використовували новий ключ, і зробили безпечне резервне копіювання нового ключа, видаліть старий ключ розшифрування з конфігурації.

## Розшифрування всіх даних {#decrypting-all-data}

У цьому прикладі показано, як зупинити шифрування API Secret у спокої. Якщо ви шифруєте інші види API, адаптуйте кроки відповідно.

Щоб вимкнути шифрування у спокої, розмістіть провайдера `identity` як перший запис у вашому файлі конфігурації шифрування:

```yaml
---
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
      # перерахуйте тут будь-які інші ресурси, які ви раніше
      # шифрували у спокої
    providers:
      - identity: {} # додайте цей рядок
      - aescbc:
          keys:
            - name: key1
              secret: <BASE 64 ENCODED SECRET> # залиште це на місці
                                               # переконайтеся, що воно йде після "identity"
```

Потім виконайте таку команду, щоб примусити розшифрування всіх Secrets:

```shell
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
```

Після того, як ви замінили всі наявні зашифровані ресурси резервними даними, які не використовують шифрування, ви можете видалити налаштування шифрування з `kube-apiserver`.

## Налаштування автоматичного перезавантаження {#configuring-automatic-reloading}

Ви можете налаштувати автоматичне перезавантаження конфігурації провайдера шифрування. Ця настройка визначає, чи має <a class='glossary-tooltip' title='Компонент панелі управління, що обслуговує API Kubernetes.' data-bs-toggle='tooltip' data-bs-placement='top' href='/uk/docs/concepts/architecture/#kube-apiserver' target='_blank' aria-label='API-сервер'>API-сервер</a> завантажувати файл, який ви вказали для `--encryption-provider-config` тільки один раз при запуску, або автоматично кожного разу, коли ви змінюєте цей файл. Увімкнення цієї опції дозволяє змінювати ключі для шифрування у спокої без перезапуску API-сервера.

Щоб дозволити автоматичне перезавантаження, налаштуйте API server для запуску з параметром: `--encryption-provider-config-automatic-reload=true`. Коли ввімкнено, зміни файлів перевіряються кожну хвилину для спостереження за модифікаціями. Метрика `apiserver_encryption_config_controller_automatic_reload_last_timestamp_seconds` визначає час, коли нова конфігурація набирає чинності. Це дозволяє виконувати ротацію ключів шифрування без перезапуску API-сервера.

## Що далі

- Дізнайтеся більше про [розшифрування даних, які вже збережені у спокої](/docs/tasks/administer-cluster/decrypt-data/)
- Дізнайтеся більше про [API конфігурацію EncryptionConfiguration (v1)](/docs/reference/config-api/apiserver-config.v1/).
