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

# Подготовка инфраструктуры AWS с помощью Terraform

> Создайте кластер Amazon EKS для управляемого режима или добавьте необходимые для него компоненты в уже существующий VPC или кластер с помощью Terraform или OpenTofu

Закрытая предварительная версия

Управляемый режим работает в вашем собственном кластере Amazon EKS. В каждый релиз входят четыре корневых модуля Terraform (далее — корневые модули), которые либо создают кластер, соответствующий требованиям, либо добавляют недостающие компоненты в уже существующие VPC или кластер. Корневые модули создают кластер с системной группой узлов и управляемыми дополнениями (`vpc-cni`, `kube-proxy`, `coredns`, `aws-ebs-csi-driver`), а также роли IAM, ключи KMS и теги; `existing-eks` устанавливает только те дополнения, которые перечислены в `install_addons`. Затем, если целевой платформой является Helm, команда `clicklink clctl init` устанавливает платформенный слой на основе выходных значений и bundle платформы: Karpenter, контроллер AWS Load Balancer, класс хранилища и компоненты с закреплёнными версиями (см. раздел [Инициализация коннектора из выходных значений Terraform](#hand-off)). Для корневых модулей требуется Terraform 1.10+ или OpenTofu 1.12+, а также провайдер AWS `~> 6.0`. Во всех командах на этой странице вместо `terraform` можно использовать `tofu`.

![Процесс подготовки коннектора ClickHouse в AWS с помощью Terraform](https://mintcdn.com/private-7c7dfe99/rJQNifKkddKyB_KW/images/cloud/reference/byoc-connector-terraform-flow.svg?fit=max\&auto=format\&n=rJQNifKkddKyB_KW\&q=85\&s=8b0e95133f61d6b4278f29df9631e44e)

## Перед началом работы

Вам потребуется:

* Terraform 1.10+ или OpenTofu 1.12+, а также провайдер AWS `~> 6.0`.
* Учётная запись AWS с правами на создание и изменение ресурсов, необходимых для выбранного корневого модуля.
* `curl`, инструмент для вычисления SHA-256 (`sha256sum` или `shasum`) и `cosign` для загрузки и проверки архива релиза.
* Данные, полученные на этапе [регистрации](/docs/ru/products/bring-your-own-cloud/connector/onboarding#registration): значение `chart_repository_arn`, обязательное для каждого корневого модуля, а также конечная точка коннектора, токен регистрации и bundle платформы, которые понадобятся для передачи в `init` на завершающем этапе.

Для `production` и `existing-vpc` заранее продумайте, как машина, на которой запускаются `clicklink clctl init` и `kubectl`, будет получать доступ к приватному API EKS: например, через VPN, бастион, пиринговую сеть или проброс порта через SSM.

## 1. Выберите корневой модуль Terraform для своей среды

Все четыре корневых модуля выдают одинаковый вывод `clicklink`. Передача результата в `clicklink clctl init` происходит одинаково, какой бы из них вы ни применили.

| Корень | Исходное состояние | Создаёт |
| - | - | - |
| `minimal` | Кластеры для разработки и проверки концепции | То же, одна зона, общедоступная конечная точка, без конечных точек и CMK |
| `production` | Аккаунт и регион без ресурсов | VPC, кластер EKS, группа узлов, IAM, KMS |
| `existing-vpc` | Существующая VPC | Кластер EKS, группа узлов, IAM, KMS, теги подсетей |
| `existing-eks` | Уже работающий кластер | IAM, именованные дополнения, разрешения на использование ключей, теги обнаружения |

### `minimal`

`minimal` ослабляет настройки публичной конечной точки, интерфейсных конечных точек, журналов потоков (flow logs), срока хранения журналов и размера системного пула. Каждая ослабленная переменная есть в обоих корневых модулях под тем же именем. Чтобы перевести любую из них на значение для продакшна, достаточно изменить `terraform.tfvars` и повторно выполнить apply. Единственная зона для рабочей нагрузки и отсутствие ключей KMS зафиксированы: зону подсети изменить нельзя, а в корневом модуле нет переменной для шифрования секретов EKS. Чтобы устранить эти ограничения, придётся развернуть `production` как новый кластер.

### `production`

VPC охватывает три зоны (`availability_zone_count`, от 2 до 4) с частной подсетью `/19` и публичной подсетью `/21` в каждой зоне, одним NAT-шлюзом на зону, шлюзовой конечной точкой S3, интерфейсными конечными точками для ECR, STS, EKS, EC2, CloudWatch Logs, SSM, SQS, KMS и ELB, а также журналами потоков VPC. Кластер EKS использует закрытую конечную точку API и аутентификацию через access entries; все типы журналов control plane записываются в группу журналов, принадлежащую корневому модулю, а Secrets шифруются управляемым клиентом ключом KMS. В кластер устанавливаются управляемые дополнения `vpc-cni`, `kube-proxy`, `coredns` и `aws-ebs-csi-driver`, а также создаётся одна системная группа узлов без taint с меткой `clickhouseGroup=system` (по умолчанию от двух до четырёх узлов `m7g.large`). Корневой модуль также создаёт ресурсы IAM для Karpenter с очередью прерываний и тегами `karpenter.sh/discovery`, роли IRSA для контроллера AWS Load Balancer и для исполнителя коннектора, а также ключи KMS для томов EBS и бакетов объектного хранилища.

### `existing-vpc` и `existing-eks`

Ни один из корневых модулей не изменяет ресурсы, которые он не создавал: таблицы маршрутизации, NAT-шлюзы, конечные точки, правила групп безопасности, группы узлов, шаблоны запуска, конфигурацию кластера и ключи KMS. Оба модуля помечают частные подсети тегами `karpenter.sh/discovery=<cluster_name>` и `kubernetes.io/role/internal-elb=1`; `existing-vpc` также помечает публичные подсети тегом `kubernetes.io/role/elb=1`, а `existing-eks` добавляет тег к группе безопасности кластера.

Для `existing-vpc` в VPC уже должно быть предусмотрено следующее:

* Включены поддержка DNS и DNS-имена хостов.
* От двух до четырёх частных подсетей как минимум в двух зонах доступности с отключённым параметром `map_public_ip_on_launch` и маршрутизацией к NAT-шлюзу либо к интерфейсным конечным точкам для ECR, STS, EKS, EC2, CloudWatch Logs, SSM, SQS, KMS и ELB. Добавьте шлюзовую конечную точку S3: без неё трафик к объектному хранилищу будет идти через NAT-шлюзы.
* Публичные подсети нужны, только если вам требуются load balancer с доступом из интернета. Если в VPC нет публичного уровня, оставьте `public_subnet_ids` пустым.

При использовании `existing-eks` в кластере уже должны быть:

* Kubernetes версии 1.34 или новее.
* Режим аутентификации `API` или `API_AND_CONFIG_MAP`. Для кластера в режиме `CONFIG_MAP` план выводит команду переключения.
* IAM OIDC-провайдер для issuer кластера.
* Приватные подсети как минимум в двух зонах доступности с исходящим доступом к API AWS через NAT или интерфейсные конечные точки. По умолчанию корневой модуль определяет их по подсетям кластера, исключая те, чья таблица маршрутизации ведёт к интернет-шлюзу. Задайте `private_subnet_ids`, если подсети кластера — это подсети `/28`, предназначенные только для плоскости управления, или если узлы должны размещаться в других подсетях.
* Karpenter не установлен: этот корневой модуль сам создаёт IAM-ресурсы Karpenter и очередь прерываний. Очередь называется `<cluster_name>-clicklink`, поэтому она не будет конфликтовать с очередью, оставшейся от ранее удалённой установки Karpenter.
* Системные узлы без taint-ов с метками из `system_node_selector` (по умолчанию `clickhouseGroup=system`). Этот корневой модуль не создаёт группу узлов.

Если отсутствует хотя бы один из них, `terraform plan` завершится с ошибкой.

Если дополнение из `install_addons` уже установлено и работает в самоуправляемом режиме, EKS возвращает ошибку `Conflicts found when trying to apply`. Задайте `addon_resolve_conflicts_on_create = "OVERWRITE"`, чтобы управляемое дополнение заменило существующую установку, или исключите его из `install_addons`.

## 2. Скачайте и проверьте архив релиза Terraform

Корневые сертификаты поставляются одним архивом на каждый релиз, и их версия совпадает с версией бинарного файла `clicklink`. Загрузите архив для текущего релиза вместе с контрольной суммой и cosign bundle:

```bash theme={null}
CLICKLINK_VERSION="$(curl -fsSL https://releases.clicklink.clickhouse.com/latest-version.txt)"
# Or pin a specific release: CLICKLINK_VERSION='vX.Y.Z'
TERRAFORM_TARBALL="clicklink-terraform-${CLICKLINK_VERSION}.tar.gz"
for suffix in '' .sha256 .bundle; do
  curl -fsSLO "https://releases.clicklink.clickhouse.com/${TERRAFORM_TARBALL}${suffix}"
done
if command -v sha256sum >/dev/null; then
  sha256sum -c "${TERRAFORM_TARBALL}.sha256"
else
  shasum -a 256 -c "${TERRAFORM_TARBALL}.sha256"
fi
```

Перед распаковкой проверьте подпись с помощью cosign:

```bash theme={null}
cosign verify-blob \
  --bundle "${TERRAFORM_TARBALL}.bundle" \
  --certificate-identity-regexp '^https://github\.com/ClickHouse/data-plane-clicklink/\.github/workflows/release\.yaml@refs/tags/v[0-9]+\.[0-9]+\.[0-9]+(-.*)?$' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  "${TERRAFORM_TARBALL}"
```

Затем распакуйте его:

```bash theme={null}
tar -xzf "${TERRAFORM_TARBALL}"
cd "clicklink-terraform-${CLICKLINK_VERSION}"
```

Архив распаковывается в один каталог, содержащий `aws/production`, `aws/minimal`, `aws/existing-vpc`, `aws/existing-eks` и `aws/modules`. Корневые конфигурации ссылаются на модули по пути `../modules`. Не разделяйте распакованное дерево и не копируйте из него отдельные корневые конфигурации. В корневых файлах README из архива передача управления через `init` может быть показана без `--platform-bundle`; поддерживается команда из раздела [инициализация коннектора из выходных данных Terraform](#hand-off).

## 3. Настройте и примените выбранный корень

В корневом каталоге проекта скопируйте файл с примером переменных и заполните его:

```bash theme={null}
cp terraform.tfvars.example terraform.tfvars
```

Для каждого корневого модуля обязательны `region`, `cluster_name` и `chart_repository_arn`. `cluster_name` задаёт имя кластера, служит префиксом для всех ресурсов и используется как значение тега обнаружения. В `production`, `minimal` и `existing-vpc` оно должно содержать от 3 до 32 строчных латинских букв, цифр и дефисов, начинаться с буквы и не заканчиваться дефисом. В `existing-eks` указывается имя уже работающего кластера длиной до 32 символов. `chart_repository_arn` — это репозиторий ECR с чартом кластера ClickHouse; его предоставляет команда сопровождения аккаунта ClickHouse при [регистрации](/docs/ru/products/bring-your-own-cloud/connector/onboarding#registration). Для корневых модулей, создающих кластер, также обязателен параметр `cluster_admin_principal_arns` — субъекты, которые получают права администратора кластера через записи доступа EKS. Учётная запись, от имени которой запускается корневой модуль, должна входить в этот список, иначе впоследствии она не сможет подключиться к кластеру. Создатель кластера не получает доступ автоматически. Требования для отдельных корневых модулей:

* Для `minimal` обязателен `endpoint_public_access_cidrs` — список разрешённых IPv4-адресов для публичной конечной точки API. Сеть, из которой вы запускаете `init` и `kubectl`, должна входить в этот список. Значение `/0` отклоняется, если не задано `allow_public_endpoint_from_anywhere = true`. При `endpoint_public_access = false` список может быть пустым — тогда конечная точка будет только приватной, как в `production`.
* Для `existing-vpc` обязательны `vpc_id` и `private_subnet_ids`. `public_subnet_ids` указывать необязательно: он нужен для балансировщиков нагрузки, доступных из интернета.
* Для `existing-eks` других обязательных переменных нет. В `install_addons` перечисляются управляемые дополнения, которых нет в кластере, а `ebs_kms_key_arn` задаёт ключ для томов сервиса.

Затем выполните инициализацию, планирование и применение:

```bash theme={null}
terraform init
terraform providers lock -platform=linux_amd64 -platform=darwin_arm64
terraform plan
terraform apply
```

В архиве нет lock-файла провайдеров. Команда `terraform providers lock` сгенерирует его — закоммитьте этот файл в свою копию. По умолчанию состояние хранится локально. В файле `versions.tf` есть закомментированный блок `backend "s3"`, который показывает, как настроить общее состояние.

> [!NOTE]
>
> Конечные точки API в конфигурациях `production` и `existing-vpc` приватные. Выполняйте `init` и `kubectl` изнутри VPC (через проброс порта SSM на системный узел, бастион, VPN или пиринговую сеть) либо явно включите публичный доступ с помощью `endpoint_public_access = true` и задайте список разрешённых адресов в `endpoint_public_access_cidrs`.

## 4. Инициализируйте коннектор с помощью выходных значений Terraform

Экспортируйте выходные значения и передайте их в `init` вместе с platform bundle, выполняя команду на машине, где kube-контекст указывает на новый кластер:

```bash theme={null}
terraform output -json > outputs.json
clicklink clctl init --enroll https://<subdomain>.<connector-domain> --target helm --managed \
  --from-terraform outputs.json --platform-bundle bundle.yaml
```

Корневые модули поддерживают только цель Helm. На ВМ (`--target systemd`) команда `init` отклоняет `--platform-bundle`, а `clicklink clctl platform approve --bundle` устанавливает только закреплённые компоненты, поэтому в кластере не оказывается средства выделения узлов. Используйте `--target systemd` только для коннекторов, регистрирующих ClickHouse, который вы запускаете самостоятельно; с этими корневыми модулями такой вариант не поддерживается.

`--platform-bundle` устанавливает то, чего нет в корневых модулях: Karpenter с `EC2NodeClass` и пулами узлов `clickhouse-server` и `clickhouse-keeper`, контроллер AWS Load Balancer, класс хранилища `gp3-encrypted` (с шифрованием ключом EBS, если он есть в выходных данных), а также компоненты платформы, закреплённые в bundle: контроллер снимков, ClickHouse operator и коллекторы мониторинга. Bundle — это манифест платформы, который ClickHouse Cloud формирует для вашего окружения; его передаёт ваша команда по работе с аккаунтом в ходе онбординга, а раздел `cluster:` в нём закрепляет версии Karpenter и контроллера load balancer. Для этого флага требуются `--target helm`, `--managed` и `--from-terraform`. Уже установленные компоненты не изменяются, поэтому команду можно безопасно запускать повторно; `init` выводит отчёт о том, что было установлено, что пропущено и почему. Без этого флага `init` регистрирует коннектор, но ничего из перечисленного не устанавливает, и кластер не сможет запустить сервис, пока эти компоненты не будут развёрнуты. Последующие [обновления платформы](/docs/ru/products/bring-your-own-cloud/connector/platform-updates) затрагивают контроллер снимков, оператор и коллекторы; Karpenter, контроллер load balancer и класс хранилища остаются в том виде, в каком их установила `init`.

`--from-terraform` принимает либо полный документ, который выводит `terraform output -json`, либо отдельный объект из `terraform output -json clicklink`. Выходные данные `clicklink` содержат идентификационные данные кластера (`account_id`, `region`, `cluster_name`, `cluster_endpoint`, `cluster_ca`), провайдер OIDC, пространство имен коннектора, роль IAM исполнителя (`executor_role_arn`), ключ EBS, роль узлов и очередь Karpenter, роль контроллера load balancer и `system_node_selector`. `init` считывает из файла идентификационные данные кластера и пространство имен коннектора. Команда задаёт `executor_role_arn` в качестве аннотации IRSA для ServiceAccount `pcm-executor` коннектора и назначает подам коннектора селектор узлов. Управляемые сервисы эту роль не используют: `clicklink clctl executor prepare` создаёт отдельную роль для каждого сервиса (по умолчанию `CH-S3-<service>-<region>-00-Role`), которая привязывается к сервису при его создании; см. [модель привилегий](/docs/ru/products/bring-your-own-cloud/connector/reference/privilege-model#identities).

`init` отклоняет флаги, такие как `--cluster-name` или `--target-namespace`, если их значения расходятся с файлом, и выводит оба значения. Уберите флаг или исправьте выходные данные. Команда также отклоняет kube-контекст, если его API-сервер не совпадает с `cluster_endpoint` или его EKS ARN указывает на другой кластер. В выходных данных есть поле `schema`, сейчас равное `1`. `clctl` отклоняет файл, если не поддерживает указанное в нём значение `schema`.

Остальные шаги регистрации выполняются по стандартной процедуре, описанной в разделе [онбординг](/docs/ru/products/bring-your-own-cloud/connector/onboarding#install-and-enroll).

## Ключи KMS и необходимые привилегии

`production` и `existing-vpc` создают три управляемых клиентом ключа KMS с включённой ротацией — для секретов EKS, томов EBS и бакетов объектного хранилища, если только вы не передадите ARN в `kms`. `existing-eks` создаёт ключ хранилища, если не задан `storage_kms_key_arn`, а для томов сервисов принимает `ebs_kms_key_arn`, не создавая собственный ключ. `minimal` не создаёт ключей вовсе; если не задан `storage_kms_key_arn`, его бакеты по-прежнему шифруются с помощью SSE-S3. Созданный ключ содержит один оператор для root-учётной записи аккаунта, который делегирует управление доступом IAM. Для ключа, который вы предоставляете сами, требуется такое же делегирование либо следующие привилегии в его политике ключа:

| Ключ | Субъект | Действия |
| - | - | - |
| Секреты EKS | `<cluster_name>-cluster` | `kms:Encrypt`, `kms:Decrypt`, `kms:DescribeKey` |
| EBS | `<cluster_name>-ebs-csi-driver`, `<cluster_name>-karpenter-controller` | `kms:Encrypt`, `kms:Decrypt`, `kms:ReEncrypt*`, `kms:GenerateDataKey*`, `kms:DescribeKey`, `kms:CreateGrant` с условием `kms:GrantIsForAWSResource = true` |
| Хранилище | Каждая роль `CH-S3-<service>-<region>-00-Role`, создаваемая командой `clicklink clctl executor prepare --storage-kms-key-arn` | `kms:Decrypt`, `kms:GenerateDataKey`, `kms:DescribeKey` |
| Хранилище | `<cluster_name>-clicklink-executor` — для записи ключа `_tde/` рядом с резервными копиями сервиса | `kms:GenerateDataKey`, `kms:Decrypt` |

Корневые модули в любом случае подключают политики ролей IAM для ключей секретов EKS и EBS, а политику исполнителя для ключа хранилища — всякий раз, когда в корневом модуле есть ключ хранилища; политику каждой сервисной роли подключает `executor prepare`. Корневые тома системных узлов хранят образы и журналы кубелета, а не данные сервисов, поэтому используют ключ EBS аккаунта по умолчанию.

## Удаление инфраструктуры, управляемой Terraform

`terraform destroy` удаляет всё, что было создано корневым модулем. Созданные ключи KMS переходят в 30-дневный период ожидания удаления. Группы логов удаляются вместе с хранящимися в них журналами, поэтому заранее экспортируйте всё необходимое. Инстансы, запущенные Karpenter, и тома, созданные ClickHouse Operator, не отражены в Terraform state. Поэтому сначала удалите свои сервисы и Karpenter, иначе удаление VPC и роли узлов завершится ошибкой.

`existing-eks` не удаляет сам кластер. Удаляются роли, очередь прерываний и связанные с ней правила, запись доступа (access entry), а также добавленные модулем теги. Установленные им дополнения `vpc-cni`, `kube-proxy` и `coredns` выводятся из-под управления EKS, но их поды продолжают работать. Дополнение драйвера EBS CSI, если оно было установлено модулем, удаляется вместе с корневым модулем, поскольку его роль IRSA тоже уничтожается. Чтобы сохранить драйвер, перед удалением пересоздайте дополнение с собственной ролью.

При удалении снимаются все теги, добавленные этими корневыми модулями, в том числе тег `kubernetes.io/role/internal-elb`, существовавший ещё до применения модуля: `aws_ec2_tag` берёт существующий тег под своё управление. Чтобы сохранить теги, перед удалением задайте `manage_subnet_tags = false` (`existing-vpc`) или `manage_discovery_tags = false` (`existing-eks`) и выполните apply либо удалите ресурсы `aws_ec2_tag` из state с помощью `terraform state rm`.
