Service Mesh su OCI — Oracle Cloud Infrastructure

Prima legge di Finagle: Se un esperimento funziona, qualcosa è andato male.”

1. Premessa

La mia età avanza, l’andropausa inizia ad essere visibile ad occhio nudo e il mio personale switch --v (-verbose, inventato da qualche pisquano per aumentare il numero di parole al minuto) non funziona più come soleva far qualche decennio fa. La risultante di tutto ciò non alimenta il debito tecnico — in qualsiasi punto della matrice che tenta di definirlo (avventato vs. prudente, volontario vs. involontario) — ma l’inquietante, terrificante e terribile debito mnemonico.

In sostanza, tendo a non ricordare gli esperimenti e le sessioni in Matrix (terminale con bash rigorosamente a fosfori verdi su sfondo nero, e sessioni CLI su una nuvola a caso da qualche parte) che tanto mi hanno divertito la settimana precedente.

L’unico neurone attivo rimasto (si chiama Goffredo, ci salutiamo con affetto ogni mattina, non ve lo presento perchè soffre di TeraTimidezza) ha un backlog lungo giorni e giorni, e quindi non mi rimane che affidare la memoria temporanea ad un insignificante post confidando in una piacevole sorpresa quando, tra qualche giorno, lo ritroverò nel feed di qualche sociorete ricordando (!) di non averlo mai scritto.

Andiamo subito al sodo, se mi dilungo corro il rischio di cadere nel fuso orario della dimenticanza e mi ritrovo a scrivere un articolo sul sincronismo tra “Echoes” dei Pink Floyd e “2001 — A space odyssey” di Stanley Kubrick senza sapere come sono arrivato a tale illuminata considerazione.

Divido i passi da seguire per creare un Service Mesh su OCI in tre categorie:

  • il setup preparatorio di OCI per gestire correttamente un cluster K8S
  • la creazione del Cluster Kubernetes
  • L’installazione ed il test del Service Mesh

2. Setup di OCI

Dopo essermi ricordato l’acronimo OCI (Oracle Cloud Infrastructure), procederemo alla creazione dell’identità e delle risorse di rete necessarie.

2.1 Identità

Una volta collegati alla nostra console OCI, andiamo prontamente a creare un utente dedicato allo scopo su Identity -> Users -> Create User.

Creato correttamente l’utente, dovrò poi gestire una one-time password molto simile ad un ruggito di Brontosauro, segnarmela nel mio salvamemoria (occhio, viene data una sola possibilità), e aspettarmi che successivamente OCI chieda di cambiarla una volta effettuato il login.

Aggiungiamo l’utente creato al gruppo Administrator:

e continuiamo con il setup: occorre creare una policy che consenta al mio utente di gestire, dal servizio Kubernetes, tutte le risorse presenti nella tenancy. Nulla di più semplice: basta andare su Identity -> Policies e creare una Policy che riporti l’istruzione:

allow service OKE to manage all-resources in tenancy

ed il gioco è fatto: provvederemo a completare quel che manca tra poco.

2.2 La rete e lo zampino di Postak

Il setup di OCI per gestire un cluster K8S può essere facilitato, in fase di creazione delle componenti di rete (VCN — Virtual Cloud Networks, Load Balancers, etc.) attraverso uno script terraform (da installare con brew install terraform se siete su Mac, o andando a cercare su Big G le istruzioni per installarlo su altre piattaforme), da configurare, scritto dal mitologico Postak, che trovate a quest’indirizzo su GitHub: https://github.com/postak/vcn4container.

E’ l’ora (finalmente!) di aprire una Matrix shell e clonare il progetto dal link sopra descritto:

andando a modificare il file terraform.tfvars con i parametri OCI richiesti e che sono reperibili dalla console, e che consistono in:

  • tenancy_ocid
  • compartment_ocid
  • fingerprint
  • private_key_path
  • user_ocid
  • region

Mmmmh. Il debito mnemonico, però, mi fa riflettere sulla completezza delle informazioni che ho disposizione, forse manca qualcosa. Goffredo (vedi sopra) è sotto stress, ma riesce a risolvere l’arcano dopo qualche secondo (sta invecchiando anche lui ma vi prego di essere gentili, non si chiede l’età ad un neurone): debbo generare il fingerprint, aggiungendo una Public Key nella schermata di dettaglio dell’utente creato:

ed automagicamente OCI mi mette a disposizione il fingerprint, che includerò nel file terraform.tfvars. Siamo pronti per far girare terraform? Goffredo annuisce, forse un po’ troppo lentamente.

terraform init
terraform plan
terraform apply

Ed in un battito d’ali di farfalla la rete per il nostro Cluster Kubernetes gestito in OCI è pronta, composta da:

Postak dixit

Passiamo al prossimo segmento, e cioè la creazione del cluster vero e proprio.


3. Setup del Cluster Kubernetes su OCI

3.1 C’è sempre più di un modo per farlo

Approntare un Cluster Kubernetes su OCI può significare:

