> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Хранилище и тома

> Как оператор подготавливает постоянное хранилище для кластеров ClickHouse, включая основной том данных, многодисковые (JBOD) конфигурации, расширение ёмкости и то, что нельзя изменить после создания.

В этом руководстве описано, как оператор подготавливает постоянное хранилище для
`ClickHouseCluster`: основной том данных, подключение дополнительных дисков в
многодисковой конфигурации (JBOD), расширение ёмкости и правила, определяющие, что
можно и нельзя изменять после создания кластера.

Подробное справочное описание каждого поля см. в разделе
[Конфигурация → Конфигурация хранилища](/docs/ru/products/kubernetes-operator/guides/configuration#storage-configuration)
и в [справочнике по API](/docs/ru/products/kubernetes-operator/reference/api-reference).

<div id="primary-data-volume">
  ## Основной том данных
</div>

`spec.dataVolumeClaimSpec` — это стандартный Kubernetes `PersistentVolumeClaimSpec`.
Оператор преобразует его в `volumeClaimTemplate` StatefulSet, поэтому контроллер StatefulSet
создает и сохраняет по одному PersistentVolumeClaim для каждой реплики и монтирует его
по пути к данным ClickHouse `/var/lib/clickhouse`.

```yaml theme={null}
apiVersion: clickhouse.com/v1alpha1
kind: ClickHouseCluster
metadata:
  name: my-cluster
spec:
  dataVolumeClaimSpec:
    storageClassName: fast-ssd   # optional; depends on the installed CSI driver
    resources:
      requests:
        storage: 100Gi
```

* Если `accessModes` не указан, оператор по умолчанию устанавливает значение `ReadWriteOnce`.
* PVC для каждой реплики сохраняется при удалении кластера, поэтому данные переживают
  удаление и повторное создание пользовательского ресурса. Для данных на
  [зашифрованной политике](#at-rest-encryption) это дополнительно требует сохранения
  ключа шифрования — см. примечание в этом разделе.
* Такое же поле есть у `KeeperCluster` и работает оно так же.

<div id="ephemeral-storage">
  ## Запуск без постоянного тома данных
</div>

`dataVolumeClaimSpec` необязателен. Если не указать его и не смонтировать собственный том
по пути к данным, ClickHouse будет записывать данные в эфемерную файловую систему контейнера, а
вебхук допуска вернёт предупреждение о том, что данные могут быть потеряны при перезапуске кластера.

Этот вариант предназначен только для временных или тестовых кластеров. Чтобы использовать собственное хранилище
вместо `dataVolumeClaimSpec` — например, `emptyDir` или заранее подготовленный
том, — задайте его через `spec.podTemplate.volumes` и смонтируйте в
`/var/lib/clickhouse` с помощью `spec.containerTemplate.volumeMounts`.

<Note>
  `dataVolumeClaimSpec` и пользовательский том по пути к данным взаимоисключающи.
  Если задан `dataVolumeClaimSpec`, монтирование пользовательского тома в `/var/lib/clickhouse`
  будет отклонено. Зарезервированные имена томов `clickhouse-storage-volume`,
  `clickhouse-server-tls-volume` и `clickhouse-server-custom-ca-volume` нельзя
  использовать в `podTemplate.volumes`.
</Note>

<div id="expanding-storage">
  ## Расширение хранилища
</div>

Чтобы увеличить том, повысьте значение `resources.requests.storage` и примените изменения.
Оператор обновит существующие PVC на месте.

```yaml theme={null}
spec:
  dataVolumeClaimSpec:
    resources:
      requests:
        storage: 200Gi   # was 100Gi
```

<Note>
  Расширение работает только в том случае, если в нижележащем StorageClass задано
  `allowVolumeExpansion: true`. Kubernetes не поддерживает уменьшение PVC, поэтому
  новый размер должен быть больше или равен текущему.
</Note>

<div id="multi-disk-jbod">
  ## Многодисковое (JBOD) хранилище
</div>

`spec.additionalVolumeClaimTemplates` добавляет дополнительные диски к каждой
реплике ClickHouse помимо основного `dataVolumeClaimSpec`. Каждая запись представляет собой именованный шаблон PVC
— `metadata.name` и `spec` PVC — который обрабатывается точно так же, как
основной диск данных, поэтому контроллер StatefulSet создает и сохраняет по одному PVC для
каждой реплики с именем `<name>-<statefulset>-0`.

```yaml theme={null}
spec:
  dataVolumeClaimSpec:
    storageClassName: fast-ssd
    resources:
      requests:
        storage: 100Gi
  additionalVolumeClaimTemplates:
    - metadata:
        name: disk1
      spec:
        storageClassName: fast-ssd
        resources:
          requests:
            storage: 100Gi
    - metadata:
        name: disk2
      spec:
        storageClassName: fast-ssd
        resources:
          requests:
            storage: 100Gi
```

Оператор монтирует каждый дополнительный том в `/var/lib/clickhouse/disks/<name>`
и **генерирует `storage_configuration` ClickHouse за вас** — вам не нужно задавать
её вручную. Он регистрирует каждый дополнительный диск и добавляет его во
встроенную политику хранения `default`.

Основной диск данных (`default`) и каждый дополнительный диск входят в один общий том
политики `default`, поэтому ClickHouse распределяет новые части данных между ними
по круговому алгоритму. Полезная ёмкость равна сумме всех дисков, и каждая таблица,
которая не задаёт собственную `storage_policy`, — включая таблицы `system.*` — использует
этот общий набор.

<Note>
  Путь монтирования сохраняет имя шаблона без изменений, но идентификатор диска внутри
  `storage_configuration` заменяет дефисы на символы подчёркивания. Шаблон с именем
  `cold-disk` монтируется в `/var/lib/clickhouse/disks/cold-disk` и отображается как
  `cold_disk` в сгенерированной конфигурации.
</Note>

<div id="custom-storage-policies">
  ## Пользовательские политики хранения
</div>

Для описанной выше структуры JBOD `extraConfig` **не** нужен — оператор автоматически создаёт
политику `default`. Используйте `spec.settings.extraConfig` только в тех случаях, когда
вам нужны политики хранения *помимо* автоматически сгенерированной по умолчанию, например
многоуровневая политика hot/cold с `move_factor` и `prefer_not_to_merge` или диск на базе S3.
Добавленная там конфигурация накладывается поверх сгенерированного `storage_configuration`.

Описание полей политики см. в
[документации ClickHouse по хранилищу](https://clickhouse.com/docs/engines/table-engines/mergetree-family/mergetree#table_engine-mergetree-multiple-volumes).

<div id="at-rest-encryption">
  ## Шифрование данных при хранении
</div>

Параметр `spec.settings.encryption` включает шифрование данных таблиц при хранении. Оператор
генерирует 16-байтный ключ AES — он хранится в Secret управляемого кластера или
передаётся через `externalSecret` — а также отдельную политику хранения, которая оборачивает
каждый диск с данными в тип диска ClickHouse `encrypted`.

```yaml theme={null}
spec:
  settings:
    encryption: {}   # enables the feature; the policy defaults to "encrypted"
```

Шифрование включается для каждой таблицы отдельно; политика хранения по умолчанию остаётся без шифрования. Выберите
зашифрованную политику при создании таблицы:

```sql theme={null}
CREATE TABLE secret_data (id UInt64) ENGINE = MergeTree ORDER BY id
SETTINGS storage_policy = 'encrypted';
```

Установите `encryption.policyName`, чтобы использовать другое имя политики.

<Note>
  Это шифрует части данных MergeTree, записанные с использованием зашифрованной политики,
  алгоритмом AES-128-CTR. Метаданные ClickHouse server и журналы в корневом каталоге
  данных при этом не шифруются — для них используйте шифрование на уровне диска,
  например LUKS или CSI-драйвер.
  Включение шифрования в работающем кластере запускает однократный поочередный перезапуск,
  чтобы добавить ключ; реплики могут ненадолго сообщать об ошибке перезагрузки
  конфигурации, пока этот перезапуск не завершится.

  Ключ хранится в Secret кластера, которым управляет оператор; этот Secret принадлежит
  пользовательскому ресурсу и удаляется вместе с ним. Зашифрованные части невозможно прочитать без
  ключа: если зашифрованные данные должны сохраниться после удаления CR (PVC сохраняются),
  передайте ключ через `externalSecret` или сделайте резервную копию записи `disk-encryption-key`
  до удаления. Не удаляйте управляемый Secret — оператор сгенерирует
  новый ключ, и существующие зашифрованные части станут нечитаемыми.
</Note>

<div id="immutability">
  ## Что нельзя изменить после создания
</div>

Структура хранилища по большей части фиксируется после создания кластера. Вебхук допуска отклоняет
обновления, которые привели бы к отвязке или повторной привязке PersistentVolumeClaims:

* Наличие `dataVolumeClaimSpec` неизменно — вы не можете **добавить** том
  данных в кластер, созданный без него, и не можете **удалить** его из кластера, созданного
  с ним.
* Набор `additionalVolumeClaimTemplates` фиксирован — вы не можете **добавлять**,
  **удалять** или **переименовывать** записи после создания.
* Увеличение `resources.requests.storage` у существующей записи **допускается** (при условии
  поддержки со стороны StorageClass, см. [Расширение хранилища](#expanding-storage)).
* Шифрование нельзя **отключить** после включения, а `encryption.policyName` нельзя
  **переименовать** — таблицы, уже использующие эту зашифрованную политику, станут недоступны.

<div id="validation-reference">
  ## Справочник по валидации
</div>

| Условие                                                                                        | Результат                                                                              |
| ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| Нет `dataVolumeClaimSpec` и нет пользовательского тома в `/var/lib/clickhouse`                 | Предупреждение — возможна потеря данных при перезапуске                                |
| Пользовательский том смонтирован в `/var/lib/clickhouse`, при этом задан `dataVolumeClaimSpec` | Отклонено                                                                              |
| Задан `additionalVolumeClaimTemplates`, но отсутствует `dataVolumeClaimSpec`                   | Отклонено                                                                              |
| Дополнительный диск с именем `default`                                                         | Отклонено — это имя зарезервировано для диска ClickHouse по умолчанию                  |
| Имя дополнительного диска оканчивается на `-encrypted`                                         | Отклонено — совпадает со сгенерированными именами зашифрованных дисков                 |
| Дополнительный диск с именем `clickhouse-storage-volume`                                       | Отклонено — конфликтует с именем основного тома данных                                 |
| Повторяющееся имя дополнительного диска                                                        | Отклонено                                                                              |
| Имя не соответствует `^[a-z]([-a-z0-9]*[a-z0-9])?$` или длиннее 63 символов                    | Отклонено схемой CRD                                                                   |
| Добавление или удаление `dataVolumeClaimSpec` после создания                                   | Отклонено                                                                              |
| Добавление, удаление или переименование `additionalVolumeClaimTemplates` после создания        | Отклонено                                                                              |
| Зарезервированное имя тома в `podTemplate.volumes`                                             | Отклонено                                                                              |
| `encryption.policyName` задано как `default`                                                   | Отклонено схемой CRD — зашифрованная политика не должна заменять политику по умолчанию |
| Отключение `encryption` или переименование его политики после создания                         | Отклонено схемой CRD                                                                   |

<div id="related-guides">
  ## Связанные руководства
</div>

* [Конфигурация](/docs/ru/products/kubernetes-operator/guides/configuration) — полный справочник по всем полям, включая `extraConfig`.
* [Масштабирование кластеров](/docs/ru/products/kubernetes-operator/guides/scaling) — как добавлять и удалять реплики и сегменты.
