Introducción

La pregunta llegó por un canal de Slack a las 10:17 AM de un lunes cualquiera: «¿Qué estamos ejecutando exactamente en todos nuestros entornos cloud?». No se refería a lo que decía la documentación de IaC, ni a los reportes de facturación. Se refería a qué está realmente corriendo ahora mismo, en todas las cuentas, proveedores y regiones. La respuesta tardó una hora en armarse y, al final, no fue un inventario concreto, sino: «Esto es lo que creemos, con algunos vacíos que habría que investigar».

Este episodio no ocurrió en una startup emergente, sino en un equipo de ingeniería de élite que ya operaba en AWS, Azure y GCP con Kubernetes en el medio. La causa raíz no fue falta de talento, sino la ausencia de un inventario unificado de infraestructura como infraestructura de base. Según el Flexera’s 2024 State of the Cloud Report, el 89% de las empresas ya ejecutan cargas de trabajo en múltiples nubes públicas, pero la mayoría lo hizo por acumulación: decisiones individuales que, sumadas, crearon un footprint cloud sin visibilidad consolidada.

Qué ocurrió

El problema surgió cuando dos organizaciones con infraestructuras independientes se fusionaron. Cada equipo había operado bajo sus propias reglas:

  • Diferentes convenciones de etiquetado: en un lado, los recursos se etiquetaban con owner:equipo-x; en el otro, con team=xyz. Algunos recursos ni siquiera tenían etiquetas.
  • Recursos huérfanos: instancias EC2 en AWS sin dueño claro, clusters de Kubernetes en GCP creados para pruebas piloto pero nunca eliminados, y cuentas de Azure con permisos residuales.
  • Herramientas fragmentadas: cada proveedor exponía su propia consola con interfaces y modelos mentales distintos. AWS usaba tags, GCP usaba labels, y Azure tenía su propio sistema de propiedades. No había un «botón de mostrar todo» que funcionara cruzando proveedores.

La pregunta en Slack expuso una realidad incómoda: no existía un punto único de verdad. Lo que los equipos creían saber (basado en documentación o memoria) no coincidía con lo que realmente existía en producción. Peor aún, los reportes de costos —que suelen usarse como proxy de inventario— solo mostraban lo que se facturaba, no qué recursos estaban activos.

Impacto para DevOps / Infraestructura / Cloud / Seguridad

Para equipos de DevOps e Infraestructura

  • Tiempo perdido en auditorías: Un equipo de DevOps promedio puede perder hasta 15 horas semanales (según datos de CloudHealth) solo en descubrir qué recursos existen, quién los creó y si aún son necesarios. Este tiempo se multiplica en entornos multi-cloud.
  • Riesgo de «zombies»: Recursos abandonados o no documentados son un vector común para brechas de seguridad. En 2023, el 34% de los incidentes reportados a CISA involucraron recursos no gestionados o huérfanos (CVE-2023-2868).
  • Inconsistencias en IaC: Sin un inventario real, los equipos dependen de lo declarado en Terraform o CloudFormation. Pero si hay recursos creados manualmente o por herramientas externas (como consolas de proveedor), el estado real diverge del declarado. Esto genera «drift» y fallos en despliegues automatizados.

Para equipos de Seguridad

  • Superficie de ataque ampliada: Cada recurso no inventariado es un posible punto de entrada. En un estudio de 2024 de Aqua Security, el 62% de los contenedores en producción tenían configuraciones inseguras (como permisos root o imágenes sin parches), pero solo el 18% de estos recursos estaban etiquetados correctamente para ser auditados.
  • Dificultad en cumplimiento: Normativas como SOC 2 o ISO 27001 exigen inventarios actualizados. Sin visibilidad multi-proveedor, los equipos de seguridad deben recurrir a auditorías manuales, que consumen semanas y tienen una tasa de error del 22% (según PwC).

