DEV Community

Cover image for Pare de queimar dinheiro na AWS: Guia técnico para encontrar recursos zumbis com TypeScript
Alex Souza
Alex Souza

Posted on

Pare de queimar dinheiro na AWS: Guia técnico para encontrar recursos zumbis com TypeScript

Como identificar NAT Gateways ociosos e Volumes EBS órfãos programaticamente (ou resolver isso em 5 minutos sem código).

Se você gerencia infraestrutura na AWS, provavelmente já sentiu aquele calafrio ao abrir a fatura no final do mês.

Não estou falando dos custos óbvios das suas instâncias EC2 de produção. Estou falando do "custo fantasma". Aquele NAT Gateway que ficou ligado em um ambiente de staging deletado há três meses. Aquele disco EBS de 500GB que foi desconectado da instância, mas continua lá, cobrando US$ 0,08/GB todo mês.

Um único NAT Gateway ocioso custa aproximadamente US$ 32,00/mês.
Parece pouco? Multiplique isso por 3 regiões e deixe rodando por um ano.
Você acabou de jogar R$ 2.400,00 no lixo por um único recurso que não trafegou um único byte.

Infográfico no estilo iceberg digital flutuando no oceano. Acima da linha d'água estão os 'Custos Visíveis' (servidores brancos). Abaixo da linha d'água, uma massa enorme de 'Custos Ocultos' em verde, representando recursos esquecidos como volumes EBS e NAT Gateways.

A AWS não facilita a visualização desses desperdícios. O Cost Explorer te mostra o quanto você gastou, mas raramente aponta o dedo para qual ID específico está drenando seu orçamento.

Como engenheiro de software, minha primeira reação ao ver isso foi: "Não vou pagar por isso. Vou resolver com código."

Abaixo, vou mostrar como você pode criar seu próprio auditor de custos usando TypeScript e o AWS SDK v3.

O Jeito "Hardcore": Auditando via Código

Para detectar recursos zumbis, precisamos cruzar dados de inventário (EC2) com dados de utilização (CloudWatch).

Aqui está um exemplo prático de um script em TypeScript que varre uma região em busca de Discos EBS Disponíveis (não anexados) e NAT Gateways Ociosos.

Pré-requisitos

npm install @aws-sdk/client-ec2 @aws-sdk/client-cloudwatch
npm install -D typescript ts-node @types/node
Enter fullscreen mode Exit fullscreen mode

O Script (audit-zombies.ts)

Este script simula a lógica que utilizo para encontrar recursos esquecidos.

import {
  EC2Client,
  DescribeVolumesCommand,
  DescribeNatGatewaysCommand,
} from '@aws-sdk/client-ec2';
import {
  CloudWatchClient,
  GetMetricStatisticsCommand,
} from '@aws-sdk/client-cloudwatch';

// Configuração: Região Alvo
const REGION = 'us-east-1';

const ec2 = new EC2Client({ region: REGION });
const cw = new CloudWatchClient({ region: REGION });

async function findZombies() {
  console.log(`🔍 Iniciando varredura em: ${REGION}...`);

  // --- 1. DETECTAR EBS ÓRFÃOS ---
  // Um volume "available" não está anexado a nenhuma instância
  const volumesData = await ec2.send(
    new DescribeVolumesCommand({
      Filters: [{ Name: 'status', Values: ['available'] }],
    })
  );

  if (volumesData.Volumes?.length) {
    console.log(
      `\n🚨 ALERTA: ${volumesData.Volumes.length} Volumes EBS Órfãos encontrados:`
    );
    volumesData.Volumes.forEach((vol) => {
      const cost = (vol.Size || 0) * 0.08; // Estimativa gp3
      console.log(
        ` - ID: ${vol.VolumeId} | Tamanho: ${
          vol.Size
        }GB | Desperdício: ~$${cost.toFixed(2)}/mês`
      );
    });
  } else {
    console.log('\n✅ Nenhum volume EBS órfão.');
  }

  // --- 2. DETECTAR NAT GATEWAYS OCIOSOS ---
  // Listamos NATs ativos e verificamos se houve conexões nos últimos 7 dias
  const natData = await ec2.send(
    new DescribeNatGatewaysCommand({
      Filter: [{ Name: 'state', Values: ['available'] }],
    })
  );

  if (natData.NatGateways?.length) {
    console.log(
      `\n📡 Analisando ${natData.NatGateways.length} NAT Gateways...`
    );

    for (const nat of natData.NatGateways) {
      // Busca métricas do CloudWatch (ActiveConnectionCount)
      const metrics = await cw.send(
        new GetMetricStatisticsCommand({
          Namespace: 'AWS/NATGateway',
          MetricName: 'ActiveConnectionCount',
          Dimensions: [{ Name: 'NatGatewayId', Value: nat.NatGatewayId }],
          StartTime: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), // Últimos 7 dias
          EndTime: new Date(),
          Period: 86400,
          Statistics: ['Sum'],
        })
      );

      const totalConnections =
        metrics.Datapoints?.reduce((acc, dp) => acc + (dp.Sum || 0), 0) || 0;

      if (totalConnections === 0) {
        console.log(`⚠️  NAT ZUMBI DETECTADO: ${nat.NatGatewayId}`);
        console.log(`   Custo: ~$32.00/mês | VpcId: ${nat.VpcId}`);
      }
    }
  }
}

