Rédacteur – Cette série d’articles en sept parties est désormais terminée :
Vous pouvez également télécharger l'ensemble complet des articles, ainsi que des informations sur la mise en œuvre de microservices à l'aide de NGINX Plus, sous forme d'ebook – Microservices : De la conception au déploiement . Et consultez notre série sur l’ architecture de référence des microservices et la page Solutions de microservices .
Il s'agit du sixième article d'une série sur la création d'applications avec des microservices. Le premier article présente le modèle d’architecture des microservices et discute des avantages et des inconvénients de l’utilisation des microservices. Les articles suivants traitent de différents aspects de l’architecture des microservices : l’utilisation d’une passerelle API , la communication interprocessus , la découverte de services et la gestion des données pilotée par les événements . Dans cet article, nous examinons les stratégies de déploiement de microservices.
Le déploiement d’une application monolithique signifie l’exécution de plusieurs copies identiques d’une seule application, généralement volumineuse. Vous provisionnez généralement N serveurs (physiques ou virtuels) et exécutez M instances de l'application sur chacun d'eux. Le déploiement d’une application monolithique n’est pas toujours entièrement simple, mais il est beaucoup plus simple que le déploiement d’une application de microservices.
Une application de microservices se compose de dizaines, voire de centaines de services. Les services sont écrits dans une variété de langages et de frameworks. Chacune d’entre elles est une mini-application avec ses propres exigences spécifiques en matière de déploiement, de ressources, de mise à l’échelle et de surveillance. Par exemple, vous devez exécuter un certain nombre d’instances de chaque service en fonction de la demande pour ce service. De plus, chaque instance de service doit être dotée des ressources CPU, mémoire et E/S appropriées. Ce qui est encore plus difficile, c’est que malgré cette complexité, le déploiement des services doit être rapide, fiable et rentable.
Il existe quelques modèles de déploiement de microservices différents. Examinons d’abord le modèle d’instances de service multiples par hôte.
Une façon de déployer vos microservices consiste à utiliser le modèle Plusieurs instances de service par hôte . Lorsque vous utilisez ce modèle, vous provisionnez un ou plusieurs hôtes physiques ou virtuels et exécutez plusieurs instances de service sur chacun d’eux. À bien des égards, il s’agit de l’approche traditionnelle du déploiement d’applications. Chaque instance de service s’exécute sur un port connu sur un ou plusieurs hôtes. Les machines hôtes sont généralement traitées comme des animaux de compagnie .
Le diagramme suivant montre la structure de ce modèle.
Il existe plusieurs variantes de ce modèle. Une variante consiste à ce que chaque instance de service soit un processus ou un groupe de processus. Par exemple, vous pouvez déployer une instance de service Java en tant qu’application Web sur un serveur Apache Tomcat . Une instance de service Node.js peut être constituée d'un processus parent et d'un ou plusieurs processus enfants.
L’autre variante de ce modèle consiste à exécuter plusieurs instances de service dans le même processus ou groupe de processus. Par exemple, vous pouvez déployer plusieurs applications Web Java sur le même serveur Apache Tomcat ou exécuter plusieurs bundles OSGI dans le même conteneur OSGI.
Le modèle d’instances de service multiples par hôte présente à la fois des avantages et des inconvénients. L’un de ses principaux avantages est que son utilisation des ressources est relativement efficace. Plusieurs instances de service partagent le serveur et son système d’exploitation. C'est encore plus efficace si un processus ou un groupe de processus exécute plusieurs instances de service, par exemple plusieurs applications Web partageant le même serveur Apache Tomcat et la même JVM.
Un autre avantage de ce modèle est que le déploiement d’une instance de service est relativement rapide. Il vous suffit de copier le service sur un hôte et de le démarrer. Si le service est écrit en Java, vous copiez un fichier JAR ou WAR. Pour les autres langages, comme Node.js ou Ruby, vous copiez le code source. Dans les deux cas, le nombre d’octets copiés sur le réseau est relativement faible.
De plus, en raison de l’absence de frais généraux, le démarrage d’un service est généralement très rapide. Si le service est un processus propre, il vous suffit de le démarrer. Sinon, si le service est l’une des nombreuses instances exécutées dans le même processus de conteneur ou groupe de processus, vous pouvez soit le déployer dynamiquement dans le conteneur, soit redémarrer le conteneur.
Malgré son attrait, le modèle d’instances de service multiples par hôte présente certains inconvénients importants. L’un des principaux inconvénients est qu’il y a peu ou pas d’isolement des instances de service, à moins que chaque instance de service ne soit un processus distinct. Bien que vous puissiez surveiller avec précision l’utilisation des ressources de chaque instance de service, vous ne pouvez pas limiter les ressources utilisées par chaque instance. Il est possible qu’une instance de service défectueuse consomme toute la mémoire ou le processeur de l’hôte.
Il n’y a aucun isolement si plusieurs instances de service s’exécutent dans le même processus. Toutes les instances peuvent, par exemple, partager le même tas JVM. Une instance de service qui se comporte mal pourrait facilement interrompre les autres services exécutés dans le même processus. De plus, vous n’avez aucun moyen de surveiller les ressources utilisées par chaque instance de service.
Un autre problème important avec cette approche est que l’équipe d’exploitation qui déploie un service doit connaître les détails spécifiques de la manière de le faire. Les services peuvent être écrits dans une variété de langages et de frameworks, il y a donc de nombreux détails que l'équipe de développement doit partager avec les opérations. Cette complexité augmente le risque d’erreurs lors du déploiement.
Comme vous pouvez le constater, malgré sa familiarité, le modèle d’instances de service multiples par hôte présente quelques inconvénients importants. Voyons maintenant d’autres façons de déployer des microservices qui évitent ces problèmes.
Une autre façon de déployer vos microservices est le modèle d’instance de service par hôte . Lorsque vous utilisez ce modèle, vous exécutez chaque instance de service de manière isolée sur son propre hôte. Il existe deux spécialisations différentes de ce modèle : Instance de service par machine virtuelle et instance de service par conteneur.
Lorsque vous utilisez le modèle Instance de service par machine virtuelle , vous regroupez chaque service sous forme d'image de machine virtuelle (VM), telle qu'une AMI Amazon EC2 . Chaque instance de service est une machine virtuelle (par exemple, une instance EC2) lancée à l'aide de cette image de machine virtuelle. Le diagramme suivant montre la structure de ce modèle :
Il s’agit de l’approche principale utilisée par Netflix pour déployer son service de streaming vidéo. Netflix regroupe chacun de ses services sous forme d'AMI EC2 à l'aide d'Aminator . Chaque instance de service en cours d’exécution est une instance EC2.
Il existe de nombreux outils que vous pouvez utiliser pour créer vos propres machines virtuelles. Vous pouvez configurer votre serveur d'intégration continue (CI) (par exemple, Jenkins ) pour appeler Aminator afin de regrouper vos services sous forme d'AMI EC2. Packer.io est une autre option pour la création automatisée d'images de machines virtuelles. Contrairement à Aminator, il prend en charge une variété de technologies de virtualisation, notamment EC2, DigitalOcean, VirtualBox et VMware.
La société Boxfuse dispose d’un moyen convaincant de créer des images de machines virtuelles, qui surmonte les inconvénients des machines virtuelles que je décris ci-dessous. Boxfuse conditionne votre application Java sous la forme d'une image de machine virtuelle minimale. Ces images sont rapides à créer, démarrent rapidement et sont plus sécurisées car elles exposent une surface d’attaque limitée.
La société CloudNative propose Bakery, une offre SaaS permettant de créer des AMI EC2. Vous pouvez configurer votre serveur CI pour invoquer Bakery après la réussite des tests de votre microservice. The Bakery regroupe ensuite votre service sous forme d'AMI. L'utilisation d'une offre SaaS telle que The Bakery signifie que vous n'avez pas à perdre de temps précieux à configurer l'infrastructure de création d'AMI.
Le modèle d’instance de service par machine virtuelle présente un certain nombre d’avantages. L’un des principaux avantages des machines virtuelles est que chaque instance de service s’exécute de manière totalement isolée. Il dispose d’une quantité fixe de CPU et de mémoire et ne peut pas voler de ressources à d’autres services.
Un autre avantage du déploiement de vos microservices en tant que machines virtuelles est que vous pouvez tirer parti d’une infrastructure cloud mature. Les clouds tels qu'AWS offrent des fonctionnalités utiles telles que l'équilibrage de charge et la mise à l'échelle automatique.
Un autre grand avantage du déploiement de votre service en tant que machine virtuelle est qu’il encapsule la technologie d’implémentation de votre service. Une fois qu’un service a été empaqueté sous forme de VM, il devient une boîte noire. L’API de gestion de la VM devient l’API de déploiement du service. Le déploiement devient beaucoup plus simple et plus fiable.
Le modèle d’instance de service par machine virtuelle présente toutefois certains inconvénients. L’un des inconvénients est l’utilisation moins efficace des ressources. Chaque instance de service a la surcharge d’une machine virtuelle entière, y compris le système d’exploitation. De plus, dans un IaaS public typique, les machines virtuelles sont de tailles fixes et il est possible que la machine virtuelle soit sous-utilisée.
De plus, un IaaS public facture généralement les machines virtuelles, qu’elles soient occupées ou inactives. Un IaaS tel qu’AWS offre une mise à l’échelle automatique, mais il est difficile de réagir rapidement aux changements de la demande . Par conséquent, vous devez souvent surprovisionner les machines virtuelles, ce qui augmente le coût du déploiement.
Un autre inconvénient de cette approche est que le déploiement d’une nouvelle version d’un service est généralement lent. Les images de VM sont généralement lentes à créer en raison de leur taille. De plus, les machines virtuelles sont généralement lentes à s’instancier, encore une fois en raison de leur taille. De plus, un système d’exploitation prend généralement un certain temps à démarrer. Notez cependant que cela n’est pas universellement vrai, car des machines virtuelles légères telles que celles construites par Boxfuse existent.
Un autre inconvénient du modèle d’instance de service par machine virtuelle est que vous (ou quelqu’un d’autre dans votre organisation) êtes généralement responsable d’une grande quantité de tâches lourdes et indifférenciées. À moins que vous n'utilisiez un outil tel que Boxfuse qui gère la charge de travail liée à la création et à la gestion des machines virtuelles, cela relève de votre responsabilité. Cette activité nécessaire mais chronophage vous détourne de votre activité principale.
Voyons maintenant une autre façon de déployer des microservices, plus légère mais qui présente néanmoins de nombreux avantages des machines virtuelles.
Lorsque vous utilisez le modèle Instance de service par conteneur , chaque instance de service s'exécute dans son propre conteneur. Les conteneurs sont un mécanisme de virtualisation au niveau du système d'exploitation . Un conteneur est constitué d'un ou de plusieurs processus exécutés dans un sandbox. Du point de vue des processus, ils ont leur propre espace de noms de port et leur propre système de fichiers racine. Vous pouvez limiter la mémoire et les ressources CPU d'un conteneur. Certaines implémentations de conteneurs ont également une limitation du débit d'E/S. Les exemples de technologies de conteneurs incluent Docker et Solaris Zones .
Le diagramme suivant montre la structure de ce modèle :
Pour utiliser ce modèle, vous empaquetez votre service sous forme d’image de conteneur. Une image de conteneur est une image de système de fichiers composée des applications et des bibliothèques requises pour exécuter le service. Certaines images de conteneur sont constituées d'un système de fichiers racine Linux complet. D'autres sont plus légers. Pour déployer un service Java, par exemple, vous créez une image de conteneur contenant l’environnement d’exécution Java, peut-être un serveur Apache Tomcat et votre application Java compilée.
Une fois que vous avez empaqueté votre service sous forme d’image de conteneur, vous lancez ensuite un ou plusieurs conteneurs. Vous exécutez généralement plusieurs conteneurs sur chaque hôte physique ou virtuel. Vous pouvez utiliser un gestionnaire de cluster tel que Kubernetes ou Marathon pour gérer vos conteneurs. Un gestionnaire de cluster traite les hôtes comme un pool de ressources. Il décide où placer chaque conteneur en fonction des ressources requises par le conteneur et des ressources disponibles sur chaque hôte.
Le modèle d’instance de service par conteneur présente à la fois des avantages et des inconvénients. Les avantages des conteneurs sont similaires à ceux des machines virtuelles. Ils isolent vos instances de service les unes des autres. Vous pouvez facilement surveiller les ressources consommées par chaque conteneur. De même, comme les machines virtuelles, les conteneurs encapsulent la technologie utilisée pour implémenter vos services. L'API de gestion des conteneurs sert également d'API pour la gestion de vos services.
Cependant, contrairement aux machines virtuelles, les conteneurs sont une technologie légère. Les images de conteneurs sont généralement très rapides à créer. Par exemple, sur mon ordinateur portable, il ne faut que 5 secondes pour empaqueter une application Spring Boot sous forme de conteneur Docker. Les conteneurs démarrent également très rapidement car il n’y a pas de long mécanisme de démarrage du système d’exploitation. Lorsqu'un conteneur démarre, c'est le service qui s'exécute.
L’utilisation de conteneurs présente certains inconvénients. Bien que l'infrastructure des conteneurs soit en pleine évolution, elle n'est pas aussi mature que celle des machines virtuelles. De plus, les conteneurs ne sont pas aussi sécurisés que les machines virtuelles, car ils partagent le noyau du système d'exploitation hôte.
Un autre inconvénient des conteneurs est que vous êtes responsable de la lourde tâche indifférenciée consistant à administrer les images du conteneur. De plus, à moins que vous n’utilisiez une solution de conteneur hébergée telle que Google Container Engine ou Amazon EC2 Container Service (ECS), vous devez administrer l’infrastructure du conteneur et éventuellement l’infrastructure de machine virtuelle sur laquelle elle s’exécute.
De plus, les conteneurs sont souvent déployés sur une infrastructure avec une tarification par machine virtuelle. Par conséquent, comme décrit précédemment, vous devrez probablement supporter le coût supplémentaire lié au surprovisionnement des machines virtuelles afin de gérer les pics de charge.
Il est intéressant de noter que la distinction entre conteneurs et machines virtuelles risque de s’estomper. Comme mentionné précédemment, les machines virtuelles Boxfuse sont rapides à créer et à démarrer. Le projet Clear Containers vise à créer des machines virtuelles légères. [Éditeur – Comme annoncé en décembre 2017, le développement de Clear Containers se poursuit désormais dans le projet open source Kata Containers .] On observe également un intérêt croissant pour les unikernels . Docker, Inc. a récemment acquis Unikernel Systems.
Il existe également le concept plus récent et de plus en plus populaire du déploiement sans serveur, qui est une approche qui évite le problème du choix entre le déploiement de services dans des conteneurs ou des machines virtuelles. Examinons-le maintenant.
AWS Lambda est un exemple de technologie de déploiement sans serveur. Il prend en charge les services Java, Node.js et Python. Pour déployer un microservice, vous le conditionnez sous forme de fichier ZIP et le téléchargez sur AWS Lambda. Vous fournissez également des métadonnées, qui spécifient entre autres le nom de la fonction invoquée pour gérer une demande (également appelée événement). AWS Lambda exécute automatiquement suffisamment d’instances de votre microservice pour gérer les demandes. Vous êtes simplement facturé pour chaque requête en fonction du temps pris et de la mémoire consommée. Bien sûr, le diable est dans les détails et vous verrez bientôt qu’AWS Lambda a des limites. Mais l’idée que ni vous, en tant que développeur, ni personne dans votre organisation n’avez à vous soucier d’un quelconque aspect des serveurs, des machines virtuelles ou des conteneurs est incroyablement attrayante.
Une fonction Lambda est un service sans état. Il gère généralement les demandes en appelant les services AWS. Par exemple, une fonction Lambda appelée lorsqu'une image est téléchargée dans un bucket S3 peut insérer un élément dans une table d'images DynamoDB et publier un message dans un flux Kinesis pour déclencher le traitement de l'image. Une fonction Lambda peut également appeler des services Web tiers.
Il existe quatre façons d'appeler une fonction Lambda :
cron
Comme vous pouvez le constater, AWS Lambda est un moyen pratique de déployer des microservices. La tarification basée sur la demande signifie que vous ne payez que pour le travail que vos services effectuent réellement. De plus, comme vous n’êtes pas responsable de l’infrastructure informatique, vous pouvez vous concentrer sur le développement de votre application.
Il existe cependant quelques limitations importantes. Il n’est pas destiné à être utilisé pour déployer des services de longue durée, tels qu’un service qui consomme des messages provenant d’un courtier de messages tiers. Les demandes doivent être traitées dans un délai de 300 secondes. Les services doivent être sans état, car en théorie, AWS Lambda peut exécuter une instance distincte pour chaque demande. Ils doivent être rédigés dans l’une des langues prises en charge. Les services doivent également démarrer rapidement, sinon ils risquent d'être interrompus et interrompus.
Le déploiement d’une application de microservices est un défi. Il existe des dizaines, voire des centaines de services écrits dans une variété de langages et de frameworks. Chacune d’entre elles est une mini-application avec ses propres exigences spécifiques en matière de déploiement, de ressources, de mise à l’échelle et de surveillance. Il existe plusieurs modèles de déploiement de microservices, notamment l'instance de service par machine virtuelle et l'instance de service par conteneur. Une autre option intéressante pour le déploiement de microservices est AWS Lambda, une approche sans serveur. Dans la prochaine et dernière partie de cette série, nous verrons comment migrer une application monolithique vers une architecture de microservices.
Rédacteur – Cette série d’articles en sept parties est désormais terminée :
Vous pouvez également télécharger l'ensemble complet des articles, ainsi que des informations sur la mise en œuvre de microservices à l'aide de NGINX Plus, sous forme d'ebook – Microservices : De la conception au déploiement . Et consultez notre série sur l’ architecture de référence des microservices et la page Solutions de microservices .
Le blogueur invité Chris Richardson est le fondateur du CloudFoundry.com original, un PaaS (Platform as a Service) Java précoce pour Amazon EC2. Il conseille désormais les organisations pour améliorer la manière dont elles développent et déploient des applications. Il blogue également régulièrement sur les microservices sur https://microservices.io .
« Cet article de blog peut faire référence à des produits qui ne sont plus disponibles et/ou qui ne sont plus pris en charge. Pour obtenir les informations les plus récentes sur les produits et solutions F5 NGINX disponibles, explorez notre famille de produits NGINX . NGINX fait désormais partie de F5. Tous les liens NGINX.com précédents redirigeront vers un contenu NGINX similaire sur F5.com."