Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Review Apps CI/CD di Heroku ricreate su Google Cloud Platform

By Mike SparrAug 26, 20207 min read

Questa pagina è disponibile anche in English, Deutsch, Español, Français, 日本語 e Português.

Tra le funzionalità più apprezzate di Heroku c'è la soluzione Review Apps: durante una pull request (PR) genera un ambiente effimero con un'istanza dell'app e, una volta completato il merge della PR, lo elimina automaticamente.

Ispirato da questo approccio e da un recente incontro con un cliente di DoiT International, ho deciso di replicare lo stesso comportamento su Google Cloud Platform (GCP) con un approccio cloud-native e i più diffusi strumenti open source.

Esperienza per gli sviluppatori (demo di 20 minuti)

Adottando i principi GitOps, il team di sviluppo deve pensare solo a scrivere codice: nel momento in cui apre una PR, in pochi secondi o minuti una versione pronta per la revisione del codice è disponibile online.

I commit successivi aggiornano la review app finché revisori e tester non la approvano e ne effettuano il merge. Quando l'app passa a un ambiente superiore, la review app viene distrutta — e il ciclo ricomincia per ogni nuova feature.

Demo di review app in stile Heroku e pipeline CI/CD GitOps (20 minuti)

Guarda il video demo su YouTube

Componenti coinvolti

  • Github — controllo del codice sorgente
  • Kustomize — gestione della configurazione Kubernetes-native
  • Argo CD — CD GitOps dichiarativo per Kubernetes
  • Kong Ingress Controller — API gateway
  • Google Kubernetes Engine (GKE) — Kubernetes gestito
  • Google Cloud Build — server CI
  • Google Container Registry (GCR) — registry privato per immagini container
  • Google Secret Manager — gestione centralizzata dei secret
  • Google Cloud DNS — servizio DNS con API ( opzionale)

Architettura

Il funzionamento di base delle review app è semplice: quando uno sviluppatore apre una pull request (PR) nel repository, la pipeline di deployment crea una copia dell'app e la pubblica in un ambiente isolato con un URL univoco, pronto per la revisione.

La PR dello sviluppatore crea la Review App

Le funzionalità aggiuntive comprendono la promozione dell'applicazione in produzione dopo il merge della PR e la rimozione della review app.

Il merge da parte del revisore o admin promuove l'app ed elimina la Review App

TL;DR

Per ottenere il risultato mostrato servono questi passaggi:

  1. Creare due repository sorgente separati su Github: App e Config
  2. Abilitare le API Google ed eseguire il bootstrap del cluster GKE e di Argo CD
  3. Installare Kong API Gateway (ingress controller) tramite il repository Config
  4. Creare un record DNS A che punti all'IP esterno di kong-proxy
  5. Collegare Cloud Build al repository Github
  6. Creare una chiave privata e archiviarla in Google Secret Manager
  7. Aggiungere la chiave pubblica al repository Github Config
  8. Creare 3 trigger di Cloud Build ( push , PR, merge)
  9. Autorizzare il service account di Cloud Build ad accedere ai Secret
  10. Aggiungere i file di configurazione di Cloud Build al repository App
  11. Aggiungere i manifest Kubernetes e gli overlay Kustomize al repository Config

Creare i repository sorgente su Github

I repository qui sotto sono esempi funzionanti; nelle sezioni successive vedremo passo passo come costruirli.

  • Demo App — Dockerfile e script CI di Cloud Build
  • Demo App Config — script di setup e manifest Kubernetes per Argo CD

Abilitare le API ed eseguire il bootstrap di GKE e Argo CD

Nello script che segue ho abilitato le API dei servizi Google Cloud e avviato un cluster Kubernetes.

In un articolo precedente ho introdotto il concetto del pattern app of apps, usato anche dal team di sviluppo Argo in Intuit. In questa soluzione, la creazione e la rimozione dinamica di un'"Application" si presta perfettamente al nostro caso d'uso: creare e distruggere review app on demand.

Installare Kong API Gateway (ingress controller)

Per Kong basta aggiungere un file kong.yaml nella cartella /apps del repository Config. Argo CD rileverà e monitorerà qualsiasi repository o cartella che gli si indica. Ho scelto Kong perché ogni Ingress creato configura un host: la soluzione ideale per generare dinamicamente nuovi URL per le review app.

Aggiungete i file di configurazione di Kong nella cartella di destinazione e Kong verrà installato sul vostro cluster Kubernetes (ripetete lo stesso per qualsiasi altra app).