a) Impostare tutto con terraform seguendo le istruzioni su https://github.com/oracle/terraform-provider-oci e quindi essere responsabili per i nodi master e i nodi worker (e pagando il consumo di risorse su tutti i nodi)

b) Continuare a seguire questo articolo sperando che il Postak sia nei paraggi o aspettando che venga creata Postakpedia nel caso il debito mnemonico passi dallo stadio ‘fastidioso’ allo stadio ‘pericoloso’ (le screwups sono sempre in agguato). Poi invocare qualche divinità (Postacchini, Folchi, Chtulhu), e proseguire. Il vantaggio di questa opzione risiede nella gestione autonoma, da parte di OCI, delle componenti di sistema di Kubernetes (ad esempio, i Master Node ed amenità connesse) che quindi non vengono contabilizzati nel computo dei costi. Non male.

3.2 …e noi usiamo il Kubernetes ‘gestito’

Corriamo - quindi - a seguire la versione b) del nostro malefico piano. Ci colleghiamo con l’utenza Gabba creata precedentemente, e ci viene chiesto di cambiare la one-time password ricevuta con una password definitiva (almeno per le prossime ore, la sicurezza non è mai troppa).

Da pochi giorni è comparso, sulla console OCI, un tab molto sospetto (Containers):

che utilizzeremo per creare il Cluster K8S, premendo un visibile bottone blu in questa pagina:

Click that frickin’ button…

che apre un form su cui bisogna impostare il nome del Cluster (GabbaCluster), la versione di Kubernetes (es. 1.9.7), la VCN ed i due Load Balancers creati dallo script del Postak, le spunte su Kubernetes Dashboard Enabled (yes) e Tiller (Helm) enabled (yes).

E’ possibile creare il Node Pool (l’insieme dei nodi worker sotto il nostro controllo) già in questo form, ma per chiarezza lo faremo in un secondo momento.

…and fill the form!

Excellent. Una volta avviata, la procedura di creazione del cluster richiede circa 5 minuti.

Making stuff available…

3.3 Creazione del Node Pool

Una volta creato il cluster, possiamo procedere alla creazione del Node Pool, che configureremo con la stessa versione di K8S (1.9.7), su Oracle Linux 7.4, con una Shape che include 1 OCPU, 15 GB di RAM e fino a 512 TB di storage.

Il sistema richiede la chiave SSH pubblica, che provvederemo a tradurre da una chiave che già abbiamo, public.pem, con il comando:

ssh-keygen -f public.pem -i -mPKCS8

Una volta completato il form, si procederà con l’avvio della creazione del Node Pool denominato (guarda un po’) GabbaNode.

Creating nodes

Dopo qualche minuto Goffredo mi implora di portarlo fuori a respirare aria di città. Povero, lo capisco, con il tempo (credo) ha bisogno di pause ripetute e passare dal terminale a fosfori verdi al riallineamento dei bulbi oculari guardando il maggio-paesaggio fuori la finestra. Lo sguardo sul mondo esterno durerà poco, purtroppo: la creazione dei nodi non richiede più di 15 minuti, la maggior parte dei quali è impiegata per aggiornare il software dei nodi stessi.

Active Active Active

L’ultimo step di questo segmento ci server per accedere al cluster Kubernetes da Matrix. Ci aiuterà, nella pagina dei Cluster, premere il bottone “Access Kubeconfig”:

Access Kubeconfig

che ci fornisce le indicazioni per ottenere il prezioso Kubeconfig. Le seguiamo bovinamente:

…ed il cluster K8S è attivo!

4. Service Mesh!

Cos’è un Service Mesh? In breve, se le esigenze di uno stile architetturale a microservizi richiede l’applicazione di pattern di osservabilità, di resilienza, di controllo del traffico (pensiamo alla sicurezza, al circuit-breaking, ed a tutte le indicazioni esplicite e non derivanti dall’adozione di questo stile), il Service Mesh si propone di indirizzare molti di questi temi.

Detta in maniera meno sciencey, il Service Mesh (ad esempio, Istio) consiste nel fornire un Control Plane (il centro di comando e controllo delle connessioni, degli instradamenti e dei rilevamenti telemetrici) ed un pattern per costruire il Data Plane (l’insieme dei microservizi osservati): il Sidecar.

Istio stuff

Il pattern Sidecar (nel caso di Istio, Envoy, sviluppato da Lyft) consiste nell’iniettare nei pod applicativi (alla parola iniettare Goffredo ha un tremito, è un neurofifone) un proxy con un impronta RAM minimale in grado di intercettare flussi, generare telemetria, e ricevere comandi (ad esempio, policy e regole di instradamento) provenienti dal Control Plane (pod di sistema Istio).

Per questo esempio, su Oracle Cloud Infrastructure, utilizzeremo Istio ed applicheremo delle regole per osservare il cambiamento del comportamento da parte di un’applicazione. L’applicazione di esempio (BookInfo) si presta egregiamente — nella sua semplicità — a questo tipo di interazione.

Architettura Bookinfo

Ogni microservizio di Bookinfo è scritto in un linguaggio diverso:

  • Python per il Front-End
  • JavaScript su Node, un microservizio Java presente in varie versioni, e un microservizio Ruby sul Back-End,

