Come costruire un'applicazione scalabile di Symfony su Kubernetes

Le moderne applicazioni Web sono complesse. Le aspettative dei tuoi utenti riguardo alla tua applicazione sono in costante aumento: oggi un'applicazione deve essere veloce, conveniente, facile da usare e bella.

Soddisfare queste esigenze può diventare un'altra difficoltà nel percorso verso la creazione di un ottimo prodotto. Anche se affronti un problema reale, devi implementarlo nel modo giusto per guadagnarti da vivere.

Per facilitare questa nuova difficoltà e ridurre il tempo impiegato per la creazione e il mantenimento di queste funzionalità previste, un'applicazione moderna di solito sfrutta molti componenti diversi, dalle reti di distribuzione di contenuti (CDN) ai servizi di ricerca full text e ai sistemi di bilanciamento del carico.

Panoramica sull'architettura delle applicazioni Web moderne (da Web Architecture 101 di Jonathan Fulton)

Questa architettura mira a creare un'applicazione su servizi generici (cache, ricerca full-text, coda lavori, ecc.). Ciò riduce naturalmente il tempo necessario per mantenere questi servizi in quanto sono generalmente gestiti da qualcun altro (e talvolta open-source).

Quando si utilizza tale infrastruttura, è fondamentale poter interagire facilmente con tutti i suoi componenti all'interno dell'applicazione. È qui che Kubernetes e Symfony stanno lavorando insieme per aiutarti a ottenere risultati incredibili, estremamente rapidamente.

Kubernetes: un orchestratore di container Docker

Alcuni anni fa, il progetto Docker ha iniziato a emergere come un modo per consentire agli sviluppatori di creare facilmente infrastrutture come la precedente. Con poche linee di configurazione, qualsiasi sviluppatore che utilizza Docker è in grado di creare una rete di contenitori interconnessi, astraggendo la complessità della configurazione di ciascuno dei servizi.

Questo progetto ha rivoluzionato il modo in cui molti sviluppatori hanno pensato all'infrastruttura. Al giorno d'oggi, è comune usare il termine DevOps, riferendosi a persone in grado di sviluppare applicazioni pur avendo in mente l'infrastruttura adatta.

Kubernetes è il passaggio naturale seguente: crea un ambiente pronto per la produzione per l'esecuzione dei container Docker, garantendo sicurezza, resilienza e scalabilità. Con l'aiuto di Docker e Kubernetes, sarai in grado di creare facilmente applicazioni sfruttando un set completo di servizi generici, aiutandoti a creare ottimi prodotti molto più rapidamente.

In questo articolo, mi concentrerò più precisamente su Kubernetes su Google Cloud Platform (GCP) per fare un esempio, ma questo potrebbe essere applicato a qualsiasi provider di cloud.

Usare Symfony in Kubernetes

È sempre utile pensare all'integrazione della tua applicazione nella tua infrastruttura prima di svilupparla. Ti consente di determinare quali servizi ti servono in base alle tue esigenze aziendali e come interagire con essi dalla tua applicazione.

Uno degli elementi più importanti da tenere a mente quando si crea un'applicazione è la sua capacità di ridimensionamento.

"Ridimensionare un'applicazione" significa in realtà aumentare il numero di istanze di produzione del codice dell'applicazione per gestire più richieste. Pertanto, per creare una "applicazione scalabile", c'è sempre un'unica idea principale da tenere a mente: non archiviare lo stato dell'applicazione nel contenitore del codice. Se il contenitore del codice ha uno stato, questo stato verrà duplicato durante il ridimensionamento, portando a problemi di coerenza che potrebbero interrompere l'applicazione.

Come ho spiegato nel mio articolo sulla creazione di una suite di test veloce con Symfony, ci sono due luoghi principali in cui vive lo stato della nostra applicazione: il database e il filesystem.

Utilizzare Flysystem per archiviare i file dell'applicazione nell'archivio file gestito

Praticamente tutti i fornitori di cloud hanno almeno un modo di archiviare elementi simili a file esternamente (GCP ha Google Cloud Storage). Non esitate a fare affidamento su di loro per archiviare i file delle applicazioni: sono infinitamente estensibili, forniscono un CDN facile da configurare e veloci e affidabili.

Di solito utilizzo Flysystem per accedere e interagire con tali servizi. Flysystem è una libreria che fornisce un'astrazione per il filesystem. Oltre a aiutarti a creare una suite di test migliore, Flysystem è anche compatibile con molti provider, tra cui quasi sicuramente il tuo provider cloud.

Per Google Cloud Storage, utilizzo personalmente https://github.com/Superbalist/flysystem-google-cloud-storage.

Configurare Doctrine per utilizzare il servizio SQL fornito

La maggior parte dei provider cloud ti darà anche l'opportunità di fare affidamento sul proprio servizio SQL gestito. GCP ha il servizio Google Cloud SQL, che supporta MySQL e PostgreSQL.

Questi prodotti sono un ottimo modo per archiviare lo stato del database dell'applicazione in un luogo scalabile e affidabile. Se usi Google Cloud SQL con Kubernetes, ti consiglio di utilizzare il proxy Cloud SQL. Creerà un proxy per il tuo database che potrai usarlo come un database classico con Doctrine.

Usa Redis per la cache e le sessioni

La cache e le sessioni dell'applicazione fanno parte dello stato del progetto. Devono essere condivisi tra le tue istanze per evitare problemi.

Redis è perfettamente adatto a questi casi d'uso: come archivio di valori-chiave di memoria, è estremamente veloce ed è in grado di gestire centinaia di migliaia di connessioni in parallelo. Probabilmente non sarà il collo di bottiglia della tua domanda.

Fortunatamente, Symfony è già progettato dalla natura per consentire la configurazione di Redis come gestore di sessione e come backend della cache:

  • per configurarlo come gestore di sessione, uso personalmente https://github.com/snc/SncRedisBundle
  • per configurarlo come backend della cache, bastano poche righe di configurazione:
struttura:
    cache:
        app: cache.adapter.redis
        default_redis_provider: "redis: // localhost"

Utilizzare una posizione condivisa per i registri

Mentre i log delle applicazioni non fanno tecnicamente parte del tuo stato, averli inviati in molti contenitori diversi è un incubo per il debug dei problemi. Di solito è una buona idea archiviarli in una posizione condivisa anziché all'interno del contenitore.

Ci sono molti gestori disponibili in Monolog che possono aiutarti a questo livello: ElasticSearch, MongoDB, ... Tuttavia, mi piace Sentry: è un servizio super utile che crea automaticamente rapporti molto dettagliati sui tuoi problemi. Ne parlerò un po 'di più e come usarlo in Symfony in un prossimo articolo :).

Usa le variabili di ambiente per configurare la tua applicazione da Kubernetes

C'è uno stato che possiamo facilmente dimenticare: credenziali e segreti. Anche se non cambieranno in fase di esecuzione, non dovrebbero essere archiviati nel contenitore del codice per motivi di sicurezza.

Fortunatamente, è possibile fare di meglio con Kubernetes. In realtà, ci sono anche due modi per farlo meglio:

  • puoi fare affidamento sulle variabili d'ambiente di Kubernetes per iniettare i valori direttamente nei tuoi contenitori e usare le funzionalità delle variabili d'ambiente di Symfony.
  • oppure puoi utilizzare il sistema di gestione segreto dedicato di Kubernetes che ti consente di archiviare, gestire e montare i segreti come file nei tuoi contenitori, che è supportato da Symfony con processori di variabili d'ambiente (env (file: your_secret_file)).

Questa idea di non memorizzare lo stato di un'applicazione vicino al suo codice sta diventando qualcosa di standard. I concetti che ho elencato qui sono solo la punta dell'iceberg: non esitare a dare un'occhiata all'App per dodici fattori e alle build riproducibili per saperne di più.

Hai qualcos'altro da aggiungere a questo articolo? Non esitate a commentare!