- Gerenciamento de Estado — Inicializa o bucket S3 usado para armazenar o estado do Terraform do ambiente.
- Infraestrutura EKS — Provisiona a VPC, sub-redes, NAT gateways, funções IAM e o cluster EKS e node groups gerenciados.
- Armazenamento e Balanceamento de Carga — Implantar o EBS CSI driver para volumes persistentes e o AWS Load Balancer Controller para ingress ALB.
- Escalação Automática Karpenter — Configura provisionamento dinâmico de nós com suporte a instâncias Spot e tratamento de interrupção via SQS e EventBridge.
- Escalação Automática KEDA — Implantar o KEDA para escalação automática em nível de pod baseada em limites de CPU e memória.
- Serviços de Dados — Provisionar Supabase (auto-hospedado ou Cloud), ElastiCache Redis e Amazon MQ RabbitMQ.
- Serviços Odin — Implantar a pilha de aplicação EKB (Web, FastAPI, Celery, Automator) via Helm.
- Observabilidade SigNoz — Implantar rastreamento distribuído, métricas e agregação de logs via SigNoz e o agente k8s-infra.
- Implantação Final — Executar um
terragrunt applycompleto para reconciliar quaisquer recursos restantes.
<YOUR_*> no template do ambiente estejam preenchidos. Vários valores — incluindo o ID da VPC, endpoint do cluster EKS e endpoints Redis e RabbitMQ — só estão disponíveis após a conclusão de fases específicas, portanto o guia indica exatamente quando capturá-los e aplicá-los.
Pré-requisitos
- AWS CLI configurada com permissões apropriadas
- Terraform (>= 1.0)
- Terragrunt (versão mais recente)
kubectlpara gerenciamento do Kuberneteshelmpara gerenciamento de charts Helm
Guia de Instalação
Instalando o Terragrunt
macOS (Homebrew)Instalando o kubectl
macOS (Homebrew)Instalando o Helm
macOS (Homebrew)Verificando a Instalação
Configuração da AWS CLI
Criando um Novo Ambiente
Passo 1: Copie o Template do Ambiente
A pastaenv-template-folder contém arquivos pré-estruturados com placeholders <YOUR_*> prontos para serem preenchidos. Copie-a inteiramente para criar sua nova pasta de ambiente.
Passo 2: Verifique se Todos os Placeholders Estão Presentes
<YOUR_*>. Os passos abaixo orientam sobre como preenchê-los arquivo por arquivo.
Passo 3: Provisionar Certificados SSL (AWS ACM)
Antes de definir variáveis de ambiente, você precisa dos ARNs dos certificados. Use o Console AWS para solicitar certificados SSL no AWS Certificate Manager (ACM) para todos os domínios que seu ambiente servirá. Opção A: Certificado wildcard único (recomendado) Um único certificado wildcard cobre todos os subdomínios com um único ARN. Por exemplo, se seu domínio base forapp.example.com, um único certificado *.app.example.com cobre:
Opção B: Certificados por serviço
Solicite um certificado por domínio se não puder usar um wildcard. Repita os passos abaixo para cada domínio:
<YOUR_WEB_DOMAIN>, <YOUR_API_DOMAIN>, <YOUR_AUTOMATOR_DOMAIN>, <YOUR_SUPABASE_DOMAIN> (apenas se ENABLE_SUPABASE=true), <YOUR_SIGNOZ_DOMAIN> (apenas se ENABLE_SIGNOZ=true).
Solicitando um certificado no Console AWS
- Abra o console do AWS Certificate Manager
- Mude para a região correta (canto superior direito) — deve corresponder a
<YOUR_AWS_REGION> - Clique em Request a certificate → Request a public certificate → Next
- Em Fully qualified domain name, insira o wildcard (por exemplo,
*.app.example.com) ou um domínio específico - Defina Validation method como DNS validation
- Clique em Request — o certificado é criado no estado
Pending validation
Inclua o ponto final (
.) no final dos valores CNAME se seu provedor DNS exigir.- Faça login no Cloudflare → selecione seu domínio → vá para DNS → Records → Add record
- Defina Type como
CNAME - Cole o nome CNAME do ACM em Name e o valor CNAME do ACM em Target
- Defina Proxy status como DNS only (ícone de nuvem cinza) — o certificado não será validado através do proxy Cloudflare
- Clique em Save
- Abra o console Route 53 → Hosted zones → selecione sua zona → Create record
- Defina Record type como
CNAME - Cole o nome CNAME do ACM em Record name (apenas a parte do subdomínio) e o valor em Value
- Defina TTL como
300e clique em Create records
arn:aws:acm:<regiao>:<account-id>:certificate/<uuid>. Mantenha o(s) ARN(s) à mão para o próximo passo.
Passo 4: Defina as Variáveis de Ambiente
Defina estas variáveis de ambiente do shell antes de executar quaisquer comandos Terragrunt. Elas são lidas diretamente porterragrunt.hcl via get_env().
Instâncias Spot e Cargas de Trabalho Estatais
As instâncias Spot são configuradas por NodePool emvalues/karpender.yaml, não via variáveis de ambiente. Cada NodePool declara sua própria estratégia de capacidade:
O NodePool
application usa famílias de instâncias m/c (geração 5+) com apenas On-Demand. Os pods do serviço Supabase são fixados aqui via nodeSelector: workload-type: "application" para garantir que nunca sejam interrompidos por um evento de reivindicação Spot.
O NodePool database-dedicated nunca usa Spot. Ele usa consolidationPolicy: WhenEmpty para que o Karpenter não evicta um nó que ainda tem um pod em execução, tornando-o seguro para cargas de trabalho estatais como réplicas PostgreSQL e CloudNativePG.
Diretrizes para aplicações estatais no Spot:
- Não agende bancos de dados, filas persistentes ou qualquer pod com
PersistentVolumeClaimem NodePools Spot. - Use um
nodeSelectordirecionandonode-type: database-dedicatedcom a toleração correspondentedatabase-workload: "true"para pods de banco de dados. - Use
nodeSelector: workload-type: "application"para serviços sem estado面向 ao usuário que devem permanecer disponíveis sem interrupção. - Para cargas de trabalho em segundo plano (Web, API, Celery, Automator), o NodePool Spot
generalé apropriado — o tratador de interrupção SQS do Karpenter drena nós Spot graciosamente antes que a AWS os reivindique, e a contagem mínima de réplicas do KEDA (≥ 2) garante disponibilidade durante a substituição de nós. - Para desabilitar Spot globalmente, remova
"spot"da lista de valores em cada NodePool dentro devalues/karpenter.yaml.
karpenter em terragrunt.hcl:
Passo 5: Atualize os Valores Específicos do Ambiente
Faça uma busca e substituição em todos os arquivos na sua nova pasta de ambiente para os seguintes placeholders:5.1 terragrunt.hcl — Configuração principal do cluster
5.2 state/terragrunt.hcl — Bucket de estado S3
5.3 values/infrastructure.yaml — AWS Load Balancer Controller
5.4 values/karpenter-values.yaml — Controlador Karpenter
5.5 values/karpenter-nodeclasses.yaml — Classes de nós Karpenter
5.6 values/aws-ebs-csi-driver.yaml — EBS CSI Driver
5.7 values/karpenter.yaml — Karpenter NodePools
Os nomes das classes de nós (
general, compute-intensive, memory-intensive, gpu, database) devem corresponder às entradas em karpenter-nodeclasses.yaml.
5.8 values/keda.yaml — Escalonador KEDA
Nenhum placeholder específico do ambiente é necessário. Limites de recursos e contagens de réplicas são pré-configurados com padrões sensatos. Revise e ajuste se necessário.
5.9 values/supabase.yaml — Aplicação Supabase (apenas se ENABLE_SUPABASE=true)
5.10 values/ha-supabase-db.yaml — Supabase HA Database (apenas se ENABLE_HA_SUPABASE_DB=true)
A classe de armazenamento (
ebs-csi-gp2), contagens de instâncias e limites de recursos são pré-configurados. Ajuste postgres.storage.size e postgres.walStorage.size para o volume de dados esperado.
5.11 values/cloudnative-pg.yaml — Operador CloudNativePG (apenas se ENABLE_CNPG=true)
Nenhum placeholder específico do ambiente é necessário. Isto implanta apenas o controlador do operador CNPG. As configurações padrão (3 réplicas, limites de recursos) são adequadas para a maioria dos ambientes.
5.12 values/odin-services.yaml — Serviços de aplicação Odin
Supabase (
dataServiceConfig) — auto-hospedado (ENABLE_SUPABASE=true):
Supabase (
dataServiceConfig) — Supabase Cloud (ENABLE_SUPABASE=false):
Redis:
ENABLE_SUPABASE=true):
Chaves Supabase do frontend web — Supabase Cloud (
ENABLE_SUPABASE=false):
5.13 values/signoz.yaml — Observabilidade SigNoz (apenas se ENABLE_SIGNOZ=true)
5.14 values/signoz-k8s-infra.yaml — Métricas SigNoz K8s (apenas se ENABLE_SIGNOZ=true)
O endpoint do coletor OTel (
signoz-otel-collector.monitoring.svc.cluster.local:4317) é pré-configurado assumindo que tanto SigNoz quanto k8s-infra são implantados no namespace monitoring. Nenhuma alteração é necessária, a menos que você use um nome de release personalizado.
Lembrete da Ordem de Implantação
Alguns valores só estão disponíveis após a implantação de certa infraestrutura. Siga esta ordem:- Antes de qualquer implantação — Defina:
<YOUR_ENV_NAME>,<YOUR_AWS_REGION>,<YOUR_AWS_ACCOUNT_ID>,<YOUR_ENVIRONMENT>,<YOUR_PROJECT>,<YOUR_VPC_CIDR>, todos os nomes de domínio, todos os ARNs de certificado, todos os valores do Supabase,<YOUR_TOOLKIT_ENCRYPTION_KEY>, nome de usuário/senha do RabbitMQ - Após criação do cluster EKS — Defina:
<YOUR_VPC_ID>(infrastructure.yaml),<YOUR_EKS_CLUSTER_ENDPOINT>(karpenter-values.yaml) - Após
terraform applypara serviços AWS — Defina:<YOUR_REDIS_HOST>,<YOUR_RABBITMQ_HOST>(odin-services.yaml)
Passo 6: Verifique se Não Há Placeholders Restantes
Fase 1: Configuração do Gerenciamento de Estado
Finalidade: Criação do bucket S3 para o estado do Terraform. O módulo de gerenciamento de estado de cada ambiente cria um bucket S3 com o padrãoodin-terraform-state-{nome-do-ambiente}, configura criptografia, versionamento e bloqueio de acesso público, e usa estado local para o próprio módulo de estado (padrão de inicialização).
Fase 2: Implantação da Infraestrutura EKS
Finalidade: Rede principal (VPC, sub-redes, NAT gateway), funções e políticas IAM, cluster EKS e node groups gerenciados.2.1 Execução Seca — Infraestrutura EKS
Infraestrutura PrincipalUsando um Registro Docker Personalizado / Privado
Por padrão, as imagens EKB são puxadas do Docker Hub usando um segredo chamadoregcred. Se o cliente hospeda imagens em um registro diferente, siga estes passos antes de implantar odin-services.
Passo 1 — Criar o imagePullSecret no namespace alvo
values/odin-services.yaml
2.2 Implantar Infraestrutura EKS
Passo 1: Infraestrutura PrincipalFase 3: Armazenamento e Balanceamento de Carga
Finalidade: EBS CSI driver para volumes persistentes, AWS Load Balancer Controller rodando no node group gerenciado.3.1 Execução Seca — Armazenamento e Balanceamento de Carga
EBS CSI Driver3.2 Implantar Armazenamento e Balanceamento de Carga
Passo 1: EBS CSI DriverFase 4: Escalação Automática Karpenter
Finalidade: Funções IAM para Karpenter, tratamento de interrupção Spot, controlador Karpenter e node pools.4.1 Execução Seca — Karpenter
Recursos IAM do Karpenterterragrunt.hcl)
Um erro esperado pode aparecer durante o plan:
API did not recognize GroupVersionKind from manifest (CRD may not be installed). Isto pode ser ignorado com segurança — o Kubernetes valida recursos contra a API ao vivo durante o plan, antes que os CRDs sejam instalados.4.2 Implantar Karpenter
Passo 1: Recursos IAM do Karpenterterragrunt.hcl)
Fase 5: Escalação Automática KEDA
Finalidade: KEDA para escalação automática em nível de aplicação.5.1 Execução Seca — KEDA
5.2 Implantar KEDA
Fase 6: Serviços de Dados
Finalidade: Supabase (banco de dados), ElastiCache (Redis), RabbitMQ (fila de mensagens).Implante primeiro o operador CloudNativePG, depois o cluster HA Supabase DB, e então a aplicação Supabase. O cluster DB deve estar pronto antes que o Supabase inicie.
6.1 Execução Seca — Serviços de Dados
Passo 1: Operador CloudNativePG (se habilitado)6.2 Implantar Serviços de Dados
Passo 1: Operador CloudNativePG (se habilitado)EXTERNAL-IP se LoadBalancer) como valor de SUPABASE_POSTGRES_HOST em values/odin-services.yaml e como secret.db.postgresHost em values/supabase.yaml.
Passo 3: Aplicação Supabase (se habilitada)
Todos os pods do serviço Supabase rodam exclusivamente no NodePool application do Karpenter (apenas On-Demand) para prevenir interrupções Spot.
Fase 7: Serviços Odin
Finalidade: Implantação de aplicação via Helm.Antes de implantar, reduza temporariamente o
fastapiBackend para uma única réplica para a execução inicial de migração do banco de dados — defina replicaCount: 1, workers: 1 e keda.minReplicas: 1. Uma vez que a migração seja concluída com sucesso, reverta esses valores para seus padrões de produção antes de reimplementar.7.1 Execução Seca — Serviços Odin
7.2 Implantar Serviços Odin
Fase 8: Observabilidade SigNoz
Finalidade: Monitoramento de logs e métricas.8.1 Execução Seca — Charts SigNoz
8.2 Implantar Charts SigNoz
Fase 9: Implantação Final
9.1 Implantação Completa
9.2 Verificar Implantação
Solução de Problemas
Problemas de lock de estadoLimpeza
Monitoramento e Logging
Referência Rápida — Todos os Comandos de Implantação
Substitua
nome-do-seu-ambiente pelo nome do seu ambiente real ao longo de todo o processo. Sempre execute execuções secas (terragrunt plan) primeiro para validar sua configuração antes de aplicar alterações.