Tanquem el mòdul 2 amb un diagnòstic incòmode: tot el que AlpinaShop ha construït està exposat. La VM alpinashop-web-1 té el port 80 obert a internet i el 22 accessible des de qualsevol adreça, la instància alpinashop-pedidos és abastable per IP pública, el Service de GKE va publicar una IP sense HTTPS i no existeix cap frontera entre el que ha de ser públic i el que no ho hauria de ser mai. Aquesta lliçó construeix aquesta frontera.

La xarxa és la capa sobre la qual s'apuntala tot la resta. Abans de posar un balancejador, un CDN o un WAF cal decidir on viu cada màquina, quins rangs d'adreces fa servir, qui pot parlar amb qui i per on surt el trànsit cap a internet. A Google Cloud aquesta decisió es materialitza en una VPC (Virtual Private Cloud): una xarxa privada definida per programari, aïllada de la resta de clients, dins de la qual conviuen les teves instàncies, els teus clústers, les teves bases de dades i els teus balancejadors.

La xarxa VPC de Google Cloud té una propietat que sorprèn qui ve d'AWS o d'un centre de dades tradicional: és global. Una única xarxa pot abastar totes les regions del planeta, i dues màquines a Bèlgica i a Tòquio dins de la mateixa VPC es parlen per IP privada sense túnels ni passarel·les. Les subxarxes, en canvi, són regionals. Entendre aquesta asimetria és el 80 % d'entendre la xarxa de Google.

En aquesta lliçó dissenyaràs i implementaràs la xarxa alpinashop-vpc amb les seves subxarxes, planificaràs l'adreçament sense encavalcaments, escriuràs el conjunt real de regles de tallafoc d'AlpinaShop, donaràs sortida a internet a màquines sense IP pública amb Cloud NAT, arribaràs a les APIs de Google sense passar per internet amb Private Google Access i connectaràs per fi alpinashop-pedidos per IP privada.

Avís. Aquesta lliçó té implicacions de seguretat directes. El disseny que es proposa és raonable per a una pime com AlpinaShop, però qualsevol arquitectura de xarxa que hagi d'anar a producció l'ha de revisar un professional de seguretat, i si tractes dades personals o mitjans de pagament, també un responsable de compliment normatiu.

Contingut

  1. Què és una VPC i en què es diferencia d'una xarxa tradicional
  2. Xarxa per defecte, mode automàtic i mode personalitzat
  3. Planificació de l'adreçament: CIDR sense encavalcaments
  4. Creació d'alpinashop-vpc i les seves subxarxes
  5. Rangs secundaris per a GKE
  6. Adreces IP internes i externes, efímeres i estàtiques
  7. Regles de tallafoc VPC: el model complet
  8. El conjunt real de regles d'AlpinaShop
  9. Rutes i la passarel·la per defecte
  10. Cloud NAT: sortida a internet sense IP pública
  11. Private Google Access: arribar a les APIs sense sortir a internet
  12. Accés privat a serveis: Cloud SQL per IP privada
  13. VPC Flow Logs: diagnòstic i auditoria
  14. Què queda fora d'aquesta lliçó

  1. Què és una VPC i en què es diferencia d'una xarxa tradicional

En un centre de dades clàssic, la xarxa és física: switches, VLAN, cablejat, rangs que algú va apuntar en un full de càlcul fa vuit anys. A Google Cloud, la xarxa és una abstracció de programari muntada sobre la xarxa global de Google. Les diferències pràctiques són aquestes:

Concepte Xarxa tradicional VPC de Google Cloud
Abast Un centre de dades, una seu Global: totes les regions alhora
Segmentació VLAN + encaminadors físics Subxarxes regionals dins de la mateixa xarxa
Connexió entre seus Enllaços dedicats, VPN Automàtica dins de la VPC, per la xarxa interna de Google
Tallafoc Aparell en un punt de la xarxa Distribuït: s'aplica a cada interfície de cada VM
Canviar un rang Finestra de manteniment S'afegeix una subxarxa nova; ampliar el rang és una comanda
Cost de la xarxa interna Amortització del maquinari Trànsit entre zones i regions, mesurat per GB

Tres conseqüències que convé gravar des del principi:

  • La xarxa és un recurs global del projecte. No pertany a una regió. Quan crees alpinashop-vpc a alpinashop-prod, existeix a tot arreu.
  • Les subxarxes són regionals, no zonals. Una subxarxa a europe-west1 cobreix europe-west1-b, -c i -d. Una VM a qualsevol d'aquestes zones pot prendre una IP d'aquesta subxarxa. Això és el que permet que el MIG regional alpinashop-web-mig reparteixi instàncies entre tres zones fent servir una sola subxarxa.
  • El tallafoc no és "en un lloc". No hi ha un tallafoc perimetral pel qual passi el trànsit: cada regla s'aplica a l'hipervisor, a la mateixa interfície de xarxa de cada VM. Per això el trànsit entre dues VM de la mateixa subxarxa també està subjecte a regles, i per això no pots "saltar-te" el tallafoc posant les màquines juntes.

  1. Xarxa per defecte, mode automàtic i mode personalitzat

Quan vas crear el projecte alpinashop-prod, Google va crear automàticament una xarxa anomenada default. És còmoda per provar i mala idea per a producció. Vegem per què.

Existeixen dos modes de xarxa:

Mode automàtic (--subnet-mode=auto) Mode personalitzat (--subnet-mode=custom)
Subxarxes Una per regió, creades soles, amb rangs fixos 10.128.0.0/9 Cap: les crees tu, amb el rang que decideixis
Regions noves Apareix una subxarxa automàticament No canvia res
Control del CIDR Cap Total
Risc d'encavalcament amb l'oficina o amb una altra VPC Alt Controlat
Regles de tallafoc inicials Permissives (inclou SSH i RDP des de 0.0.0.0/0) Cap, tret de les implícites

La xarxa default és de mode automàtic i a més porta regles de tallafoc preconfigurades que obren el port 22 (SSH) i el 3389 (RDP) a tot internet. Això és exactament el problema que AlpinaShop arrossega des del mòdul 2.

