Principi cloud-native e 12-factor
Progettare cloud-native significa costruire microservizi indipendenti, rilasciabili singolarmente e comunicanti via API, seguendo i principi 12-factor. I punti che l’esame premia: la configurazione vive nell’ambiente (mai hardcoded nel codice), i backing service (database, cache, code) sono risorse collegate e sostituibili, i log sono un flusso di eventi su stdout/stderr raccolto dalla piattaforma (in Cloud Logging), e i processi sono stateless e disposable — devono poter partire e morire in fretta senza perdere dati.
Stateless non vuol dire “senza stato”, ma stato esternalizzato: la sessione utente, i file, i contatori non vivono nella memoria dell’istanza (che scala e viene distrutta), bensì in backing service dedicati. Sessione e cache condivisa vanno in Memorystore (Redis/Memcached gestito); i dati persistenti in Firestore, Cloud SQL o Spanner; i file utente in Cloud Storage (spesso serviti al client con un signed URL a scadenza, senza esporre le credenziali). Questo abilita autoscaling orizzontale e failover senza sticky session.
Scelta del compute
Il cuore dell’esame è scegliere il servizio giusto per lo scenario, bilanciando controllo, latenza, costo e operatività:
- Cloud Run: container stateless serverless che scala fino a zero. Ideale per API HTTP, web app ed elaborazioni request-driven. Leve chiave:
concurrency(più richieste per istanza),min-instancesper mitigare il cold start, e il traffic splitting tra revision per canary e blue/green. - GKE: orchestrazione Kubernetes quando servono controllo fine su networking, sidecar/service mesh, workload con requisiti particolari (GPU, DaemonSet, protocolli non-HTTP) o portabilità multi-cloud. Massima flessibilità, maggiore onere operativo.
- Cloud Functions: event-driven, unità di codice attivata da un trigger (HTTP, evento Cloud Storage, messaggio Pub/Sub). Perfetta per glue code, reazioni a eventi e integrazioni leggere; meno adatta a servizi long-running o con molte dipendenze.
- App Engine: PaaS per web app quando si vuole delegare l’infrastruttura restando su un modello applicativo gestito.
Regola pratica: container stateless request-driven → Cloud Run; serve Kubernetes o controllo profondo → GKE; reagire a un singolo evento → Cloud Functions. Il vero vantaggio del container è la portabilità: la stessa immagine (build con Cloud Build, conservata in Artifact Registry) gira in locale, su Cloud Run e su GKE.
Caching, sessione e resilienza
Il caching riduce latenza e carico sui backing service: Memorystore ospita cache applicativa, sessioni condivise, rate limiting e leaderboard. Su cache locali per istanza non si può fare affidamento, perché l’autoscaling le rende incoerenti. Definisci sempre una strategia di invalidazione e una TTL.
Per la reliability, progetta per il fallimento. Applica retry con exponential backoff e jitter solo su errori transitori e idempotenti, per non amplificare il sovraccarico; abbina timeout, circuit breaker e graceful degradation (servi dati cache o una risposta ridotta quando una dipendenza è giù, invece di crollare). Per il lavoro asincrono con controllo del rate usa Cloud Tasks; per il fan-out di eventi a più consumer usa Pub/Sub. Gestisci i segreti in Secret Manager (mai in chiaro nel codice o nelle env) e autentica i servizi con Workload Identity/impersonation invece delle service account key. Diagnostica la latenza con Cloud Trace e i consumi CPU/memoria con Cloud Profiler.
Trappole tipiche d’esame
- App che perde le sessioni dopo lo scale → soluzione: esternalizza lo stato in Memorystore; niente sessione in memoria locale, altrimenti sticky session e incoerenze.
- Reagire a un file caricato su Cloud Storage → soluzione: Cloud Functions event-driven sul trigger dell’oggetto, non un servizio Cloud Run in polling.
- Cold start penalizza la latenza percepita → soluzione: su Cloud Run imposta
min-instancese alza laconcurrency; non migrare a GKE solo per questo. - Job asincroni con rate limiting verso un’API fragile → soluzione: Cloud Tasks (esecuzione con controllo del rate), non Pub/Sub, che serve il fan-out di eventi.
- Dipendenza esterna intermittente → soluzione: retry con exponential backoff e jitter + graceful degradation; il retry aggressivo senza backoff peggiora l’incidente.
- Credenziali per accedere ai servizi Google → soluzione: Workload Identity/impersonation e Secret Manager; mai service account key o secret in chiaro nelle env.