7.2 KiB
Guia Pulumi
O que é Pulumi?
Pulumi é uma ferramenta de Infrastructure as Code (IaC): em vez de clicar no console da AWS, você descreve os recursos em código Python (ou outras linguagens) e o Pulumi cria, atualiza e destrói esses recursos de forma controlada e reproduzível.
Conceitos básicos
| Conceito | O que é |
|---|---|
| Projeto | O diretório com Pulumi.yaml — define o nome e a linguagem do projeto |
| Stack | Um ambiente independente do mesmo projeto (ex: dev, prod, Inovyo). Cada stack tem seu próprio estado e configuração |
| Estado | Arquivo que o Pulumi mantém mapeando cada recurso do código a um recurso real na AWS. É a "memória" do Pulumi |
pulumi preview |
Mostra o que vai mudar, sem aplicar nada — equivalente a um "dry run" |
pulumi up |
Aplica as mudanças: cria, atualiza ou remove recursos para corresponder ao código |
| Output | Valores exportados pelo código após o deploy (ex: a URL do ALB) |
Como o Pulumi sabe o que mudar?
- Você edita o código ou o arquivo de configuração
pulumi previewcompara o código com o estado salvo e mostra o diffpulumi upaplica o diff na AWS e atualiza o estado
Pré-requisitos
- Pulumi CLI instalado
- AWS CLI configurado com credenciais válidas para a conta
- Python 3.12+ e
venv
Estrutura do projeto
infra/ecs_alb/
├── Pulumi.yaml # Metadados do projeto (nome, runtime)
├── Pulumi.Inovyo.yaml # Configuração da stack "Inovyo" (região, VPC, ECS, env vars...)
├── __main__.py # Ponto de entrada — define ALB, cluster ECS e chama ecs.deploy_app()
├── conf.py # Lê as configurações do Pulumi e as expõe como variáveis Python
├── ecs.py # Cria task definition, service, target groups, listeners e auto-scaling
├── ecr.py # Referencia a imagem no ECR pelo digest ou tag
├── iam.py # Cria execution role e task role com políticas (Bedrock, DynamoDB, Secrets Manager...)
└── kms.py # Chave KMS (usada opcionalmente para criptografia de segredos)
Setup inicial
cd infra/ecs_alb
# Criar e ativar virtualenv
python -m venv .venv
source .venv/bin/activate
# Instalar dependências
pip install -r requirements.txt
# Selecionar a stack
pulumi stack select <stack-name>
Comandos principais
| Comando | O que faz |
|---|---|
pulumi preview |
Mostra o que será criado/alterado/destruído sem aplicar |
pulumi preview --diff |
Igual ao anterior, com diff detalhado de cada recurso |
pulumi up |
Aplica as mudanças na AWS |
pulumi up --yes |
Aplica sem pedir confirmação interativa |
pulumi destroy |
Remove todos os recursos da stack da AWS |
pulumi stack ls |
Lista todas as stacks do projeto |
pulumi stack output |
Exibe os outputs exportados (ex: URL do ALB) |
pulumi refresh |
Sincroniza o estado Pulumi com o estado real da AWS |
Sempre prefira pulumi preview antes de pulumi up para revisar o impacto das mudanças.
Arquivo de configuração: Pulumi.Inovyo.yaml
Toda a configuração da stack fica nesse arquivo. As seções principais:
Rede
app-ecs:network:
vpc_id: <vpc-id>
alb_internal: false
alb_subnet_ids: # Subnets públicas do ALB (mínimo 2, mesma região)
- <subnet-publica-1>
- <subnet-publica-2>
alb_allow_ingress_cidr: # IPs que podem acessar o ALB
- <ip-permitido>/32
ecs_subnet_ids: # Subnets privadas dos containers
- <subnet-privada-1>
- <subnet-privada-2>
ECS / Container
app-ecs:ecs:
- task_name: assisnte-analitico-db-dev
ecr_repo_name: assistente-analitico-db-dev
# Use ecr_image_digest OU ecr_image_tag (nunca os dois)
ecr_image_digest: sha256:<digest>
cpu: 256
memory: 512
desired_count: 1
use_load_balancer: true
auto_scaling:
min_capacity: 1
max_capacity: 3
target_value: 60.0 # % de CPU alvo para escalar
lb_configs:
- name: api
listener_port: 8000
target_port: 8000
container_port: 8000
- name: streamlit
listener_port: 8501
target_port: 8501
container_port: 8501
env_variables:
TABLE: poc_dnx_monthly_summary
REGION: us-east-1
Fluxo de deploy de nova imagem
Após buildar e publicar uma nova imagem Docker (veja deployment.md):
1. Obter o digest da nova imagem:
aws ecr describe-images \
--repository-name assistente-analitico-db-dev \
--region us-east-1 \
--query 'sort_by(imageDetails, &imagePushedAt)[-1].imageDigest' \
--output text
2. Atualizar o Pulumi.Inovyo.yaml:
ecr_image_digest: sha256:<novo-digest>
3. Revisar e aplicar:
cd infra/ecs_alb
pulumi preview --diff --stack <stack-name>
pulumi up --stack <stack-name>
Adicionar ou alterar variáveis de ambiente do container
Edite a seção env_variables em Pulumi.Inovyo.yaml e rode pulumi up. O Pulumi atualizará a task definition e forçará o re-deploy do serviço ECS automaticamente.
env_variables:
NOVA_VARIAVEL: valor
Verificar o output após o deploy
pulumi stack output --stack <stack-name>
Retorna a URL do ALB, por exemplo:
url: http://alb-assistente-analitico-xxxxxxxx.us-east-1.elb.amazonaws.com
Alterar capacidade de auto-scaling
Edite auto_scaling em Pulumi.Inovyo.yaml:
auto_scaling:
min_capacity: 1 # mínimo de tasks rodando
max_capacity: 5 # máximo de tasks
target_value: 70.0 # escala quando CPU média ultrapassar 70%
Depois rode pulumi up.
Permitir acesso ao ALB por Security Group
Por padrão, o acesso ao ALB é restrito por CIDR (alb_allow_ingress_cidr). Para permitir um security group no lugar de um IP, são necessárias duas alterações:
1. Edite __main__.py — troque cidr_blocks por security_groups na regra de ingress do ALB:
ingress=[aws.ec2.SecurityGroupIngressArgs(
protocol="-1",
from_port=0,
to_port=0,
security_groups=config.network["alb_allow_ingress_sgs"],
)],
2. Edite Pulumi.Inovyo.yaml — substitua alb_allow_ingress_cidr por:
app-ecs:network:
alb_allow_ingress_sgs:
- <security-group-id>
Para manter ambos (IP e SG ao mesmo tempo), adicione os dois campos à mesma
SecurityGroupIngressArgs, ou crie entradas separadas emingress.
Solução de problemas
pulumi up falha com erro de estado inconsistente:
pulumi refresh --stack <stack-name> # sincroniza estado com AWS
pulumi up --stack <stack-name>
Recurso preso em estado de update:
pulumi stack export --stack <stack-name> > state.json
# Editar state.json para remover o recurso problemático
pulumi stack import --stack <stack-name> < state.json
Ver logs do container após o deploy:
aws logs tail <nome-do-log-group> --follow --region us-east-1
Verificar tasks rodando no ECS:
aws ecs list-tasks --cluster <nome-do-cluster> --region us-east-1