Tota organització seriosa fa servir mode personalitzat per tres motius:

  1. Control de l'adreçament. Si demà AlpinaShop connecta la seva oficina per VPN (tema de 07-03), els rangs no poden xocar. Amb mode automàtic, Google decideix per tu a totes les regions presents i futures.
  2. Superfície d'atac mínima. No hi ha subxarxes a regions que no fas servir ni regles permissives que algú es va oblidar de revisar.
  3. Reproductibilitat. La xarxa es descriu en codi (Terraform, a 06-07) i es recrea idèntica a alpinashop-dev.

La primera tasca real, doncs, és crear una xarxa personalitzada i deixar de fer servir default:

# Fixem el projecte de treball (configuracio anomenada del modul 1)
gcloud config set project alpinashop-prod

# Veiem que hi ha ara mateix
gcloud compute networks list
gcloud compute networks subnets list --filter="network:default"

Més endavant, quan tot estigui migrat, la xarxa default s'elimina. No s'elimina el primer dia: hi ha recursos vius a dins. L'ordre correcte és crear la xarxa nova → moure càrregues → esborrar la vella.

  1. Planificació de l'adreçament: CIDR sense encavalcaments

Abans d'escriure una sola comanda, es planifica sobre paper. Un pla d'adreçament dolent es paga durant anys, perquè el rang primari d'una subxarxa es pot ampliar, però no reduir ni moure, i perquè dues xarxes amb rangs encavalcats no es poden connectar mai.

Recordatori mínim de CIDR:

Notació Màscara Adreces totals Adreces usables a GCP
/24 255.255.255.0 256 252
/22 255.255.252.0 1 024 1 020
/20 255.255.240.0 4 096 4 092
/16 255.255.0.0 65 536 65 532

Google reserva quatre adreces a cada subxarxa: la de xarxa, la passarel·la (sempre la segona, x.x.x.1), i dues reservades per a ús futur (les dues últimes). Per això un /24 dona 252 IP utilitzables, no 254.

El pla d'AlpinaShop reserva el bloc privat 10.10.0.0/16 per a producció i deixa espai deliberat entre subxarxes:

Ús Rang Regió Comentari
sn-web-euw1 (primari) 10.10.0.0/24 europe-west1 Instàncies del MIG del catàleg
sn-datos-euw1 (primari) 10.10.1.0/24 europe-west1 Backends interns i treballs per lots
sn-web-euw1 secundari gke-pods 10.20.0.0/16 — Pods d'alpinashop-cluster
sn-web-euw1 secundari gke-servicios 10.21.0.0/20 — Services d'alpinashop-cluster
Accés privat a serveis (Cloud SQL) 10.30.0.0/20 — Rang cedit a Google per a serveis gestionats
Reservat per a subxarxes futures 10.10.2.0/24 … 10.10.255.0/24 — No assignar sense actualitzar aquest document
Reservat per a alpinashop-dev 10.60.0.0/16 — Una altra VPC, un altre projecte
Oficina d'AlpinaShop (VPN futura) 192.168.10.0/24 — No fer-lo servir mai dins de la VPC

Regles d'or en planificar:

  • No facis servir mai 10.0.0.0/24 ni 192.168.1.0/24. Són els rangs que fa servir mig món, inclosa la xarxa domèstica dels teus companys; el dia que hi hagi VPN, xocaran.
  • Deixa forats. És més fàcil demanar perdó que reorganitzar adreces.
  • Documenta el pla i versiona'l. El document d'adreçament viu al repositori, no a la memòria de la Marta.
  • Els rangs de pods de Kubernetes són grans. Un /16 per a pods no és exagerat: GKE reserva un bloc per node.

  1. Creació d'alpinashop-vpc i les seves subxarxes

Amb el pla tancat, la implementació són tres comandes:

# 1) La xarxa, en mode personalitzat i amb encaminament global
gcloud compute networks create alpinashop-vpc \
  --project=alpinashop-prod \
  --subnet-mode=custom \
  --bgp-routing-mode=global \
  --description="Xarxa principal de produccio d'AlpinaShop"

Dos paràmetres mereixen explicació:

  • --subnet-mode=custom: no crea cap subxarxa automàticament. És el que volem.
  • --bgp-routing-mode=global: quan en el futur hi hagi un Cloud Router (VPN o Interconnect, tema de 07-03), les rutes apreses es propagaran a totes les regions, no només a la de l'encaminador. És el valor correcte per a una xarxa que pot créixer; canviar-lo després obliga a reconfigurar l'encaminador.
# 2) Subxarxa de la capa web
gcloud compute networks subnets create sn-web-euw1 \
  --project=alpinashop-prod \
  --network=alpinashop-vpc \
  --region=europe-west1 \
  --range=10.10.0.0/24 \
  --enable-private-ip-google-access \
  --enable-flow-logs \
  --logging-aggregation-interval=interval-5-sec \
  --logging-flow-sampling=0.5 \
  --logging-metadata=include-all

# 3) Subxarxa de dades i backends interns
gcloud compute networks subnets create sn-datos-euw1 \
  --project=alpinashop-prod \
  --network=alpinashop-vpc \
  --region=europe-west1 \
  --range=10.10.1.0/24 \
  --enable-private-ip-google-access \
  --enable-flow-logs \
  --logging-flow-sampling=0.5

Què fa cada opció, en detall:

  • --range: el rang primari. És el que es reparteix entre les interfícies de les VM.
  • --enable-private-ip-google-access: permet que una VM sense IP pública arribi a les APIs de Google (Cloud Storage, BigQuery, Secret Manager…). Ho desenvolupem a l'apartat 11. Activa'l sempre; no té cost ni contraindicació.
  • --enable-flow-logs i els seus paràmetres: activa el registre de fluxos. --logging-flow-sampling=0.5 mostreja la meitat dels fluxos, cosa que redueix el cost de registres a la meitat mantenint utilitat de diagnòstic. Ho veiem a l'apartat 13.

Comprovació:

gcloud compute networks subnets describe sn-web-euw1 \
  --region=europe-west1 \
  --format="table(name, ipCidrRange, gatewayAddress, privateIpGoogleAccess)"

Veuràs que gatewayAddress és 10.10.0.1: la passarel·la sempre és la segona adreça del rang, i no és una màquina que puguis tocar, sinó una funció distribuïda de la xarxa.

  1. Rangs secundaris per a GKE

