Hay una conversación que AlpinaShop lleva siete módulos aplazando, y que la lección anterior ha vuelto a poner sobre la mesa tres veces: activar los logs de acceso a datos cuesta, Security Command Center Premium se descartó por precio, y tres mil euros se repartieron como si fueran mucho dinero — que para una empresa de cuarenta personas lo son.
Ninguna de esas decisiones se puede tomar bien sin saber de dónde sale cada euro de la factura. Y hoy nadie en AlpinaShop lo sabe.
La factura de julio fueron 1.058 €. La de enero fueron 210 €. Nadie decidió multiplicarla por cinco: fue creciendo lección a lección, servicio a servicio, sin que ninguna decisión concreta pareciera cara. Cuando Marta abrió el desglose para preparar el presupuesto del año siguiente, se encontró con dos partidas que no supo explicar y que juntas eran el 40 % del total.
Esta lección abre esa factura entera. Al terminar sabrás por qué la nube sorprende, entenderás qué es un SKU y cómo consultar la facturación en BigQuery para responder "quién gasta qué", montarás presupuestos que actúan en lugar de solo avisar, conocerás las palancas de ahorro ordenadas por retorno real, cazarás los gastos fantasma con un script, y verás la factura de AlpinaShop antes y después, desglosada y comentada con honestidad — incluido lo que no se pudo ahorrar y lo que se decidió gastar de más a propósito.
Contenido
- Por qué la factura de la nube sorprende
- Entender la factura: SKU, uso y descuentos
- La exportación de facturación a BigQuery
- Las consultas que responden "quién gasta qué"
- FinOps para una pyme: informar, optimizar, operar
- Presupuestos, alertas y acciones automáticas
- Cuotas como límite duro
- Palancas de ahorro ordenadas por retorno
- El coste oculto del tráfico
- Etiquetado y asignación de costes
- Detección de anomalías y gastos fantasma
- El caso completo de AlpinaShop: antes y después
- Herramientas: Recommender, Active Assist y la calculadora
- Por qué la factura de la nube sorprende
En el modelo tradicional, el gasto en infraestructura era una decisión anual, visible y negociada: se compraban servidores, alguien firmaba, y durante tres años el coste era el mismo cada mes. Era caro, rígido e ineficiente — y predecible.
En la nube ocurre lo contrario, y la diferencia se puede resumir en cuatro puntos:
| Factor | Efecto |
|---|---|
| Coste variable | La factura depende del uso, y el uso depende del tráfico, de los usuarios y de los errores |
| Decisiones técnicas con efecto económico | Un SELECT * de Lucía puede costar más que el servidor donde corre la tienda |
| Sin freno natural | Nadie firma una orden de compra para crear un clúster. Se crea en dos clics |
| Desfase temporal | El gasto de hoy se ve en la factura de dentro de un mes, cuando ya se hizo |
El tercer punto es el decisivo, y merece un ejemplo real. En 04-06, para evaluar Cloud Composer frente a Workflows, Marta creó un entorno de Composer. La evaluación duró dos días, la decisión fue Workflows, y nadie borró el entorno. Cloud Composer no escala a cero: mantiene una infraestructura permanente. Ese entorno lleva cuatro meses funcionando sin que nadie lo use, a unos 280 € al mes.
Nadie decidió gastar 1.120 €. Simplemente, nadie decidió no gastarlos.
La primera regla de la gestión de costes en la nube: el problema casi nunca es que algo sea caro. Es que nadie sabía que estaba encendido.
- Entender la factura: SKU, uso y descuentos
La factura de Google Cloud tiene tres niveles de agregación, y hay que saber leerlos en orden inverso al que aparecen.
| Nivel | Ejemplo | Utilidad |
|---|---|---|
| Servicio | Compute Engine | Demasiado grueso: dice qué pero no por qué |
| SKU | "N1 Predefined Instance Core running in EMEA" | El nivel útil: unidad facturable concreta |
| Uso | 1.460 horas × 0,0348 $ | El detalle |
Un SKU (Stock Keeping Unit) es la unidad mínima de facturación: una combinación concreta de recurso, región y modalidad. Cada servicio tiene decenas o cientos.
Ejemplo real del desglose de Compute Engine para el MIG de AlpinaShop antes de retirarlo:
| SKU | Uso | Coste |
|---|---|---|
| N1 Predefined Instance Core running in EMEA | 1.460 vCPU-h | 29,50 € |
| N1 Predefined Instance Ram running in EMEA | 5.840 GiB-h | 16,20 € |
| Balanced PD Capacity in EMEA | 40 GiB-mes | 3,80 € |
| Network Inter Zone Egress | 12 GiB | 0,14 € |
| Network Internet Egress from EMEA to EMEA | 85 GiB | 10,20 € |
Aprendizaje inmediato: el coste de una VM no es "una VM". Son vCPU y memoria y disco y tráfico, cada uno con su SKU y su precio. Por eso cambiar de e2-medium a e2-small no reduce el coste a la mitad: reduce dos de los cinco SKU.
Los descuentos que se aplican solos y los que hay que pedir
| Descuento | Cómo se obtiene | Ahorro típico |
|---|---|---|
| Por uso sostenido (SUD) | Automático en Compute Engine si la VM corre buena parte del mes | Hasta ~30 % |
| Por uso comprometido (CUD) | Se contrata: 1 o 3 años | 30-55 % |
| Nivel gratuito | Automático, mensual | Variable |
| Spot / preemptible | Se elige al crear el recurso | 60-91 % |
| Descuentos por volumen | Negociados con Google (empresas grandes) | Variable |
El descuento por uso sostenido es interesante porque es invisible: se aplica solo, y explica por qué la factura de una VM encendida todo el mes es menor que horas × precio de lista. Y también por qué apagar una VM por las noches ahorra menos de lo que la aritmética sugiere: al bajar del umbral, se pierde parte del descuento automático.
Todos los precios de esta lección son órdenes de magnitud en
europe-west1para razonar. Cambian, varían por región y dependen del contrato. Verifícalos siempre en la página de precios oficial y en la calculadora.
- La exportación de facturación a BigQuery
En 01-04 se activó y se prometió explotarla. Ha llegado el momento.
La consola de facturación sirve para ver tendencias. Para responder preguntas concretas —¿por qué subió la factura el martes 14?, ¿cuánto cuesta el entorno de desarrollo?— hace falta SQL.
# 1. Dataset destino en alpinashop-datos
bq --location=EU mk --dataset \
--description="Exportacion de facturacion" \
alpinashop-datos:facturacion
# 2. La exportacion se configura en la consola:
# Facturacion > Exportacion de facturacion > Configuracion de BigQuery
# Activar "Coste detallado" (nivel de recurso), no solo "Coste estandar"Activa siempre la exportación de coste detallado, aunque genere más filas. La diferencia:
| Exportación | Granularidad | Responde a |
|---|---|---|
| Costes estándar | Servicio + SKU + proyecto + etiqueta | "¿Cuánto gasta BigQuery en producción?" |
| Costes detallados | + recurso concreto | "¿Qué bucket concreto cuesta 40 €?" |
| Precios | Catálogo de precios | Simulaciones |
Sin el detalle por recurso, sabrás que Cloud Storage cuesta 25 € pero no qué bucket. Y esa es justo la pregunta que hay que responder.
Dos avisos prácticos:
- Los datos tardan. La exportación se rellena con varias horas de retraso y se corrige durante días: los costes de ayer pueden cambiar mañana. No sirve para alertas en tiempo real; para eso están los presupuestos.
- La tabla es enorme y está particionada por
_PARTITIONTIME. Consultarla sin filtro de fecha procesa meses de datos, y esa consulta te cuesta dinero. Es irónico y pasa constantemente.
- Las consultas que responden "quién gasta qué"
Estas seis consultas cubren el 95 % de las preguntas reales. Merece la pena guardarlas como vistas.
1. Gasto por proyecto, últimos 30 días.
SELECT
project.id AS proyecto,
ROUND(SUM(cost), 2) AS coste,
ROUND(SUM(IFNULL((SELECT SUM(c.amount) FROM UNNEST(credits) c), 0)), 2) AS creditos,
ROUND(SUM(cost) + SUM(IFNULL((SELECT SUM(c.amount) FROM UNNEST(credits) c), 0)), 2) AS neto
FROM `alpinashop-datos.facturacion.gcp_billing_export_resource_v1_XXXXXX`
WHERE DATE(_PARTITIONTIME) >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
GROUP BY proyecto
ORDER BY neto DESCEl campo credits es un array anidado con descuentos, promociones y nivel gratuito, y siempre son valores negativos. Sumarlo al coste da el neto real. Olvidarlo es el error número uno al analizar facturación en BigQuery: se ven cifras infladas y nadie entiende por qué no cuadran con la consola.
2. Los 20 SKU más caros: dónde está el dinero de verdad.
SELECT
service.description AS servicio,
sku.description AS sku,
ROUND(SUM(cost), 2) AS coste,
ROUND(SUM(usage.amount), 2) AS uso,
ANY_VALUE(usage.unit) AS unidad
FROM `alpinashop-datos.facturacion.gcp_billing_export_resource_v1_XXXXXX`
WHERE DATE(_PARTITIONTIME) >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
GROUP BY servicio, sku
ORDER BY coste DESC
LIMIT 203. Gasto por etiqueta: la que justifica la disciplina de 01-04.
SELECT
(SELECT value FROM UNNEST(labels) WHERE key = 'entorno') AS entorno,
(SELECT value FROM UNNEST(labels) WHERE key = 'equipo') AS equipo,
(SELECT value FROM UNNEST(labels) WHERE key = 'centro-coste') AS centro_coste,
(SELECT value FROM UNNEST(labels) WHERE key = 'aplicacion') AS aplicacion,
ROUND(SUM(cost), 2) AS coste
FROM `alpinashop-datos.facturacion.gcp_billing_export_resource_v1_XXXXXX`
WHERE DATE(_PARTITIONTIME) >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
GROUP BY entorno, equipo, centro_coste, aplicacion
ORDER BY coste DESC4. Recursos concretos más caros (requiere exportación detallada).
SELECT
resource.name AS recurso,
service.description AS servicio,
ROUND(SUM(cost), 2) AS coste
FROM `alpinashop-datos.facturacion.gcp_billing_export_resource_v1_XXXXXX`
WHERE DATE(_PARTITIONTIME) >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
AND resource.name IS NOT NULL
GROUP BY recurso, servicio
ORDER BY coste DESC
LIMIT 305. Evolución diaria: para ver el escalón.
SELECT
DATE(usage_start_time) AS dia,
service.description AS servicio,
ROUND(SUM(cost), 2) AS coste
FROM `alpinashop-datos.facturacion.gcp_billing_export_resource_v1_XXXXXX`
WHERE DATE(_PARTITIONTIME) >= DATE_SUB(CURRENT_DATE(), INTERVAL 60 DAY)
GROUP BY dia, servicio
HAVING coste > 0.5
ORDER BY dia DESC, coste DESC6. Recursos SIN etiquetar: la deuda de gobierno hecha número.
SELECT
project.id AS proyecto,
service.description AS servicio,
ROUND(SUM(cost), 2) AS coste_sin_atribuir
FROM `alpinashop-datos.facturacion.gcp_billing_export_resource_v1_XXXXXX`
WHERE DATE(_PARTITIONTIME) >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
AND (SELECT COUNT(*) FROM UNNEST(labels) WHERE key = 'centro-coste') = 0
GROUP BY proyecto, servicio
HAVING coste_sin_atribuir > 1
ORDER BY coste_sin_atribuir DESCLa consulta 6 es la más incómoda y la más útil. Todo lo que aparece es gasto que no se puede atribuir a nadie. En AlpinaShop, la primera vez que se ejecutó, salieron 380 € de 1.058 €: el 36 % de la factura no tenía dueño.
- FinOps para una pyme: informar, optimizar, operar
FinOps es la disciplina de gestionar el coste de la nube como una responsabilidad compartida entre finanzas, tecnología y negocio. Tiene tres fases que se recorren en ciclo:
flowchart LR
I["INFORMAR<br/>visibilidad, asignacion,<br/>previsiones"] --> O["OPTIMIZAR<br/>dimensionar, descuentos,<br/>eliminar desperdicio"]
O --> P["OPERAR<br/>politicas, automatismos,<br/>revision continua"]
P --> I
| Fase | Qué se hace | En AlpinaShop |
|---|---|---|
| Informar | Exportación, etiquetas, paneles, presupuestos | Apartados 3, 4, 6, 10 |
| Optimizar | Dimensionar, apagar, descuentos, arquitectura | Apartado 8 |
| Operar | Políticas que impiden el desperdicio, automatismos | Apartados 6, 7, 10, 11 |
El error clásico es empezar por optimizar. Sin visibilidad, se optimiza lo que se ve —que suele ser lo menos importante— y se ignora el entorno de Composer de 280 € que nadie sabía que existía. Primero se mide, luego se corta.
¿Quién es el dueño del coste?
En una empresa grande hay un equipo de FinOps. En una de cuarenta personas, la pregunta es real y tiene una respuesta incómoda:
| Modelo | Cómo funciona | Problema |
|---|---|---|
| Nadie | Se mira la factura cuando asusta | El de AlpinaShop hasta hoy |
| Finanzas | Contabilidad vigila el total | No entiende qué es un SKU ni puede actuar |
| Solo infraestructura | Marta lo lleva todo | No controla lo que gastan las consultas de Lucía |
| Responsabilidad distribuida con un coordinador | Cada equipo ve y responde de su gasto; alguien coordina | El correcto |
Para AlpinaShop:
- Marta coordina: mantiene el panel, revisa mensualmente y propone.
- Cada persona ve su gasto: Lucía el de BigQuery y Dataflow, Dani el de Cloud Run y Cloud Build.
- Dirección aprueba los compromisos plurianuales.
- Una reunión de 30 minutos al mes con el panel abierto.
Esa reunión mensual, que parece burocracia, es la práctica de FinOps con mejor relación coste/beneficio que existe. Lo que se mira en grupo una vez al mes no se descontrola.
- Presupuestos, alertas y acciones automáticas
Un presupuesto en Google Cloud no limita el gasto: avisa. Esto sorprende a todo el mundo y hay que interiorizarlo:
No existe un botón de "no gastes más de X". El presupuesto envía notificaciones; detener el gasto lo tienes que automatizar tú.
Presupuesto básico
gcloud billing budgets create \
--billing-account=BILLING_ACCOUNT_ID \
--display-name="AlpinaShop total mensual" \
--budget-amount=1200EUR \
--threshold-rule=percent=0.5 \
--threshold-rule=percent=0.8 \
--threshold-rule=percent=1.0 \
--threshold-rule=percent=1.2 \
--threshold-rule=percent=0.8,basis=forecasted-spend \
--notifications-rule-monitoring-notification-channels=CHANNEL_IDLa última regla es la más valiosa y la que menos se usa: basis=forecasted-spend avisa cuando Google prevé que se superará el umbral a fin de mes. Avisa el día 8, no el día 26. Es la única alerta que llega a tiempo de hacer algo.
Presupuestos que conviene tener, en lugar de uno solo:
| Presupuesto | Importe | Por qué |
|---|---|---|
| Total de la organización | 1.200 € | Visión global |
alpinashop-prod |
700 € | El que importa |
alpinashop-dev |
100 € | Aquí se descontrola todo |
alpinashop-datos |
250 € | BigQuery y Dataflow son variables |
| Solo BigQuery, por etiqueta | 150 € | Una consulta puede disparar esto sola |
La acción automática
Aquí es donde el presupuesto deja de ser un aviso y pasa a ser un control. El flujo:
flowchart LR
B["Presupuesto<br/>umbral superado"] --> PS["Pub/Sub<br/>alertas-presupuesto"]
PS --> F["Cloud Function<br/>reaccionar-presupuesto"]
F -->|"100% en dev"| A1["Apagar VM de desarrollo"]
F -->|"120% en dev"| A2["Desvincular facturacion"]
F -->|"cualquier umbral"| A3["Avisar en el canal"]
# main.py — funcion reaccionar-presupuesto (Cloud Functions 2a gen, 06-03)
import base64, json, os, logging
from google.cloud import compute_v1
from googleapiclient import discovery
PROYECTO_DEV = "alpinashop-dev"
ZONA = "europe-west1-b"
def reaccionar_presupuesto(evento, contexto):
datos = json.loads(base64.b64decode(evento["data"]).decode("utf-8"))
nombre = datos.get("budgetDisplayName", "")
gastado = float(datos.get("costAmount", 0))
presupuesto= float(datos.get("budgetAmount", 1))
umbral = float(datos.get("alertThresholdExceeded", 0))
ratio = gastado / presupuesto if presupuesto else 0
logging.info(json.dumps({
"severity": "WARNING", "message": "Umbral de presupuesto superado",
"presupuesto": nombre, "gastado": gastado, "ratio": round(ratio, 2),
}))
# Solo se actua sobre DESARROLLO. Produccion NUNCA se apaga sola.
if "dev" not in nombre.lower():
return
if ratio >= 1.0:
apagar_vms_desarrollo()
if ratio >= 1.2:
desvincular_facturacion(PROYECTO_DEV)
def apagar_vms_desarrollo():
cliente = compute_v1.InstancesClient()
for inst in cliente.list(project=PROYECTO_DEV, zone=ZONA):
if inst.status == "RUNNING":
cliente.stop(project=PROYECTO_DEV, zone=ZONA, instance=inst.name)
logging.warning(f"VM detenida por presupuesto: {inst.name}")
def desvincular_facturacion(proyecto):
# MEDIDA EXTREMA: detiene practicamente todo el proyecto
svc = discovery.build("cloudbilling", "v1")
svc.projects().updateBillingInfo(
name=f"projects/{proyecto}",
body={"billingAccountName": ""}
).execute()
logging.critical(f"FACTURACION DESVINCULADA de {proyecto}")Tres advertencias que hay que leer dos veces:
- Nunca automatices el apagado de producción. Un pico de ventas en campaña dispara el presupuesto; apagar la tienda en el mejor día del año es peor que cualquier factura.
- Desvincular la facturación es destructivo y en parte irreversible. Los recursos se detienen y algunos se eliminan pasado un plazo. Solo tiene sentido en desarrollo, y aun así conviene pensarlo.
- Los mensajes de presupuesto pueden llegar duplicados. La función tiene que ser idempotente (06-03): apagar una VM ya apagada no debe fallar.
- Cuotas como límite duro
Donde el presupuesto avisa, la cuota impide. Es el único mecanismo que realmente frena el gasto.
| Tipo | Qué limita | Uso para coste |
|---|---|---|
| De tasa | Peticiones por minuto a una API | Contener bucles descontrolados |
| De asignación | Recursos simultáneos: vCPU, IP, discos | El más eficaz |
# Ver las cuotas de CPU de una region
gcloud compute regions describe europe-west1 --format="table(quotas.metric, quotas.limit, quotas.usage)"Limitar la cuota de vCPU en desarrollo es el freno más eficaz que existe, porque es imposible saltárselo: si la cuota son 8 vCPU, nadie puede crear una VM de 32 aunque quiera.
Las cuotas de coste de BigQuery
BigQuery bajo demanda cobra por bytes leídos, y una sola consulta mal escrita puede costar más que un mes de servidores. Hay dos frenos, y ambos deberían estar puestos siempre:
# 1. Limite de bytes procesados por dia y por usuario
gcloud alpha services quota update \
--service=bigquery.googleapis.com \
--consumer=projects/alpinashop-datos \
--metric=bigquery.googleapis.com/quota/query/usage \
--unit=1/d/{project}/{user} \
--value=1099511627776 # 1 TiB por usuario y dia-- 2. Limite por consulta individual, en la sesion o en el script
SET @@maximum_bytes_billed = 107374182400; -- 100 GiBY en la herramienta de línea de comandos:
El mensaje que devuelve una consulta bloqueada es explícito —"Query exceeded limit for bytes billed"— y produce el efecto pedagógico correcto: quien la escribió aprende a filtrar por partición antes de reescribirla.
- Palancas de ahorro ordenadas por retorno
Esta es la sección práctica. Ordenadas por euros ahorrados por hora de trabajo invertida, que es el criterio que importa cuando el equipo es pequeño.
Palanca 1 — Apagar lo que no se usa (retorno inmediato)
Lo más rentable no es optimizar: es eliminar. Y siempre hay algo.
# Entornos de desarrollo fuera de horario, con Cloud Scheduler + Workflows
gcloud scheduler jobs create http apagar-desarrollo \
--location=europe-west1 \
--schedule="0 20 * * 1-5" \
--time-zone="Europe/Madrid" \
--uri="https://workflowexecutions.googleapis.com/v1/projects/alpinashop-dev/locations/europe-west1/workflows/apagar-entorno/executions" \
--http-method=POST \
--oauth-service-account-email=sa-scheduler@alpinashop-dev.iam.gserviceaccount.com
gcloud scheduler jobs create http encender-desarrollo \
--location=europe-west1 \
--schedule="0 8 * * 1-5" \
--time-zone="Europe/Madrid" \
--uri="https://workflowexecutions.googleapis.com/v1/projects/alpinashop-dev/locations/europe-west1/workflows/encender-entorno/executions" \
--http-method=POST \
--oauth-service-account-email=sa-scheduler@alpinashop-dev.iam.gserviceaccount.comLa aritmética que convence a cualquiera: un entorno encendido de 8:00 a 20:00 de lunes a viernes son 260 horas de las 730 del mes. Un 64 % de ahorro por dos trabajos programados.
Con dos matices honestos: los discos se siguen pagando aunque la VM esté apagada, y se pierde parte del descuento por uso sostenido. El ahorro real ronda el 50-55 %, no el 64 %.
Palanca 2 — Dimensionar correctamente
Google observa el uso real durante 8 días y recomienda:
gcloud recommender recommendations list \
--project=alpinashop-prod --location=europe-west1-b \
--recommender=google.compute.instance.MachineTypeRecommender \
--format="table(description, primaryImpact.costProjection.cost.units)"Existen recomendadores para VM, discos persistentes, Cloud SQL, direcciones IP y muchos más. Aplicarlos es de las cosas más rentables por hora invertida.
La advertencia: las recomendaciones se basan en la ventana observada. Si esa ventana es agosto y el pico es en octubre, dimensionar a la baja según agosto es prepararse un problema. Contrasta siempre con el pico anual.
Palanca 3 — Descuentos por compromiso
| Uso sostenido (SUD) | Uso comprometido (CUD) | |
|---|---|---|
| Cómo | Automático | Se contrata |
| Compromiso | Ninguno | 1 o 3 años, se paga igual |
| Ahorro | Hasta ~30 % | 30-55 % |
| Flexibilidad | Total | Los basados en gasto son flexibles; los de recursos, no |
| Riesgo | Ninguno | Pagar por lo que ya no usas |
Hay dos tipos de compromiso, y elegir mal es caro:
| Tipo | Se compromete a | Riesgo |
|---|---|---|
| Por recursos | X vCPU y Y GiB en una región y familia concretas | Alto: si migras o cambias de familia, sigues pagando |
| Por gasto (flexible) | Gastar al menos X €/hora en un servicio | Bajo: se aplica a lo que uses |
Regla práctica: comprométete solo con la parte estable de tu consumo, típicamente el 50-70 % del mínimo histórico. Nunca con el total.
Y la lección que AlpinaShop aprendió a su costa: si Marta hubiera contratado en enero un compromiso a un año sobre las vCPU del MIG, hoy —tras migrar a Cloud Run en 07-02— seguiría pagando por unas VM que ya no existen. La optimización arquitectónica invalida los compromisos. Primero se estabiliza la arquitectura, después se compromete.
Palanca 4 — VMs Spot
Instancias con descuento del 60-91 % que Google puede reclamar con 30 segundos de aviso.
| Sirven para | No sirven para |
|---|---|
| Procesamiento por lotes con reintentos | Bases de datos |
| Entrenamiento de modelos con puntos de control | Servicios web de cara al cliente |
| Trabajadores de Dataflow y Dataproc | Nada con estado local |
| CI/CD | Nada que no tolere reinicios |
gcloud dataproc clusters create cluster-analitica \
--region=europe-west1 \
--num-workers=2 \
--num-secondary-workers=8 \
--secondary-worker-type=spot # 8 de 10 trabajadores al 30% del precioEl patrón correcto es el de esa orden: núcleo estable pequeño + mayoría spot. Si Google reclama los spot, el trabajo se ralentiza pero no muere.
Palanca 5 — Clases de almacenamiento y ciclo de vida
| Clase | Coste relativo | Recuperación mínima | Uso |
|---|---|---|---|
| Standard | 1× | — | Acceso frecuente |
| Nearline | ~0,5× | 30 días | Menos de una vez al mes |
| Coldline | ~0,3× | 90 días | Trimestral |
| Archive | ~0,12× | 365 días | Copias legales |
resource "google_storage_bucket" "datalake" {
name = "alpinashop-datalake"
location = "EUROPE-WEST1"
lifecycle_rule {
condition { age = 30 }
action { type = "SetStorageClass" storage_class = "NEARLINE" }
}
lifecycle_rule {
condition { age = 90 }
action { type = "SetStorageClass" storage_class = "COLDLINE" }
}
lifecycle_rule {
condition { age = 365 }
action { type = "SetStorageClass" storage_class = "ARCHIVE" }
}
lifecycle_rule {
condition { num_newer_versions = 3 }
action { type = "Delete" } # limitar versiones antiguas
}
}La trampa de las clases frías, que hay que conocer antes de configurarlas: tienen cargos por recuperación anticipada. Un objeto en Coldline borrado o leído antes de 90 días factura como si hubiera estado los 90. Poner Archive a datos que se consultan cada dos meses sale más caro que Standard.
La última regla, sobre versiones, resuelve un problema real: con versionado activado (y debe estarlo, por 07-04), cada modificación deja una copia. Un bucket con versionado y sin límite de versiones crece indefinidamente y nadie lo mira.
Palanca 6 — Particionado y clustering en BigQuery
BigQuery bajo demanda cobra por bytes leídos, no por tiempo. Una tabla de 500 GB sin particionar cuesta lo mismo consultar un día que un año.
CREATE OR REPLACE TABLE `alpinashop-datos.alpinashop_analitica.pedidos_opt`
PARTITION BY DATE(fecha_pedido)
CLUSTER BY categoria_producto, provincia
OPTIONS (
partition_expiration_days = 1095,
require_partition_filter = TRUE -- <<< la opcion que salva la factura
)
AS SELECT * FROM `alpinashop-datos.alpinashop_analitica.pedidos`;require_partition_filter = TRUE es la opción más rentable de todo BigQuery. Rechaza cualquier consulta que no filtre por partición:
Cannot query over table 'pedidos_opt' without a filter over column(s) 'fecha_pedido' that can be used for partition elimination
Un mensaje de error a cambio de evitar escaneos completos de 500 GB.
Efecto medido sobre la consulta habitual de Lucía:
| Versión | Bytes leídos | Coste por ejecución |
|---|---|---|
Sin particionar, SELECT * |
480 GB | ~2,70 € |
| Particionada, filtro de 30 días | 41 GB | ~0,23 € |
| + clustering por categoría | 6 GB | ~0,03 € |
Noventa veces más barata. Y la misma consulta ejecutada 40 veces al mes en un cuadro de mando pasa de 108 € a 1,20 €.
Palanca 7 — Bajo demanda frente a ediciones de BigQuery
| Modelo | Cómo se paga | Cuándo conviene |
|---|---|---|
| Bajo demanda | Por TB leído | Uso irregular o bajo. AlpinaShop |
| Standard / Enterprise (slots) | Por capacidad de cómputo reservada, con autoescalado | Uso alto y sostenido |
El punto de equilibrio ronda un consumo mensual constante equivalente a varios cientos de euros bajo demanda. Por debajo, bajo demanda gana casi siempre. Por encima, las reservas dan además coste predecible, que a veces vale más que el ahorro.
Palanca 8 — CDN y caché
Cada respuesta servida desde la caché de Cloud CDN (03-03) es tráfico que no sale del origen y cómputo que no se ejecuta.
| Métrica | Sin CDN | Con CDN al 85 % de aciertos |
|---|---|---|
| Egress desde el origen | 300 GB | 45 GB |
| Coste de egress | ~36 € | ~5,40 € + coste de CDN |
| Instancias de Cloud Run | Más | Menos |
Y la palanca gratuita que casi nadie activa: comprimir. Con gzip o brotli, una página HTML de 200 KB viaja en 30 KB. Un 85 % menos de bytes facturados, y además carga más rápido.
Palanca 9 — Escalado a cero
Ya cuantificada en 07-02: el catálogo pasó de ~50 € a ~7 € al mes. La regla general:
Todo lo que no reciba tráfico constante debería escalar a cero. Cloud Run, Cloud Functions y los trabajos por lotes lo hacen; las VM y los clústeres, no.
Resumen ordenado por retorno
| # | Palanca | Ahorro típico | Esfuerzo | €/hora invertida |
|---|---|---|---|---|
| 1 | Eliminar lo no usado | 10-40 % | Muy bajo | Altísimo |
| 2 | Apagar desarrollo fuera de horario | 50 % de dev | Bajo | Muy alto |
| 3 | require_partition_filter + clustering |
50-95 % de BigQuery | Bajo | Muy alto |
| 4 | Dimensionar con Recommender | 20-40 % de cómputo | Bajo | Alto |
| 5 | Ciclo de vida de almacenamiento | 40-70 % de storage | Bajo | Alto |
| 6 | CDN y compresión | 60-85 % de egress | Medio | Alto |
| 7 | Escalado a cero | 60-90 % del servicio | Medio | Alto |
| 8 | VMs Spot en lotes | 60-90 % de esos lotes | Medio | Medio |
| 9 | Compromisos de uso | 30-55 % de lo comprometido | Bajo, con riesgo | Medio |
| 10 | Ediciones de BigQuery | Variable | Alto | Bajo si no hay escala |
- El coste oculto del tráfico
Se introdujo en 07-03 y aquí se cierra con los cuatro escondites y su remedio.
| Trayecto | Coste orientativo |
|---|---|
| Entrada desde internet | Gratis |
| Dentro de una zona, IP interna | Gratis |
| Entre zonas de la misma región | ~0,01 $/GB |
| Entre regiones de la UE | ~0,02 $/GB |
| A otro continente | 0,05-0,15 $/GB |
| Salida a internet, Premium | ~0,12 $/GB |
| Balanceador: reglas + datos procesados | Cargo fijo + por GB |
| Escondite | Cómo aparece | Remedio |
|---|---|---|
| Réplica HA de Cloud SQL | Replicación continua entre zonas | Es el precio de la disponibilidad. Se acepta y se conoce |
| Aplicación y BD en zonas distintas | Cada consulta cruza zona | Colocar deliberadamente |
| Logs y copias hacia otra región | Por cada línea de log | Buckets de logs en la misma región |
| Balanceadores olvidados | Cargo fijo por regla de reenvío, haya o no tráfico | Auditoría periódica (apartado 11) |
- Etiquetado y asignación de costes
La disciplina de 01-04, ahora explotada. Las cuatro etiquetas de AlpinaShop:
| Etiqueta | Valores | Responde a |
|---|---|---|
entorno |
prod, dev, pruebas |
¿Cuánto cuesta desarrollo? |
equipo |
infra, desarrollo, datos |
¿Quién gasta? |
centro-coste |
tienda, analitica, plataforma |
¿A qué línea de negocio se imputa? |
aplicacion |
catalogo, informes, ml |
¿Qué producto cuesta qué? |
Reglas que las hacen útiles:
- Valores de un conjunto cerrado.
equipo: variosdestruye el análisis. - En todos los recursos que facturen. Un recurso sin etiqueta es gasto sin dueño.
- Aplicadas por Terraform, nunca a mano.
- Ojo: no todos los recursos admiten etiquetas. El egress de red, algunos SKU de balanceador y ciertos cargos de soporte no las llevan. Siempre habrá un residuo sin atribuir; lo importante es que sea pequeño y conocido.
La política que impide crear recursos sin etiqueta
Se aplica en Terraform, que es donde se crea todo:
variable "etiquetas" {
type = map(string)
description = "Etiquetas obligatorias de AlpinaShop"
validation {
condition = alltrue([
for k in ["entorno", "equipo", "centro-coste", "aplicacion"] :
contains(keys(var.etiquetas), k)
])
error_message = "Faltan etiquetas obligatorias: entorno, equipo, centro-coste, aplicacion."
}
validation {
condition = contains(["prod", "dev", "pruebas"], lookup(var.etiquetas, "entorno", ""))
error_message = "entorno debe ser prod, dev o pruebas."
}
validation {
condition = contains(["infra", "desarrollo", "datos"], lookup(var.etiquetas, "equipo", ""))
error_message = "equipo debe ser infra, desarrollo o datos."
}
}El plan falla si faltan etiquetas o si sus valores no son válidos. Es prevención en el punto de creación, que es infinitamente más eficaz que perseguir recursos huérfanos después. Y se complementa con las etiquetas de recurso (tags) de la organización y las políticas de 07-07, que actúan incluso sobre lo que se cree fuera de Terraform.
- Detección de anomalías y gastos fantasma
Detección de anomalías
Google Cloud incluye detección automática de anomalías de coste en la consola de facturación: compara el gasto con el patrón histórico y avisa de desviaciones. Es gratuita, no hay que configurarla, y conviene revisarla mensualmente.
La versión propia, más ajustable:
-- Servicios cuyo gasto de ayer se desvia mas de 3 sigmas de su media de 30 dias
WITH diario AS (
SELECT service.description AS servicio, DATE(usage_start_time) AS dia, SUM(cost) AS coste
FROM `alpinashop-datos.facturacion.gcp_billing_export_resource_v1_XXXXXX`
WHERE DATE(_PARTITIONTIME) >= DATE_SUB(CURRENT_DATE(), INTERVAL 45 DAY)
GROUP BY servicio, dia
),
estad AS (
SELECT servicio,
AVG(coste) AS media,
STDDEV(coste) AS desviacion
FROM diario
WHERE dia BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 31 DAY)
AND DATE_SUB(CURRENT_DATE(), INTERVAL 2 DAY)
GROUP BY servicio
)
SELECT d.servicio, d.dia, ROUND(d.coste,2) AS coste_ayer,
ROUND(e.media,2) AS media_30d,
ROUND(SAFE_DIVIDE(d.coste - e.media, e.desviacion), 1) AS sigmas
FROM diario d JOIN estad e USING (servicio)
WHERE d.dia = DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)
AND e.desviacion > 0
AND d.coste > e.media + 3 * e.desviacion
AND d.coste > 2
ORDER BY sigmas DESCEl filtro d.coste > 2 evita el ruido: un servicio que pasa de 0,02 € a 0,20 € son 9 sigmas y no le importa a nadie.
Los gastos fantasma
Recursos que cuestan dinero y no dan valor a nadie. Siempre hay. En todas las empresas.
| Fantasma | Por qué aparece | Coste típico |
|---|---|---|
| IP estáticas reservadas sin usar | Se reserva, se cambia el diseño, no se libera | ~7 €/mes cada una. Una IP sin usar cuesta más que una en uso |
| Discos persistentes huérfanos | Se borra la VM sin marcar el disco para borrado | 0,04-0,17 €/GB/mes |
| Instantáneas antiguas | Se hacen y no caducan | Acumulativo |
| Imágenes de contenedor antiguas | Cada compilación deja una | Crece con el pipeline |
| Endpoints de Vertex AI olvidados | Se despliega un modelo para probar | Alto: la máquina corre 24×7 |
| Clústeres de desarrollo encendidos | Se crean para una prueba | Muy alto |
| Entornos de Composer | No escalan a cero | ~280 €/mes |
| Balanceadores sin backends | Se prueba y se abandona | ~18 €/mes cada uno |
| Buckets de datos temporales | alpinashop-dataflow acumula ficheros de staging |
Crece indefinidamente |
| Suscripciones de Pub/Sub sin consumidor | Retienen mensajes hasta caducar | Almacenamiento |
El script de auditoría de fantasmas
#!/usr/bin/env bash
# auditoria-fantasmas.sh — busca recursos que cuestan y no sirven
set -uo pipefail
PROYECTOS=(alpinashop-prod alpinashop-dev alpinashop-datos alpinashop-cicd alpinashop-red)
for P in "${PROYECTOS[@]}"; do
echo "############ $P ############"
echo "--- IP estaticas reservadas y NO usadas (~7 EUR/mes cada una) ---"
gcloud compute addresses list --project="$P" \
--filter="status:RESERVED" --format="table(name, region, address)"
echo "--- Discos persistentes sin adjuntar ---"
gcloud compute disks list --project="$P" \
--filter="-users:*" --format="table(name, zone, sizeGb, type)"
echo "--- Instantaneas de mas de 180 dias ---"
gcloud compute snapshots list --project="$P" \
--filter="creationTimestamp<$(date -u -d '180 days ago' +%Y-%m-%d)" \
--format="table(name, diskSizeGb, creationTimestamp)"
echo "--- Endpoints de Vertex AI (comprobar si se usan) ---"
gcloud ai endpoints list --project="$P" --region=europe-west1 \
--format="table(displayName, createTime)" 2>/dev/null
echo "--- Reglas de reenvio: balanceadores, ~18 EUR/mes cada uno ---"
gcloud compute forwarding-rules list --project="$P" \
--format="table(name, region, IPAddress, target)"
echo "--- Clusteres de GKE ---"
gcloud container clusters list --project="$P" \
--format="table(name, location, status, currentNodeCount)" 2>/dev/null
echo "--- Entornos de Cloud Composer (~280 EUR/mes cada uno) ---"
gcloud composer environments list --project="$P" --locations=europe-west1 \
--format="table(name, state)" 2>/dev/null
echo "--- Instancias de Cloud SQL detenidas (siguen pagando disco) ---"
gcloud sql instances list --project="$P" \
--filter="state!=RUNNABLE" --format="table(name, state, settings.tier)"
echo "--- Imagenes de contenedor de mas de 90 dias ---"
gcloud artifacts docker images list \
"europe-west1-docker.pkg.dev/$P/alpinashop" --include-tags \
--filter="createTime<$(date -u -d '90 days ago' +%Y-%m-%d)" \
--format="table(package, version, createTime)" 2>/dev/null
echo
doneEjecútalo el primer lunes de cada mes. Es media hora que en AlpinaShop encontró, la primera vez, 430 € mensuales.
Y para que los fantasmas no vuelvan, políticas automáticas:
# Caducidad automatica de imagenes antiguas en Artifact Registry
gcloud artifacts repositories update alpinashop \
--location=europe-west1 \
--update-labels=limpieza=activa
# Politica de limpieza: borrar sin etiqueta y con mas de 30 dias,
# conservando siempre las 10 versiones mas recientes
gcloud artifacts repositories set-cleanup-policies alpinashop \
--location=europe-west1 --policy=politica-limpieza.json[
{
"name": "borrar-antiguas-sin-etiqueta",
"action": {"type": "Delete"},
"condition": {"tagState": "UNTAGGED", "olderThan": "30d"}
},
{
"name": "conservar-recientes",
"action": {"type": "Keep"},
"mostRecentVersions": {"keepCount": 10}
}
]
- El caso completo de AlpinaShop: antes y después
La factura de julio: 1.058 €
| Servicio | € | Comentario |
|---|---|---|
| Cloud Composer | 280 | 🔴 Entorno de evaluación de 04-06, nunca borrado |
Cloud SQL (alpinashop-pedidos HA + réplica) |
150 | HA regional + réplica de informes |
| Vertex AI (endpoint) | 140 | 🔴 Endpoint del recomendador desplegado "para probar" |
| GKE Autopilot | 120 | Clúster del catálogo |
| Dataflow | 90 | Trabajo de pedidos en streaming |
| BigQuery | 75 | 15 almacenamiento + 60 consultas |
| Compute Engine (MIG) | 50 | 2 × e2-medium 24×7 |
| Cloud Logging / Monitoring | 45 | Retención por defecto, sin exclusiones |
| Egress de red | 35 | Salida a internet y entre zonas |
| Cloud Storage | 25 | 4 buckets, sin ciclo de vida |
| Balanceador + IP | 20 | |
| Cloud Build | 15 | |
| Pub/Sub | 5 | |
| Secret Manager + KMS | 5 | |
| Cloud Functions | 3 | procesar-imagen-producto |
| Total | 1.058 € |
Los dos hallazgos que Marta no supo explicar son las dos primeras filas en rojo: 420 € al mes, el 40 % de la factura, en dos recursos que no daban valor a nadie. El de Composer llevaba cuatro meses; el endpoint de Vertex AI, tres. Coste acumulado del despiste: más de 1.500 €.
Y el detalle que lo hace doloroso: DA-002 decidió expresamente que las recomendaciones se harían por lotes y no con un endpoint 24×7. La decisión estaba escrita y era correcta. Lo que faltó fue borrar el endpoint de la prueba.
Una decisión de arquitectura solo ahorra dinero si alguien ejecuta la parte de "y ahora apaga lo otro".
La factura después: 425 €
| Servicio | Antes | Después | Qué se hizo |
|---|---|---|---|
| Cloud Composer | 280 | 0 | 🗑️ Borrado. Se usa Workflows (04-06) |
| Vertex AI | 140 | 8 | 🗑️ Endpoint eliminado; predicciones por lotes (DA-002) |
| GKE Autopilot | 120 | 0 | 🗑️ Retirado tras 07-02 |
| Cloud SQL | 150 | 105 | Dimensionado + compromiso a 1 año sobre la parte estable |
| Dataflow | 90 | 55 | Trabajadores secundarios spot + dimensionado |
| BigQuery | 75 | 38 | Particionado + clustering + require_partition_filter |
| Compute Engine | 50 | 0 | 🗑️ MIG apagado (07-02) |
| Cloud Run | 0 | 7 | ✨ Sustituye al MIG |
| Logging / Monitoring | 45 | 28 | Exclusiones de ruido y retención ajustada (06-06) |
| Egress | 35 | 22 | CDN + compresión |
| Cloud Storage | 25 | 14 | Ciclo de vida y límite de versiones |
| Balanceador + IP | 20 | 20 | Sin cambio |
| Cloud Build | 15 | 12 | Limpieza de imágenes antiguas |
| Pub/Sub | 5 | 5 | |
| Secret Manager + KMS | 5 | 5 | |
| Cloud Functions | 3 | 3 | |
| Cloud VPN HA (2 túneles) | 0 | 60 | ✨ Nuevo: enlace a Sabadell (07-03) |
| VPC Flow Logs | 0 | 8 | ✨ Nuevo: visibilidad de red |
| Logs de acceso a datos | 0 | 35 | ✨ Nuevo: requisito de 07-04 |
| Total | 1.058 € | 425 € | −60 % |
La lectura honesta
Lo que se ahorró de verdad, por orden de impacto:
- Borrar dos recursos olvidados: 412 €. El 65 % del ahorro total salió de media hora ejecutando un script de auditoría. Ninguna optimización técnica se acerca a ese retorno.
- Decisiones de arquitectura: 163 €. GKE y el MIG retirados a favor de Cloud Run. Pero cuidado con atribuirlo todo aquí: Cloud Run no se eligió para ahorrar, se eligió por trabajo operativo y portabilidad (DA-001). El ahorro fue una consecuencia agradable, no el objetivo.
- Optimizaciones de configuración: 76 €. Particionado, ciclo de vida, spot, exclusiones de logs. Trabajo real de ingeniería para un tercio del ahorro que dio borrar dos cosas.
- Compromiso de uso: 20 €. Modesto a propósito. Solo sobre Cloud SQL, que es lo único que no va a cambiar de arquitectura en un año.
Lo que NO se ahorró, y por qué:
| Concepto | € | Por qué se mantiene |
|---|---|---|
| Balanceador global + IP | 20 | Es el precio de tener CDN, WAF, TLS gestionado e IP anycast. Ahora es el 5 % de la factura y el 74 % del coste del catálogo: no se toca |
| Cloud SQL HA | 105 | La alta disponibilidad cuesta el doble. Se paga a propósito (07-06) |
| Réplica de informes | Incluida | Evita que las consultas de Lucía afecten a los pedidos. Vale su precio |
| Egress | 22 | Servir la tienda tiene un coste. Ya está optimizado con CDN |
Lo que se decidió gastar de MÁS, a propósito — y esta es la parte que casi nunca aparece en un caso de estudio:
| Concepto | € | Por qué |
|---|---|---|
| Cloud VPN HA, dos túneles | 60 | Uno solo costaría la mitad y sería un punto único de fallo. Se paga la redundancia |
| VPC Flow Logs | 8 | Sin ellos no se puede investigar un incidente de red |
| Logs de acceso a datos | 35 | Deuda #5 de 07-04. Es un requisito legal de facto: sin ellos no se puede acotar una brecha |
103 € al mes de gasto nuevo y deliberado en fiabilidad y seguridad. Sin ese matiz, el titular "hemos bajado un 60 % la factura" sería una media verdad. La verdad completa es: se eliminaron 736 € de desperdicio, se optimizaron 260 € y se reinvirtieron 103 € en cosas que hacían falta.
Optimizar coste no es recortar. Es dejar de pagar lo que no aporta para poder pagar lo que sí.
Coste unitario: la métrica que de verdad importa
El número absoluto engaña. Lo que hay que seguir es el coste por unidad de negocio:
| Métrica | Julio | Después |
|---|---|---|
| Factura mensual | 1.058 € | 425 € |
| Pedidos al mes | 1.200 | 1.200 |
| Coste por pedido | 0,88 € | 0,35 € |
| Coste como % del ingreso (ticket ~65 €) | 1,4 % | 0,55 % |
Esta métrica es la que hay que presentar a dirección, por dos motivos. Primero, porque hace comparables meses distintos: si en octubre la factura sube a 600 € pero se procesan 3.000 pedidos, el coste por pedido baja a 0,20 € y la subida es una buena noticia. Y segundo, porque convierte la infraestructura de "un gasto que hay que recortar" en "un coste variable del negocio", que es lo que realmente es.
- Herramientas: Recommender, Active Assist y la calculadora
| Herramienta | Para qué |
|---|---|
| Recommender | Recomendaciones por tipo de recurso: máquinas, discos, IP, IAM, Cloud SQL |
| Active Assist | El paraguas que agrupa Recommender, Insights y las predicciones |
| Pricing Calculator | Estimar antes de crear |
| Detección de anomalías | Incluida en la consola de facturación, gratuita |
| Informes de facturación | Agrupación y filtrado sin SQL |
| Cloud Billing API | Automatizar consultas y precios |
# Todas las recomendaciones de coste de un proyecto, de un vistazo
for R in google.compute.instance.MachineTypeRecommender \
google.compute.disk.IdleResourceRecommender \
google.compute.address.IdleResourceRecommender \
google.compute.image.IdleResourceRecommender \
google.cloudsql.instance.IdleRecommender \
google.cloudsql.instance.OverprovisionedRecommender; do
echo "=== $R ==="
gcloud recommender recommendations list \
--project=alpinashop-prod --location=europe-west1-b --recommender="$R" \
--format="table(description, primaryImpact.costProjection.cost.units)" 2>/dev/null
doneConsejo sobre la calculadora: úsala antes de crear, no después de la factura. Diez minutos estimando el coste de una arquitectura evitan la sorpresa del mes siguiente, y sobre todo permiten comparar dos diseños en euros y no en intuiciones.
Errores Comunes y Consejos
- Optimizar antes de medir. Se acaba afinando lo visible mientras 280 € al mes se van en algo que nadie sabía que existía.
- Olvidar el array
creditsen las consultas de facturación. Las cifras salen infladas y nadie entiende por qué no cuadran con la consola. - Consultar la tabla de facturación sin filtro de partición. La consulta que analiza tu coste te cuesta dinero.
- Creer que un presupuesto limita el gasto. Solo avisa. Frenar hay que automatizarlo, y con cuidado.
- Automatizar el apagado de producción por presupuesto. Un pico de ventas apagaría la tienda el mejor día del año.
- Comprometerse a 1 o 3 años antes de estabilizar la arquitectura. Si migras después, pagas por lo que ya no usas.
- Comprometer el 100 % del consumo. Solo la parte estable, un 50-70 % del mínimo histórico.
- Poner Archive a datos que se consultan cada dos meses. Los cargos por recuperación anticipada lo hacen más caro que Standard.
- Tablas de BigQuery sin
require_partition_filter. UnSELECT *sin filtro puede costar más que un mes de servidores. - Versionado de buckets sin límite de versiones. El bucket crece indefinidamente y nadie lo mira.
- Etiquetas con valores libres.
equipo: variosdestruye el análisis. Conjunto cerrado y validación en Terraform. - Reservar IP estáticas "por si acaso". Una IP reservada sin usar cuesta más que una en uso.
- Borrar una VM sin marcar el disco para borrado automático. El disco huérfano sigue facturando.
- Consejo: ejecuta el script de fantasmas el primer lunes de cada mes. Es la actividad de mayor retorno por hora de toda la lección.
- Consejo: sigue el coste por unidad de negocio, no el absoluto. Es lo único que hace comparables meses distintos.
- Consejo: la reunión mensual de 30 minutos con el panel abierto es la práctica de FinOps más rentable que existe.
- Consejo: pon
--max-instancesen todo lo que escale. Es un cortafuegos de coste (07-02). - Consejo: usa la calculadora antes de crear. Comparar dos diseños en euros es mejor que discutirlos en intuiciones.
Ejercicios
Ejercicio 1 — Investigar una subida de factura
La factura de AlpinaShop ha pasado de 425 € a 690 € de un mes a otro. No ha habido campaña ni despliegues grandes. Dirección pregunta qué ha pasado.
Escribe la secuencia completa de consultas SQL sobre la exportación de facturación que usarías para llegar a la causa raíz, explicando qué buscas en cada paso y cómo interpretas el resultado. Indica al menos cuatro causas plausibles y cómo distinguirías entre ellas con datos.
Ejercicio 2 — Optimizar el entorno de datos
El proyecto alpinashop-datos cuesta 250 € al mes:
- BigQuery consultas: 95 € (bajo demanda)
- BigQuery almacenamiento: 40 €
- Dataflow: 70 €
- Cloud Storage (
alpinashop-datalake): 45 €
Datos adicionales: la tabla eventos_web tiene 1,2 TB, no está particionada y se consulta unas 200 veces al día desde un cuadro de mando. El trabajo de Dataflow procesa pedidos en streaming las 24 horas, aunque los pedidos llegan casi todos entre las 9:00 y las 23:00. El data lake tiene 3 TB, de los cuales el 80 % son ficheros de más de un año que solo se consultan para auditorías anuales.
Propón un plan de optimización con el ahorro estimado de cada medida, el esfuerzo, y el riesgo asociado. Ordénalo por retorno.
Ejercicio 3 — Presentar el caso a dirección
Prepara la presentación de Marta al consejo de AlpinaShop sobre la gestión de costes del último trimestre. Debe incluir: qué se ha conseguido, cómo se ha conseguido, qué se gasta de más a propósito, cuál es la métrica que se va a seguir a partir de ahora, y qué se pide para el trimestre siguiente.
Escríbelo como se lo diría a un consejo que no es técnico. Máximo una página. Y explica después qué tres decisiones de comunicación has tomado y por qué.
Soluciones
Solución 1 — Investigar una subida de factura
Paso 1 — Localizar el servicio y el momento. Nunca se empieza por el detalle: primero se acota.
SELECT
service.description AS servicio,
ROUND(SUM(CASE WHEN DATE(usage_start_time) >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
THEN cost END), 2) AS mes_actual,
ROUND(SUM(CASE WHEN DATE(usage_start_time) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 60 DAY)
AND DATE_SUB(CURRENT_DATE(), INTERVAL 31 DAY)
THEN cost END), 2) AS mes_anterior
FROM `alpinashop-datos.facturacion.gcp_billing_export_resource_v1_XXXXXX`
WHERE DATE(_PARTITIONTIME) >= DATE_SUB(CURRENT_DATE(), INTERVAL 60 DAY)
GROUP BY servicio
HAVING mes_actual > 1
ORDER BY (mes_actual - IFNULL(mes_anterior, 0)) DESCLa primera fila da el servicio responsable de la mayor parte de los 265 €.
Paso 2 — Averiguar la forma temporal. Es el paso que más información aporta y el que casi nadie hace:
SELECT
DATE(usage_start_time) AS dia,
ROUND(SUM(cost), 2) AS coste
FROM `alpinashop-datos.facturacion.gcp_billing_export_resource_v1_XXXXXX`
WHERE DATE(_PARTITIONTIME) >= DATE_SUB(CURRENT_DATE(), INTERVAL 60 DAY)
AND service.description = 'SERVICIO_SOSPECHOSO'
GROUP BY dia
ORDER BY diaLa forma de la curva es el diagnóstico:
| Forma | Significado |
|---|---|
| Escalón que empieza un día y se mantiene | Se creó un recurso permanente. Fantasma o despliegue |
| Pico de uno o dos días | Un trabajo puntual, una consulta, una prueba |
| Rampa creciente | Algo que acumula: almacenamiento, logs, instantáneas |
| Dientes de sierra más altos | Aumento de tráfico o de frecuencia de un proceso |
Paso 3 — Bajar a SKU y a recurso.
SELECT
sku.description AS sku,
resource.name AS recurso,
ROUND(SUM(cost), 2) AS coste,
ROUND(SUM(usage.amount), 2) AS uso,
ANY_VALUE(usage.unit) AS unidad
FROM `alpinashop-datos.facturacion.gcp_billing_export_resource_v1_XXXXXX`
WHERE DATE(_PARTITIONTIME) >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
AND service.description = 'SERVICIO_SOSPECHOSO'
GROUP BY sku, recurso
ORDER BY coste DESC LIMIT 20Paso 4 — Correlacionar con los cambios. Con la fecha del escalón:
FECHA="2026-09-14"
gcloud logging read "
protoPayload.methodName=~'(create|insert|Create|Insert)'
AND timestamp>=\"${FECHA}T00:00:00Z\"
AND timestamp<=\"${FECHA}T23:59:59Z\"" \
--project=alpinashop-datos --limit=100 \
--format="table(timestamp, protoPayload.methodName,
protoPayload.authenticationInfo.principalEmail,
protoPayload.resourceName)"Las cuatro causas plausibles y cómo distinguirlas:
| Causa | Firma en los datos | Confirmación |
|---|---|---|
| Recurso nuevo olvidado | Escalón limpio, mismo importe cada día, un solo resource.name |
Logs de auditoría del día del escalón; script de fantasmas |
| Consulta de BigQuery desbocada | Pico en el SKU "Analysis"; usage.amount en TB dispar |
INFORMATION_SCHEMA.JOBS_BY_PROJECT ordenado por total_bytes_billed |
| Crecimiento de almacenamiento o logs | Rampa suave, sin escalón; SKU de "Storage" | Tamaño del bucket o volumen de ingesta de Logging |
| Aumento de tráfico real | Sube egress y Cloud Run y peticiones del balanceador a la vez | Métricas de negocio: si suben los pedidos, es buena noticia |
La cuarta merece el matiz que da criterio: una subida proporcional a la actividad de negocio no es un problema de coste. Se verifica con la métrica unitaria del apartado 12: si el coste por pedido se mantiene, el negocio ha crecido; si se dispara, hay ineficiencia.
Para el caso de BigQuery, la consulta definitiva:
SELECT
user_email,
DATE(creation_time) AS dia,
COUNT(*) AS consultas,
ROUND(SUM(total_bytes_billed)/POW(1024,4), 2) AS tib_facturados,
ROUND(SUM(total_bytes_billed)/POW(1024,4) * 5.5, 2) AS coste_estimado_eur
FROM `alpinashop-datos.region-eu.INFORMATION_SCHEMA.JOBS_BY_PROJECT`
WHERE creation_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
AND job_type = 'QUERY' AND state = 'DONE'
GROUP BY user_email, dia
ORDER BY tib_facturados DESC LIMIT 20Y en cuanto se identifique la causa, la acción no es solo corregir: es poner el control que impide que se repita — require_partition_filter si fue una consulta, el script mensual si fue un fantasma, una alerta de anomalía si fue una rampa.
Solución 2 — Optimizar el entorno de datos
Análisis previo. Los cuatro conceptos tienen causas muy distintas y el orden de ataque no es el orden de la lista.
Medida 1 — Particionar y agrupar eventos_web. (Ahorro: ~75 €/mes · Esfuerzo: 4 h · Riesgo: bajo)
Una tabla de 1,2 TB sin particionar, consultada 200 veces al día, es la definición del problema. Cada consulta lee 1,2 TB salvo que BigQuery pueda podar, y sin partición no puede.
CREATE OR REPLACE TABLE `alpinashop-datos.alpinashop_analitica.eventos_web_opt`
PARTITION BY DATE(momento)
CLUSTER BY tipo_evento, pagina
OPTIONS (
partition_expiration_days = 400,
require_partition_filter = TRUE
)
AS SELECT * FROM `alpinashop-datos.alpinashop_analitica.eventos_web`;Estimación: el cuadro de mando consulta típicamente los últimos 30 días → de 1,2 TB a unos 30 GB por consulta, y el clustering recorta más. Reducción realista del 80-85 % del coste de consultas: 95 € → ~20 €.
Riesgo y mitigación: require_partition_filter romperá las consultas existentes sin filtro. Se despliega en dos fases: crear la tabla optimizada, migrar el cuadro de mando y las consultas guardadas, verificar, y solo entonces sustituir la original. Nunca al revés.
Bonus gratuito: partition_expiration_days = 400 elimina solo los eventos de más de 400 días, lo que además reduce el almacenamiento con el tiempo.
Medida 2 — Ciclo de vida del data lake. (Ahorro: ~28 €/mes · Esfuerzo: 1 h · Riesgo: muy bajo)
2,4 TB (el 80 % de 3 TB) son de más de un año y solo se leen en auditorías anuales. Están en Standard.
lifecycle_rule {
condition { age = 90 }
action { type = "SetStorageClass" storage_class = "NEARLINE" }
}
lifecycle_rule {
condition { age = 365 }
action { type = "SetStorageClass" storage_class = "COLDLINE" }
}
lifecycle_rule {
condition { age = 1095 }
action { type = "SetStorageClass" storage_class = "ARCHIVE" }
}Cálculo: 2,4 TB pasando de Standard a Coldline (~0,3×) ahorra en torno al 70 % de su parte. 45 € → ~17 €.
Por qué Coldline y no Archive para el tramo de un año: con recuperación mínima de 365 días, Archive castiga cualquier lectura anticipada. Una auditoría anual está justo en el límite y podría dispararse el cargo. Coldline (90 días) es el punto seguro; Archive se reserva para lo de más de tres años, que ya nadie va a tocar.
Medida 3 — Dataflow: repensar el streaming. (Ahorro: ~35 €/mes · Esfuerzo: 1-2 días · Riesgo: medio)
Un trabajo de streaming 24×7 cuando los pedidos llegan entre las 9:00 y las 23:00. Tres opciones, y la elección depende de un requisito de negocio, no técnico:
| Opción | Ahorro | Impacto |
|---|---|---|
| (a) Trabajadores secundarios spot + dimensionar | ~25 € | Ninguno. Empezar por aquí |
| (b) Streaming solo de 8:00 a 24:00; Pub/Sub retiene por la noche | ~25 € | Los pedidos nocturnos aparecen por la mañana |
| (c) Sustituir por proceso por lotes cada 15 min | ~50 € | Latencia de 15 min en la analítica |
La pregunta que decide: ¿alguien mira los datos de pedidos en tiempo real? En AlpinaShop, la respuesta honesta es no: Lucía mira el cuadro de mando por la mañana. La opción (c) es la correcta y es la que más ahorra, pero exige reescribir el pipeline y por eso se plantea después de (a), que es gratis.
Plan realista: aplicar (a) esta semana (~25 €), y evaluar (c) el trimestre siguiente.
Medida 4 — Almacenamiento de BigQuery a largo plazo. (Ahorro: ~8 €/mes · Esfuerzo: 30 min · Riesgo: nulo)
BigQuery aplica automáticamente un precio de almacenamiento a largo plazo (~50 % menos) a las particiones no modificadas en 90 días. La trampa: cualquier UPDATE sobre una partición reinicia el contador.
SELECT table_name, partition_id,
ROUND(total_logical_bytes/POW(1024,3), 2) AS gib,
last_modified_time
FROM `alpinashop-datos.alpinashop_analitica.INFORMATION_SCHEMA.PARTITIONS`
WHERE total_logical_bytes > 0
ORDER BY total_logical_bytes DESCSi aparecen particiones antiguas con last_modified_time reciente, hay un proceso reescribiéndolas innecesariamente. Corregirlo es gratis y el descuento se aplica solo.
También conviene evaluar el modelo de facturación físico frente al lógico: con datos muy comprimibles puede salir más barato, aunque el descuento a largo plazo funciona distinto. Se compara con INFORMATION_SCHEMA antes de cambiar.
Plan ordenado por retorno:
| Orden | Medida | Ahorro | Esfuerzo | €/hora |
|---|---|---|---|---|
| 1 | Ciclo de vida del data lake | 28 € | 1 h | 28 |
| 2 | Particionar y agrupar | 75 € | 4 h | 19 |
| 3 | Almacenamiento a largo plazo | 8 € | 0,5 h | 16 |
| 4 | Dataflow spot (a) | 25 € | 4 h | 6 |
| 5 | Dataflow a lotes (c) | +25 € | 12 h | 2 |
Resultado: 250 € → ~115 €, un 54 % menos, con las cuatro primeras medidas en unas dos jornadas de trabajo.
Y la medida que no cuesta nada y que hay que aplicar el primer día, antes que ninguna de las anteriores:
gcloud alpha services quota update \
--service=bigquery.googleapis.com \
--consumer=projects/alpinashop-datos \
--metric=bigquery.googleapis.com/quota/query/usage \
--unit=1/d/{project}/{user} --value=549755813888 # 512 GiB/usuario/diaPorque todo lo anterior optimiza el consumo actual, pero nada impide que mañana alguien escriba una consulta que cueste 300 € en una tarde. La cuota es el único control que lo impide.
Solución 3 — Presentar el caso a dirección
Gestión del coste de la plataforma tecnológica — Informe del tercer trimestre Marta Ruiz, responsable de infraestructura
Resumen. El coste mensual de nuestra plataforma tecnológica ha pasado de 1.058 € a 425 €, un 60 % menos, sin reducir ninguna capacidad y habiendo añadido medidas de seguridad y de continuidad que antes no teníamos. En términos de negocio, el coste tecnológico por pedido ha bajado de 0,88 € a 0,35 €: de un 1,4 % a un 0,55 % del importe medio de un pedido.
De dónde viene el ahorro. Dos terceras partes no vienen de negociar mejor ni de recortar: vienen de haber encontrado dos servicios encendidos que nadie usaba —una herramienta que evaluamos en primavera y un modelo de recomendaciones que probamos en verano— y que juntos costaban 420 € al mes. Ninguna persona decidió gastarlo; simplemente nadie decidió apagarlo. Ya está corregido, y desde este mes ejecutamos una revisión automática el primer lunes de cada mes para que no vuelva a ocurrir. La lección es que en la nube el gasto crece por omisión, no por decisión, y eso exige una rutina.
El tercio restante son mejoras técnicas: hemos trasladado la tienda a una tecnología que solo cobra cuando hay visitas —de madrugada no pagamos nada—, hemos reorganizado los datos para que las consultas del cuadro de mando lean lo justo, y hemos movido los archivos antiguos a un almacenamiento más barato.
Lo que gastamos de más, a propósito. Quiero que conste explícitamente que 103 € al mes son gasto nuevo y deliberado: la conexión con la tienda de Sabadell está duplicada para que un corte no nos deje sin inventario, y hemos activado el registro de quién accede a los datos de clientes, que es lo que nos permitiría responder ante la Agencia de Protección de Datos si algún día hubiera un incidente. Sin ese registro no podríamos acotar qué pasó, y eso es una exposición legal, no solo técnica. Optimizar el coste no significa recortar en fiabilidad ni en cumplimiento: significa dejar de pagar lo que no aporta para poder pagar lo que sí.
La métrica que seguiremos. A partir de ahora informaremos del coste por pedido, no del total. Es importante entender por qué: en la campaña de otoño la factura va a subir, y eso será una buena noticia. Si vendemos el triple, el coste por pedido bajará aunque el importe total crezca. El número absoluto no dice nada por sí solo; el unitario sí.
Lo que pedimos para el próximo trimestre. Nada de presupuesto adicional. Solo dos decisiones:
- Autorización para un compromiso a un año sobre la base de datos, que es lo único que sabemos con certeza que no va a cambiar. Ahorra en torno a un 30 % de esa partida a cambio de comprometernos.
- Media hora al mes de dirección para revisar el panel de costes con nosotros. Es la medida más barata y más eficaz de todas: lo que se mira en grupo no se descontrola.
Las tres decisiones de comunicación, y por qué:
1. Empezar por el número de negocio, no por el técnico. El titular no es "hemos migrado a Cloud Run": es "el coste por pedido ha bajado de 0,88 € a 0,35 €". Un consejo no puede evaluar una decisión de arquitectura, pero sí sabe perfectamente qué significa que cada pedido cueste la mitad. Traducir a la unidad del negocio no es simplificar: es hablar en la moneda en la que ellos deciden.
2. Contar el fallo antes de que lo pregunten. Se podría haber presentado el ahorro como mérito técnico y callar que 420 € se iban en dos recursos olvidados. Decirlo tiene tres efectos que compensan de sobra la incomodidad: da credibilidad a todo lo demás del informe, justifica la rutina mensual —que sin la anécdota parecería burocracia innecesaria— y protege de la pregunta incómoda dentro de seis meses. Un informe que solo cuenta aciertos se cree a medias.
3. Anticipar la mala noticia y reencuadrarla. La factura va a subir en campaña. Si eso se explica después, parece una excusa; explicado antes, es previsión — y además enseña al consejo a leer la métrica correcta. Es la misma razón por la que el gasto nuevo de 103 € se declara de forma destacada en lugar de esconderlo en el neto: si dirección descubre por su cuenta un gasto que no se le contó, pierde la confianza en todo el informe, por muy bueno que sea el resultado.
Y una cuarta que no se ve pero está: no se pide dinero, se piden decisiones. Un informe que termina pidiendo presupuesto se lee con desconfianza; uno que termina pidiendo media hora al mes y una autorización que ahorra, se lee como gestión.
Conclusión
La factura de AlpinaShop ha dejado de ser una sorpresa mensual para convertirse en un dato que se entiende, se atribuye y se gobierna.
Sabes por qué la nube sorprende: coste variable, decisiones técnicas con efecto económico, ausencia de freno natural y desfase temporal — con la primera regla grabada: el problema casi nunca es que algo sea caro, sino que nadie sabía que estaba encendido.
Sabes leer una factura: servicio, SKU y uso, con la constatación de que una VM no es un coste sino cinco SKU distintos. Distingues los descuentos que se aplican solos —uso sostenido— de los que hay que contratar, y sabes que el sostenido explica por qué apagar por las noches ahorra menos de lo que la aritmética promete.
Tienes la exportación a BigQuery configurada con coste detallado —sin el cual sabes que Storage cuesta 25 € pero no qué bucket— y las seis consultas que responden las preguntas reales, con los dos errores clásicos evitados: olvidar el array credits y consultar sin filtro de partición. Incluida la consulta más incómoda, la del gasto sin etiquetar, que en AlpinaShop reveló que el 36 % de la factura no tenía dueño.
Entiendes FinOps —informar, optimizar, operar— con el orden que importa: primero medir, luego cortar. Y el modelo de responsabilidad para una empresa pequeña, con la práctica de mayor retorno de toda la disciplina: una reunión de treinta minutos al mes con el panel abierto.
Sabes montar presupuestos con la regla de previsión que avisa el día 8 y no el 26, varios en lugar de uno solo, y la acción automática por Pub/Sub y función — con las tres advertencias: nunca apagar producción, desvincular la facturación es destructivo, y los mensajes llegan duplicados. Y sabes que el único freno duro son las cuotas, incluidas las de bytes de BigQuery, que hay que poner siempre.
Tienes las nueve palancas ordenadas por retorno, con la primera muy por delante de todas: eliminar lo que no se usa. Y las demás con sus trampas dichas — dimensionar según agosto cuando el pico es en octubre, comprometerse antes de estabilizar la arquitectura, poner Archive a datos que se leen cada dos meses, versionado sin límite de versiones. Con require_partition_filter señalada como la opción más rentable de todo BigQuery: noventa veces más barata la misma consulta.
Sabes dónde se esconde el coste del tráfico y tienes la disciplina de etiquetado convertida en control real, con validaciones de Terraform que hacen fallar el plan si falta una etiqueta o su valor no está en el conjunto cerrado — prevención en el punto de creación, que vence siempre a perseguir huérfanos después.
Cazas anomalías con estadística y fantasmas con un script que hay que ejecutar el primer lunes de cada mes: IP reservadas que cuestan más que las usadas, discos huérfanos, instantáneas eternas, endpoints de Vertex AI, clústeres de pruebas, entornos de Composer y balanceadores sin backends.
Y tienes el caso completo: 1.058 € desglosados con dos partidas en rojo que sumaban el 40 % de la factura y llevaban meses ahí, frente a 425 € después. Con la lectura honesta que es lo más valioso del apartado: el 65 % del ahorro salió de media hora ejecutando un script, la arquitectura aportó menos de lo que parece —y además Cloud Run no se eligió para ahorrar—, las optimizaciones técnicas dieron un tercio de lo que dio borrar dos cosas, y 103 € al mes son gasto nuevo y deliberado en redundancia, visibilidad de red y logs de acceso a datos. Más la métrica que hay que presentar de ahora en adelante: el coste por pedido, que convierte la infraestructura de gasto a recortar en coste variable del negocio.
De todo ello queda una frase que resume la lección entera y que enlaza con lo que viene:
Optimizar coste no es recortar. Es dejar de pagar lo que no aporta para poder pagar lo que sí.
Y esa frase tiene una contrapartida que hay que decir con la misma claridad. En esta lección se ha decidido pagar la alta disponibilidad de Cloud SQL sin discutirla, se han duplicado los túneles VPN sabiendo que uno costaría la mitad, y se ha aceptado que el balanceador global —que ahora es el 74 % del coste del catálogo— no se toca. Tres decisiones de fiabilidad tomadas por intuición, sin un objetivo que las justifique con números.
Porque AlpinaShop todavía no ha respondido a la pregunta más básica de todas: ¿qué significa exactamente que la tienda "funcione bien"? Hay alertas desde 06-04, pero una alerta dice que algo pasó, no si el servicio está cumpliendo lo que promete. No hay un objetivo declarado, no hay forma de saber si 43 minutos de caída al mes son aceptables o inadmisibles, no hay criterio para decidir si se puede desplegar un viernes, y —lo más grave, señalado ya como deuda crítica en 07-04— nadie ha comprobado nunca que las copias de seguridad se puedan restaurar.
La siguiente lección responde a todo eso con números: SLI, SLO, presupuesto de error, arquitecturas de alta disponibilidad por niveles, modos de fallo y su mitigación, y un plan de recuperación ante desastres con RTO y RPO — incluido el ensayo de restauración de alpinashop-pedidos que lleva demasiado tiempo pendiente.
Curso de Google Cloud Platform (GCP)
Módulo 1: Introducción a Google Cloud Platform
- ¿Qué es Google Cloud Platform?
- Configuración de tu cuenta de GCP
- Descripción general de la consola de GCP
- Proyectos, jerarquía de recursos y facturación
- Regiones, zonas y modelo de responsabilidad compartida
- Cloud Shell y la CLI de gcloud
Módulo 2: Servicios principales de GCP
- Compute Engine: máquinas virtuales en Google Cloud
- Cloud Storage: almacenamiento de objetos
- Cloud SQL: bases de datos relacionales gestionadas
- App Engine: plataforma como servicio
- Google Kubernetes Engine (GKE)
- Bases de datos NoSQL: Firestore, Bigtable y Spanner
- Cómo elegir el servicio de cómputo adecuado
Módulo 3: Redes y seguridad
- Redes VPC
- Balanceo de carga en la nube
- Cloud CDN
- Gestión de identidad y acceso (IAM)
- Cloud Armor
- Secretos y cifrado: Secret Manager y Cloud KMS
- Cloud DNS, certificados TLS y publicación segura de servicios
Módulo 4: Datos y análisis
- BigQuery: el almacén de datos analítico
- Cloud Dataflow: procesamiento de datos por lotes y en streaming
- Cloud Dataproc: Spark y Hadoop gestionados
- Cloud Pub/Sub: mensajería asíncrona
- Cloud Data Fusion: integración de datos sin código
- Orquestación de pipelines con Cloud Composer y Workflows
- Gobierno del dato y cuadros de mando con Dataplex y Looker Studio
Módulo 5: Aprendizaje automático e IA
- Vertex AI: la plataforma de machine learning de GCP
- AutoML: modelos a medida sin escribir código
- TensorFlow en GCP: entrenamiento y servicio de modelos
- API de lenguaje natural
- API de visión
- IA generativa en Vertex AI: modelos Gemini y embeddings
- MLOps: del modelo al producto con Vertex AI Pipelines
Módulo 6: DevOps y monitoreo
- Cloud Build: integración continua en GCP
- Cloud Source Repositories y gestión del código fuente
- Cloud Functions: funciones sin servidor
- Cloud Monitoring (antes Stackdriver): métricas, paneles y alertas
- Cloud Deployment Manager e infraestructura como código nativa
- Cloud Logging y Cloud Trace: logs, trazas y diagnóstico
- Terraform en GCP: infraestructura como código en la práctica
Módulo 7: Temas avanzados de GCP
- Híbrido y multinube con Anthos
- Computación sin servidor con Cloud Run
- Redes avanzadas: VPC compartida, peering y conectividad híbrida
- Mejores prácticas de seguridad
- Gestión y optimización de costos
- Fiabilidad: SLO, alta disponibilidad y recuperación ante desastres
- Gobierno a escala: organización, políticas y auditoría
