Les microservices désignent une approche architecturale de la création d'applications cloud. Chaque application est conçue comme un ensemble de services, et chaque service s'exécute dans des processus spécifiques et communique via des API. L'évolution qui a conduit à l'architecture de microservices cloud a débuté il y a plus de 20 ans. Le concept de structure de services est plus ancien que les conteneurs et a précédé l'ère des applications web modernes. L'architecture de microservices est une méthode de développement d'applications qui est devenue une bonne pratique au fil du temps.
Pour comprendre les avantages des architectures de microservices, il est essentiel de connaître leur origine.
Applications monolithiques
À l'origine, chaque application résidant sur un seul serveur comprenait trois couches :
Ces couches étaient créées dans une seule pile située sur un seul serveur monolithique dans un data center. Cette configuration était courante dans tous les secteurs d'activité et toutes les architectures technologiques. De manière générale, une application est un ensemble de modules de code qui remplissent une fonction spécifique (base de données, divers types de logique métier, code de rendu graphique ou journalisation, par exemple).
Dans cette architecture monolithique, les utilisateurs interagissaient avec la couche de présentation, qui communiquait avec la couche de logique applicative et la couche de base de données, et les informations étaient ensuite retransmises au client. Cette méthode permettait d'organiser les applications efficacement. Toutefois, elle créait de nombreux points de défaillance uniques, ce qui pouvait entraîner de longues pannes en cas de défaillance matérielle ou de bogue de code. Malheureusement, cette structure ne comprenait pas de fonction « d'autorétablissement ». Si une partie du système était endommagée, sa réparation nécessitait une intervention humaine sous la forme d'un correctif matériel ou logiciel.
De plus, l'achat d'un nouveau serveur était indispensable pour faire évoluer l'une de ces couches. Vous deviez acheter une application monolithique s'exécutant sur un seul serveur et segmenter une partie des utilisateurs vers le nouveau système. Cette segmentation entraînait la création de silos de données utilisateur qui devaient être rapprochés à l'aide de lots de rapports nocturnes. Heureusement, les besoins des clients ont diminué à mesure que les pages web et les applications mobiles sont devenues plus populaires, et de nouvelles méthodes de développement d'applications ont commencé à apparaître.
Architecture orientée services
Au milieu des années 2000, les architectures ont commencé à changer, de sorte que plusieurs couches se trouvaient désormais à l'extérieur d'un seul serveur sous la forme de silos de services indépendants. Les applications étaient conçues pour intégrer ces services en utilisant un bus de services d'entreprise pour la communication. Cette approche permet aux administrateurs de faire évoluer ces services indépendamment en regroupant les serveurs via des fonctionnalités proxy. Elle a également permis de raccourcir les cycles de développement en permettant aux ingénieurs de se concentrer sur une seule partie de la structure de services applicatifs. Le découplage des services et le développement indépendant nécessitaient l'utilisation d'API, l'ensemble des règles de syntaxe utilisées par les services pour communiquer entre eux.
Les architectures orientées services ont également coïncidé avec l'essor de la machine virtuelle (VM), qui a rendu les ressources des serveurs physiques plus efficaces. Le déploiement des services sur des machines virtuelles plus petites était beaucoup plus rapide par rapport à celui des applications monolithiques précédentes sur des serveurs bare-metal. Cette combinaison de technologies a permis de développer de meilleures solutions haute disponibilité (HA), à la fois dans l'architecture de services et avec les technologies d'infrastructure associées.
Microservices
À l'heure actuelle, les microservices cloud transforment la stratégie d'architecture orientée services en ensemble de services fonctionnels granulaires. La combinaison d'ensembles de microservices dans de grands macroservices permet de mettre à jour encore plus rapidement le code d'une fonction dans un service global ou une application utilisateur plus importante. Un microservice tente de résoudre un seul défi tel qu'une recherche de données, une fonction de journalisation ou une fonction de service web. Cette approche améliore la flexibilité. Par exemple, vous pouvez mettre à jour le code d'une seule fonction sans avoir à remanier, voire à redéployer le reste de l'architecture de microservices. Les points de défaillance sont plus indépendants les uns des autres, ce qui crée une architecture d'application globale plus stable.
Cette approche peut également permettre l'autorétablissement des microservices. Par exemple, supposons qu'un microservice d'un cluster contienne trois sous-fonctions. Si l'une de ces sous-fonctions échoue, le microservice est réparé. Avec des outils d'orchestration comme Kubernetes, l'autorétablissement peut se produire sans intervention humaine, car il a lieu en arrière-plan, en plus d'être automatique et transparent pour le client.
Les architectures de microservices sont apparues en même temps que les conteneurs Docker, une solution d'empaquetage et de déploiement. Les images de machine virtuelle sont plébiscitées en tant que mécanisme de déploiement depuis de nombreuses années. Toutefois, les conteneurs sont encore plus efficaces que les machines virtuelles, car ils permettent de déployer le code (et les bibliothèques de codes requises) sur n'importe quel système Linux (ou n'importe quel système d'exploitation qui prend en charge les conteneurs Docker). Les conteneurs sont le vecteur de déploiement idéal pour les microservices. Leur lancement s'effectue en quelques secondes, de sorte qu'ils peuvent être redéployés rapidement après une défaillance ou une migration, et ils peuvent évoluer rapidement pour répondre à la demande. Les conteneurs étant natifs de Linux, le matériel ordinaire peut être appliqué à de vastes fermes de microservices dans n'importe quel data center, cloud privé ou multicloud hybride.
Dans la mesure où les microservices sont étroitement liés aux architectures cloud natives quasiment depuis le début, ils sont devenus impossibles à distinguer les uns des autres à bien des égards. Comme les microservices et les conteneurs sont très abstraits, ils peuvent être exécutés sur n'importe quel système d'exploitation compatible (généralement Linux). Ce système d'exploitation peut fonctionner partout : dans le cloud public, sur site, dans un hyperviseur virtuel ou même sur un serveur bare-metal. À mesure que l'utilisation du cloud s'est accrue pour le développement, les architectures et les pratiques cloud natives ont été de nouveau migrées vers des data centers sur site. De nombreuses entreprises construisent leur environnement local pour partager les mêmes caractéristiques de base que le cloud, ce qui permet d'utiliser une seule méthode de développement sur tous les sites (on parle également d'approche cloud native globale). Cette approche cloud native est rendue possible et nécessaire par l'adoption d'architectures de microservices et de technologies de conteneur.
Les microservices sont décentralisés et s'exécutent sur différents serveurs, mais ils fonctionnent toujours ensemble pour une application. Dans l'idéal, chaque microservice remplit une seule fonction, ce qui simplifie le routage entre les services via la communication par API. Autres avantages :
Conteneurs
Les conteneurs sont immuables : après leur déploiement, ils ne peuvent pas (ou ne doivent pas) être modifiés. Si une nouvelle version du code devient disponible, le conteneur est détruit et un nouveau conteneur basé sur le code le plus récent est déployé à sa place. Les conteneurs peuvent être lancés en quelques secondes ou millisecondes, de sorte que des composants de service supplémentaires peuvent être déployés immédiatement au moment et à l'emplacement où ils sont nécessaires. En raison de la faible empreinte des ressources par rapport aux machines virtuelles ou au bare-metal, les conteneurs constituent le meilleur mécanisme de déploiement pour les microservices. Alors que les machines virtuelles contiennent tous les composants du système d'exploitation, les conteneurs ne comprennent que le code de microservice et les bibliothèques de codes nécessaires. Les autres fonctionnalités nécessaires sont partagées sur un système d'exploitation commun, et les autres microservices s'exécutent dans des conteneurs.
Orchestration
Les outils d'orchestration de conteneurs sont presque aussi anciens que les conteneurs. Des milliers de microservices fonctionnent ensemble pour créer des services et des applications. Une gestion manuelle de ces services serait presque impossible, même avec une multitude d'administrateurs. Dans un contexte de stagnation des budgets en personnel IT, de montée en puissance de l'automatisation et d'adoption de pratiques DevOps, il est primordial de disposer de bons outils d'orchestration.
La première version de Kubernetes (K8s) a été publiée en 2015, peu après l'essor des conteneurs Docker, et elle est rapidement devenue le principal outil d'orchestration dans le domaine des conteneurs. Kubernetes permet aux développeurs d'enregistrer une application ou un microservice basé sur des conteneurs dans une bibliothèque commune et de fournir un fichier manifeste au contrôleur Kubernetes. Kubernetes déploie ensuite l'application sur ses nœuds workers en fonction des spécifications du fichier manifeste, à l'aide de l'image de conteneur disponible dans le registre commun.
« L'état souhaité », un concept clé dans Kubernetes, permet à la solution d'intégrer des fonctionnalités d'autorétablissement et de mise à niveau automatique. Par exemple, supposons que vous souhaitiez l'état suivant : 10 instances d'un microservice spécifique (dans un pod de conteneurs) de la version 1.1 sont toujours en cours d'exécution. Kubernetes surveille le déploiement pour assurer l'état souhaité. Si l'un des conteneurs est défaillant et que seuls 9 conteneurs sont en cours d'exécution, Kubernetes déploie un autre conteneur et le lance pour obtenir l'état souhaité de 10 instances de la version 1.1. Si le manifeste est modifié pour spécifier la version 1.2, Kubernetes voit l'état souhaité comme non satisfait et effectue une mise à jour du déploiement des 10 instances vers la version 1.2 (en supposant que la version 1.2 est une image disponible dans le registre du conteneur).
On comprend facilement pourquoi Kubernetes est si rapidement devenu la principale solution d'orchestration de conteneurs et pourquoi chaque grand fournisseur de cloud public (Amazon Web Services, Microsoft Azure, Google Cloud Platform) possède sa propre version de Kubernetes.