Abstrair o provider do Kubernetes num módulo
TLDR: Extrair o stack Kubernetes compartilhado para um módulo com abstração de provider, para que o mesmo
terraform applysirva tanto o cluster gerido da DigitalOcean quanto o EKS via uma única variávelprovider_type— transformando a migração para EKS numa troca de variável em vez de uma reescrita destrutiva e sem volta.
Contexto
O stack em src/shared/kubernetes/terraform/ era hardcoded no provedor antigo. A migração pendente para EKS seria uma reescrita in-place do stack: destrutiva e de mão única.
O resto do projeto já usa o padrão de abstração de provider (src/modules/providers/{cache,database,messagebroker,storage}/), onde uma variável provider_type seleciona a implementação e os outputs são normalizados. O Kubernetes era a única peça grande sem essa abstração.
Com a extração, a migração vira uma mudança de variável, e o rollback é igualmente simples. Os dois providers ficam no código, permitindo blue/green ou reversão rápida.
Objetivos
- Criar
src/modules/providers/kubernetes/com os sub-providersdigitaloceaneaws. - Manter todos os outputs existentes (
kubernetes_cluster_endpoint,kubernetes_cluster_token,kubernetes_cluster_ca_certificate,kubernetes_cluster_id,ingress_loadbalancer_ip) para não quebrar projeto consumidor. - Reescrever o
main.tfdo stack para delegar ao módulo novo. - Migrar os recursos existentes via
terraform state mv, no mesmo arquivo de state. - Ter a implementação AWS (EKS + node groups + LB de ingress) pronta, habilitável só virando o
provider_type.
Fora de escopo
rbac.tf,cert-manager.tf,ingress-controller.tf,metrics-server.tfedatadog.tfficam no nível do stack, sem mudança — falam apenas com a API do Kubernetes e são agnósticos de provedor.- Fazer o switch em si. Esta spec entrega a capacidade; virar a chave é outra decisão.
Mudanças
Novo: src/modules/providers/kubernetes/
kubernetes/
├── main.tf # provider_type → active = providers[provider_type]
├── variables.tf # interface unificada
├── outputs.tf # outputs normalizados, encaminhados do provider ativo
└── providers/
├── digitalocean/ # cluster gerido + node pools
└── aws/ # aws_eks_cluster + aws_iam_role + aws_eks_node_group
Mesmo padrão de src/modules/providers/database/: count = var.provider_type == "X" ? 1 : 0 mais um locals.active.
Modificado: src/shared/kubernetes/terraform/
main.tf— passa a chamarmodule "kubernetes".node-pools.tf— absorvido pelo módulo; apagado.variables.tf— ganhaprovider_type(default no provedor antigo, por segurança), mantémkubernetes_version, adiciona as variáveis de AWS (aws_region,eks_node_instance_types).outputs.tf— re-exporta os outputs do módulo com os mesmos nomes.data.tf— remote state condicional, conforme o provider.versions.tf—hashicorp/aws ~> 5.0ao lado do provider existente.
Migração de state
Feita uma vez, à mão, no momento do merge — sem script:
bash
cd src/shared/kubernetes/terraform
ward exec -- terraform state mv 'digitalocean_kubernetes_cluster.main' \
'module.kubernetes.module.digitalocean[0].digitalocean_kubernetes_cluster.this'
ward exec -- terraform state mv 'digitalocean_project_resources.kubernetes' \
'module.kubernetes.module.digitalocean[0].digitalocean_project_resources.this'
ward exec -- terraform plan # obrigatório: zero mudanças
Como fazer o switch depois
shared.network.apply(a VPC AWS já está rascunhada emsrc/shared/network/).provider_type = "aws"no vault.make shared.kubernetes.apply— o terraform destrói o cluster antigo e cria o EKS no mesmo workspace. Alternativa: blue/green num workspace temporário e cutover de DNS.
Rollback é o inverso: voltar o provider_type.
Como verificar
terraform plancom oprovider_typeoriginal mostra zero mudanças depois dostate mv— é o que prova que o refactor é não-destrutivo.terraform plancomprovider_type = "aws"mostra o grafo completo de EKS (cluster, node groups, IAM roles).- Todos os outputs existentes continuam resolvendo para os mesmos valores.
kubectl get nodescontinua funcionando contra o cluster antigo até o provider ser virado.
Documentação
CLAUDE.md— caminho do módulo novo.- Arquitetura de abstração — o padrão que esta spec aplica.
- Adicionar aprendizado sobre o padrão de
terraform state mvse ele revelar pegadinha não-óbvia.