Para equipos de Cloud y Finanzas

  • Costos ocultos: Recursos no etiquetados o abandonados pueden representar hasta el 15% del gasto mensual en cloud (datos de FinOps Foundation). En un footprint de $500K/mes, esto significa $75K perdidos en recursos fantasma.
  • Falta de trazabilidad: Sin un esquema de etiquetado unificado, asignar costos por equipo o proyecto es imposible. En empresas con múltiples adquisiciones, este problema se agrava: cada organización tiene su propia convención de tags.

Detalles técnicos

El problema de los tags: un caso concreto

En el episodio descrito, los equipos manejaban al menos tres convenciones distintas para el tag owner:

  1. owner:equipo-frontend
  2. team=xyz
  3. Recursos sin etiqueta.
Ejemplo de impacto:
# Recurso en AWS EC2 (sin tag)
ResourceId: i-0abc123def456789
State: running
Age: 18 meses (¿quién lo creó?)

# Recurso en GCP (con etiqueta inconsistente)
ResourceId: gke-cluster-dev-team-a
Labels:
  team: "front-end"
  env: "dev"
Owner: undefined (¿mail? ¿equipo?)
Consecuencia: Un comando para listar recursos huérfanos en AWS:
aws ec2 describe-instances \
  --filters "Name=instance-state-name,Values=running" \
  --query "Reservations[].Instances[?Tags[?Key=='owner'==`null`]]"

Devuelve 0 resultados, porque los tags no siguen un estándar. En GCP, el mismo comando:

gcloud compute instances list --filter="labels.owner!=*"

Tampoco funciona si el tag se llamaba team en lugar de owner.

Limitaciones de las herramientas nativas

  • AWS Resource Explorer: Permite búsquedas cruzando cuentas, pero no consolida datos de otros proveedores. Además, solo indexa recursos dentro del mismo proveedor.
  • GCP Resource Manager: Ofrece APIs para listar recursos, pero requiere autenticación por proyecto y no tiene integración con Azure.
  • Azure Resource Graph: Útil para consultas dentro de Azure, pero no cruza con AWS o GCP.

Solución técnica: CloudQuery + SQL

Herramientas como CloudQuery (ahora parte de env0) sincronizan el estado real de múltiples proveedores en una base de datos SQL. Ejemplo de configuración para un entorno multi-cloud:

# cloudquery.yml
providers:
  - name: aws
    config:
      regions:
        - us-east-1
        - eu-west-1
  - name: gcp
    config:
      project_ids:
        - project-dev
        - project-prod
  - name: azure
    config:
      subscriptions:
        - sub-001
        - sub-002

Tras la sincronización, los datos se estructuran en tablas como:

-- Recursos EC2 en AWS
SELECT id, instance_type, state, tags
FROM aws_ec2_instances
WHERE state = 'running' AND tags->>'owner' IS NULL;

-- Recursos de Compute en Azure
SELECT id, name, properties->>'provisioningState'
FROM azure_compute_virtual_machines
WHERE properties->>'provisioningState' = 'Succeeded';
Ventaja clave: Una vez sincronizados, las consultas SQL reemplazan a los bucles manuales entre consolas. Por ejemplo, encontrar recursos no etiquetados en todos los proveedores:
SELECT
  provider,
  resource_id,
  resource_type
FROM cloud_inventory
WHERE tags IS NULL
   OR tags = '{}';

Qué deberían hacer los administradores y equipos técnicos

Paso 1: Implementar un inventario unificado (antes de que sea demasiado tarde)

  1. Elegir una herramienta:
CloudQuery (open-source): Soporta AWS, Azure, GCP, Kubernetes, Cloudflare y más. Versión mínima requerida: v4.0.0.

Amazon Resource Explorer 2.0: Para entornos solo-AWS (limitado).

