IaC β Ansible e Pulumi
IaC β Ansible Roles + Pulumi
Visao Geral
A infraestrutura do CPPS usa 3 ferramentas complementares, cada uma com dominio bem definido:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ Git (fonte unica de verdade) βββββββββββββ¬βββββββββββββββββββ¬βββββββββββββββββββββ¬βββββββββββββββββββ β β β βΌ βΌ βΌ ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β Pulumi β β Ansible β β Argo CD β β β β β β β β Provisiona β β Configura β β Deploya β β o que EXISTE β β o que RODA β β workloads β β no Proxmox β β DENTRO β β no K3s β β β β β β β β VMs, LXCs, β β Pacotes, β β Helm charts,β β discos, rede,β β servicos, β β manifests, β β cloud-init β β hardening, β β CRDs β β β β LINSTOR, β β β β Estado: β β drivers β β Estado: β β Pulumi state β β β β Git + etcd β β (S3) β β Estado: β β β β β β idempotente β β β ββββββββ¬ββββββββ ββββββββ¬ββββββββ ββββββββββββββββ β β β output: IP β ββββββββββββββββββββ Pulumi cria VM β Ansible configuraFronteira clara β nenhuma ferramenta invade o dominio da outra
| Pergunta | Ferramenta |
|---|---|
| βPreciso de uma VM com 8 cores, 32G RAM, disco em LINSTORβ | Pulumi |
| βA VM precisa ter Docker, NVIDIA driver, NTP, hardening SSHβ | Ansible |
| βQuero rodar Airflow no K3s com Helm chartβ | Argo CD |
| βPreciso limpar /boot dos nodes Proxmoxβ | Ansible |
| βQuero criar uma rede/VLAN no Proxmoxβ | Pulumi |
| βPreciso instalar LINSTOR nos nodes GPUβ | Ansible |
Ansible β Roles e Playbooks
O que sao Roles
Uma role Ansible e um pacote reutilizavel de tarefas. Em vez de repetir os mesmos comandos em cada playbook, encapsula em uma role e reutiliza.
Analogia: uma role e como uma funcao. O playbook e o main() que chama as funcoes.
config/roles/βββ common/ β base para qualquer servidorβββ proxmox-cleanup-boot/ β limpeza de kernels antigosβββ proxmox-upgrade/ β upgrade PVE 8β9 completoβββ nvidia-driver/ β driver GPU condicionalβββ linstor/ β cluster storage distribuidoEstrutura de cada Role
config/roles/minha-role/βββ defaults/main.yaml β variaveis com valores padrao (SEMPRE documentar)βββ tasks/main.yaml β lista de tarefas (o que fazer)βββ handlers/main.yaml β acoes reativas (ex: reiniciar servico se config mudou)βββ templates/ β arquivos Jinja2 (config files dinamicos)- defaults/: valores que podem ser sobrescritos no inventory ou via
-e - tasks/: lista ordenada de acoes. Cada task e idempotente (rodar 2x = mesmo resultado)
- handlers/: executam so quando notificados por uma task que mudou algo
- templates/: arquivos com variaveis
{{ }}que Ansible renderiza
Roles existentes
common
Baseline para qualquer servidor. Instala pacotes utilitarios, configura DNS fallback e timezone.
# Uso em playbook:roles: - commonVariaveis: common_packages, common_dns_fallback, common_ntp_servers
proxmox-cleanup-boot
Limpa kernels antigos do /boot. O Proxmox acumula kernels a cada atualizacao e quando /boot enche (~920 MB tipico), novos upgrades falham.
Usa o script config/scripts/cleanup-boot.sh β copia para o node, roda dry-run,
depois executa.
make pve-cleanup-boot TARGET=proxmox_sp # todos os nodes SPmake pve-cleanup-boot TARGET=pve-ippri-31 # node especificoproxmox-upgrade
Upgrade completo de PVE (ex: 8β9). Sequencia:
- Verifica versao e pre-requisitos (
pve8to9 --full) - Garante DNS fallback (evitar problema de resolucao pos-reboot)
- Atualiza repositorios (bookworm β trixie)
apt full-upgrade(async, ate 1h de timeout)- Reboot
- Valida: versao PVE, storage, rede
make pve-upgrade TARGET=pve-ippri-33 # upgrade 1 nodeImportante: o playbook usa serial: 1 no orquestrador (config/proxmox/upgrade.yaml),
garantindo que faz 1 node por vez (nao derruba o cluster inteiro).
Variaveis: pve_target_suite, pve_current_suite, pve_reboot_timeout, pve_dns_fallback
nvidia-driver
Instala driver NVIDIA. So executa em nodes que tem gpu_model definido no inventory.
Detecta automaticamente se a GPU esta presente e se o driver ja esta instalado.
make pve-nvidia TARGET=pve-labri-31 # node com GPUmake pve-nvidia TARGET=proxmox_franca # todos os de Franca (so instala onde tem GPU)Variaveis: nvidia_driver_package, nvidia_pin_kernel, nvidia_pinned_kernel_version
linstor
Instala e configura cluster LINSTOR + DRBD. Documentacao completa em linstor-sp.md.
5 fases: repositorio β storage LVM β servicos β cluster β integracao Proxmox.
make pve-linstor TARGET=linstor_sp # cluster SP inteiroPlaybooks (orquestradores)
Os playbooks ficam em config/proxmox/ e orquestram as roles:
config/proxmox/βββ upgrade.yaml β cleanup-boot + upgrade + nvidia (serial: 1)βββ cleanup-boot.yaml β so limpezaβββ nvidia.yaml β so driver GPUβββ linstor.yaml β instala LINSTORCada playbook aceita a variavel target para filtrar hosts:
# Um nodeuv run ansible-playbook config/proxmox/upgrade.yaml -e target=pve-ippri-33
# Um grupouv run ansible-playbook config/proxmox/upgrade.yaml -e target=proxmox_sp
# Via Makefile (mais simples)make pve-upgrade TARGET=pve-ippri-33Inventory
O inventory define TODOS os hosts e suas variaveis:
inventory/hosts.yamlβββ routers (vyos)βββ servers (debian-proxy, vm-cpps-02, vm-cpps-03)βββ proxmoxβ βββ proxmox_franca (labri-21..33, com linstor_role e gpu_model)β βββ proxmox_sp (ippri-11..34, com gpu_model, linstor_ip, linstor_nvme_devices)βββ linstor_sp (ippri-31, 33, 34 β vars LINSTOR especificas)Variaveis por host:
ansible_host: IP de conexaogpu_model: modelo da GPU (condiciona role nvidia-driver)linstor_role: papel LINSTOR (satellite, controller, combined, controller_primary)linstor_ip: IP na rede dedicada LINSTORlinstor_interface: interface de rede para LINSTORlinstor_nvme_devices: lista de NVMe para o pool LINSTOR
Pulumi β Provisionamento de VMs (backlog)
Estado atual
Pulumi ainda nao esta implementado. Toda criacao de VM e feita manualmente na UI do Proxmox. O plano e importar as VMs existentes e depois criar novas via codigo.
Por que Pulumi (e nao Terraform)
- Python nativo: sem aprender HCL (linguagem do Terraform). O time ja conhece Python.
- Type safety: IDE autocomplete, erros de tipo antes de executar
- Logica real: loops, condicionais, funcoes β sem hacks de DSL
- State management: backend S3 (SeaweedFS que ja temos) ou Pulumi Cloud
Estrutura planejada
infra/βββ proxmox/ βββ Pulumi.yaml β config do projeto βββ Pulumi.dev.yaml β config do stack (dev/prod) βββ __main__.py β entry point βββ config.py β defaults (CPU, RAM, rede, cloud-init) βββ vms/ βββ vyos.py β definicao da VM VyOS βββ debian_proxy.py β definicao do debian-proxy βββ vm_cpps_02.py β definicao do vm-cpps-02 (K3s) βββ vm_cpps_03.py β definicao do vm-cpps-03Exemplo de como ficaria
import pulumifrom pulumi_proxmoxve import vm
vm_cpps_02 = vm.VirtualMachine("vm-cpps-02", node_name="pve-labri-21", vm_id=103, name="vm-cpps-02", cpu=vm.VirtualMachineCpuArgs(cores=12), memory=vm.VirtualMachineMemoryArgs(dedicated=32768), # 32G disks=[vm.VirtualMachineDiskArgs( interface="scsi0", size=170, datastore_id="linstor", # LINSTOR storage )], network_devices=[vm.VirtualMachineNetworkDeviceArgs( bridge="vmbr1", )], initialization=vm.VirtualMachineInitializationArgs( type="nocloud", ip_configs=[vm.VirtualMachineInitializationIpConfigArgs( ipv4=vm.VirtualMachineInitializationIpConfigIpv4Args( address="192.168.0.51/23", gateway="192.168.0.1", ), )], ),)Fases de adocao
- Import:
pulumi importdas VMs que ja existem no Proxmox (nao recria nada) - Codificar: escrever definicao Python de cada VM baseado no estado importado
- Validar:
make plan(pulumi preview) mostra diferencas entre codigo e real - Criar novas VMs: a partir daqui, toda VM nova e criada via
make apply
Fluxo Pulumi β Ansible
1. Pulumi cria VM (CPU, RAM, disco, rede, cloud-init) β output: IP da VM2. IP e adicionado ao inventory/hosts.yaml (manual ou via Pulumi stack output) β3. Ansible configura a VM (pacotes, servicos, hardening) β4. VM pronta para uso (ou para receber workloads K3s via ArgoCD)No futuro, o passo 2 pode ser automatizado: Pulumi gera o inventory dinamicamente a partir do state. Mas por agora, manter manual e mais simples e auditavel.
Decisoes pendentes
| Decisao | Opcoes | Status |
|---|---|---|
| State backend | SeaweedFS S3 (ja temos), Pulumi Cloud (gratis tier), local | Decidir antes do import |
| Provider Proxmox | pulumi-proxmoxve (community) | Unica opcao viavel |
| Primeiro import | Comeca por qual VM? | Sugestao: vm-cpps-03 (simples, sem dependencias) |
Makefile β Interface unificada
# === VM Configuration (Ansible) ===make configure # aplica configs VyOS + Traefikmake verify # dry-run (nao muda nada)make status # ping em todos os hosts
# === Proxmox Operations (Ansible) ===make pve-upgrade TARGET=<host|grupo> # upgrade PVE 8β9make pve-cleanup-boot TARGET=<host|grupo> # limpar /bootmake pve-nvidia TARGET=<host|grupo> # driver GPUmake pve-linstor TARGET=<host|grupo> # instalar LINSTOR
# === VM Provisioning (Pulumi β futuro) ===make plan # pulumi previewmake apply # pulumi upTARGET pode ser:
- Um host:
pve-ippri-33 - Um grupo:
proxmox_sp,proxmox_franca,linstor_sp - Todos:
proxmox
Estrutura completa do repositorio
devops/βββ apps/ β workloads K3s (ArgoCD)β βββ airflow/β βββ authentik/β βββ argocd/ β 17 Application manifestsβ βββ ...ββββ config/ β configuracao (Ansible)β βββ roles/ β roles reutilizaveisβ β βββ common/β β βββ proxmox-cleanup-boot/β β βββ proxmox-upgrade/β β βββ nvidia-driver/β β βββ linstor/β βββ proxmox/ β playbooks Proxmoxβ β βββ upgrade.yamlβ β βββ cleanup-boot.yamlβ β βββ nvidia.yamlβ β βββ linstor.yamlβ βββ vyos/playbook.yaml β firewall/routerβ βββ traefik/playbook.yaml β reverse proxyβ βββ scripts/cleanup-boot.shββββ infra/ β provisionamento (Pulumi β futuro)β βββ proxmox/ββββ inventory/hosts.yaml β todos os hosts e variaveisβββ ansible.cfgβββ Makefile β interface unificadaββββ docs/β βββ infraestrutura.mdβ βββ proxmox-inventario.mdβ βββ linstor-sp.mdβ βββ iac-ansible-pulumi.md β este documentoβ βββ ...ββββ roadmap/ βββ iac.md βββ gpu-platform.md βββ data-platform.md βββ execucao.md