Da Trantor a Terminus con fnproject.io

Gabriele Provinciali
10 min readApr 4, 2018

--

From the point of ignition, to the final drive, the point of a journey is not to arrive (Neil Peart, 1987)

“Arrival at Trantor”, di MarkJayBee — DeviantArt

Cos’è un container, che tu ne prenda cura?

E’ innegabile: il numero di pubblicazioni tecniche, di esempi, di corsi online, di tecnoprofezie e di letteratura disponibile sulla Grande Rete riguardo Docker — e, più in genere, sulle magiche e salubri proprietà derivanti dall’utilizzo dei software container — ha subìto negli ultimi tre anni un’interessante accelerazione geometrica in grado di far colpo su molti dipartimenti IT che, coraggiosi o diffidenti, sono comunque esposti al funambolistico equilibrio di framework architetturali bilanciati tra moda, efficienza operativa, impatti organizzativi e modernità.

Quasiasi presentazione, workshop, discorso, post o cinguettio sociale centrato sui microservizi e su Docker ha come base di partenza la rottura (i più gentili parlano di decomposizione — spero — funzionale) del monolito applicativo: metafora che incarna l’alternativa offerta da soluzioni leggere e agili e moderne rispetto alle lungaggini e peccati originali insiti nei classici macrocontainer (ad esempio, JEE) che, al confronto, sembrano vestigia di un passato innominabile.

Che sia vero oppure no, mai il termine monolito ha avuto un’accezione così inquietante dall’apparizione nel film di Kubrick esattamente cinquant’anni fa.

Anche le tecnologie afferenti al Serverless Computing sembrano non essere esenti da tale fenomeno: il disegno e l’utilizzo di funzioni completamente basate su Cloud (il futuro) spesso sembrano non essere completamente correlate o compatibili con lo stato dell’arte presente nei nostri Data Center (il presente). Se consideriamo il termine Serverless come un’astrazione delle componenti infrastrutturali e — soprattutto — delle operazioni applicabili su tale infrastruttura (provisioning, scalabilità, patching), quello che per uno sviluppatore di nuova generazione può essere considerato il Nirvana, spesso, può viceversa rappresentare una fastidiosa passeggiata lungo le rive dell’Acheronte per una persona delle operations.

Utilizzando — con la necessaria dose di ironia e cuor leggero, intendiamoci bene — le visioni che il “Buon Dottore” Isaac Asimov ci ha lasciato in eredità, sembra proprio di trovarsi nei capitoli iniziali di “Cronache della Galassia”, il primo libro della trilogia originale che narra l’epopea della Fondazione.

Da un lato, il pianeta Trantor, la gigantesca e sofisticata capitale dell’Impero, dove l’automazione, la centralizzazione delle attività e la consuetudine, ottimizzata da tempo, regnano sovrane, accompagnate però dal rischio di ipertrofia. Dall’altro, il pianeta periferico Terminus, la capitale della Fondazione, dell’agilità e del nuovo corso, dove però c’è ancora molto da fare in un ambiente di frontiera (forse il corrispettivo spaziale del selvaggio West).

In ogni caso, il periodo di transizione tra le due capitali (e tra due modi diversi di governare un impero) è stimata da Hari Seldon, ideatore e pioniere della psicostoria come scienza predittiva (mi domando se sarà basata su Hadoop), in mille anni. Un millennio. Tempo lungo per i singoli umani, tempo sufficientemente corto per gli umani come specie da salvare sotto guida più o meno illuminata.

Da Trantor a Terminus

Asimov ritratto da Rowena Morrill

Un ipotetico viaggio — a carico di un’impresa o di un’amministrazione — da Trantor a Terminus, e cioè da un approccio applicativo centralizzato basato sui macrocontainer (il monolito) ad uno distribuito basato sui microservizi — è lungo 10.000 parsec (qualsiasi cosa voglia dire, è la distanza citata da Asimov tra i due pianeti immaginari) e non esente da insidie: molte delle rotte possibili passano attraverso approcci che non mi convincono completamente.

Ad esempio, l’approccio Bimodale, dove la stessa organizzazione si divide in ‘classico’ e ‘nuovo’, adottando due velocità e modus operandi differenti secondo parametri quali dimensioni dei progetti, competenze dei gruppi di lavoro e dei dipartimenti, criteri strategici.

A mio avviso, questa dicotomia non rappresenta in maniera fedele la complessità di una grande organizzazione, che probabilmente incorpora meccanismi e modelli più vicini ad un concetto MultiModale (più dimensioni di progetto, più velocità, strategie parallele, inevitabili contaminazioni tra classico e nuovo). In ogni caso, l’interazione tra classico e nuovo rimane un fatto.

Uno dei criteri di successo di Docker e — sopratttutto — di Kubernetes come orchestratore e schedulatore di container (in forma infrastrutturale) e di microservizi (in forma logica) è la connotazione Cloud-Native: nativo del Cloud, non solamente in termini di modello di deployment ma in termini di stile architetturale, capacità tecniche e, perché no, restrizioni creative rispetto al modello classico. La popolarità dell’accoppiata Docker/Kubernetes è dovuta anche alla disponibilità e quindi flessibilità di installazione: stazione di sviluppo, modello On-Premise, Cloud Privato, Cloud Pubblico. Minikube ne è un esempio. Come semplice mozzo o come navigatore interstellare esperto, troverò (quasi) sempre un ambiente molto vicino alle mie necessità o al mio ruolo aziendale.

