Files
AI-inovyo-assistende-db/docs/pulumi-guide.md
2026-05-14 15:29:03 -03:00

257 lines
7.2 KiB
Markdown

# 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?
1. Você edita o código ou o arquivo de configuração
2. `pulumi preview` compara o código com o estado salvo e mostra o diff
3. `pulumi up` aplica o diff na AWS e atualiza o estado
---
## Pré-requisitos
- [Pulumi CLI](https://www.pulumi.com/docs/install/) 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
```bash
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
```yaml
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
```yaml
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](deployment.md)):
**1. Obter o digest da nova imagem:**
```bash
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`:**
```yaml
ecr_image_digest: sha256:<novo-digest>
```
**3. Revisar e aplicar:**
```bash
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.
```yaml
env_variables:
NOVA_VARIAVEL: valor
```
---
## Verificar o output após o deploy
```bash
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`:
```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:
```python
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:
```yaml
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 em `ingress`.
---
## Solução de problemas
**`pulumi up` falha com erro de estado inconsistente:**
```bash
pulumi refresh --stack <stack-name> # sincroniza estado com AWS
pulumi up --stack <stack-name>
```
**Recurso preso em estado de update:**
```bash
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:**
```bash
aws logs tail <nome-do-log-group> --follow --region us-east-1
```
**Verificar tasks rodando no ECS:**
```bash
aws ecs list-tasks --cluster <nome-do-cluster> --region us-east-1
```