El clúster alpinashop-cluster que vam crear a 02-05 necessita adreces per a pods i per a services, i aquestes adreces no surten del rang primari de la subxarxa, sinó de rangs secundaris (el que Google anomena alias IP ranges). Aquest és el model de xarxa nativa de VPC de GKE, i és el que es fa servir sempre a Autopilot.

gcloud compute networks subnets update sn-web-euw1 \
  --region=europe-west1 \
  --add-secondary-ranges=gke-pods=10.20.0.0/16,gke-servicios=10.21.0.0/20

Per què rangs tan grans:

Element Rang Capacitat aproximada
Nodes 10.10.0.0/24 (primari) 252 nodes
Pods 10.20.0.0/16 65 536 adreces; GKE assigna un /24 per node per defecte
Services (ClusterIP) 10.21.0.0/20 4 096 serveis

La conseqüència de més abast: amb xarxa nativa de VPC, un pod té una IP real de la VPC. No hi ha NAT intern entre pods i VM. Això significa que una regla de tallafoc pot referir-se directament al rang de pods, i que una VM de sn-datos-euw1 pot rebre trànsit d'un pod i veure'n la IP d'origen autèntica. És més simple de raonar i més fàcil d'auditar.

En crear un clúster nou s'indiquen els rangs així (referència per a quan recreïs el clúster a la xarxa nova):

gcloud container clusters create-auto alpinashop-cluster \
  --region=europe-west1 \
  --network=alpinashop-vpc \
  --subnetwork=sn-web-euw1 \
  --cluster-secondary-range-name=gke-pods \
  --services-secondary-range-name=gke-servicios

  1. Adreces IP internes i externes, efímeres i estàtiques

