Pular para o conteúdo

Crossplane

Avançado14 min de leituraiac

Crossplane transforma o Kubernetes em plano de controle para infraestrutura: um bucket, um banco ou uma fila viram recursos da API do cluster, reconciliados continuamente por controladores. Em vez de um apply que roda quando alguém executa o pipeline, você tem o mesmo laço de convergência que já mantém seus Deployments no lugar.

A diferença conceitual em relação ao Terraform é essa: reconciliação contínua em vez de execução pontual. Alguém mudou o bucket no console? O controlador desfaz sozinho, em minutos, sem esperar o próximo pipeline.

O provider instala CRDs para os recursos daquela nuvem. A credencial fica no cluster, com RBAC controlando quem pode criar o quê.

apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
metadata: { name: empresa-relatorios-prod }
spec:
forProvider:
region: sa-east-1
providerConfigRef: { name: aws-prod }
deletionPolicy: Orphan # apagar o recurso do cluster NÃO destrói o bucket
Janela do terminal
kubectl get managed # tudo que o Crossplane gerencia
kubectl describe bucket empresa-relatorios-prod # eventos explicam falha de provisão

deletionPolicy é o primeiro ajuste a fazer conscientemente: por padrão, apagar o objeto no cluster destrói o recurso na nuvem. Um kubectl delete errado, ou um namespace removido, vira perda de dado. Para recurso com estado, use Orphan e proteja com política de admissão.

O ganho real não é declarar bucket em YAML — é publicar uma abstração para os times de produto. Você define um tipo próprio (PostgresDB) e a composição decide o que isso significa na sua organização: instância, sub-rede, backup, alarmes e Secret com a conexão.

# O time de produto escreve só isto:
apiVersion: plataforma.exemplo.com/v1alpha1
kind: PostgresDB
metadata: { name: loja-prod, namespace: loja }
spec:
tamanho: medio
ambiente: prod
writeConnectionSecretToRef: { name: loja-db }

Por trás, a Composition materializa cinco ou dez recursos com os padrões da empresa já embutidos: criptografia ligada, backup de 30 dias, sem acesso público, tags de custo. É o mesmo objetivo de um bom módulo Terraform, com duas vantagens: a interface é uma API Kubernetes de verdade (com RBAC, validação e kubectl explain) e o estado converge sozinho.

O preço: escrever e depurar Composition é trabalho de plataforma, não de fim de semana. Composition Functions melhoraram muito a expressividade, mas a curva existe.

Não é uma escolha excludente, e a divisão que funciona costuma ser:

Terraform/OpenTofu Crossplane
Fundação (rede, contas, o próprio cluster) ✅ ❌ (dependência circular)
Recursos por aplicação, sob demanda ok ✅
Autoatendimento para times de produto via pipeline ✅ pela API do cluster
Correção automática de drift por job agendado ✅ contínua
Maturidade de ecossistema e de pessoas ✅ menor

A dependência circular é o limite mais importante: o cluster que roda o Crossplane precisa existir antes, e não pode ser gerenciado por ele. Provisione a fundação com Terraform.

Existe ainda o caminho híbrido — o provider de Terraform dentro do Crossplane — mas ele soma as duas complexidades; use por transição, não como destino.

Como tudo é objeto do cluster, Argo CD ou Flux aplicam esses manifests do Git, e você recupera revisão e histórico:

Git → Argo CD → CRs do Crossplane → controladores → nuvem

Sem GitOps, você trocou “quem aplicou o Terraform” por “quem fez kubectl apply”, que é pior — não há plano para revisar antes.

Crossplane compensa quando: existe um time de plataforma dedicado, o Kubernetes já é a interface do dia a dia, vários times precisam de autoatendimento e o drift contínuo é uma dor real. Não compensa quando o cluster é novo, a infraestrutura muda uma vez por mês, ou não há quem depure um controlador em incidente — nesses casos, um módulo Terraform bem feito entrega quase o mesmo valor com muito menos peça em movimento.

E lembre do que muda no plantão: um erro de composição não falha um pipeline, ele reconcilia continuamente. Coloque observabilidade nos controladores e alerta para recurso que não fica Ready antes de abrir para os times.

Próximo passo: feche a trilha garantindo que essas mudanças são verificadas antes de existir, em Testando infraestrutura.