Bene! Se è arrivato fin qui, probabilmente ha già letto la Parte 1 (Il Perché) e vuole approfondire come configurare al meglio gli ambienti di sviluppo cloud-native. Ottimo!
Prendiamo come riferimento un team di progetto reale e vediamo come migliorarne il flusso di sviluppo.
Questa guida è stata pensata per GCP (Google Cloud Platform), ma gli stessi concetti si possono applicare anche ad AWS.
Foto di Jason Richard su Unsplash
📖 Caso di studio
Un'azienda chiamata MajesticFantastic ha alcuni prodotti legati ai pagamenti 💸
Il team del progetto billing si occupa dello sviluppo di un'applicazione di fatturazione.
È composta da:
- Alcuni microservizi distribuiti come container in GKE 🛳
- Servizi cloud GCP utilizzati: Pub/Sub, Cloud SQL (PostgreSQL), Cloud Monitoring, Container Registry.
- Ambienti attuali: Dev, Prod.
- Un team di 2 sviluppatori: David e Martha. A breve si uniranno al team uno sviluppatore di nome Ezekiel e altri colleghi, dato che l'azienda è in una fase di forte crescita. Tempi entusiasmanti! 🚀
Proof Of Concept
Introdurremo un nuovo tipo di ambiente, che chiameremo "ambiente Personale".
Per l'ambiente personale, il nostro POC sarà composto da:
- Un progetto GCP che farà da progetto Host. Ospiterà il cluster GKE, l'istanza Cloud SQL e le immagini container in GCR.
- Più progetti GCP personali — uno per ogni sviluppatore. Ciascun progetto conterrà le risorse non condivise, dedicate al singolo sviluppatore. Nel nostro caso, per esempio, ospiterà i topic e le subscription Pub/Sub.
- Una Shared VPC. Avrà come host il progetto Host e ogni progetto Personale farà da progetto di servizio della Shared VPC.
Cluster GKE multi-tenant
Assegneremo un namespace K8s a ciascun ambiente (per esempio, l'ambiente di David avrà il namespace david-env, quello di Martha martha-env e così via).
Ogni ambiente dovrà accedere esclusivamente al proprio namespace, senza dipendere dalle risorse presenti nei namespace degli altri ambienti.
Nota: per ora non applicheremo alcuna misura di sicurezza. Le misure di sicurezza potranno essere introdotte in seguito; ne parleremo nel dettaglio alla fine dell'articolo.
Cloud SQL multi-tenant
Cloud SQL supporta Users e Databases, quindi possiamo allocare uno User e un Database per ogni ambiente (Nota: usiamo una sola istanza Cloud SQL e ne paghiamo una sola!)
Creeremo una singola istanza Cloud SQL privata e la "collegheremo" alla nostra Shared VPC tramite private service access.
Ed eccoci alla parte pratica! 👩🔧
Il repository developer-envs contiene tutto il codice IaC e GitOps necessario.
Infrastructure-as-Code (IaC)
Niente operazioni manuali. Useremo Terraform come Infrastructure-as-Code per fare il bootstrap. Mostrami il codice!
Useremo il Terraform Kubernetes Provider per configurare un namespace K8s per ogni ambiente, oltre a creare ConfigMap generali contenenti i parametri legati all'infrastruttura (per esempio il nome del topic Pub/Sub, l'ID del progetto GCP e così via).
In tutta la soluzione ho usato i moduli Terraform di Google nell'ambito del Cloud Foundation Toolkit: li ho trovati piuttosto comodi da usare. Includono anche alcune best practice di Google, quindi vale davvero la pena dargli un'occhiata.
L'utilizzo di uno strumento infra-as-code (come Terraform) è fondamentale in quest'ottica, perché l'obiettivo è ridurre e automatizzare il lavoro ripetitivo soggetto a errore umano e mantenere allineate tutte le configurazioni man mano che si scala. Un po' di lavoro in più adesso, molto meno lavoro in seguito.
GitOps
Useremo poi ArgoCD per gestire e distribuire i diversi ambienti in K8s. ArgoCD è un noto strumento GitOps di continuous delivery che, a mio parere, si sposa bene con il nostro caso d'uso multi-tenant. Mostrami il codice!
Definiremo la maggior parte delle risorse K8s come file YAML e useremo Kustomize per personalizzare la configurazione.
Kustomize è uno strumento di configurazione che permette di definire una configurazione "base" e diversi "overlay" sopra di essa, tutti basati sulla configurazione di partenza (una sorta di ereditarietà semplificata). È ideale quando si hanno più ambienti che devono condividere un antenato di configurazione comune.
Per nostra fortuna, la nostra soluzione di CD, ArgoCD, supporta Kustomize tramite integrazione nativa.
Trovo Kustomize semplice e immediato, ma naturalmente si può scegliere uno strumento diverso (come Helm).
Microservizi di esempio
Distribuiremo due microservizi piuttosto semplici e basilari, scritti in Go.
Il microservizio env-producer pubblicherà periodicamente eventi di pagamento su un topic Pub/Sub ogni 10 secondi.
Il microservizio env-consumer consumerà i messaggi degli "eventi di pagamento" da Pub/Sub e li salverà in modo persistente in una tabella PostgreSQL.
L'aspetto chiave di questi servizi è che la configurazione multi-ambiente è del tutto trasparente per loro, perché esponiamo i dettagli dell'ambiente come variabili d'ambiente. Separare la configurazione dal codice è una pratica fondamentale del manifesto Twelve-Factor, che vale la pena conoscere.
In sostanza, questi microservizi verranno eseguiti separatamente in ogni ambiente, integrandosi unicamente con le risorse specifiche dell'ambiente stesso.

