Pular para o conteúdo

Pulumi e CDK

Avançado14 min de leituraiac

HCL é uma linguagem de configuração: não tem laço de verdade, condicional expressiva nem tipos ricos, e ninguém escreve teste unitário para ela. Pulumi, AWS CDK e CDKTF partem da ideia oposta — descrever infraestrutura em TypeScript, Python, Go ou C#, com abstração, tipo e teste da linguagem que o time já usa.

A promessa é real. O custo também, e ele aparece meses depois.

Ganha-se reuso com tipos, IDE que completa e verifica, laço e condicional naturais, teste unitário da lógica de composição, e uma linguagem só para aplicação e infraestrutura.

Paga-se com poder demais: em HCL, a pior coisa que alguém faz é repetir um bloco; em TypeScript, alguém escreve uma fábrica de construtores com herança e o plan deixa de ser previsível. Some a isso a barreira para quem opera e não programa naquela linguagem, e a dependência de um ecossistema de bibliotecas e versões.

O critério prático: o time inteiro que vai manter isso programa com conforto nessa linguagem? Se a resposta for “duas pessoas sim, o resto não”, HCL é a escolha responsável.

Pulumi usa os mesmos providers do Terraform por baixo e mantém state em backend próprio (Pulumi Cloud) ou no seu bucket. O ciclo é o mesmo: preview e up.

import * as aws from "@pulumi/aws";
const ambientes = ["dev", "hom", "prod"];
for (const ambiente of ambientes) {
const bucket = new aws.s3.BucketV2(`relatorios-${ambiente}`, {
bucket: `empresa-relatorios-${ambiente}`,
});
new aws.s3.BucketPublicAccessBlock(`bloqueio-${ambiente}`, {
bucket: bucket.id,
blockPublicAcls: true,
blockPublicPolicy: true,
});
}
Janela do terminal
pulumi preview --diff # equivalente ao plan: leia antes de aplicar
pulumi up
pulumi stack output --show-secrets

O nome lógico do recurso (o primeiro argumento) é o endereço no state. Alterá-lo destrói e recria — é o for_each com chave errada do Terraform, com outra roupa.

O AWS CDK sintetiza CloudFormation e é a opção mais integrada quando você vive só na AWS. O CDKTF sintetiza JSON do Terraform e roda no ciclo plan/apply de sempre, o que permite adotar a linguagem sem trocar o motor nem o state.

Em qualquer um deles, gere o artefato intermediário e revise-o no pull request:

Janela do terminal
cdktf synth # gera cdktf.out/*.tf.json — versione o diff no PR
cdk diff # mostra o que muda no CloudFormation

Sem essa etapa, o revisor lê uma mudança de código e não faz ideia de qual recurso vai ser destruído. Com ela, você recupera a leitura que o HCL dava de graça.

Aqui está o ganho mais defensável: verificar regras da sua organização em teste unitário, rápido, sem tocar na nuvem.

test("bucket nunca é público", async () => {
const infra = await import("./index");
const bloqueio = await promise(infra.bloqueio.blockPublicAcls);
expect(bloqueio).toBe(true);
});

Isso vale principalmente para quem escreve abstrações consumidas por outros times — um componente interno “serviço web padrão” com testes vale mais que o mesmo componente em HCL. Para quem só declara vinte recursos, o teste unitário rende pouco perto do custo.

Os sintomas de que a liberdade virou dívida:

  • Ninguém consegue dizer quais recursos existem sem executar o programa.
  • O diff do preview muda quando ninguém mudou infraestrutura (lógica dependente de data, variável de ambiente, ordem de map).
  • Há herança de três níveis entre componentes.
  • O upgrade de uma biblioteca muda o nome lógico de recursos e propõe recriar produção.

Regras que mantêm isso sob controle: nada de aleatoriedade ou de dependência de relógio no código de infraestrutura; nomes lógicos explícitos e estáveis; abstração só depois da terceira repetição; e o artefato sintetizado sempre visível na revisão.

  • HCL (Terraform/OpenTofu) — padrão para a maioria dos times; mais gente sabe ler, ecossistema maior, menos formas de errar.
  • CDKTF/Pulumi — quando o time é de desenvolvimento, a lógica de composição é genuinamente complexa e existe quem mantenha os testes.
  • AWS CDK — quando você é AWS-only e já usa CloudFormation.
  • Crossplane — quando o Kubernetes é a interface de plataforma; é o assunto da próxima página.

Misturar mais de uma abordagem no mesmo domínio é o pior dos mundos: dois states, duas convenções e nenhuma pessoa que entenda o conjunto.

Próximo passo: veja a alternativa que usa a API do Kubernetes como plano de controle em Crossplane.