Pulumi: Infrastructure as Code com Python e TypeScript para PME

O Pulumi é uma ferramenta de Infrastructure as Code (IaC) que permite definir infraestrutura na nuvem usando linguagens de programação reais como Python, TypeScript e Go. Ao contrário do Terraform, que usa uma DSL própria (HCL), o Pulumi aproveita o ecossistema, as ferramentas e o conhecimento que a equipa já tem. Neste artigo explicamos como instalar, configurar backends auto-alojados e fazer a implantação de infraestrutura numa PME.

ℹ O Pulumi usa linguagens de programação reais (Python, TypeScript, Go) — não precisa de aprender uma DSL própria.

Neste artigo

1. Introdução ao Pulumi

O Pulumi é uma plataforma de código aberto de Infrastructure as Code lançada em 2018. A ideia central é simples: em vez de aprender uma linguagem declarativa específica (como HCL do Terraform), o engenheiro escreve infraestrutura numa linguagem que já conhece. Isto significa que pode usar funções, loops, classes, tipos e bibliotecas padrão para gerar configuração dinâmica.

Para uma PME, isto traduz-se numa vantagem concreta: a equipa de desenvolvimento que já escreve Python ou TypeScript não precisa de aprender uma sintaxe nova para gerir infraestrutura. A integração é mais rápido e o código é testável com as mesmas ferramentas (pytest, jest, depuradores).

O Pulumi suporta os principais fornecedores de nuvem (Azure, AWS, Google Cloud), fornecedores auto-alojados (Hetzner, DigitalOcean, Vultr) e Kubernetes. O estado da infraestrutura pode ser guardado no serviço Pulumi Cloud (gratuito até 333 recursos) ou num backend auto-alojado — ficheiro local, S3, Azure Blob ou um servidor próprio.

2. Instalação e Configuração

O Pulumi instala-se com um único comando no Linux, macOS e Windows. O instalador adiciona o binário ao PATH e configura o directório ~/.pulumi.

# Instalar Pulumi
curl -fsSL https://get.pulumi.com | sh
# Verificar instalação
pulumi version
# Login com backend auto-alojado
pulumi login --auto-alojado https://pulumi-api.exemplo.pt
# Ou usar backend local (ficheiro)
pulumi login file://./pulumi-state

Após a instalação, é necessário configurar as credenciais do fornecedor de nuvem. Para Azure, usa-se o az login; para AWS, aws configure; para Hetzner, define-se a variável de ambiente HCLOUD_TOKEN.

⚠ Configurar PULUMI_ACCESS_TOKEN e backend antes da primeira implantação — sem isso, o estado fica local e não é partilhado.

3. Primeiro Projecto em Python

Um projecto Pulumi em Python começa com pulumi new, que cria a estrutura de directórios, o ficheiro Pulumi.yaml (configuração do projecto) e um ambiente virtual Python.

# Novo projecto Python (Azure)
pulumi new azure-python
# Para AWS
pulumi new aws-python
# Para Hetzner
pulumi new https://github.com/pulumi/pulumi-hetzner/tree/main/examples/server

O ficheiro principal é __main__.py. Aqui definimos os recursos usando os pacotes do fornecedor. O exemplo abaixo cria um resource group e uma virtual network no Azure:

# main.py exemplo
import pulumi_azure as azure

rg = azure.core.ResourceGroup(
    'rg-pme',
    location='westeurope'
)

vnet = azure.network.VirtualNetwork(
    'vnet',
    resource_group_name=rg.name,
    address_space=['10.0.0.0/16']
)

# Exportar saídas
pulumi.export('resource_group', rg.name)
pulumi.export('vnet_id', vnet.id)

A vantagem sobre HCL é evidente: pode usar loops for, condições if, ler configuração de ficheiros JSON/YAML e estruturar o código em funções e módulos reutilizáveis.

4. Implantação de Infraestrutura

A implantação faz-se com pulumi up. O comando mostra uma pré-visualização dos recursos que vão ser criados, modificados ou removidos, e pede confirmação antes de aplicar.

# Implantação (com pré-visualização interactivo)
pulumi up
# Implantação sem confirmação (CI/CD)
pulumi up --yes
# Verificar estado actual
pulumi stack ls
# Ver saídas exportados
pulumi stack output
# Destruir infraestrutura
pulumi destroy