Cada VM té sempre una IP interna (de la subxarxa) i, opcionalment, una IP externa. I cadascuna pot ser efímera (s'assigna en arrencar i es perd en aturar la màquina) o estàtica (reservada, sobreviu a la instància).

Tipus Abast Persistència Cost orientatiu Ús típic a AlpinaShop
Interna efímera Subxarxa Mentre visqui la VM Gratis Instàncies del MIG
Interna estàtica Subxarxa Reservada Gratis Backends interns amb nom fix
Externa efímera Internet Mentre visqui la VM Es factura mentre està en ús Res en producció
Externa estàtica regional Internet Reservada Cost petit; més cara si està sense fer servir Balancejador regional, Cloud NAT
Externa estàtica global Internet (anycast) Reservada Cost petit IP del balancejador HTTPS global (03-02)

Reservem ja la IP global que farà servir el balancejador de la lliçó següent i les IP que necessitarà Cloud NAT:

# IP global anycast per al balancejador HTTPS extern (la farem servir a 03-02 i 03-07)
gcloud compute addresses create alpinashop-lb-ip \
  --project=alpinashop-prod \
  --global \
  --ip-version=IPV4

gcloud compute addresses describe alpinashop-lb-ip --global --format="value(address)"

# IP regional estatica per a la sortida de Cloud NAT
gcloud compute addresses create alpinashop-nat-ip \
  --project=alpinashop-prod \
  --region=europe-west1

Reservar la IP de sortida de NAT té un avantatge concret: la passarel·la de pagament d'AlpinaShop exigeix una llista d'IP autoritzades. Si la IP de sortida fos efímera, canviaria en recrear el NAT i el cobrament deixaria de funcionar un dimarts a la tarda sense motiu aparent.

Un advertiment de facturació: una IP externa estàtica reservada i no associada a res es factura igualment, i a una tarifa més alta que si estigués en ús. És una de les fuites de cost més habituals. Revisa-les periòdicament:

gcloud compute addresses list --filter="status=RESERVED" \
  --format="table(name, region, address, status)"

  1. Regles de tallafoc VPC: el model complet

El tallafoc de VPC és stateful (si permets la connexió d'entrada, la resposta surt sense necessitat de regla) i distribuït (s'aplica a cada interfície). Una regla té aquests elements:

Element Valors Notes
Direcció INGRESS (entrada) o EGRESS (sortida) Per defecte INGRESS
Acció allow o deny No hi ha "log only"; per a això hi ha --enable-logging
Prioritat 0 – 65535, guanya la menor Per defecte 1000
Origen (ingress) Rangs CIDR, etiquetes de xarxa, comptes de servei Se'n tria un dels tres tipus
Destí (egress) Rangs CIDR
Destinataris Tota la xarxa, etiquetes de xarxa, o comptes de servei El "a qui s'aplica"
Protocols i ports tcp:80,443, udp:53, icmp, all

A més existeixen quatre regles implícites que no veus a la llista i no pots esborrar:

Regla implícita Direcció Acció Prioritat
Permetre tota la sortida EGRESS allow 65535
Denegar tota l'entrada INGRESS deny 65535
Permetre DHCP, DNS i metadades (169.254.169.254) EGRESS allow Sempre
Bloquejar el port 25 sortint EGRESS deny Sempre (antispam)

La conseqüència pràctica és la que defineix la disciplina de treball: per defecte no entra res i surt tot. Tot el que vulguis permetre d'entrada s'ha d'escriure; tot el que vulguis impedir de sortida, també.

Etiquetes de xarxa davant de comptes de servei

És la decisió de disseny més important del tallafoc. Es pot seleccionar a quines màquines s'aplica una regla de dues maneres:

Criteri Etiquetes de xarxa (--target-tags) Comptes de servei (--target-service-accounts)
Qui les pot posar Qualsevol amb compute.instances.setTags Només qui pot actuar com aquest compte de servei
Canvi en calent Sí, al vol Requereix aturar la instància
Risc Un desenvolupador pot etiquetar la seva VM com a web i heretar-ne els permisos de xarxa Controlat per IAM
Llegibilitat Molt alta Alta
Recomanació Acceptable per a entorns petits Preferible en producció

AlpinaShop fa servir un model mixt i explícit: etiquetes per a les regles d'entrada des d'internet (on la llegibilitat importa i les màquines són del MIG) i comptes de servei per a l'accés a dades. I documenta aquesta decisió, perquè barrejar els dos criteris sense criteri és una font clàssica de forats.

  1. El conjunt real de regles d'AlpinaShop

Aquest és el conjunt complet. Llegeix-lo sencer abans d'executar-lo: cada regla respon a una necessitat concreta.

# ---------------------------------------------------------------
# 1) Transit HTTP/HTTPS NOMES des dels rangs del balancejador de Google
#    130.211.0.0/22 i 35.191.0.0/16 son els rangs des dels quals
#    Google Cloud origina les peticions del balancejador i les
#    comprovacions d'estat. NO son "internet".
# ---------------------------------------------------------------
gcloud compute firewall-rules create fw-allow-lb-health-web \
  --network=alpinashop-vpc \
  --direction=INGRESS \
  --action=allow \
  --priority=1000 \
  --source-ranges=130.211.0.0/22,35.191.0.0/16 \
  --target-tags=web-catalogo \
  --rules=tcp:80,tcp:8080 \
  --description="HTTP i health checks des del balancejador global"

# ---------------------------------------------------------------
# 2) SSH NOMES des del rang de l'Identity-Aware Proxy (IAP).
#    35.235.240.0/20 es el rang des del qual IAP obre el tunel TCP.
#    Amb aixo NO cal cap IP publica a les VM.
# ---------------------------------------------------------------
gcloud compute firewall-rules create fw-allow-ssh-iap \
  --network=alpinashop-vpc \
  --direction=INGRESS \
  --action=allow \
  --priority=1000 \
  --source-ranges=35.235.240.0/20 \
  --rules=tcp:22 \
  --description="SSH unicament a traves d'IAP (veure 03-04)"

# ---------------------------------------------------------------
# 3) La capa web pot parlar amb la capa de dades per PostgreSQL.
#    Selector per compte de servei: nomes les maquines que corren
#    com a sa-catalogo-web poden obrir el 5432.
# ---------------------------------------------------------------
gcloud compute firewall-rules create fw-allow-web-to-datos \
  --network=alpinashop-vpc \
  --direction=INGRESS \
  --action=allow \
  --priority=1000 \
  --source-service-accounts=sa-catalogo-web@alpinashop-prod.iam.gserviceaccount.com \
  --target-tags=capa-datos \
  --rules=tcp:5432 \
  --description="Acces PostgreSQL des de l'aplicacio del cataleg"

# ---------------------------------------------------------------
# 4) Denegar explicitament la resta d'entrada, amb registre.
#    Prioritat 65000: per sota de totes les regles anteriors,
#    per damunt de la regla implicita 65535. Serveix per VEURE als
#    registres que s'esta intentant i no es permet.
# ---------------------------------------------------------------
gcloud compute firewall-rules create fw-deny-all-ingress \
  --network=alpinashop-vpc \
  --direction=INGRESS \
  --action=deny \
  --priority=65000 \
  --source-ranges=0.0.0.0/0 \
  --rules=all \
  --enable-logging \
  --description="Denegacio explicita amb registre de tot el no permes"

Diagrama del resultat:

flowchart TB
    Internet([Internet])
    LB[Balancejador HTTPS global<br/>130.211.0.0/22 · 35.191.0.0/16]
    IAP[Identity-Aware Proxy<br/>35.235.240.0/20]

    subgraph VPC["alpinashop-vpc · global"]
      subgraph SNW["sn-web-euw1 · 10.10.0.0/24 · europe-west1"]
        MIG["alpinashop-web-mig<br/>etiqueta: web-catalogo<br/>SA: sa-catalogo-web"]
        GKE["alpinashop-cluster<br/>pods 10.20.0.0/16"]
      end
      subgraph SND["sn-datos-euw1 · 10.10.1.0/24"]
        BATCH["Lots / backends interns<br/>etiqueta: capa-datos"]
      end
      NAT[Cloud NAT]
    end

    PSA["Accés privat a serveis<br/>10.30.0.0/20"]
    SQL[(alpinashop-pedidos<br/>IP privada)]

    Internet -->|443| LB
    LB -->|80/8080 etiqueta web-catalogo| MIG
    IAP -->|22| MIG
    MIG -->|5432 SA sa-catalogo-web| SQL
    MIG --> NAT --> Internet
    SQL --- PSA
    PSA --- VPC

Per què 0.0.0.0/0 al port 22 és un error

És el patró més estès i el més perillós. Obrir tcp:22 a 0.0.0.0/0 significa literalment que qualsevol màquina del planeta pot intentar autenticar-se al teu servidor. Les conseqüències no són teòriques:

  • Un servidor amb el 22 obert rep milers d'intents d'autenticació al dia des del primer minut. Els escàners automàtics escombren els rangs de tots els proveïdors de núvol contínuament.
  • N'hi ha prou amb una credencial feble, una clau reutilitzada o una fallada a sshd perquè es converteixi en una intrusió.
  • El soroll als registres amaga els atacs reals.
  • Tanca la porta a la traçabilitat: no saps qui va entrar, només quina clau es va fer servir.

L'alternativa correcta és IAP TCP forwarding, la regla número 2 del bloc anterior. Amb ella:

  • Les VM no necessiten IP pública.
  • L'accés passa per Google, que exigeix autenticació amb la identitat corporativa (Marta, Dani) i aplica IAM: qui no tingui el rol roles/iap.tunnelResourceAccessor no arriba ni a la salutació d'SSH.
  • Cada sessió queda registrada amb la identitat real de la persona.
# Connexio SSH sense IP publica, a traves d'IAP
gcloud compute ssh alpinashop-web-1 \
  --zone=europe-west1-b \
  --tunnel-through-iap

Els detalls d'IAP i els seus permisos els desenvolupem a 03-04 (IAM); aquí n'hi ha prou de saber que la regla de tallafoc del 22 apunta a 35.235.240.0/20 i mai a internet.

Comprovar regles abans que facin mal

# Veure totes les regles ordenades per prioritat
gcloud compute firewall-rules list \
  --filter="network:alpinashop-vpc" \
  --sort-by=priority \
  --format="table(name, direction, priority, sourceRanges.list(), targetTags.list(), allowed[].map().firewall_rule().list())"

# Simular: pot aquesta VM rebre transit al 22 des d'internet?
gcloud compute networks get-effective-firewalls alpinashop-web-1 \
  --zone=europe-west1-b 2>/dev/null || \
gcloud compute instances network-interfaces get-effective-firewalls alpinashop-web-1 \
  --zone=europe-west1-b

  1. Rutes i la passarel·la per defecte

Les rutes decideixen per on surt un paquet. Cada VPC neix amb dos tipus de ruta automàtiques:

Ruta Destí Salt següent Es pot esborrar
Ruta de subxarxa El CIDR de cada subxarxa La mateixa VPC No (es crea i s'esborra amb la subxarxa)
Ruta per defecte 0.0.0.0/0 Passarel·la d'internet Sí

Que la ruta per defecte es pugui esborrar és una eina de seguretat molt potent: si elimines la ruta 0.0.0.0/0 d'una VPC, cap màquina d'aquesta xarxa pot sortir a internet, ni tan sols amb IP pública. És el patró de les xarxes aïllades per al tractament de dades sensibles. AlpinaShop no hi arriba en producció, però és útil per al projecte d'anàlisi de la Lucía si algun dia tracta dades personals.

gcloud compute routes list --filter="network:alpinashop-vpc" \
  --format="table(name, destRange, nextHopGateway, priority)"

Les rutes personalitzades (per exemple, enviar cert trànsit a un appliance de xarxa) i les rutes apreses per BGP des d'una VPN pertanyen a 07-03.

  1. Cloud NAT: sortida a internet sense IP pública

Ja hem dit que les VM no han de tenir IP pública. Però necessiten sortir a internet per actualitzar paquets del sistema, instal·lar dependències de Python o cridar l'API de la passarel·la de pagament. La solució és Cloud NAT: un servei gestionat, sense instàncies que mantenir, que tradueix les adreces privades a una o diverses IP públiques de sortida.

Punts clau:

  • Cloud NAT és només de sortida. Ningú no pot iniciar una connexió des d'internet cap a una VM a través d'ell. És exactament el que volem.
  • No és una màquina: no hi ha coll d'ampolla que dimensionar ni pedaços que aplicar.
  • Es configura per regió i s'associa a un Cloud Router, que en aquest cas no fa BGP: és només el punt d'ancoratge del servei.
# 1) Cloud Router (obligatori per a NAT, encara que aqui no anunciï rutes)
gcloud compute routers create alpinashop-router-euw1 \
  --network=alpinashop-vpc \
  --region=europe-west1

# 2) La passarel·la NAT, amb la IP estatica reservada a l'apartat 6
gcloud compute routers nats create alpinashop-nat-euw1 \
  --router=alpinashop-router-euw1 \
  --region=europe-west1 \
  --nat-custom-subnet-ip-ranges=sn-web-euw1,sn-datos-euw1 \
  --nat-external-ip-pool=alpinashop-nat-ip \
  --enable-logging \
  --log-filter=ERRORS_ONLY \
  --min-ports-per-vm=128

Detall de les opcions:

  • --nat-custom-subnet-ip-ranges: només aquestes dues subxarxes surten per NAT. L'alternativa (--nat-all-subnet-ip-ranges) és còmoda però menys explícita.
  • --nat-external-ip-pool=alpinashop-nat-ip: fa servir la nostra IP estàtica. Aquesta és l'adreça que AlpinaShop comunica a la passarel·la de pagament per a la seva llista d'autoritzats. L'alternativa --auto-allocate-nat-external-ips deixa que Google triï, i les IP poden canviar.
  • --min-ports-per-vm=128: cada VM reserva 128 ports d'origen. És el paràmetre que causa la fallada més típica de Cloud NAT: si una màquina obre moltes connexions sortints simultànies (per exemple, un treball que descarrega milers de fitxers) i es queda sense ports, les connexions noves fallen amb un error confús. El símptoma es veu a les mètriques com a nat_allocation_failed.
  • --log-filter=ERRORS_ONLY: registra només les fallades. ALL genera un volum de registres considerable i cost associat.

Verificació des d'una VM sense IP pública:

gcloud compute ssh alpinashop-web-1 --zone=europe-west1-b --tunnel-through-iap

# Dins de la VM: la IP de sortida ha de ser la d'alpinashop-nat-ip
curl -s https://ifconfig.me

  1. Private Google Access: arribar a les APIs sense sortir a internet

Quan una VM sense IP pública crida storage.googleapis.com per llegir del bucket alpinashop-catalogo, per on va aquest trànsit? Hi ha dues respostes possibles, i la bona no és l'evident.

  • Sense Private Google Access: la petició surt per Cloud NAT, va a internet, resol una IP pública de Google i torna. Funciona, però surt de la xarxa de Google, consumeix capacitat de NAT i es factura com a trànsit de sortida.
  • Amb Private Google Access activat a la subxarxa: la petició s'encamina internament cap als frontals de les APIs de Google. No passa per internet, no consumeix ports de NAT i no es factura com a egress a internet.

Ja el vam activar en crear les subxarxes amb --enable-private-ip-google-access. Si necessites activar-lo després:

gcloud compute networks subnets update sn-web-euw1 \
  --region=europe-west1 \
  --enable-private-ip-google-access

gcloud compute networks subnets describe sn-datos-euw1 \
  --region=europe-west1 \
  --format="value(privateIpGoogleAccess)"

És una opció que ha d'estar activada sempre, a totes les subxarxes, a tots els entorns. No té cost, no té contraindicació i afecta gairebé tot el que farà AlpinaShop: llegir el bucket, escriure a BigQuery (mòdul 4), llegir un secret de Secret Manager (03-06) o descarregar una imatge d'Artifact Registry.

Existeix una variant, Private Service Connect, que permet arribar a APIs de Google o serveis de tercers per una IP privada teva, amb control de DNS. És una peça d'arquitectures més grans i s'estudia a 07-03.

  1. Accés privat a serveis: Cloud SQL per IP privada

A 02-03 vam crear alpinashop-pedidos amb IP pública i ens hi vam connectar amb l'Auth Proxy. Funcionava, però la instància era abastable des d'internet (encara que protegida per xarxes autoritzades i credencials). Ara la movem a IP privada, que és la configuració correcta.

El mecanisme s'anomena accés privat a serveis i consisteix en això: cedeixes un rang de la teva VPC a Google, Google hi crea els recursos gestionats (la instància de Cloud SQL) i estableix un emparellament entre la teva xarxa i la seva. Des de la teva VPC, la base de dades apareix amb una IP normal d'aquest rang.

flowchart LR
    subgraph VPC["alpinashop-vpc"]
      VM["alpinashop-web-1<br/>10.10.0.5"]
      RES["Rang reservat<br/>10.30.0.0/20"]
    end
    subgraph GOOG["Xarxa de serveis gestionats de Google"]
      SQL[(alpinashop-pedidos<br/>10.30.0.3)]
    end
    VM -->|5432 per IP privada| RES
    RES -.emparellament de xarxes.-> GOOG
    GOOG --> SQL

Implementació, pas a pas:

# 1) Habilitar l'API de networking de serveis
gcloud services enable servicenetworking.googleapis.com --project=alpinashop-prod

# 2) Reservar el rang que cedim a Google (el del pla: 10.30.0.0/20)
gcloud compute addresses create alpinashop-psa-range \
  --global \
  --purpose=VPC_PEERING \
  --addresses=10.30.0.0 \
  --prefix-length=20 \
  --network=alpinashop-vpc \
  --description="Rang per a serveis gestionats (Cloud SQL)"

# 3) Establir la connexio privada
gcloud services vpc-peerings connect \
  --service=servicenetworking.googleapis.com \
  --ranges=alpinashop-psa-range \
  --network=alpinashop-vpc \
  --project=alpinashop-prod

# 4) Comprovar
gcloud services vpc-peerings list \
  --network=alpinashop-vpc \
  --project=alpinashop-prod

Amb la connexió establerta, s'assigna la IP privada a la instància i es retira la pública:

# Assignar IP privada dins d'alpinashop-vpc
gcloud sql instances patch alpinashop-pedidos \
  --project=alpinashop-prod \
  --network=projects/alpinashop-prod/global/networks/alpinashop-vpc \
  --no-assign-ip

# Veure la IP privada resultant
gcloud sql instances describe alpinashop-pedidos \
  --format="value(ipAddresses[].ipAddress, ipAddresses[].type)"

Detalls que eviten ensurts:

  • --no-assign-ip retira la IP pública. Fes-ho només quan hagis verificat que la connexió privada funciona des d'una VM; si no, et quedes sense accés fins a revertir-ho.
  • El rang cedit no es pot reduir després sense recrear la connexió. Un /20 dona marge per a instàncies futures (la rèplica alpinashop-pedidos-replica-informes també consumeix adreces d'aquí).
  • La cadena de connexió de l'aplicació Flask canvia de la IP pública a la privada; l'Auth Proxy continua sent vàlid i continua sent l'opció recomanada perquè afegeix xifratge i autenticació IAM, però ja no és l'única manera d'arribar-hi.
  • El canvi de xarxa d'una instància de Cloud SQL implica reinici. Planifica-ho fora d'horari comercial.

  1. VPC Flow Logs: diagnòstic i auditoria

Els registres de flux graven una mostra de les connexions que travessen les interfícies de les VM: origen, destí, ports, bytes, paquets, i si van ser permeses o denegades. Serveixen per a tres coses:

  1. Diagnosticar per què alguna cosa no connecta (va arribar el paquet? el va denegar una regla?).
  2. Auditar: veure a quins destins externs parla realment la teva infraestructura.
  3. Analitzar el cost de trànsit entre zones i regions.

Ja els vam activar en crear les subxarxes. Una consulta típica a Cloud Logging (el servei s'estudia a fons a 06-06; aquí el fem servir com a eina):

# Connexions denegades cap a la capa web a l'ultima hora
gcloud logging read '
  resource.type="gce_subnetwork"
  AND log_id("compute.googleapis.com/firewall")
  AND jsonPayload.disposition="DENIED"
' --project=alpinashop-prod --limit=20 --freshness=1h \
  --format="table(
    timestamp,
    jsonPayload.connection.src_ip,
    jsonPayload.connection.dest_ip,
    jsonPayload.connection.dest_port,
    jsonPayload.rule_details.reference
  )"
# Fluxos amb mes bytes sortints: qui esta generant transit?
gcloud logging read '
  resource.type="gce_subnetwork"
  AND log_id("compute.googleapis.com/vpc_flows")
' --project=alpinashop-prod --limit=10 --freshness=30m \
  --format="table(
    jsonPayload.connection.src_ip,
    jsonPayload.connection.dest_ip,
    jsonPayload.bytes_sent
  )"

Consideracions de cost i privadesa:

  • Els flow logs es facturen per volum de registres ingerits. En una xarxa amb trànsit intens, el mostreig al 100 % pot ser car. 0.5 és un punt de partida raonable; 0.1 per a trànsit molt alt.
  • Contenen adreces IP de clients, que a la Unió Europea són dada personal. Fixa una política de retenció d'acord amb l'RGPD i documenta el tractament. Aquesta és una d'aquelles decisions que ha de validar el responsable de compliment abans de producció.

A més dels flow logs, per a diagnòstic puntual hi ha el Network Intelligence Center i la seva eina de proves de connectivitat, que simula un paquet i et diu exactament quina regla el va permetre o denegar, sense generar trànsit real:

gcloud network-management connectivity-tests create prueba-web-a-sql \
  --source-instance=projects/alpinashop-prod/zones/europe-west1-b/instances/alpinashop-web-1 \
  --destination-cloud-sql-instance=projects/alpinashop-prod/instances/alpinashop-pedidos \
  --destination-port=5432 \
  --protocol=TCP

gcloud network-management connectivity-tests describe prueba-web-a-sql \
  --format="value(reachabilityDetails.result)"

  1. Què queda fora d'aquesta lliçó

Perquè no et quedi la sensació de buit, això és el que existeix i no hem tractat aquí:

Tema On es veu
VPC compartida entre projectes 07-03
Emparellament (peering) entre VPC pròpies 07-03
Cloud VPN, Interconnect, connectivitat híbrida 07-03
Private Service Connect a fons 07-03
Balanceig de càrrega 03-02 (la següent)
Cloud Armor i protecció DDoS 03-05
Permisos d'IAP i de xarxa 03-04
Cloud Logging a fons 06-06
Organization policies de xarxa (p. ex. prohibir IP públiques) 07-07

Errors habituals i consells

  • Fer servir la xarxa default en producció. Porta subxarxes a totes les regions i regles que obren SSH i RDP a internet. Crea una xarxa personalitzada des del principi i esborra la default quan ja no quedin recursos a dins.
  • Obrir tcp:22 a 0.0.0.0/0. L'error clàssic. Fes servir IAP amb la regla des de 35.235.240.0/20 i treu les IP públiques de les VM.
  • Oblidar els rangs del balancejador. Si no permets 130.211.0.0/22 i 35.191.0.0/16, les comprovacions d'estat fallen, el backend es marca com a no saludable i el balancejador retorna 502 sense explicació clara. És, amb diferència, la fallada número u de la lliçó següent.
  • Triar rangs "còmodes" com 10.0.0.0/16 o 192.168.1.0/24. Xocaran el dia de la VPN. Planifica i documenta l'adreçament abans de crear res.
  • Creure que les subxarxes són zonals. Són regionals. No necessites una subxarxa per zona; una subxarxa regional serveix un MIG regional en tres zones.
  • Confondre prioritat alta amb número alt. Al tallafoc de VPC guanya el número menor. Una regla allow amb prioritat 100 venç una deny amb prioritat 1000.
  • Deixar IP externes estàtiques reservades sense fer servir. Es facturen, i a tarifa superior. Audita gcloud compute addresses list --filter="status=RESERVED" cada mes.
  • No activar Private Google Access. Sense ell, tot el trànsit a les APIs de Google surt per NAT a internet: més cost, més latència i esgotament de ports de NAT.
  • Retirar la IP pública de Cloud SQL abans de comprovar la privada. Verifica primer la connectivitat privada des d'una VM i després aplica --no-assign-ip.
  • Dimensionar malament min-ports-per-vm a Cloud NAT. Un treball per lots amb moltes connexions sortints esgota els ports i provoca fallades intermitents difícils d'atribuir. Vigila la mètrica de fallades d'assignació.
  • Confiar només en el tallafoc. El tallafoc de VPC controla el nivell de xarxa. L'autenticació, l'autorització i la validació d'entrada continuen sent responsabilitat de l'aplicació.

Exercicis

Exercici 1 — Pla d'adreçament per a alpinashop-dev

La Marta necessita replicar la xarxa al projecte alpinashop-dev. El requisit és que els rangs no encavalquin amb producció (10.10.0.0/16, secundaris 10.20.0.0/16 i 10.21.0.0/20, accés privat a serveis 10.30.0.0/20) ni amb l'oficina (192.168.10.0/24), perquè en el futur es connectaran tots dos entorns.

Dissenya el pla (xarxa, dues subxarxes a europe-west1, rangs secundaris de GKE i rang per a serveis gestionats) i escriu les comandes gcloud que el creen, amb Private Google Access activat.

Exercici 2 — Regles de tallafoc per al servei intern d'informes

La Lucía necessita una VM d'informes anomenada alpinashop-informes-1 a sn-datos-euw1, amb l'etiqueta informes, que compleixi:

  1. Només la Lucía i la Marta poden entrar per SSH, i únicament a través d'IAP.
  2. La VM ha de poder consultar la rèplica alpinashop-pedidos-replica-informes pel port 5432.
  3. La VM no ha de rebre trànsit des d'internet ni des de la capa web.
  4. La VM ha de poder descarregar paquets de PyPI (sortida a internet) sense tenir IP pública.

Escriu les regles de tallafoc necessàries i explica quin component resol el punt 4.

Exercici 3 — Diagnòstic d'un 502

Després de crear el balancejador (avançament de la lliçó següent), el catàleg retorna 502 i a la consola els backends del MIG apareixen com a UNHEALTHY. L'aplicació respon correctament si fas curl http://10.10.0.5:8080/salud des d'una altra VM de la mateixa subxarxa.

Enumera les tres causes més probables per ordre de probabilitat i la comanda que faries servir per confirmar o descartar cadascuna.


Solucions

Solució 1

Pla proposat (bloc 10.60.0.0/16 reservat al document d'adreçament per a desenvolupament):

Ús Rang
sn-web-euw1-dev (primari) 10.60.0.0/24
sn-datos-euw1-dev (primari) 10.60.1.0/24
Secundari gke-pods-dev 10.70.0.0/16
Secundari gke-servicios-dev 10.71.0.0/20
Accés privat a serveis 10.80.0.0/20

Cap no encavalca amb 10.10/16, 10.20/16, 10.21/20, 10.30/20 ni amb 192.168.10.0/24.

gcloud config set project alpinashop-dev

gcloud compute networks create alpinashop-vpc-dev \
  --subnet-mode=custom \
  --bgp-routing-mode=global

gcloud compute networks subnets create sn-web-euw1-dev \
  --network=alpinashop-vpc-dev \
  --region=europe-west1 \
  --range=10.60.0.0/24 \
  --secondary-range=gke-pods-dev=10.70.0.0/16,gke-servicios-dev=10.71.0.0/20 \
  --enable-private-ip-google-access

gcloud compute networks subnets create sn-datos-euw1-dev \
  --network=alpinashop-vpc-dev \
  --region=europe-west1 \
  --range=10.60.1.0/24 \
  --enable-private-ip-google-access

gcloud compute addresses create alpinashop-psa-range-dev \
  --global --purpose=VPC_PEERING \
  --addresses=10.80.0.0 --prefix-length=20 \
  --network=alpinashop-vpc-dev

Nota: els rangs secundaris es poden donar en la creació amb --secondary-range o afegir-se després amb --add-secondary-ranges.

Solució 2

# (1) SSH nomes per IAP, aplicat a la VM d'informes
gcloud compute firewall-rules create fw-allow-ssh-iap-informes \
  --network=alpinashop-vpc \
  --direction=INGRESS --action=allow --priority=1000 \
  --source-ranges=35.235.240.0/20 \
  --target-tags=informes \
  --rules=tcp:22

# (2) La replica de Cloud SQL viu al rang d'acces privat a
#     serveis; el transit sortint esta permes per la regla
#     implicita d'EGRESS, aixi que no cal regla d'entrada.
#     Si es volgues restringir la sortida de forma explicita:
gcloud compute firewall-rules create fw-egress-informes-sql \
  --network=alpinashop-vpc \
  --direction=EGRESS --action=allow --priority=900 \
  --destination-ranges=10.30.0.0/20 \
  --target-tags=informes \
  --rules=tcp:5432

# (3) No es crea cap regla d'entrada des d'internet ni des de la
#     capa web. La regla implicita "denegar tota l'entrada" i
#     l'explicita fw-deny-all-ingress (prioritat 65000) ja ho cobreixen.
#     Verificacio que cap regla existent no aplica a l'etiqueta:
gcloud compute firewall-rules list \
  --filter="network:alpinashop-vpc AND targetTags:informes" \
  --format="table(name, direction, priority, sourceRanges.list())"

Punt 4: el resol Cloud NAT. La passarel·la alpinashop-nat-euw1 ja cobreix sn-datos-euw1, de manera que la VM, sense IP pública, surt a internet per instal·lar des de PyPI. A més, per descarregar del bucket alpinashop-catalogo o escriure a BigQuery no farà servir NAT, sinó Private Google Access, que està actiu a la subxarxa.

Quant a "només la Lucía i la Marta": el tallafoc no distingeix persones. Aquesta part es resol amb IAM donant roles/iap.tunnelResourceAccessor i roles/compute.osLogin únicament als grups corresponents; es veu a 03-04.

Solució 3

Per ordre de probabilitat:

  1. Falta la regla de tallafoc per als rangs de comprovació d'estat. És la causa més freqüent amb diferència. La comprovació s'origina a 130.211.0.0/22 i 35.191.0.0/16, no a internet ni a la subxarxa.
gcloud compute firewall-rules list \
  --filter="network:alpinashop-vpc AND sourceRanges:(130.211.0.0/22 OR 35.191.0.0/16)" \
  --format="table(name, allowed[].map().firewall_rule().list(), targetTags.list())"
  1. L'etiqueta de xarxa no coincideix. La regla apunta a web-catalogo però la plantilla d'instància del MIG no aplica aquesta etiqueta a les màquines noves.
gcloud compute instances list --filter="name~alpinashop-web-mig" \
  --format="table(name, zone, tags.items.list(), status)"
  1. La comprovació apunta a un port o ruta equivocats. L'aplicació escolta al 8080 i exposa /salud, però la comprovació està configurada al 80 o a /.
gcloud compute health-checks describe hc-catalogo \
  --format="yaml(type, httpHealthCheck.port, httpHealthCheck.requestPath)"

Eina transversal: els registres de tallafoc de fw-deny-all-ingress mostraran els intents denegats des de 35.191.0.0/16 si la causa és la primera, i la prova de connectivitat del Network Intelligence Center confirma la regla exacta que bloqueja.

Conclusió

AlpinaShop ja té una xarxa de veritat. Has entès la propietat que defineix la xarxa de Google —la VPC és global, les subxarxes són regionals— i per què això simplifica arquitectures que en altres proveïdors exigeixen malabars. Has descartat la xarxa default amb arguments i has creat alpinashop-vpc en mode personalitzat, amb encaminament global i un pla d'adreçament documentat que reserva 10.10.0.0/16 per a producció, deixa forat per créixer i no xoca amb l'oficina ni amb alpinashop-dev.

Sobre aquesta xarxa has creat sn-web-euw1 (10.10.0.0/24) i sn-datos-euw1 (10.10.1.0/24), amb rangs secundaris gke-pods (10.20.0.0/16) i gke-servicios (10.21.0.0/20) perquè alpinashop-cluster faci servir xarxa nativa de VPC i els seus pods tinguin adreces reals. Has reservat la IP global alpinashop-lb-ip per al balancejador que construïm ara mateix i la IP alpinashop-nat-ip perquè la passarel·la de pagament pugui autoritzar una adreça de sortida estable.

Has après el model de tallafoc complet —stateful, distribuït, prioritat on guanya el número menor, quatre regles implícites, selecció per etiqueta o per compte de servei— i has escrit el conjunt real d'AlpinaShop: HTTP i comprovacions d'estat només des de 130.211.0.0/22 i 35.191.0.0/16, SSH només des del rang d'IAP 35.235.240.0/20, PostgreSQL només des del compte de servei sa-catalogo-web, i una denegació explícita amb registre que t'ensenya què està trucant a la porta. I saps per què 0.0.0.0/0 al 22 no és una comoditat sinó un incident pendent.

Finalment, les màquines ja no necessiten IP pública: Cloud NAT els dona sortida controlada amb una IP estàtica coneguda, Private Google Access les porta a les APIs de Google sense trepitjar internet, l'accés privat a serveis ha posat alpinashop-pedidos en una IP privada del rang 10.30.0.0/20, i els VPC Flow Logs converteixen els problemes de xarxa en consultes de registre en lloc de conjectures.

La xarxa està llesta, però el catàleg encara se serveix per la IP d'una màquina. A la lliçó següent, 03-02, Balanceig de càrrega al núvol, posem al davant un balancejador HTTP(S) extern global: una única adreça anycast que atén des del punt de presència més proper a cada client europeu, reparteix el trànsit entre les instàncies del MIG alpinashop-web-mig, serveix les imatges directament des del bucket alpinashop-catalogo mitjançant un mapa d'URL, i comprova la salut dels backends per aquesta ruta /salud que ja hem autoritzat al tallafoc. Totes les peces de xarxa que acabem de col·locar existeixen precisament perquè aquest balancejador funcioni a la primera.

Curs de Google Cloud Platform (GCP)

Mòdul 1: Introducció a Google Cloud Platform

Mòdul 2: Serveis principals de GCP

Mòdul 3: Xarxes i seguretat

Mòdul 4: Dades i anàlisi

Mòdul 5: Aprenentatge automàtic i IA

Mòdul 6: DevOps i monitoratge

Mòdul 7: Temes avançats de GCP

Mòdul 8: Projecte final

© Copyright 2026. Tots els drets reservats