e l’intera applicazione, una volta installato Istio, cambia conformazione:

Bookinfo con Istio

4.1 Installare Istio su K8S

Basta figure. Troppe figure fanno uscire da Matrix, dove subito rientriamo andando a scaricare Istio ed esempi dal sito. Il comando curl scarica Istio localmente, il secondo rende disponibile il comando istioctl nella shell, ed il terzo (buon vecchio kubectl, mi mancavi) installa Istio nel nostro cluster Kubernetes.

curl -L https://git.io/getLatestIstio | sh -
export PATH=”$PATH:./istio-0.7.1/bin”
kubectl apply -f install/kubernetes/istio.yaml
Downloading
…And, Installing

E’ possibile verificare che l’installazione sia andata a buon fine con

kubectl get svc -n istio-system
kubectl get po -n istio-system

dove pods e services sono stati collocati su un apposito namespace (istio-system).

Notate che il servizio istio-ingress, che espone l’erogazione applicativa in modalità LoadBalancer, ha il suo indirizzo IP pubblico ed è proprio quello che utilizzeremo per capire se l’applicazione è viva e scalcia come un puledro uscito dal recinto oppure abbiamo sbagliato qualcosa e siamo costretti a entrare in modalità ‘infrastructure-as-code’ e debuggare/distruggere rapidamente quanto abbiamo costruito.

4.2 Installare BookInfo

L’applicazione BookInfo è installabile e sidecarizzata (Devoto-Oli, perdonatemi) con il comando istioctl, annidato nel comando kubectl, con il comando:

kubectl create -f <(istioctl kube-inject -f \ samples/bookinfo/kube/bookinfo.yaml)

che ci restituisce una sfilza di ‘created’… buon segno.

BookInfo

E’ tempo, poi, di effettuare il test (Goffredo, per cortesia, fai un rullo di tamburi con un paradiddle semplice), annotando l’indirizzo IP pubblico assegnato all’istio-ingress (129.213.66.43) ed aggiungendo, nell’URL, la pagina iniziale (productpage).

It works :)

Il funzionamento di BookInfo è semplice: la productpage punta (con una regola di default) ad una delle istanze del microservizio Reviews (v1, v2 o v3) che, rispettivamente, fanno in modo di mostrare una pagina senza stelle (v1), una pagina con stelle nere (v2) ed una pagina con stelle rosse (v3). Ricaricando la pagina, vedremo che le tre versioni dello stesso microservizio vengono mostrate in maniera sequenziale (senza, stelle nere, stelle rosse).

4.3 Cambiamo le regole!

BookInfo è fornito con una serie di regole di esempio, applicabili a caldo, che permettono di fare cosine interessanti: in particolare, la regola chiamata route-rule-reviews-test-v2.yaml nella directory samples/bookinfo/kube e che riporta la seguente configurazione:

regex…

permette ad un utente che ha effettuato il login come jason (un nome a caso) di accedere visualmente all’intera applicazione attraverso la productpage, che però a sua volta punterà esclusivamente alla versione v2 del microservizio Reviews. Proviamo ad applicarla.

kubectl create -f \ 
samples/bookinfo/kube/route-rule-reviews-test-v2.yaml

Accedendo alla productpage dovremo effettuare il login, sempre in massima sicurezza (utente: jason, senza password) e capire se, ricaricando la pagina, la regola è stata applicata correttamente.

Hi. I’m Jason.
Wow. It works again…

…In effetti, ricaricando la pagina, accediamo esclusivamente alle Reviews con stelle nere, e quindi la regola applicata nel nostro Service Mesh ha avuto successo! Il percorso che abbiamo seguito, quindi è quello contraddistinto dagli indicatori rossi.

5. Conclusioni — Time and a word

Vi ricordate cosa voleva dire (una ventina di anni fa - quando Goffredo-Highlander non era da solo ma in splendida compagnia di altri neuroni con cui tesseva proficue relazioni) disegnare infrastruttura, rete ed applicazioni in grado di supportare regole di traffic shaping a caldo? Oppure predisporre canary test in grado posizionare diverse versioni della stessa applicazione per un’utenza amica? O forse pensare ad una serie di Dark Launches (detta così sembra il gruppo Facebook di Darth Vader) per catturare il traffico dalla produzione in un segmento di cluster dove posso effettuare esperimenti senza temere ripercussioni sulle prestazioni complessive delle applicazioni?

Tutto questo è possibile, ora, con uno sforzo contenuto, grazie ai Container (Docker), agli orchestratori (Kubernetes) ed al Service Mesh (Istio).

La quasi totalità delle operazioni che avete visto in quest’articolo sono riproducibili in un cluster sul vostro PC/Mac/Linux, attraverso Minikube: vederlo dal vivo su di un’infrastruttura potente come OCI, in poco tempo e con regole applicabili mentre l’applicazione è in esecuzione, comunque, è divertente, educativo, e permetterà alla mia memoria di recuperare velocemente queste informazioni quando il debito mnemonico prenderà il sopravvento.

E, cioè, la settimana prossima.