Deploy di un’applicazione Laravel su Kubernetes – Parte 1

3
3130

Oggi voglio iniziare una mini-serie di articoli dedicati al deploy di un’applicazione Laravel su un cluster Kubernetes. 

Era un po’ che volevo farlo: imparare quello che ho imparato per me è stato molto stimolante e mi ha portato un sacco di benefici. Anche economici.

Prima di iniziare però voglio subito mettere un paio di cose in chiaro:

  • non sarà un tutorial “passo dopo passo”: ogni applicazione ha le sue necessità, le sue peculiarità e può necessitare di un setup totalmente diverso da quello che ho messo su io. Per questo motivo, racconterò la mia esperienza, cosa ho fatto e come ho risolto alcuni dei miei problemi, con l’obiettivo di fornire una traccia da seguire per chi si sta avvicinando ora all’argomento;
  • non sono un esperto di Kubernetes: le soluzioni che ho trovato funzionano perfettamente per me, anche se non è detto siano il meglio possibile. Trovo l’argomento molto affascinante ma NON sono ad un livello di conoscenze avanzato sotto questo punto di vista. Non aspettatevi un corso accelerato di Kubernetes su queste pagine!

Quello che leggerete sarà, insomma, un po’ un “diario” della mia esperienza.

Perché Kubernetes?

Un anno e mezzo fa, circa, ho sviluppato la mia prima app per Shopify. Ero nell’ecosistema da un anno circa, con un mio negozio, e me ne sono interessato sempre di più. Shopify è qualcosa di vivo e ci sono tanti, tantissimi problemi tuttora da risolvere. Per uno sviluppatore questo significa opportunità: ci sono 4000 app circa per un 1000000 di negozi.

Dopo qualche settimana ho mandato in produzione il primo MVP di Ahia! – Easy Price Changer, un’app dedicata alla programmazione di cambi prezzi nel proprio negozio.

Il deploy iniziale avviene su una droplet DigitalOcean, con relativo provisioning effettuato via Laravel Forge. Il setup che uso sempre per cominciare: se un’app ha 0 utenti, mettere su qualsiasi cosa possa sembrare più complessa non ha nessun senso. Un po’ alla volta, l’app ha iniziato a prendere utenti che condividevano lo stesso mio problema. Una bella soddisfazione.

Arriviamo al Black Friday 2019: un appuntamento importante per il mondo dell’e-commerce in generale. Di conseguenza, importante anche per la mia app. In tutto questo, nel frattempo avevo superato i 1500 negozi attivi e cambiato setup di conseguenza:

  • Droplet 1: Database + Webapp;
  • Droplet 2: Redis + Processi Worker per i vari job, dato che l’app ne fa largo uso;

Tutto regge bene… fino a quel giorno. A mezzanotte, momento topico, l’app inizia a processare centinaia di cambi prezzi contemporaneamente. E non ce la fa più.

Per mia fortuna, la mia integrazione con Sentry + Slack mi fa capire subito che c’è qualcosa che non va, ed il telefono inizia a ricevere decine di notifiche intorno all’1:00 AM. Email di gente incazzata, l’app che non risponde. Il classico crash nel momento peggiore. Per fortuna, l’allarme rientra in poco tempo grazie al provisioning di una Droplet 3 per far respirare la Droplet 2. Nel giro di una mezz’oretta circa l’allarme rientra.

Come esperienza mi basta: ho bisogno di qualcosa di più scalabile e devo iniziare a capire come risolvere. In modo definitivo. Il momento di passare ai container e Kubernetes è arrivato.

Tocca solo capire come organizzare la nuova architettura.

Questione di Architettura

Passare a Kubernetes, come potete ben immaginare, non è semplice questione di mettersi al PC ed iniziare a premere sui tasti finché non succede qualcosa. Serve un minimo di pianificazione e le variabili da considerare dipendono molto dall’applicazione che si sta costruendo.

Così ho iniziato a farmi qualche domanda.

  • Fino ad oggi ho avuto il database sulla stessa macchina dell’app. Con i backup giornalieri attivati, ovvio… ma è abbastanza?
  • Se avessi bisogno di gestire più worker senza andare a toccare la web app?
  • Se avessi bisogno di gestire più processi della web app senza andare a toccare i worker?
  • Come posso velocizzare e migliorare il deploy?

Partendo da queste domande ho iniziato ad elaborare delle risposte. Ho iniziato a buttare giù lo schema di quella che sarebbe stata l’architettura attuale:

  • il database passa ad una soluzione managed: con pochi dollari al mese posso avere un database che posso far scalare in caso di necessità, senza dovermi preoccupare di tutta la manutenzione “sottostante”;
  • anche per Redis passo al managed: stavolta non tanto per una necessità tecnica, bensì di velocità. L’istanza più piccola disponibile su DigitalOcean costa appena $15/mese ed è più che sufficiente per le mie necessità;
  • sarei passato ad un cluster Kubernetes (managed) per l’app, andando a creare due “deployment” ben distinti. 
    • Deployment 1: la web app ed i relativi pod;
    • Deployment 2: i processi dedicati ai vari worker per le code/job;

Ho menzionato DigitalOcean perché avevo già in mente di rimanerci, senza passare ad altri prodotti come AWS, aumentando il tempo di apprendimento e di conseguenza la messa in produzione dell’app. Tra l’altro, DigitalOcean offre tantissimi servizi di qualità, ho avuto un ottimo supporto quando ne ho avuto bisogno, quindi va bene così.

NOTA: Se può interessare a qualcuno, con questo orribile referral link marchettaro potete avere accesso ad un credit su DigitalOcean di 100 dollari spalmato su 60 giorni.

Ed ora?

Beh, per ora mi fermo un attimo. Volevo dedicare questa prima parte, forse la più importante nonostante l’assenza di codice, a parlare del processo, del ragionamento che mi ha portato qui.

Nel prossimo articolo (arriva a giorni, promesso!) entrerò nel vivo della situazione, parlando di quali servizi ho scelto, come li ho configurati e come ho organizzato il mio workflow per automatizzare tutto il più possibile. Ovviamente sì, aggiungerò anche del codice.

Ah, se vuoi rimanere aggiornato, sto preparando una newsletter. Iscriviti subito oppure usa il form qui a lato! Così non ti perdi niente 😉

Leggi subito la seconda parte!