As stacks permitem gerir múltiplos ambientes (dev, staging, produção) com a mesma base de código. Cada stack tem a sua própria configuração e estado. Para separar valores por ambiente, usa-se pulumi config set:

# Criar stack de produção
pulumi stack init produção
# Definir configuração por stack
pulumi config set azure-native:location westeurope
# Valores secretos (cifrados)
pulumi config set --secret db_password MinhaSenhaForte
# Ler configuração no código
config = pulumi.Config()
location = config.get('azure-native:location') or 'westeurope'

Em TypeScript, o mesmo projecto usa pulumi new azure-typescript e a lógica é equivalente — a escolha da linguagem é preferência da equipa.

5. Backends Auto-alojados

O estado da infraestrutura — que recursos foram criados, as suas dependências e outputs — pode ser guardado em vários backends. Para uma PME que prefira não depender do serviço Pulumi Cloud, existem opções auto-alojado.

Backend Comando Partilha de Estado
Ficheiro local pulumi login file://./state Não (utilizador único)
AWS S3 pulumi login s3://meu-bucket Sim (com bloqueio via DynamoDB)
Azure Blob pulumi login azblob://container Sim (com concessão)
Servidor auto-alojado pulumi login –auto-alojado URL Sim (multi-equipa)

O backend auto-alojado exige um servidor com a API do Pulumi (código aberto, disponível no GitHub). Para a maioria das PME, o S3 ou Azure Blob com bloqueio é suficiente e mais simples de operar.

6. Pulumi vs Terraform/OpenTofu

O Terraform foi durante anos o padrão de IaC. O OpenTofu é a derivação de código aberto (licença MPL 2.0) criado após a HashiCorp mudar a licença do Terraform para BSL em 2023. Já abordamos o OpenTofu como alternativa ao Terraform. Como se compara o Pulumi?

Comparação Pulumi Terraform/OpenTofu
Linguagem Python, TypeScript, Go, C# HCL (DSL própria)
Testes pytest, jest nativos terratest (Go externo)
Licença Apache 2.0 MPL 2.0 (OpenTofu)
Estado Pulumi Cloud, S3, Blob, auto-alojado S3, Blob, Consul, Terraform Cloud
Curva de aprendizagem Baixa se já sabe Python/TS Média (HCL é simples mas nova)
Ecossistema de módulos Registry Pulumi + pacotes npm/pip Registry Terraform (maior)

Em resumo: se a equipa já é forte em Python ou TypeScript, o Pulumi reduz a fricção. Se a equipa já domina HCL e depende de módulos do Terraform Registry, o OpenTofu é a transição mais natural. Para automação de configuração de servidores após o deploy, o Ansible complementa qualquer uma das ferramentas.

7. Erros Comuns e Lista de Verificação

Os erros mais frequentes com Pulumi resultam de estado inconsistente, credenciais mal configuradas ou conflitos de dependências entre recursos.

Problema Causa Solução
Resource já existe Criado manualmente fora do Pulumi Importar com pulumi import
Estado corrompido Múltiplos devs a editar sem bloqueio Usar backend com bloqueio (S3+DynamoDB)
Credenciais expiradas Token Azure/AWS caducou Re-autenticar: az login / aws sso login
destroy sem remover dependências Ordem de dependências invertida pulumi destroy –target-dependents

Lista de verificação antes de uma implantação em produção:

  • Backend configurado com bloqueio activado (S3+DynamoDB ou Azure Blob)
  • Credenciais do fornecedor de nuvem válidas e com permissões minimizadas
  • Stack de produção separada de dev/staging (pulumi stack init produção)
  • Segredos guardados com --secret (nunca em texto simples no código)
  • Pré-visualização executada e revisado (pulumi up --preview)
  • Saídas exportadas para integração com ferramentas posteriores (CI/CD, Ansible)
  • Plano de destruição testado em ambiente não-produção

Para aprofundar conceitos de redes e infraestrutura que complementam este artigo, recomendamos o Dia 29 do Curso de Redes — SDN, OpenFlow e Open vSwitch. A documentação oficial completa está em pulumi.com/docs.