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
- 2. Instalação e Configuração
- 3. Primeiro Projecto em Python
- 4. Implantação de Infraestrutura
- 5. Backends Auto-alojados
- 6. Pulumi vs Terraform/OpenTofu
- 7. Erros Comuns e Lista de Verificação
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.