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

# Provisione a infraestrutura da AWS com Terraform

> Crie um EKS cluster da Amazon para o modo managed ou adicione os recursos necessários a uma VPC ou a um cluster existente, usando Terraform ou OpenTofu

Em prévia privada

O modo managed é executado em um EKS cluster da Amazon de sua propriedade. Cada lançamento inclui quatro módulos raiz do Terraform (chamados de raízes a seguir) que criam um cluster que atende aos requisitos do modo ou adicionam o que for necessário a uma VPC ou a um cluster que você já tenha. As raízes criam o cluster com seu node group de sistema e os addons gerenciados (`vpc-cni`, `kube-proxy`, `coredns`, `aws-ebs-csi-driver`), além de IAM roles, chaves KMS e tags; o `existing-eks` instala apenas os addons que você especificar em `install_addons`. No target Helm, o `clicklink clctl init` instala em seguida a camada de plataforma a partir dos outputs e de um pacote de plataforma: Karpenter, o controller AWS Load Balancer, a StorageClass e os componentes com versões fixadas (consulte [inicializar o connector a partir dos outputs do Terraform](#hand-off)). As raízes exigem Terraform 1.10+ ou OpenTofu 1.12+ e o provider AWS `~> 6.0`. É possível usar `tofu` no lugar de `terraform` em todos os comandos desta página.

![Fluxo de provisionamento do Terraform para o ClickHouse Connector na AWS](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)

## Antes de começar

Você precisará de:

* Terraform 1.10+ ou OpenTofu 1.12+, além do provider AWS `~> 6.0`.
* Uma identidade AWS com permissão para criar e modificar os recursos exigidos pela raiz selecionada.
* `curl`, uma ferramenta de SHA-256 (`sha256sum` ou `shasum`) e `cosign` para baixar e verificar o arquivo do lançamento.
* Do [registro](/docs/pt-BR/products/bring-your-own-cloud/connector/onboarding#registration): o `chart_repository_arn` exigido por todas as raízes, além do seu connector endpoint, do token de inscrição e do pacote da plataforma para a etapa final de `init`.

Para `production` e `existing-vpc`, planeje como a máquina que executa `clicklink clctl init` e `kubectl` acessará a API privada do EKS, por exemplo, por meio de uma VPN, um bastion, uma rede pareada ou um encaminhamento de porta via SSM.

## 1. Escolha o diretório raiz do Terraform para o seu ambiente

As quatro raízes geram a mesma saída `clicklink`. A passagem para `clicklink clctl init` é a mesma, independentemente de qual delas você aplicar.

| Raiz | Comece com | Cria |
| - | - | - |
| `minimal` | Clusters de desenvolvimento e prova de conceito | O mesmo, com uma zona, endpoint público, sem endpoints ou CMKs |
| `production` | Uma conta e uma região sem recursos | VPC, EKS cluster, grupo de nós, IAM, KMS |
| `existing-vpc` | Uma VPC que você já possui | EKS cluster, grupo de nós, IAM, KMS, tags de sub-rede |
| `existing-eks` | Um cluster que você já opera | IAM, add-ons nomeados, permissões para chaves, tags de descoberta |

### `minimal`

`minimal` flexibiliza o endpoint público, os interface endpoints, os flow logs, a retenção de logs e o tamanho do pool do sistema. Toda variável flexibilizada existe em ambos os roots com o mesmo nome. Levar uma delas ao valor de produção exige apenas uma alteração em `terraform.tfvars` e um novo apply. Já a zona única de carga de trabalho e a ausência de chaves KMS são fixas: as sub-redes não podem mudar de zona, e o root não tem variável para a criptografia de Secrets do EKS. Para resolver esses pontos, é preciso aplicar `production` como um novo cluster.

### `production`

A VPC abrange três zonas (`availability_zone_count`, de 2 a 4), com uma sub-rede privada `/19` e uma pública `/21` por zona, um NAT gateway por zona, um gateway endpoint do S3, interface endpoints para ECR, STS, EKS, EC2, CloudWatch Logs, SSM, SQS, KMS e ELB, além de VPC flow logs. O EKS cluster tem um endpoint de API privado, autenticação por access entries, todos os tipos de log do control plane em um log group pertencente ao módulo root e Secrets criptografados com uma chave KMS gerenciada pelo cliente. O cluster recebe os addons gerenciados `vpc-cni`, `kube-proxy`, `coredns` e `aws-ebs-csi-driver`, além de um node group de sistema sem taints, com o rótulo `clickhouseGroup=system` (por padrão, de dois a quatro nós `m7g.large`). O módulo root também cria o IAM do Karpenter com uma fila de interrupção e tags `karpenter.sh/discovery`, funções IRSA para o AWS Load Balancer controller e para o executor do connector, além de chaves KMS para os volumes EBS e para os buckets de armazenamento de objetos.

### `existing-vpc` e `existing-eks`

Nenhum dos roots altera recursos que não criou: tabelas de rotas, NAT gateways, endpoints, regras de security group, node groups, launch templates, a configuração do cluster ou chaves KMS. Ambos aplicam às subnets privadas as tags `karpenter.sh/discovery=<cluster_name>` e `kubernetes.io/role/internal-elb=1`; o `existing-vpc` também aplica às subnets públicas a tag `kubernetes.io/role/elb=1`, e o `existing-eks` aplica tags ao security group do cluster.

No caso de `existing-vpc`, a VPC já deve oferecer:

* Suporte a DNS e hostnames DNS habilitados.
* De duas a quatro sub-redes privadas em pelo menos duas zonas de disponibilidade, com `map_public_ip_on_launch` desativado, com rotas para um NAT gateway ou para interface endpoints de ECR, STS, EKS, EC2, CloudWatch Logs, SSM, SQS, KMS e ELB. Adicione um gateway endpoint do S3; sem ele, o tráfego do armazenamento de objetos passa pelos NAT gateways.
* Sub-redes públicas apenas se você quiser balanceadores de carga expostos à internet. Deixe `public_subnet_ids` vazio quando a VPC não tiver um tier público.

Para `existing-eks`, o cluster já deve ter:

* Kubernetes 1.34 ou mais recente.
* Modo de autenticação `API` ou `API_AND_CONFIG_MAP`. Para um cluster `CONFIG_MAP`, o plano exibe o comando para fazer a troca.
* Um provedor OIDC do IAM para o emissor do cluster.
* Sub-redes privadas em pelo menos duas zonas de disponibilidade, com saída para as APIs da AWS por meio de NAT ou de endpoints de interface. Por padrão, o módulo raiz as obtém a partir das sub-redes do cluster, descartando aquelas cuja tabela de rotas alcança um internet gateway. Defina `private_subnet_ids` quando as sub-redes do cluster forem `/28`s exclusivas do plano de controle ou quando os nós precisarem ficar em outras sub-redes.
* Nenhuma instalação do Karpenter; este módulo raiz cria o IAM e a fila de interrupção do Karpenter. A fila se chama `<cluster_name>-clicklink`, portanto não há risco de conflito com uma fila remanescente de uma instalação do Karpenter já removida.
* Nós de sistema sem taints, com os labels definidos em `system_node_selector` (`clickhouseGroup=system` por padrão). Este módulo raiz não cria nenhum grupo de nós.

O `terraform plan` falha se algum desses itens estiver ausente.

Se um addon em `install_addons` já estiver em execução como uma instalação autogerenciada, o EKS retornará `Conflicts found when trying to apply`. Defina `addon_resolve_conflicts_on_create = "OVERWRITE"` para que o addon gerenciado assuma o controle ou remova-o de `install_addons`.

## 2. Baixe e verifique o arquivo compactado do lançamento do Terraform

As raízes são distribuídas em um arquivo compactado por lançamento, versionado junto com o binary `clicklink`. Baixe o arquivo compactado do lançamento atual, junto com o checksum e o pacote do cosign correspondentes:

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

Verifique a assinatura com o cosign antes de extrair o arquivo:

```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}"
```

Em seguida, extraia o arquivo:

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

O arquivo compactado é extraído para um único diretório contendo `aws/production`, `aws/minimal`, `aws/existing-vpc`, `aws/existing-eks` e `aws/modules`. As raízes referenciam os módulos como `../modules`. Mantenha a árvore extraída intacta, em vez de copiar uma raiz isoladamente para fora dela. Os READMEs das raízes no arquivo compactado podem mostrar a transição para o `init` sem `--platform-bundle`; o comando correto é o indicado em [inicializar o connector a partir das saídas do Terraform](#hand-off).

## 3. Configure e aplique a raiz selecionada

No diretório raiz, copie o arquivo de variáveis de exemplo e preencha-o:

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

Toda raiz exige `region`, `cluster_name` e `chart_repository_arn`. `cluster_name` define o nome do cluster, serve de prefixo para todos os recursos e é o valor da tag de descoberta. Em `production`, `minimal` e `existing-vpc`, ele deve ter de 3 a 32 caracteres entre letras minúsculas, dígitos e hifens, começando com uma letra e sem terminar com hífen. `existing-eks` recebe o nome do cluster que você já executa, com até 32 caracteres. `chart_repository_arn` é o repositório ECR do chart do cluster ClickHouse, fornecido pela sua equipe de conta no [cadastro](/docs/pt-BR/products/bring-your-own-cloud/connector/onboarding#registration). As raízes que criam um cluster também exigem `cluster_admin_principal_arns`, os principals que recebem permissões de administrador do cluster por meio de entradas de acesso do EKS. A identidade que executa a raiz deve estar nessa lista; caso contrário, não conseguirá acessar o cluster depois. O criador do cluster não recebe nenhum acesso implícito. Por raiz:

* `minimal` exige `endpoint_public_access_cidrs`, a allowlist IPv4 do endpoint público da API. A rede a partir da qual você executa `init` e `kubectl` precisa estar nela. Um `/0` é recusado, a menos que `allow_public_endpoint_from_anywhere = true`. Com `endpoint_public_access = false`, a lista pode ficar vazia e o endpoint passa a ser apenas privado, como em `production`.
* `existing-vpc` exige `vpc_id` e `private_subnet_ids`. `public_subnet_ids` é opcional e serve para balanceadores de carga expostos à internet.
* `existing-eks` não tem outras variáveis obrigatórias. `install_addons` indica os addons gerenciados que faltam no cluster, e `ebs_kms_key_arn` fornece uma chave para os volumes do serviço.

Em seguida, execute init, plan e apply:

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

O arquivo compactado não inclui um arquivo de bloqueio de providers. O comando `terraform providers lock` gera esse arquivo para que você faça commit dele na sua cópia. Por padrão, o state é local. O arquivo `versions.tf` traz um bloco `backend "s3"` comentado que mostra a estrutura de um state compartilhado.

> [!NOTE]
>
> Os endpoints de API de `production` e `existing-vpc` são privados. Execute `init` e `kubectl` de dentro da VPC (por meio de um encaminhamento de porta via SSM para um nó do sistema, um bastion, uma VPN ou uma rede com peering) ou habilite o acesso público com `endpoint_public_access = true` e uma allowlist em `endpoint_public_access_cidrs`.

## 4. Inicialize o connector usando as saídas do Terraform

Exporte as saídas e passe-as para o `init`, junto com o pacote da plataforma, em uma máquina cujo contexto do kube aponte para o novo cluster:

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

Os roots oferecem suporte apenas ao target Helm. Em uma VM (`--target systemd`), o `init` recusa `--platform-bundle`, e `clicklink clctl platform approve --bundle` instala apenas os componentes fixados, de modo que o cluster fica sem provisionador de nós. Use `--target systemd` somente para connectors que registram um ClickHouse executado por você mesmo; essa opção não é compatível com esses roots.

`--platform-bundle` instala o que os roots deixam de fora: o Karpenter com um `EC2NodeClass` e os NodePools `clickhouse-server` e `clickhouse-keeper`, o controller AWS Load Balancer, a StorageClass `gp3-encrypted` (criptografada com a chave do EBS quando os outputs incluem uma) e os componentes da plataforma fixados pelo pacote: o snapshot controller, o ClickHouse operator e os collectors de monitoramento. O pacote é o manifesto da plataforma que o ClickHouse Cloud gera para o seu ambiente; sua equipe de conta o entrega durante o onboarding, e a seção `cluster:` dele fixa as versões do Karpenter e do controller do balanceador de carga. A flag exige `--target helm`, `--managed` e `--from-terraform`. Componentes já presentes são mantidos como estão, portanto é seguro executar o comando novamente, e o `init` exibe um relatório do que instalou, do que ignorou e por quê. Sem a flag, o `init` registra o connector, mas não instala nenhum desses itens, e o cluster só consegue executar um serviço depois que eles estiverem disponíveis. As [atualizações da plataforma](/docs/pt-BR/products/bring-your-own-cloud/connector/platform-updates) posteriores alteram o snapshot controller, o operator e os collectors; o Karpenter, o controller do balanceador de carga e a StorageClass permanecem como o `init` os instalou.

`--from-terraform` aceita tanto o documento completo exibido por `terraform output -json` quanto apenas o objeto retornado por `terraform output -json clicklink`. O output `clicklink` contém a identidade do cluster (`account_id`, `region`, `cluster_name`, `cluster_endpoint`, `cluster_ca`), o provedor OIDC, o namespace do connector, a role IAM do executor (`executor_role_arn`), a chave do EBS, a role e a fila de nós do Karpenter, a role do controller do balanceador de carga e `system_node_selector`. O `init` lê do arquivo a identidade do cluster e o namespace do connector. Ele define `executor_role_arn` como a anotação IRSA na ServiceAccount `pcm-executor` do connector e aplica o seletor de nós aos pods do connector. Os serviços gerenciados não compartilham essa role: `clicklink clctl executor prepare` cria uma role por serviço (`CH-S3-<service>-<region>-00-Role` por padrão), vinculada ao serviço no momento de sua criação; consulte o [modelo de privilégios](/docs/pt-BR/products/bring-your-own-cloud/connector/reference/privilege-model#identities).

O `init` recusa flags como `--cluster-name` ou `--target-namespace` que divirjam do arquivo, informando os dois valores. Remova a flag ou corrija os outputs. Ele também recusa um contexto kube cujo servidor de API não seja `cluster_endpoint` ou cujo ARN do EKS aponte para outro cluster. O output tem um campo `schema`, atualmente `1`. O `clctl` recusa arquivos cujo `schema` não seja compatível.

O restante do registro segue o fluxo padrão descrito em [onboarding](/docs/pt-BR/products/bring-your-own-cloud/connector/onboarding#install-and-enroll).

## Chaves KMS e concessões necessárias

`production` e `existing-vpc` criam três chaves KMS gerenciadas pelo cliente, com rotação ativada, para os Secrets do EKS, os volumes EBS e os buckets de armazenamento de objetos, a menos que você informe ARNs em `kms`. `existing-eks` cria a chave de armazenamento, a menos que você defina `storage_kms_key_arn`, e aceita `ebs_kms_key_arn` para os volumes dos serviços, sem criar uma. `minimal` não cria nenhuma; sem `storage_kms_key_arn`, seus buckets continuam usando SSE-S3. Cada chave criada contém uma única instrução para a raiz da conta, que delega o acesso ao IAM. Uma chave fornecida por você precisa da mesma delegação ou das seguintes concessões em sua key policy:

| Chave | Principal | Ações |
| - | - | - |
| Secrets do 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` com a condição `kms:GrantIsForAWSResource = true` |
| Armazenamento | Cada `CH-S3-<service>-<region>-00-Role` criada por `clicklink clctl executor prepare --storage-kms-key-arn` | `kms:Decrypt`, `kms:GenerateDataKey`, `kms:DescribeKey` |
| Armazenamento | `<cluster_name>-clicklink-executor`, para o registro de chave `_tde/` ao lado dos backups de um serviço | `kms:GenerateDataKey`, `kms:Decrypt` |

Os módulos raiz anexam, em qualquer caso, as políticas da IAM role para as chaves dos Secrets do EKS e do EBS, além da política da chave de armazenamento do executor sempre que o módulo raiz tiver uma chave de armazenamento; `executor prepare` anexa a política da função de cada serviço. Os volumes raiz dos nós do sistema armazenam imagens e logs do agente de nó do Kubernetes, e não dados dos serviços, e usam a chave EBS padrão da conta.

## Destruir a infraestrutura gerenciada pelo Terraform

O `terraform destroy` remove o que a raiz criou. As chaves KMS criadas entram em uma janela de exclusão de 30 dias. Os grupos de logs são excluídos junto com os logs retidos, portanto exporte antes o que for necessário. As instâncias iniciadas pelo Karpenter e os volumes criados pelo ClickHouse Operator não constam no estado do Terraform; exclua seus serviços e desinstale o Karpenter antes, caso contrário a exclusão da VPC e da função dos nós falhará.

O `existing-eks` mantém o cluster. Ele remove as funções, a fila e as regras de interrupção, a entrada de acesso e as tags que adicionou. Os addons `vpc-cni`, `kube-proxy` e `coredns` que ele instalou deixam de ser gerenciados pelo EKS, e seus pods continuam em execução. Se ele tiver instalado um addon do driver EBS CSI, esse addon é removido junto com a raiz, pois sua função IRSA também é destruída. Para manter o driver, recrie o addon com sua própria função antes de executar o destroy.

O destroy remove todas as tags que essas raízes adicionaram, inclusive uma tag `kubernetes.io/role/internal-elb` que já existia antes da raiz, porque o `aws_ec2_tag` assume a propriedade de tags existentes. Para mantê-las, defina `manage_subnet_tags = false` (`existing-vpc`) ou `manage_discovery_tags = false` (`existing-eks`) e aplique a alteração antes de destruir, ou execute `terraform state rm` nos recursos `aws_ec2_tag`.