Se la flessibilità è la chiave di volta per l’adozione di una infrastruttura moderna basata su microcontenitori (e, sperando che lo spirito del Buon Dottore ci perdoni, la selezione di un motore gravitazionale adatto a portarci — se lo vogliamo — da Trantor a Terminus), mi domando se tale flessibilità può essere impiegata anche nelle architetture serverless dove una pluralità non definita a priori di funzioni devono essere ampiamente disponibili durante un Click Day e gradualmente ridotte (insieme ai relativi costi) in base alla diminuzione del carico.

Insieme a questa domanda, i framework serverless ne fanno scaturire molte altre:

  • Il modello di deployment di un framework serveless riesce a soddisfare tutte le esigenze, dalla stazione di sviluppo fino al Cloud Pubblico?
  • E’ facile da adottare? Dispone di strumenti adeguati per il debugging? Qual è il costo reale che permette di misurare le capabilities della mia organizzazione con le capabilities tecnologiche?
  • E’ poliglotta? L’importanza di supportare diversi run-time sembra essere più rilevante rispetto al passato?
  • E’ legato ad un fornitore specifico? Un framework serverless equivale al serveless computing?

Uno dei motori gravitazionali: fnproject.io

Il progetto fn, un framework serverless Open Source basato su Docker, scritto in Go e gestibile anche attraverso Kubernetes, si propone di affrontare alcune di queste domande mediando la logica infrastrutturale propria dei container Docker con la facilità di sviluppo in genere attribuita al serverless computing, ed è disponibile su GitHub. L’annuncio effettuato dal gruppo di lavoro fn durante la JavaOne 2017 ha suscitato interesse ed alcuni interrogativi da parte della comunità: in ogni caso, non è passato inosservato.

La prima impressione, scorrendo note, documentazione e codici di esempio, è la semplicità di installazione e della logica iniziale. Il prerequisito è avere una stazione di sviluppo con Docker ed i run-time di riferimento per lo sviluppo delle funzioni. Divertente l’idea di far percepire la semplicità di installazione e di creazione della prima funzione attraverso una GIF animata:

Bricolage a linea di comando

Considerando che tutto quello che è GUI viene visto con sospetto (alle volte giustamente), la linea di comando (CLI) rappresenta la lingua franca di tutte le figure professionali, dallo sviluppo all’esercizio, dal millennial all’esperto investigatore tecnico che ha iniziato a smanettare nel secolo scorso. Per chi usa il Mac, il package management è offerto direttamente da brew:

brew install fn

o nel mio caso, brew upgrade fn per aggiornare l’installazione esistente.

I sorgenti e gli eseguibili per tutte le piattaforme supportate sono disponibili al link https://github.com/fnproject/cli/releases.

Avere a disposizione i sorgenti rende il nostro viaggio iperluce molto interessante per chi (come Mr. Lightning) si diletta di IoT e di piattafome per l’automazione come il Raspberry Pi: Pavel Varchenko si è cimentato in questa PoC portando l’ambiente fn nei suoi cluster Raspberry. Il modello di deployment, quindi, sembra essere sufficientemente ampio con uno spettro di copertura dalle micropiattaforme fino ad architetture complesse (ampio modello di deployment nella nostra lista: check!).

Il lancio di un’instanza fn è altrettanto semplice: fn start.

Il set di comandi disponibili su fn sono (sufficientemente) parlanti: per creare, minimalisticamente testare e mettere in esecuzione una funzione utilizzeremo fn init, fn run, fn deploy, fn call.

Percorrere i primi Parsec

La creazione di un modello di funzione è disponibile attraverso il comando fn init, a cui bisogna associare un runtime di riferimento (sì, fn è poliglotta… check!). In questo caso l’ambiente di runtime è node.js: il comando di inizializzazione genera il boilerplate della funzione che possiamo testare contestualmente alla creazione di un file di input scritto in JSON.

Il comando fn start che abbiamo precedentemente eseguito ha creato una directory (data) che contiene le rotte ed i costrutti necessari a questa particolare istanza del server fn. Tutti gli altri file sono stati creati da fn init, ed includono il corpo della funzione (func.js), il descrittore YAML (func.yaml), ed un paio di file JSON (package.json e test.json).

Lo so, affrontare un viaggio interstellare con un Hello World è impresa ardua e risibile (Asimov era unico e impareggiabile, un professore di biochimica che scriveva di robotica e di imperi galattici), ma in questo modo dimostriamo che la generazione di una funzione è semplice (altro check! nella nostra lista), e che l’accensione dei motori gravitazionali per l’inizio del nostro viaggio rispetta il semplice paradigma di una funzione: l’accettazione di parametri di input, l’elaborazione e la restituzione di un output, in questo caso a forma di Unix pipe (cat payload.json | fn run).