findZombies().catch(console.error);
Enter fullscreen mode Exit fullscreen mode

Nota Técnica: Para manter o código legível neste artigo, este script não implementa paginação. Em contas de produção com centenas de recursos, a API da AWS retornará apenas os primeiros resultados e um NextToken. Você precisaria envolver essas chamadas em loops while(nextToken) para garantir que não está deixando nada para trás.

Visualização artística de uma rede complexa de servidores. No centro, uma lupa foca em um único bloco de dados vermelho isolado com a etiqueta 'WASTE' (Desperdício), representando a dificuldade de localizar recursos órfãos manualmente em meio a milhares de nós.

O Problema dessa abordagem

O script acima funciona e é um ótimo exercício de SDK. Mas, ao tentar aplicar isso no dia a dia, esbarrei na fricção operacional:

  1. Complexidade de Paginação: Como mencionei na nota acima, tratar paginação da AWS manualmente é propenso a erros (loops infinitos ou dados incompletos).
  2. Inferno Multi-Region: O script acima roda em uma região. A AWS tem mais de 30. Você precisa criar loops complexos para varrer o globo.
  3. Segurança Local: Para rodar isso, você precisa de Access Keys com permissões administrativas na sua máquina local. Se essa chave vazar, game over.
  4. Manutenção: A API da AWS muda, as métricas mudam. Manter scripts atualizados toma tempo que eu deveria usar codando features do meu produto, não auditando infra.

A engenharia deve servir para automatizar o tédio, não criar mais manutenção.

O Jeito Fácil: InfraLens (Sem Agentes, 100% Web)

Foi por isso que desenvolvi o InfraLens.

Peguei a lógica desses scripts, tratei os casos de borda (incluindo paginação automática e múltiplas regiões) e empacotei tudo em uma ferramenta Web gratuita para auditoria.

Animação da interface do InfraLens realizando uma auditoria em tempo real. A tela exibe o progresso da varredura ('Varrendo us-east-1', 'Identificando Volumes') e finaliza mostrando uma lista de recursos ociosos com o valor monetário do desperdício encontrado.
O InfraLens varre sua conta, cruza métricas do CloudWatch e gera o relatório financeiro em segundos.

Segurança: O "Elefante na Sala"

Eu sei o que você está pensando: "Vou conectar minha AWS em uma ferramenta de terceiro?"

Como desenvolvedor, sou extremamente cético com credenciais. Por isso, o InfraLens foi desenhado com uma arquitetura 100% Read-Only e Agentless.

Diferente de ferramentas antigas que pedem Access Keys permanentes, nós usamos uma Role IAM Temporária via CloudFormation.

Visualização abstrata de uma auditoria segura. Um escudo de luz verde esmeralda protege um núcleo de dados central, enquanto um feixe de luz passa sobre ele sem tocar, ilustrando o acesso 'Read-Only' e sem agentes.

Isso garante a Privacidade por Design:

  • Apenas Metadados: A Role tem permissão estrita apenas para Describe* e List*.
  • Zero Escrita: É tecnicamente impossível para a ferramenta alterar ou deletar sua infraestrutura.
  • Sem Acesso a Dados: Não conseguimos ler o conteúdo dos seus bancos de dados ou arquivos S3.

Conclusão

Você pode continuar rodando scripts manuais (e debugando paginação no fim de semana), ou pode resolver isso em 5 minutos.

Se você quer ver quanto dinheiro está deixando na mesa agora, liberei o acesso ao Modo Demo (sem login) e ao Scanner Real.

👉 Faça sua auditoria gratuita no InfraLens

Não deixe para descobrir o desperdício só quando o financeiro bater na sua porta.

Top comments (0)