Avvio e funzionamento 🏃🏻♂️
Per metterlo in funzione, cloni il repository di esempio e segua le istruzioni del README.md.

A quel punto, la console di ArgoCD dovrebbe presentarsi così
È un punto unico da cui tenere traccia di tutti i suoi ambienti in un'unica dashboard. Naturalmente potrà aggiungere qui anche gli altri ambienti (come dev e prod), magari in un "project" ArgoCD diverso.
Noterà un'applicazione chiamata argocd-config che si occupa del self-syncing dei file di configurazione e installazione di ArgoCD, oltre a 2 ulteriori applicazioni — una per ciascuno sviluppatore.
Come distribuire le modifiche al proprio ambiente
Ha apportato una modifica a uno dei servizi e desidera distribuirla nel suo ambiente. Quali sono le opzioni?
Opzione 1: creare un'immagine personalizzata
Può modificare il codice sorgente e poi creare una nuova immagine container. A quel punto, basta cambiare il tag dell'immagine nella propria applicazione su ArgoCD per distribuire rapidamente la nuova versione.

Le informazioni dell'applicazione in ArgoCD, dove uno sviluppatore può cambiare il tag dell'immagine e cliccare su Save
L'operazione si può fare manualmente o automaticamente tramite una pipeline CI o script personalizzati. (ArgoCD dispone anche di una CLI per automatizzare il processo.)
Opzione 2: eseguirlo in locale
Aspetti… cosa? Non è in contraddizione con quello che stiamo cercando di fare?
Le presento Telepresence. Telepresence è uno degli strumenti più interessanti che mi sia capitato di provare di recente. L'ho usato molte volte e mi ha aiutato a essere molto più produttivo come sviluppatore.
Spiegare in una sola frase cosa fa è un po' difficile, ma ci provo. Ecco la descrizione presa dal loro sito:
Telepresence sostituisce il normale pod in esecuzione nel cluster Kubernetes con un proxy di rete bidirezionale. Questo pod fa da proxy per i dati provenienti dal suo ambiente Kubernetes (per esempio connessioni TCP, variabili d'ambiente, volumi) verso il processo locale. Il networking del processo locale viene reindirizzato in modo trasparente, così che le chiamate DNS e le connessioni TCP passino attraverso il proxy verso il cluster Kubernetes remoto.
Detto in parole più semplici: le permette di eseguire il suo servizio in locale, sulla sua macchina, mentre le connessioni in entrata e in uscita, le variabili d'ambiente e i volumi vengono instradati tramite proxy verso il cluster K8s. Niente male! 👍
Quindi, supponiamo di aver apportato una modifica al microservizio env-consumer e di volerla testare. Basta eseguire:
E in pochi secondi è distribuito e in esecuzione con la nuova modifica.
In sostanza, sostituisce il pod del suo servizio con un pod proxy e poi esegue il servizio in locale, facendolo dialogare con il pod proxy.
L'aspetto interessante è che sta eseguendo un'applicazione locale, ma in realtà è connessa sia a Pub/Sub sia a Cloud SQL (PostgreSQL) in remoto!
E tutto questo senza modificare il codice dell'applicazione né configurare certificati e chiavi segrete. Lo stesso codice nell'ambiente personale e in produzione!
Quando ho finito, premo Ctrl+C e l'immagine torna a quella di prima. Tutto sotto controllo! 🤩

Una demo dell'esecuzione del nostro servizio di esempio con Telepresence
Ora si immagini mentre corregge un bug, lancia Telepresence, attende qualche secondo e si accorge di aver fatto crashare il servizio. Eh sì… lo corregge di nuovo. Il feedback loop qui è davvero rapido! 😁
Si noti che non ho creato alcuna immagine Docker. Sto compilando il codice sorgente modificato ed eseguendo l'eseguibile in locale. Può anche far costruire e sostituire l'immagine Docker.
Ambienti personali e onboarding
Ezekiel si è appena unito al team come sviluppatore! Benvenuto! Ha ricevuto il suo laptop e un po' di gadget. Evviva! 🥳
Nell'ambito del suo onboarding, le viene chiesto di preparare un ambiente personale per Ezekiel, in modo che possa fare esperimenti con l'applicazione e l'infrastruttura, e magari apportare qualche piccola modifica per vederne l'impatto.
Ecco come procedere:
- Modifichi il file
tf/personal.tfvarse aggiunga Ezekiel all'elenco dei tenant:
2. Applichi la modifica eseguendo terraform apply -f personal.tfvars
3. Aggiunga un'applicazione ArgoCD per l'ambiente di Ezekiel, inserendo il seguente snippet in argo/apps/applications.yaml, quindi esegua commit e push della modifica.
Tutto qui! Dato che ArgoCD è sincronizzato per monitorare la cartella apps, rileverà automaticamente l'aggiunta di ezekiel-env e preparerà l'ambiente. Sono sicuro che Ezekiel ne sarà felice.
Ambienti personali e offboarding
Oh no! David sta lasciando il team per nuove opportunità!
Peccato, ci mancherà. ⭐️ 😩
Però è anche l'occasione per vedere quanto sia facile ripulire il suo ambiente personale. 😌
Basta aprire argo/apps/applications.yaml, eliminare la definizione dell'applicazione david-env e fare commit e push. Dato che ArgoCD è sincronizzato per monitorare la cartella apps, rileverà automaticamente che david-env è stato eliminato e cancellerà l'ambiente.
Successivamente conviene rimuovere anche l'infrastruttura dell'ambiente eliminando david dall'elenco dei tenant in tf/personal.tfvars e lanciando terraform apply -f personal.tfvars
Tutto qui! Nessuna traccia di David 💀
👣 Prossimi passi
Se desidera adattare questa impostazione alla sua organizzazione, è libero di farlo. Tuttavia dovrà tenere in considerazione alcuni aspetti aggiuntivi, tra cui:
È solo un POC
Come accennato, si tratta di un POC pensato a scopo esemplificativo e introduttivo. Alcune parti dell'implementazione sono state semplificate per brevità. Non lo consideri come una best practice e si senta libero di adattarlo alle sue esigenze e preferenze.
Sicurezza
Come accennato nel capitolo precedente, la sicurezza può rappresentare un punto critico in questa soluzione. Esistono diversi modi per migliorare sicurezza e isolamento partendo da qui (per esempio RBAC, Network Policies, Resource Quotas, Pod anti-affinity. Consulti questa guida per maggiori informazioni).
Multi-tenancy
Gli esempi di multi-tenancy qui presentati riguardano servizi cloud come GKE, Pub/Sub e Cloud SQL, ma può estendere gli stessi concetti anche ad altri servizi cloud.
Progetto GCP per singolo sviluppatore
L'attuale ambito del progetto GCP per singolo sviluppatore è piuttosto ridotto. È una base di partenza per ampliare e migliorare il progetto. Per esempio, può configurare il routing di log e metriche specifici di un namespace verso il progetto GCP di un determinato sviluppatore. Un altro esempio: il progetto GCP dello sviluppatore può essere utilizzato per avviare risorse personalizzate non incluse nella linea principale del progetto, così da verificare che tutto funzioni come previsto. Il progetto GCP per singolo sviluppatore non è un requisito, ma una possibilità: può tranquillamente farne a meno se preferisce.
Shared VPC
Stiamo usando una Shared VPC, che consente ai vari progetti GCP personali di condividere la stessa rete VPC. Ciò comporta alcuni prerequisiti IAM di cui tenere conto. Per esempio, l'utente IAM dello sviluppatore deve avere il ruolo compute.networkUser nel progetto Host per poter creare risorse nella Shared VPC.
Soluzioni alternative
Le seguenti alternative puntano a fornire una soluzione. Alcune sono a pagamento. A quanto mi risulta, queste alternative non offrono una soluzione "full-stack" quando si tratta di adattare l'infrastruttura alla configurazione di deployment, come avviene nel nostro POC. Sono invece focalizzate principalmente sulla parte Kubernetes. Ognuna ha pro e contro a seconda del contesto, quindi le valuti con attenzione.
Tutto qui! Spero le sia piaciuto 🙂
In DoiT International , noi Architects & Engineers cerchiamo sempre di colmare il divario tra Infrastructure e Software Development, perché crediamo che entrambi i fronti condividano un obiettivo comune: produttività e affidabilità.
Grazie per la lettura! Per restare in contatto, ci segua sul DoiT Engineering Blog , sul canale DoiT LinkedIn e sul canale DoiT Twitter . Per le opportunità di carriera, visiti https://careers.doit-intl.com .