Terraform + External Data Sources: Para equipos que ya usan IaC (pero requiere mantenimiento constante).

  1. Configurar la sincronización:
   # Instalar CloudQuery
   brew install cloudquery/tap/cloudquery

   # Ejecutar sincronización inicial
   cloudquery sync cloudquery.yml --dsn "postgresql://user:pass@localhost:5432/cloud_inventory"
   

Frecuencia: Ejecutar cada 6 horas (para entornos estables) o en triggers de CI/CD (para entornos dinámicos).

  1. Establecer un esquema de tags mínimo:
Mandatory tags:

owner: Correo del equipo o squad (ej: [email protected]).

environment: dev, staging, prod.

cost-center: Código contable (ej: cc=12345).

Recomendado: Usar el estándar de FinOps Alliance (basado en OpenCost) para tags financieros.

Paso 2: Automatizar la detección de anomalías

Crear consultas recurrentes para identificar:

  • Recursos huérfanos: Sin tags o con tags inconsistentes.
  SELECT
    provider,
    resource_type,
    COUNT(*) as count
  FROM cloud_inventory
  WHERE tags IS NULL
     OR tags->>'owner' NOT LIKE '%@%'
  GROUP BY provider, resource_type;
  
  • Recursos públicos: Instancias EC2 con security groups abiertos a 0.0.0.0/0.
  SELECT
    provider,
    arn,
    public_ip
  FROM aws_ec2_instances
  WHERE security_groups->>'IpPermissions'::jsonb @> '[{"IpRanges": [{"CidrIp": "0.0.0.0/0"}]}]';
  
  • Clusters de Kubernetes sin dueño:
  SELECT
    namespace,
    pod_count
  FROM k8s_namespaces
  WHERE labels->>'owner' IS NULL;
  
Configurar alertas:
  • Usar Prometheus + Grafana (o herramientas como Datadog) para monitorear cambios en el inventario.
  • Ejemplo de alerta en Prometheus:
  - alert: RecursosSinEtiquetar
    expr: count(cloud_inventory{tags=""}) by (provider) > 5
    for: 1h
    labels:
      severity: warning
    annotations:
      summary: "Recursos sin etiquetar en {{ $labels.provider }}"
  

Paso 3: Integrar con procesos existentes

  • CI/CD: Añadir un paso en pipelines que valide tags antes de desplegar:
  # .gitlab-ci.yml
  validate-tags:
    stage: pre-deploy
    script:
      - ./scripts/validate_tags.sh ${TF_VAR_resource_id}
    rules:
      - if: $CI_COMMIT_BRANCH == "main"
  

Donde validate_tags.sh verifica que el recurso tenga los tags obligatorios.

  • FinOps: Usar el inventario para asignar costos por equipo:
  SELECT
    tags->>'cost-center' as cost_center,
    SUM(monthly_cost) as total_cost
  FROM cloud_inventory
  GROUP BY cost_center;
  

Paso 4: Documentar y socializar el inventario

  • Generar reportes automáticos para equipos:
Semanal: Recursos creados/modificados en la última semana.

Mensual: Recursos huérfanos y sugerencias de decomisionamiento.

  • Reuniones de revisión: Usar los datos para discutir prioridades de limpieza (ej: «Este cluster de Kubernetes en GCP lleva 12 meses sin uso»).

Conclusión

La pregunta de Slack no fue un error de ingeniería, sino un síntoma de un problema estructural: la falta de visibilidad como infraestructura de base. En entornos multi-cloud, donde los recursos se crean, modifican y eliminan de forma distribuida, depender de IaC o reportes de costos es insuficiente. Se necesita un inventario en tiempo real que unifique la realidad de múltiples proveedores en una sola fuente de verdad.

Los equipos que mejor manejan este desafío no son los que tienen la arquitectura cloud más deliberada, sino los que tratan la visibilidad como un requisito no negociable. Implementar esta capa temprano (incluso en entornos pequeños) evita que, años después, un simple mensaje en Slack revele que el emperor está desnudo: la infraestructura que se creía controlada nunca lo fue.

Por Gustavo

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *