Comment créer une application Symfony évolutive sur Kubernetes

Les applications Web modernes sont complexes. Les attentes de vos utilisateurs vis-à-vis de votre application ne cessent de croître: de nos jours, une application doit être rapide, pratique, facile à utiliser et esthétique.

Répondre à ces exigences peut devenir une autre difficulté pour créer un excellent produit. Même si vous vous attaquez à un problème réel, vous devez le mettre en œuvre correctement pour en vivre.

Pour résoudre cette nouvelle difficulté et réduire le temps consacré à la création et à la maintenance de ces fonctionnalités attendues, une application moderne exploite généralement de nombreux composants, des réseaux de diffusion de contenu (CDN) aux services de recherche en texte intégral et aux équilibreurs de charge.

Vue d'ensemble de l'architecture d'applications Web modernes (extrait de Web Architecture 101 de Jonathan Fulton)

Cette architecture a pour objectif de construire une application sur des services génériques (cache, recherche en texte intégral, file d'attente, etc.). Cela réduit naturellement le temps requis pour maintenir ces services, car ils sont généralement gérés par quelqu'un d'autre (et parfois open-source).

Lorsque vous utilisez une telle infrastructure, il est essentiel d’interagir facilement avec tous ses composants à partir de votre application. C’est là que Kubernetes et Symfony travaillent ensemble pour vous aider à obtenir des résultats incroyables, très rapidement.

Kubernetes: un orchestrateur de conteneurs Docker

Il y a quelques années, le projet Docker a commencé à apparaître pour permettre aux développeurs de créer facilement des infrastructures telles que la précédente. Avec quelques lignes de configuration, tout développeur utilisant Docker est capable de créer un réseau de conteneurs interconnectés, résumant ainsi la complexité de la configuration de chacun des services.

Ce projet a révolutionné la façon dont de nombreux développeurs ont pensé à l'infrastructure. De nos jours, il est courant d'utiliser le terme DevOps, désignant des personnes capables de développer des applications tout en gardant à l'esprit l'infrastructure appropriée.

Kubernetes est l'étape suivante naturelle: il crée un environnement prêt à la production pour que les conteneurs Docker puissent s'exécuter, offrant sécurité, résilience et évolutivité. Avec l'aide de Docker et de Kubernetes, vous serez en mesure de créer facilement des applications exploitant un ensemble complet de services génériques, ce qui vous aidera à créer d'excellents produits beaucoup plus rapidement.

Dans cet article, je vais me concentrer plus précisément sur Kubernetes sur la plateforme Google Cloud (GCP) pour en donner un exemple, mais cela pourrait s'appliquer à tout fournisseur de cloud.

Utiliser Symfony dans Kubernetes

Il est toujours utile de réfléchir à l'intégration de votre application dans votre infrastructure avant de la développer. Il vous permet de déterminer les services dont vous avez besoin en fonction de vos besoins métier et de savoir comment interagir avec eux à partir de votre application.

L'un des éléments les plus importants à garder à l'esprit lors de la création d'une application est sa capacité à évoluer.

"Adapter une application" signifie en réalité augmenter le nombre d'instances de production du code de votre application pour traiter davantage de demandes. Ainsi, pour créer une «application évolutive», il ne faut jamais oublier une seule idée principale: ne stockez pas l’état de votre application dans le conteneur de code. Si votre conteneur de code a un état, cet état sera dupliqué lors de la mise à l'échelle, ce qui entraînera des problèmes de cohérence qui pourraient endommager votre application.

Comme je l'ai expliqué dans mon article sur la création d'une suite de tests rapides avec Symfony, l'état de notre application réside principalement dans deux endroits: la base de données et le système de fichiers.

Utilisez Flysystem pour stocker vos fichiers d’application dans le magasin de fichiers géré.

Presque tous les fournisseurs de cloud ont au moins un moyen de stocker des éléments de type fichier de manière externe (GCP possède Google Cloud Storage). N’hésitez pas à vous fier à eux pour stocker vos fichiers d’application: ils sont extensibles à l’infini, sont accompagnés d’un CDN facile à configurer, et sont rapides et fiables.

J'utilise habituellement Flysystem pour accéder à ces services et interagir avec eux. Flysystem est une bibliothèque fournissant une abstraction pour le système de fichiers. En plus de vous aider à créer une meilleure suite de tests, Flysystem est également compatible avec de nombreux fournisseurs, parmi lesquels il y a presque certainement votre fournisseur de cloud.

Pour Google Cloud Storage, j'utilise personnellement https://github.com/Superbalist/flysystem-google-cloud-storage.

Configurer Doctrine pour utiliser le service SQL fourni

La plupart des fournisseurs de cloud vous donneront également la possibilité de faire appel à leur propre service SQL géré. GCP dispose du service Google Cloud SQL, qui prend en charge MySQL et PostgreSQL.

Ces produits constituent un excellent moyen de stocker l'état de la base de données de votre application dans un emplacement fiable et évolutif. Si vous utilisez Google Cloud SQL avec Kubernetes, je vous recommande d'utiliser le proxy Cloud SQL. Il créera un proxy pour votre base de données que vous pourrez utiliser comme base de données classique avec Doctrine.

Utilisez Redis pour votre cache et vos sessions

Votre cache d'application et vos sessions font partie de l'état de votre projet. Ils doivent être partagés entre vos instances afin d'éviter les problèmes.

Redis est parfaitement adapté à ces cas d’utilisation: en tant que magasin de clés de mémoire, il est extrêmement rapide et peut gérer des centaines de milliers de connexions en parallèle. Ce ne sera probablement pas le goulot d’étranglement de votre application.

Heureusement, Symfony est déjà conçu par nature pour autoriser la configuration de Redis en tant que gestionnaire de session et en tant que backend de cache:

  • pour le configurer en tant que gestionnaire de session, j'utilise personnellement https://github.com/snc/SncRedisBundle
  • pour le configurer en backend cache, quelques lignes de configuration suffisent:
cadre:
    cache:
        app: cache.adapter.redis
        default_redis_provider: "redis: // localhost"

Utilisez un emplacement partagé pour vos journaux

Bien que les journaux de vos applications ne fassent pas techniquement partie de votre état, les envoyer dans de nombreux conteneurs différents est un cauchemar pour résoudre les problèmes. C’est généralement une bonne idée de les stocker dans un emplacement partagé plutôt que dans le conteneur.

Monolog propose de nombreux gestionnaires disponibles à ce niveau: ElasticSearch, MongoDB, ... Cependant, j’ai tendance à aimer Sentry: c’est un service extrêmement utile qui crée automatiquement des rapports très détaillés sur vos problèmes. Je parlerai un peu plus de ce sujet et de la façon de l’utiliser dans Symfony dans un prochain article :).

Utilisez des variables d'environnement pour configurer votre application depuis Kubernetes

Il y a un état que nous pouvons facilement oublier: informations d'identification et secrets. Bien qu'ils ne changent pas au moment de l'exécution, ils ne doivent pas non plus être stockés dans votre conteneur de code pour des raisons de sécurité.

Heureusement, il est possible de faire mieux avec Kubernetes. En fait, il y a même deux façons de le faire mieux:

  • soit vous pouvez compter sur les variables d’environnement Kubernetes pour injecter les valeurs directement dans vos conteneurs et utiliser les fonctionnalités de variable d’environnement de Symfony.
  • ou vous pouvez utiliser le système de gestion de secrets dédié de Kubernetes qui vous permet de stocker, gérer et monter des secrets sous forme de fichiers dans vos conteneurs, qui est pris en charge par Symfony avec des processeurs de variables d’environnement (env (fichier: votre_fichier_secret)).

Cette idée de ne pas stocker l'état d'une application proche de son code est en train de devenir un standard. Les concepts que je viens d’énumérer ne sont que la partie visible de l’iceberg: n’hésitez pas à consulter l’application Twelve-Factor et les versions reproductibles pour en savoir plus.

Avez-vous quelque chose à ajouter à cet article? N'hésitez pas à commenter!