Notate il source.path (kong): è la cartella del repository che conterrà i manifest YAML che Argo CD installerà. Ho creato un file chiamato 01-install.yaml usando il manifest unico ufficiale di Kong nella cartella /kong del repository Config. ( https://bit.ly/k4k8s punta all'ultima configurazione di Kong )

curl https://raw.githubusercontent.com/Kong/kubernetes-ingress-controller/master/deploy/single/all-in-one-dbless.yaml --output kong/01-install.yaml

Creare un record DNS A per Kong Proxy

Una volta installato sul cluster, Kong crea un load balancer TCP esterno (Service) con un IP pubblico.

Servizio load balancer Kong Proxy sul cluster Kubernetes

Dovete far puntare il vostro dominio a questo IP, operazione che potete eseguire manualmente dal pannello del provider DNS. Per la mia demo iniziale ho semplicemente configurato il record A e qualche alias CNAME come mostrato sotto.

Voci DNS configurate manualmente

In alternativa potete gestire il dominio con Google Cloud DNS: in tal caso bisogna delegare i nameserver di Google e diventa possibile generare dinamicamente gli URL delle review app a partire dal numero di PR (la soluzione ideale). Una volta completato il bootstrap di GKE e Kong, potete usare i comandi seguenti per la configurazione.

Collegare Cloud Build a Github

Di solito non sopporto gli articoli che rimandano ad altri articoli, ma per brevità seguite questi due passaggi per collegare Cloud Build a Github e aggiungere una chiave SSH a Secret Manager: sono spiegati molto bene in queste due guide ufficiali di Google:

  1. Connettere Cloud Build a Github
  2. Aggiungere chiave e secret per accedere ai repository privati — attenzione: dovete spuntare la checkbox "commit" sul repository Config, in modo che la pipeline di build dell'App possa effettuare il commit delle modifiche al tag dell'immagine Docker.

Creare 3 trigger di Cloud Build

Per riprodurre il comportamento desiderato, in teoria basterebbero i trigger di PR e merge con i relativi file di configurazione, ma di norma serve anche una build e un deploy a uso degli sviluppatori, quindi ho aggiunto un terzo trigger di push sul branch develop.

Trigger di Cloud Build

Notate che nelle configurazioni qui sotto aggiungo variabili d'ambiente definite dall'utente (in fondo a ciascuna pagina). Permettono ai file di configurazione di referenziare il nome dell'app e, all'occorrenza, di aggiungere passaggi condizionali in base allo stage.

Per semplicità ho creato 3 trigger e 3 file di configurazione separati (vedi sezione successiva), ma è possibile consolidarli sfruttando queste funzionalità.

Build e deploy dell'immagine Docker del branch develop a ogni push

Pull request da un altro branch verso master (prod)

Merge della PR nel branch master (prod)

Aggiungere i file di configurazione di Cloud Build al repository App

La parte iniziale dei file di configurazione di build è piuttosto elementare: si limita a costruire un'immagine Docker e a fare il push su Google Container Registry (GCR). I passaggi successivi usano il secret di Secret Manager per clonare il repository di configurazione, modificare i file ed effettuare il push di un commit. Questo fa scattare la sincronizzazione di Argo CD, che applica le ultime modifiche e aggiorna le app sul cluster GKE.

Notate in questo file il comando sed -i ...: è il punto in cui il tag dell'immagine viene aggiornato all'ultima build pubblicata su GCR.

Notate che nello stage di PR usiamo v$_PR_NUMBER per taggare le immagini, così possono essere aggiornate sui commit successivi durante la review (potrei modificarlo in futuro). Un altro aspetto particolare è che copiamo il file da /templates/demo-app-review.yaml alla cartella /apps, in modo che Argo CD inizi a monitorare quel path.

L'altro punto interessante è la fase "Removing review app...", in cui eseguiamo rm apps/demo-app-review.yaml. Avendo attivato autoSync e prune nella configurazione di Application, Argo CD se ne accorge e rimuove la review app dal cluster GKE.

Aggiungere manifest Kubernetes e overlay Kustomize

Si potrebbe (e dovrebbe) dedicare un altro post del blog solo a Kustomize e a come abilita la gestione della configurazione Kubernetes-native. Tradizionalmente le app si pacchettizzano con Helm chart o con strumenti "sonnet" basati su codice, ma personalmente preferisco un approccio semplice ed estendibile come quello di Kustomize.

Il repository Config è organizzato in modo che ciascuna app — nel nostro caso /demo-app/base — contenga i propri manifest e un file kustomization.yaml.

  • namespace.yaml — namespace personalizzato
  • ingress.yaml — configurazione Ingress che Kong rileva e per cui aggiunge la rotta
  • service.yaml — "wrapper" di rete per i pod di backend
  • deployment.yaml — l'applicazione vera e propria (che punta all'immagine)
  • kustomization.yaml — configurazione Kustomize

A questo punto aggiungiamo gli overlay che rappresentano gli ambienti: queste configurazioni sostituiscono o applicano patch ai file YAML con valori specifici dell'ambiente, come il suffisso del nome dell'app, il namespace e l'host name dell'Ingress (per ottenere URL dinamici per le review app).

  • /overlays/develop — configurazioni dell'ambiente develop
  • /overlays/review — configurazioni dell'ambiente delle review app
  • /overlays/production — configurazioni dell'ambiente di produzione

Trovate il tutto nel repository di configurazione di esempio su Github; qui sotto riporto un esempio di overlay e file di patch per generare URL specifici per ambiente nell'Ingress.

Notate che la proprietà patchesStrategicMerge punta a un file: Kustomize fonderà il contenuto di quel file (o file) per sovrascrivere valori personalizzati come l'host name dell'Ingress, abilitando URL dedicati per ciascun ambiente.

URL dinamici opzionali per ogni PR

Per la mia demo iniziale ho usato sempre lo stesso URL, ma se utilizzate Cloud DNS basta aggiungere un passaggio al file cloudbuild-pr.yaml come quello qui sotto per rendere gli URL dinamici. Al momento in cui scrivo non l'ho ancora testato, ma ho intenzione di aggiornare i miei nameserver e provarlo.

Andrebbe inoltre aggiunto un altro comando sed -i ... nello script di configurazione per sostituire dinamicamente il file di patch ingress-host.yaml a ogni deploy della PR.

Unisciti al mio team

Unisciti a DoiT International e dai vita ad altre scoperte come questa: visita la nostra pagina dedicata alle carriere

Anche se questo post è denso di contenuti, il processo nel suo insieme non è poi così complesso: sfruttando i repository di esempio che ho condiviso potete liberare i vostri Engineers dal peso dell'infrastruttura e farli concentrare su ciò che sanno fare meglio.

Pipeline di build CI/CD funzionante con GitOps e Review Apps in stile Heroku durante la PR