Siamo pronti, quindi per calcolare ed affrontare i primi Parsec, e quindi effettuare il deployment della funzione nel nostro ambiente:

I primi Parsec, in scioltezza…

Il comando fn deploy seguito dal nome della funzione stimola un innalzamento di versione (version bump, 0.0.2), il push dell’immagine al Docker Registry (con le stesse modalità di un container, riusando i layer già presenti nel mio account su DockerHub) e la creazione o aggiornamento della rotta di accesso alla funzione stessa. I comandi fn apps list e fn routes list seguito dal nome dell’app mostrano rispettivamente la funzione in esecuzione governata da questa istanza fn e la rotta disponibili per l’accesso.

Ora, verifichiamo se la funzione in esecuzione è effettivamente invocabile:

Chiamate alla funzione

Posso invocare la funzione attraverso il comando fn call (in questo caso senza parametri, il che mi restituisce l’output di default) oppure attraverso l’onnipresente, abusato e immarcescibile curl (più i parametri e gli argomenti necessari) utilizzando la rotta predisposta dal server fn e visibile con fn routes list:

curl -H “Content-Type: application/json” -X POST -d @payload.json \ http://localhost:8080/r/myfunction/Terminus

Su GitHub il materiale disponibile è copioso, distinto per categorie, tra cui:

  • fdk (Function Development Kit), i kit di sviluppo disponibili per i linguaggi/ambienti più utilizzati (Node, Python, Go, Ruby, Java)
  • fnflow, la possibilità di scrivere flussi di funzioni a lungo termine (long-running) in grado di governare un processo composto da più funzioni in cascata, al Load Balancing.
  • Helm Chart. Helm è un package manager per Kubernetes, molto gradito dalla comunità K8S, e il Chart disponibile su GitHub consente il deployment della piattaforma fn in un Cluster Kubernetes attraverso comandi molto semplici.
  • Integrazione con Prometheus e Grafana.

Un occhio al cruscotto

L’integrazione con Prometheus e Grafana merita un punto a parte. Il tutorial descritto su GitHub consente, in pochi minuti, di accedere alla console grafica di Grafana e monitorare, come in questo esempio, una serie di funzioni accedute da diversi client in maniera concorrente.

La ‘pila’ software che utilizzeremo è la seguente:

Neil mio caso, userò comandi docker e porte conosciute (e libere!) per far partire Prometheus e Grafana da linea di comando, configurandoli come descritto nel tutorial:

Dalla CLI ad una GUI…

e per testarli stimolerò l’esecuzione concorrente di un numero di funzioni, verificando attraverso Prometheus, che espone il servizio sulla porta 9090 (http://localhost:9090), se effettivamente siano in corso di esecuzione e registrate come time series:

Prometheus (non quello di Ridley Scott, però!)

Grafana espone invece il proprio servizio sulla porta 3003. Una volta effettuato il login in massima sicurezza (id: admin, pw: admin), è possibile configurare Prometheus come data source:

e poi importare le dashboard già presenti su GitHub che opportunamente scarichiamo in locale da https://github.com/fnproject/fn/tree/master/examples/grafana

Il risultato è sicuramente funzionale ed esteticamente gradevole:

Grafana in azione!

Un lungo viaggio

La descrizione dei motori gravitazionali di Asimov (cfr. “L’orlo della Fondazione”) è così generica e poeticamente appropriata da rendere l’intera lettura assolutamente coinvolgente: il numero di ‘salti’ previsti per il viaggio deve essere calcolato accuratamente e ricalcolato per ogni minima deviazione.

Inoltre, i ‘salti’ non posso essere utilizzati quando si è troppo vicino al pianeta di origine, a quello di destinazione o a sistemi planetari intermedi. In effetti il passaggio dai macrocontainer (all-in-one, più facili da gestire dai vari dipartimenti suddivisi per ruoli e competenze) ai microcontainer (micrologica distribuita, dove ogni gruppo incorpora tutti i ruoli che cooperano all’erogazione di un determinato servizio) ricorda un po’ la logica del viaggio interstellare: ogni salto deve essere calcolato accuratamente, senza perdere di vista l’intero percorso.

In tal senso, il viaggio è appena iniziato, e le organizzazioni chiamate a selezionare le tecnologie abilitanti devono misurarsi con strumenti in grado di essere gestiti in una pletora di ambienti (sviluppo, test, collaudo, certificazione, esercizio) incrociati con vari modelli di deployment (locale, On-Premise, Cloud Privato, Cloud Pubblico) e vari ruoli (Sviluppatori, Tester, Operations): il salto da calcolare per il prossimo passo sarà soggetto a scrutinio anche per la flessibilità con cui un framework è in grado di supportare ambienti, modelli e persone diverse.

Il viaggio sarà lungo: tra le stelle o tra vari Data Center, lungo parsec o Availability Domains, ci aspetta un interregno denso e interessante. Nel frattempo, pensare al Buon Dottore mi ha fatto venir voglia, per l’ennesima volta, di rileggere la Trilogia originale, sperando che non si palesi nessun inaspettato Mulo a distruggere i miei tranquilli propositi…

--

--