Introduction aux applications infonuagiques natives

12.1 Introduction aux applications infonuagiques natives

Objectifs d'apprentissage

À la fin de cette section, vous serez capable de :

  • Analyser les différences entre les architectures monolithiques et de microservices
  • Comprendre l'architecture des applications infonuagiques natives
  • Apprendre les caractéristiques des applications infonuagiques natives
  • Établir un lien avec les avantages des applications infonuagiques natives
  • Comprendre les bonnes pratiques et les outils utilisés pour développer des applications infonuagiques natives
  • Appliquer les outils utilisés dans le développement d'applications infonuagiques natives
  • Envisager l'avenir des applications infonuagiques natives

L'informatique en nuage permet aux organisations d'offrir des solutions dans le nuage et d'utiliser les services infonuagiques pour rationaliser le développement et le déploiement. Alors que les organisations se tournent vers le nuage pour résoudre les problèmes commerciaux actuels, elles peuvent choisir de créer, déployer et gérer des applications basées sur le nuage ou des applications infonuagiques natives. Comme mentionné précédemment, le développement infonuagique natif repose sur quatre principes clés qui aident à concevoir des applications pour le nuage, comme illustré à la Figure 12.2.

Un diagramme avec des icônes affiche les quatre principes clés du développement infonuagique natif. Il comprend des descriptions de l'architecture de microservices, de la conteneurisation, de la livraison continue et de DevOps.
Figure 12.2 Les quatre principes clés du développement infonuagique natif sont les microservices, la conteneurisation, la livraison continue et DevOps. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

En bref, une application infonuagique native (cloud-native application) utilise une architecture de microservices qui tire pleinement parti des avantages du nuage tels que l'extensibilité et les services à la demande. Les applications basées sur le nuage sont des adaptations d'applications existantes, ou monolithes, migrées vers un fournisseur de services infonuagiques. Elles sont conçues pour tirer parti des plateformes infonuagiques afin de faciliter l'interopérabilité des composants locaux et infonuagiques. Bien que les applications basées sur le nuage tirent parti des plateformes infonuagiques dans une certaine mesure, elles sont généralement déployées comme un seul composant (component) monolithique, ce qui les rend inflexibles car des mises à niveau complètes de la pile sont probablement nécessaires et entraînent des temps d'arrêt.

Contrairement aux applications basées sur le nuage, les applications infonuagiques natives tirent parti des architectures de microservices qui structurent les applications comme des collections coordonnées de services petits et indépendants, autonomes et déployés dans des conteneurs logiciels gérés par un orchestrateur de conteneurs (container).

Les applications basées sur le nuage et les applications infonuagiques natives peuvent fonctionner sur des infrastructures de nuage public, privé ou nuage hybride (hybrid cloud). Un nuage hybride (hybrid cloud) combine des nuages privés, des nuages publics (public cloud) et des environnements bare metal ou virtuels. Ce qui distingue les applications infonuagiques natives des applications basées sur le nuage est le fait qu'elles tirent pleinement parti des caractéristiques inhérentes du nuage, telles que la mutualisation des ressources, les services autogérés à la demande, l'automatisation, l'extensibilité et l'élasticité rapide, pour n'en nommer que quelques-unes.

Architecture monolithique vs. microservices

Une architecture monolithique (monolithic architecture) se compose d'unités logicielles unies par une base de code unique. Dans une architecture monolithique, tous les différents composants de l'application, y compris l'interface utilisateur, la logique métier et la couche d'accès aux données, sont étroitement intégrés et déployés comme une seule unité logicielle. Les applications mainframe ou les sites web de commerce électronique hérités étaient basés sur des architectures monolithiques.

Un microservice est une unité logicielle autonome qui implémente généralement une seule capacité métier. Parce que les microservices sont indépendants et faiblement couplés, les modifications apportées à un microservice individuel peuvent être déployées séparément et ne nécessitent pas la mise à jour de l'application entière. Cela rationalise à son tour le développement d'applications et minimise les temps d'arrêt.

Les architectures monolithiques se composent généralement d'une interface utilisateur, d'une logique métier et de couches d'accès aux données qui sont étroitement couplées et généralement dépendantes les unes des autres pour fonctionner correctement. Une application qui se conforme à une architecture monolithique (également appelée monolithe (monolith)) implémente toutes les capacités métier ensemble, et les données sont partagées entre toutes ces capacités. Les monolithes sont généralement plus faciles à développer et à déployer, mais ils peuvent devenir difficiles à gérer et à faire évoluer avec le temps. La différence fondamentale entre une architecture monolithique traditionnelle et une architecture de microservices est illustrée à la Figure 12.3.

Un diagramme montre la différence entre l'architecture monolithique et l'architecture de microservices.
Figure 12.3 Les architectures monolithiques se composent de composants fortement dépendants et ne s'adaptent pas bien par rapport aux architectures de microservices avec des composants autonomes qui sont plus facilement extensibles. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

À titre d'exemple de monolithe, considérons une application qui fournit un catalogue de produits pouvant être commandés en ligne. Une application conçue à l'aide d'une architecture monolithique est présentée à la Figure 12.4. L'application comprend une interface utilisateur. La couche de logique métier comprend divers composants tels qu'un système d'inventaire pour le catalogue de produits, un service de panier pour commander des produits, un système de paiement pour acheter les produits et un système de reporting qui génère des rapports sur les ventes et les intérêts des clients. Un composant est une unité logicielle qui encapsule un ensemble de fonctions et de données connexes via une interface bien définie et des dépendances spécifiées. Une seule base de données est généralement utilisée dans le cadre de la couche d'accès aux données pour l'ensemble de l'application.

Un diagramme affiche le flux suivant : Interface utilisateur <-> Logique métier : Système d'inventaire, Service de panier, Système de paiement, Service d'expédition, Système de reporting <-> Couche d'accès aux données.
Figure 12.4 Une application est conçue à l'aide d'une architecture monolithique. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Ce sont des composants logiciels fortement dépendants qui utilisent des bibliothèques partagées. Toute modification apportée à un composant nécessite de comprendre ce dont les autres composants ont besoin de ces bibliothèques partagées. De telles modifications peuvent entraîner la rupture des dépendances entre les composants au fil du temps. Les différents composants sont également dépendants du langage de programmation et du cadriciel. Les nouveaux composants doivent être implémentés dans le même langage de programmation ou utiliser le même cadriciel que les composants existants.

D'autres défis avec les monolithes sont la gestion de la croissance et l'assurance de l'extensibilité. Au fil du temps, à mesure que de nouvelles fonctionnalités sont ajoutées pour répondre aux besoins des utilisateurs finaux, le monolithe grandit et devient plus difficile à gérer. Le déploiement du monolithe devient alors difficile car il demande plus d'efforts pour le stabiliser et le faire fonctionner correctement. L'extensibilité d'un monolithe devient également plus difficile avec le temps. Par exemple, pendant une saison des fêtes avec une augmentation rapide des ventes, le composant du système de paiement peut nécessiter des capacités supplémentaires pour prendre en charge une augmentation soudaine des transactions. Pour ajouter les capacités nécessaires uniquement au composant du système de paiement, l'application monolithique entière doit être dupliquée. Le problème est que le déploiement d'une deuxième instance de l'application entière et sa mise à disposition des utilisateurs finaux peuvent prendre beaucoup de temps. Avant que cela ne soit fait, la saison des fêtes peut déjà être terminée et la version de l'application disponible n'a pu prendre en charge qu'un nombre limité de transactions. La deuxième instance de l'application est inutile à ce stade malgré l'effort qu'il a fallu pour la déployer. Une version étendue de l'application monolithique est présentée à la Figure 12.5.

Un diagramme montre le flux suivant : Équilibreur de charge <-> Interface utilisateur <-> Logique métier : Système d'inventaire, Service de panier, Système de paiement, Service d'expédition, Système de reporting <-> Couche d'accès aux données.
Figure 12.5 Une application conçue pour utiliser une architecture monolithique est mise à l'échelle pour gérer une augmentation de l'utilisation. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

En revanche, les architectures de microservices se composent de petits services faiblement couplés qui s'exécutent indépendamment et se connectent via un réseau. Les applications qui se conforment à une architecture de microservices comprennent une collection de composants modulaires qui s'exécutent indépendamment et fournissent une API bien définie pour faciliter la communication avec d'autres services. Au lieu d'utiliser une base de données partagée pour toutes les capacités métier, chaque microservice qui implémente une seule capacité métier contient son propre magasin de données, dont le type dépend du type de données nécessaires.

Si l'exemple d'application monolithique discuté précédemment est implémenté à l'aide d'une architecture de microservices, chacun de ses composants (c'est-à-dire le système d'inventaire, le service de panier, le système de paiement et le système de reporting) devient un microservice individuel. Ces microservices s'exécutent chacun dans des conteneurs séparés et communiquent via des API. Une application conçue à l'aide d'une architecture de microservices est présentée à la Figure 12.6.

Un diagramme d'une application conçue à l'aide d'une architecture de microservices. Il comprend l'interface utilisateur, la passerelle API, le système d'inventaire, le service de panier, le système de paiement, le service d'expédition, le système de reporting, le magasin de données.
Figure 12.6 Une application est conçue à l'aide d'une architecture de microservices. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Les composants d'une architecture de microservices sont indépendants les uns des autres. Les microservices individuels peuvent être modifiés sans affecter les autres microservices. Si un microservice tombe en panne, le reste de l'application n'est pas affecté.

Les microservices sont également indépendants du langage de programmation et du cadriciel. Les nouveaux microservices peuvent utiliser différents langages de programmation ou cadriciels. Par exemple, une équipe responsable du système d'inventaire peut utiliser un langage de programmation ou un cadriciel différent de ceux utilisés pour implémenter le système de paiement. Il est également plus facile de développer ou de faire évoluer une architecture basée sur les microservices.

Des fonctionnalités supplémentaires peuvent être ajoutées aux microservices individuels indépendamment des autres microservices. Cela permet aux équipes d'itérer plus rapidement pour apporter de la valeur aux utilisateurs finaux. Les microservices peuvent également s'adapter indépendamment, comme le montre la Figure 12.7. Pendant une saison des fêtes avec une augmentation rapide des ventes, des capacités supplémentaires peuvent être ajoutées rapidement au microservice du système de paiement sans affecter les autres microservices. Ces capacités supplémentaires peuvent être réduites si nécessaire lorsque les ventes diminuent après la fin de la saison des fêtes.

Un diagramme montrant une application conçue pour utiliser une architecture de microservices est mise à l'échelle pour gérer une augmentation de l'utilisation. Il comprend l'interface utilisateur, la passerelle API, le système d'inventaire, le service de panier, l'équilibreur de charge, le service d'expédition, le système de paiement, le magasin de données.
Figure 12.7 Une application conçue pour utiliser une architecture de microservices est mise à l'échelle pour gérer une augmentation de l'utilisation. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

En résumé, un monolithe (monolith) regroupe toutes les capacités de manière fortement dépendante et exige qu'elles utilisent le même langage de programmation et le même cadriciel. Les monolithes sont plus difficiles à développer et à faire évoluer car ils nécessitent que l'application entière soit déployée comme une deuxième instance. En revanche, une application centrée sur les microservices place les capacités individuelles dans des microservices distincts qui sont déployés via des conteneurs et communiquent via des API. Les capacités individuelles sont indépendantes du langage de programmation et du cadriciel. Elles sont plus faciles à développer et à faire évoluer indépendamment.

Composants vs. Services

La construction d'applications à l'aide de composants est une approche souhaitable. Dans le cas des monolithes, cela est généralement réalisé en utilisant des bibliothèques comme composants et en les compilant ou en les liant dans un seul programme ou processus qui y accède à l'aide d'appels de fonction « in-process ». En revanche, les « services » dans une application centrée sur les microservices sont des composants « out-of-process » qui communiquent entre eux à l'aide d'une requête de service web (web service) ou d'un appel de procédure distante (remote procedure call). La Figure 12.8 illustre la manière dont les composants sont accédés dans une architecture monolithique (monolithic architecture) par rapport à une architecture de microservices.

Deux diagrammes sont présentés. L'un montre les composants dans une architecture monolithique et l'autre montre les composants dans une architecture de microservices.
Figure 12.8 Les composants d'une architecture monolithique sont accédés différemment par rapport aux composants d'une architecture de microservices. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Comme indiqué précédemment, les services utilisés par les applications centrées sur les microservices sont déployables indépendamment afin que les modifications apportées à un service n'affectent pas les autres services. Cela suppose que les services sont bien encapsulés et conçus avec des limites de service minimalement cohésives. L'utilisation d'appels de services web et de RPC (remote procedure call) facilite cet objectif. Un service web (web service) est une unité logicielle disponible en tant que ressource sur Internet. Un appel de procédure distante (RPC) (remote procedure call (RPC)) est un protocole de requête-réponse utilisé par un programme pour accéder aux services d'autres programmes sur un réseau. Cependant, cette approche présente des inconvénients. Les RPC sont plus coûteux que les appels in-process, et les API distantes doivent donc être à grain plus grossier (c'est-à-dire que les API à grain grossier exposent plus de méthodes dans leurs interfaces par opposition aux API à grain fin).

Un défi lié à l'utilisation des services est la modification de l'attribution des responsabilités entre les composants. Cela peut être difficile, surtout si le service se compose de plusieurs processus déployés ensemble, tels qu'un processus d'application et un processus de magasin de données qui ne sont utilisés que par ce service. Un autre défi est qu'il peut être difficile de définir correctement les limites de service des composants. En d'autres termes, la difficulté est d'intégrer le logiciel dans un composant (component) qui peut être utilisé comme un service. Les services utilisent des API, donc toute modification de l'API doit être coordonnée avec les autres composants. Les modifications d'API doivent être rétrocompatibles afin que les composants qui n'utilisent pas la dernière version mise à jour de l'API puissent toujours fonctionner. Enfin, les tests sont également plus compliqués.

SOA vs. Microservices

L'architecture de microservices n'est pas le premier style architectural à utiliser des composants autonomes et à implémenter des capacités métier individuelles. Le style architectural orienté services, un style de conception logicielle bien établi, commande la même approche. Une architecture orientée services (SOA) (service-oriented architecture (SOA)) exige que les applications conformes soient structurées comme des services discrets, réutilisables et interopérables qui communiquent via un bus de services d'entreprise (enterprise service bus) (ESB) via des protocoles de message tels que SOAP,1 ActiveMQ,2 ou Apache Thrift.3

Un bus de services d'entreprise (ESB) (enterprise service bus (ESB)) implémente un système de communication de type bus entre les fournisseurs de services et les consommateurs de services qui interagissent. Les services, l'ESB et les protocoles de messagerie constituent collectivement une application SOA. Dans la Figure 12.9, l'architecture présentée à gauche illustre une SOA typique par rapport à l'architecture de microservices typique illustrée à droite. Comme c'est le cas pour les services dans une architecture de microservices, les services SOA peuvent être mis à jour indépendamment. Cependant, l'ESB représente un point de défaillance unique pour l'ensemble du système.

Deux diagrammes sont présentés. L'un montre l'architecture SOA. L'autre montre l'architecture de microservices.
Figure 12.9 Dans une SOA, les services communiquent via un ESB, par rapport à une architecture de microservices où les services communiquent généralement via des protocoles REST. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Contrairement aux services dans une SOA, les microservices communiquent généralement entre eux de manière sans état en utilisant des protocoles REST légers implémentés via HTTP. De plus, les microservices peuvent être implémentés en utilisant différents langages de programmation et cadriciels car ils peuvent communiquer via des API agnostiques au langage de programmation. Les avancées dans les technologies de conteneurisation (containerization) permettent de déployer, de mettre à niveau, de faire évoluer et de redémarrer les microservices indépendamment, en contrôlant mieux leurs cycles de vie. En cas de défaillance d'un microservice, le reste de l'application n'est pas affecté. Ainsi, les applications utilisant des microservices peuvent être plus tolérantes aux pannes car elles ne dépendent pas d'un seul ESB comme c'est le cas pour les applications SOA.

Concepts en pratique

Architecture de microservices et applications infonuagiques natives

Comme discuté dans le Chapitre 9 Génie logiciel et le Chapitre 10 Gestion des architectures d'entreprise et de solution, les styles architecturaux, les patrons d'architecture et les patrons de conception sont généralement utilisés pour renforcer les attributs de qualité des solutions logicielles. Le style architectural de microservices est utilisé pour décomposer les applications monolithiques en services plus petits basés sur les capacités métier. Il est partiellement basé sur le style SOA (service-oriented architecture) mais ne repose pas sur un bus de services d'entreprise pour permettre la communication entre les services.

Un exemple de patron de conception de microservices est le patron de conception de microservice Backend for Frontend (BFF).4 Ce patron de conception implique la création de services dorsaux dédiés, adaptés aux besoins spécifiques des clients frontaux. L'objectif de ce patron est d'assurer une interaction efficace et rationalisée entre les composants frontaux et dorsaux. À titre d'exemple d'utilisation de ce patron, considérons une plateforme de commerce électronique comme l'exemple de catalogue de produits en ligne décrit ci-dessus. La plateforme de commerce électronique peut servir à la fois des applications clientes web et mobiles. L'implémentation du patron BFF signifie la création de composants dorsaux dédiés qui servent chaque application cliente. Étant donné que les interactions utilisateur entre ces deux applications clientes sont différentes, les API entre ces clients et les services dorsaux dédiés peuvent être optimisées pour mieux s'adapter à ces types de clients.

En plus d'optimiser la passerelle d'API (API gateway), l'architecture de microservices utilisée alloue également efficacement les ressources à chaque service qu'une application infonuagique native (cloud-native application) utilise, rendant l'application flexible et adaptable à une architecture infonuagique. Les conteneurs sont un patron d'architecture utilisé pour déployer des microservices sur toute plateforme qui exploite un moteur d'exécution de conteneurs (container). La combinaison des microservices et des conteneurs avec un autre patron d'architecture appelé orchestration de conteneurs permet de faire évoluer, de gérer et d'automatiser le déploiement d'applications conteneurisées basées sur des microservices. C'est un exemple de la façon dont une combinaison de styles architecturaux et de patrons associés peut améliorer considérablement la qualité des applications d'entreprise. Cependant, comme indiqué précédemment, il existe des défis associés à l'utilisation des microservices et d'autres styles architecturaux qui doivent également être pris en compte lors de la conception d'une solution d'entreprise.

Défis des microservices

Les microservices améliorent la capacité d'une équipe de développement à tirer parti du développement distribué. Le temps de développement peut être réduit car les microservices peuvent être développés simultanément. Cependant, il existe des défis connus liés au passage à une architecture de microservices. En plus de la complexité et de l'efficacité, qui sont deux défis majeurs d'une architecture basée sur les microservices, les huit catégories de défis suivantes ont été identifiées.

Construction de microservices

Certains microservices peuvent avoir besoin d'accéder à d'autres microservices pour fournir certaines fonctionnalités d'application. Cela crée des dépendances entre les microservices. Du temps doit être consacré à l'identification de ces dépendances. L'ajout de dépendances entre les microservices peut entraîner l'achèvement d'une construction qui déclenche plusieurs constructions ultérieures.

Un autre type de dépendance est le partage de données où un microservice peut avoir besoin d'accéder à des données gérées par un autre microservice. Certaines préoccupations concernant le partage de données incluent l'extensibilité. À mesure que des microservices sont ajoutés, pour assurer la cohérence et la redondance des données, un microservice qui nécessite une modification de schéma dans une base de données doit être partagé avec d'autres microservices. Ces préoccupations doivent également être prises en considération lors de la gestion des dépendances.

Connectivité des microservices

Les applications basées sur les microservices se composent de plusieurs microservices qui doivent communiquer entre eux. Les microservices s'exécutent dans des environnements conteneurisés où le nombre d'instances de microservices et leurs emplacements changent dynamiquement. La découverte de services peut être utilisée pour localiser chaque instance de microservice. Sans découverte de services, une application basée sur les microservices peut être difficile à maintenir.

Gestion des versions des microservices

Un microservice peut être mis à jour pour satisfaire de nouvelles exigences ou résoudre certains problèmes de conception. D'autres microservices qui dépendent d'une version plus ancienne du microservice mis à jour pourraient échouer. Les dépendances entre les microservices lors de la mise à jour d'un microservice peuvent entraîner une rupture de la rétrocompatibilité. Une façon d'y remédier est d'intégrer une logique conditionnelle qui ajoute le numéro de version ou suit la gestion des versions, ce qui peut devenir difficile à gérer. Alternativement, plusieurs versions actives peuvent être fournies pour différents clients, mais elles peuvent également devenir difficiles à gérer.

Test des microservices

Le test des microservices peut devenir plus difficile, en particulier avec les tests d'intégration et les tests de bout en bout. Une seule transaction effectuée dans une application peut s'étendre sur plusieurs microservices. Une défaillance dans un microservice peut entraîner des défaillances dans d'autres microservices. De plus, des défaillances peuvent survenir dans le microservice lui-même, dans son conteneur (container), ou dans le réseau interconnectant les microservices, ce qui rend la conception des tests d'intégration plus difficile. Pour ces raisons, un plan de tests d'intégration doit prendre en compte les interdépendances entre les microservices.

Journalisation des microservices

Les microservices sont des systèmes distribués et, par conséquent, la journalisation traditionnelle est inefficace pour déterminer quels microservices ont échoué. À mesure que de plus en plus de microservices sont ajoutés, la complexité de la journalisation des activités des microservices augmente de manière exponentielle et devient plus difficile à gérer. En particulier, l'agrégation de journaux est nécessaire pour suivre les erreurs qui pourraient s'étendre sur plusieurs microservices, comme le montre la Figure 12.10.

Un diagramme montre une architecture de microservices configurée pour utiliser l'agrégation de journaux et le traçage distribué.
Figure 12.10 Une architecture de microservices est configurée pour utiliser l'agrégation de journaux et le traçage distribué, qui sont généralement utilisés dans un système distribué basé sur les microservices. L'agrégation de journaux fait référence au stockage de divers niveaux d'avertissements et d'erreurs pour un ensemble combiné de microservices. Le traçage distribué aide à relier les informations journalisées par plusieurs services afin qu'elles puissent être suivies comme un seul fil d'exécution. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)
Débogage des microservices

Le débogage à distance via un environnement de développement intégré (integrated development environment) local ne fonctionnera pas sur plusieurs microservices. Un IDE fournit aux développeurs un accès à des ressources (par exemple, éditeur de code source, outils d'automatisation de la construction, débogueurs) pour concevoir, développer, déboguer et tester des programmes. Le débogage d'une application basée sur les microservices est difficile car les erreurs ne sont pas propagées de manière utile. De plus, les formats de journalisation peuvent également différer entre les microservices. Le débogage nécessite de tracer divers messages d'erreur et codes d'état à travers le réseau, ce qui est inefficace et rend difficile l'acquisition des informations nécessaires pour déboguer les erreurs. Actuellement, il n'existe pas de solution facile pour déboguer efficacement de telles applications ; cependant, des outils (par exemple, Helios,5 Rookout,6 Lightrun,7) existent aujourd'hui pour résoudre ce problème.

Déploiement de microservices

Le déploiement d'une application monolithique peut sembler moins complexe car il est limité à une seule unité de déploiement. En revanche, une application basée sur les microservices est plus complexe à déployer car les interconnexions entre les microservices sont plus visibles. De plus, il y a plus d'unités déployables et les dépendances entre elles nécessitent des configurations plus complexes. Cette augmentation du nombre d'unités déployables impose un ordre dans lequel les microservices doivent être déployés. Elle nécessite également un investissement plus important dans l'automatisation pour les gérer pratiquement et aider à garantir que l'ensemble de l'application basée sur les microservices est résiliente et limite les risques de basculement.

Surveillance des microservices

En raison des interdépendances entre les microservices, tout temps d'arrêt d'un microservice résultant de mises à jour ou de défaillances peut entraîner des défaillances en cascade pour d'autres microservices. La surveillance d'une application basée sur les microservices est difficile car elle nécessite une connaissance des performances et de la disponibilité des appels d'API pour tous les microservices de l'application. En plus de surveiller les conteneurs hébergeant les microservices, il est crucial d'avoir une vue centralisée de l'ensemble de l'application basée sur les microservices. Cette vue holistique aide à identifier tout problème potentiel et assure une identification efficace des problèmes.

Architecture d'application infonuagique native

Une application infonuagique native (cloud-native application) tire parti des cadriciels d'informatique en nuage (cloud computing) pour implémenter une collection de microservices faiblement couplés dans le nuage. L'architecture d'application infonuagique native permet d'allouer efficacement les ressources aux microservices individuels que l'application infonuagique native utilise. Un exemple d'architecture d'application infonuagique native est illustré à la Figure 12.11.

Un diagramme montre une architecture d'application infonuagique native. Il comprend l'interface utilisateur, la passerelle API, le système d'inventaire, le service de panier, le système de paiement, le service d'expédition, le système de reporting, le magasin de données, l'application infonuagique native et l'environnement d'exécution, l'ordonnancement et l'orchestration, et l'infrastructure infonuagique.
Figure 12.11 Une architecture d'application infonuagique native comprend l'application infonuagique native et la plateforme d'informatique en nuage qu'elle exploite. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

L'infrastructure infonuagique, présentée à la Figure 12.11, est fournie par une plateforme d'informatique en nuage. La plateforme d'informatique en nuage fournit également un service d'ordonnancement et d'orchestration pour gérer les conteneurs dans lesquels les microservices de l'application infonuagique native sont déployés. Les microservices utilisés dans une application infonuagique native s'exécutent généralement à différents emplacements au sein d'une plateforme infonuagique, ce qui permet à l'application de s'étendre horizontalement. Par conséquent, les applications infonuagiques natives doivent être conçues en tenant compte de la redondance. Cela permet à l'application de résister aux pannes d'équipement.

Enfin, l'application infonuagique native et l'environnement d'exécution sont l'endroit où l'application infonuagique native fonctionne. Une architecture infonuagique native tire parti d'une architecture de microservices banalisée. Dans cette architecture, les capacités métier sont implémentées comme des microservices gérés par le nuage, ce qui rend l'application infonuagique native plus fiable et extensible.

Les applications infonuagiques natives doivent être conçues pour inclure une journalisation standardisée et prendre en charge des événements qui peuvent être associés à un catalogue de journalisation standard. L'extensibilité et la gestion de plusieurs microservices nécessitent des services de base tels que l'équilibrage de charge, la découverte de services et le routage, qui sont tous gérés par la couche d'ordonnancement et d'orchestration. En résumé, la conception d'applications infonuagiques natives pour tirer parti des services d'un cadriciel d'informatique en nuage permet d'ajouter et de prendre en charge de nouvelles capacités métier plus rapidement.

Exemple d'architecture web native

La Figure 12.12 illustre un exemple d'architecture web native, une application infonuagique native (cloud-native application) basée sur le web. Cette application infonuagique native se compose de plusieurs microservices qui sont déployés et gérés sur le nuage. Chaque microservice est autonome et indépendant du langage de programmation et du cadriciel. Les microservices sont conteneurisés et gérés par un orchestrateur de conteneurs (container). Chaque microservice contient son propre magasin de données qui correspond le mieux à ses besoins en données. Certains de ces magasins de données sont des bases de données relationnelles, tandis que d'autres sont des bases de données NoSQL.

Un diagramme montre une application web native.
Figure 12.12 Une application web native tire parti des fonctionnalités des plateformes infonuagiques modernes.8 (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

L'un des microservices stocke son état dans un cache Redis distribué. Une passerelle d'API (API gateway) est utilisée pour acheminer le trafic entre les applications clientes et les microservices. Plus important encore, cette application infonuagique native tire pleinement parti des fonctionnalités d'extensibilité et de résilience (resiliency) des plateformes infonuagiques modernes.

Pleins feux sur l'industrie

L'application infonuagique native dans l'industrie

Les applications infonuagiques natives sont largement utilisées dans l'industrie aujourd'hui. En particulier, Netflix, Uber et WeChat exposent des systèmes infonuagiques natifs qui se composent de nombreux services indépendants. Pouvez-vous élaborer sur les caractéristiques spécifiques de ces systèmes et expliquer pourquoi l'approche infonuagique native est plus adaptée aux types de solutions fournies par ces entreprises ? À titre d'exemple, Netflix a publié l'article « Completing the Netflix Cloud Migration »9 discutant des avantages de cette migration. Une étude de cas10 a également été publiée discutant de l'adoption par Netflix des environnements de calcul infonuagiques natifs pour leurs services.

Caractéristiques des applications infonuagiques natives

Comme mentionné précédemment, les applications infonuagiques natives, contrairement aux applications basées sur le nuage, tirent parti des caractéristiques inhérentes du nuage telles que la mutualisation des ressources, les services autogérés à la demande, l'automatisation, l'extensibilité et l'élasticité rapide. Voici une liste des principales capacités des applications infonuagiques natives qui rendent cela possible.

Applications basées sur les microservices

Comme indiqué précédemment, les microservices sont basés sur un patron d'architecture logicielle où chaque fonctionnalité d'une application monolithique correspondante est placée dans son propre microservice car elle implémente une capacité métier distincte. Ces microservices sont déployés et exécutés dans des conteneurs qui communiquent via des API d'application, des flux d'événements et des courtiers de messages. Les outils d'ordonnancement et d'orchestration gèrent ces conteneurs car ils aident à coordonner et à planifier les conteneurs utilisés pour implémenter les services d'application s'exécutant sur des ressources informatiques. Les équipes de développement de microservices peuvent rapidement ajouter de nouvelles capacités chaque fois que les besoins de l'entreprise changent.

Les microservices peuvent également être mis à l'échelle, lorsqu'une seule capacité est soumise à une charge trop importante, indépendamment des autres microservices. Cela réduit le temps et les coûts associés à la nécessité de mettre à l'échelle une autre instance de l'application entière. Généralement, la mise à l'échelle est réalisée en conteneurisant les microservices et en gérant les conteneurs à l'aide d'un cadriciel de gestion de conteneurs (par exemple, K8s) fourni par une plateforme infonuagique. Une autre alternative consiste à tirer parti de la fonction en tant que service (Function as a Service) (par exemple, AWS Lambdas ou fonctions Google/Microsoft) dans le cadre des microservices et à s'appuyer sur la ou les plateformes infonuagiques pour gérer l'extensibilité.

Les microservices sont également distribués et faiblement couplés, ce qui les rend plus faciles à itérer. Parce que les microservices sont indépendants et communiquent uniquement via des API, les équipes peuvent soumettre du code pour les microservices via un pipeline DevOps. Une fois testés, les microservices peuvent être déployés automatiquement, ce qui facilite l'itération des équipes aussi rapidement que nécessaire pour apporter de la valeur aux utilisateurs finaux. De plus, ces itérations sont minimales, et s'il y a une instance où un microservice échoue, le reste de l'application reste fonctionnel, ce qui rend les mises à jour moins risquées.

Langages et cadriciels les mieux adaptés aux microservices

Le langage de programmation et le cadriciel sont choisis en fonction de ce qui convient le mieux à la fonctionnalité fournie par le microservice. Les applications infonuagiques natives sont polyglottes, ce qui signifie que les microservices sont indépendants du langage et du cadriciel, ce qui permet de choisir différentes piles technologiques et cadriciels pour différents microservices d'une seule application infonuagique native (cloud-native application).

Cadriciel basé sur les conteneurs

Un conteneur est une unité logicielle standardisée qui isole logiquement une application, lui permettant de s'exécuter indépendamment des ressources physiques. L'empaquetage d'une unité logicielle standardisée qui isole une application, lui permettant de s'exécuter indépendamment des ressources physiques, est la conteneurisation (containerization). Les conteneurs fournissent des environnements cohérents, complets et portables pour l'exécution d'applications partout, y compris tous les fichiers système et les dépendances nécessaires à l'exécution des applications. La conteneurisation facilite la création d'applications infonuagiques natives et maximise les avantages des conteneurs. Les conteneurs empêchent les microservices d'interférer les uns avec les autres. Ils empêchent les applications de consommer toutes les ressources partagées de l'hôte. Ils permettent également plusieurs instances du même microservice.

Les conteneurs améliorent l'efficacité et l'efficience de DevOps grâce à des constructions, des tests et des déploiements rationalisés. Ils fournissent également des environnements de production cohérents, isolés des autres applications et processus. Parce que les conteneurs peuvent s'exécuter de manière cohérente partout, ils facilitent les environnements de calcul hybrides et multinuages. Les conteneurs sont légers car ils sont isolés de la couche du système d'exploitation d'un système informatique. Cela les rend efficaces et peu gourmands en ressources. Les conteneurs sont portables car ils incluent toutes les dépendances et configurations requises, ainsi, eux et le code qu'ils contiennent, peuvent être déplacés entre différents environnements.

La Figure 12.13 montre comment les conteneurs en production peuvent s'exécuter sur n'importe quelle ressource informatique dotée d'une plateforme de conteneurisation. Les conteneurs sont extensibles en raison de leur petite taille, ce qui facilite le démarrage, la mise à l'échelle ou l'arrêt rapide des conteneurs en fonction de l'utilisation. Les conteneurs peuvent être rentables car ils nécessitent moins de ressources et sont plus faciles à mettre à l'échelle.

Un diagramme montre le flux suivant : Développeur d'applications infonuagiques natives (client) -> Application -> Définition d'image -> Créer des images -> Plateforme de conteneurs [flèches vers tous les éléments suivants] Nuage, Machines virtuelles, Serveurs sur site, Dépôt d'images.
Figure 12.13 Une image est construite pour déployer une application dans des conteneurs qui s'exécutent sur différentes ressources informatiques. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Les conteneurs sont des instances d'une image de conteneur (container image). Une image de conteneur (container image) représente un état binaire qui est construit en « superposant » une application et ses dépendances sur la « couche » requise de binaires et de bibliothèques du système d'exploitation, ce qui établit une relation parent-enfant entre les couches d'image. La Figure 12.14 montre le processus de construction d'une image. Par exemple, à la racine de l'arbre parent-enfant se trouve une couche qui fournit un système de fichiers formaté. Au-dessus de cette couche se trouve une image de base qui pourrait contenir Ubuntu, Debian, CentOS ou un autre système d'exploitation. Cette image de base peut alors être un parent d'une autre image, telle qu'une image qui ajoute Python. Enfin, une autre image au-dessus de l'image Python peut contenir l'application qui a été implémentée en Python, telle qu'une application web Django. Django est un cadriciel d'application web à code source ouvert, qui est un cadriciel logiciel qui facilite le développement, la maintenance et l'extensibilité des applications web. En effet, ces couches d'images sont organisées en une hiérarchie d'images où chaque couche crée un instantané.

Un diagramme montre le flux suivant : Développeur d'applications infonuagiques natives (client) -> Application -> Définition d'image -> Définition d'image (Conteneur inscriptible, ajouter l'image Django, ajouter l'image Python, Ubuntu (image de base), fs (noyau) -> Créer des images -> Plateforme de conteneurs [flèches vers tous les éléments suivants] Nuage, Machines virtuelles, Serveurs sur site, Dépôt d'images.
Figure 12.14 Les images sont construites comme des couches d'une application, de ses dépendances et d'autres couches requises. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Un avantage de cette structure hiérarchique est qu'elle permet de partager des images à différents niveaux de la hiérarchie. Si vous souhaitez exécuter l'application web Django, vous extrayez l'intégralité de la hiérarchie de l'image construite. Cependant, d'autres couches de la hiérarchie peuvent être partagées avec d'autres éléments (par exemple, la couche Python), réduisant ainsi le besoin de déplacer des piles d'applications entières. L'image de conteneur construite est un artefact indépendant et autonome qui peut être déployé dans n'importe quel environnement doté d'un environnement d'exécution de conteneur (par exemple, Docker) installé. L'Open Container Initiative est une communauté qui tente de gouverner et d'aborder l'uniformité et la normalisation des environnements d'exécution et des images de conteneurs. Il s'agit d'une initiative importante pour que les conteneurs puissent « construire une fois et exécuter partout ».

Cadriciel basé sur les API

Les microservices qui dépendent les uns des autres communiquent à l'aide d'API bien définies. Ces API aident à configurer les couches d'infrastructure pour faciliter le partage des ressources entre elles. Les API connectent les microservices et les conteneurs tout en simplifiant la maintenance et la sécurité. Elles permettent aux microservices de communiquer entre des services autrement faiblement couplés sans partager les mêmes piles technologiques, bibliothèques ou cadriciels. Les microservices infonuagiques natifs utilisent des API légères basées sur des protocoles tels que le transfert d'état représentationnel (representational state transfer) pour exposer leurs fonctionnalités. Le style architectural pour fournir des standards entre les ressources afin qu'elles puissent communiquer entre elles sur le Web est appelé transfert d'état représentationnel (REST) (representational state transfer (REST)).

Cadriciel orchestré dynamiquement

Comme déjà mentionné, la couche d'ordonnancement et d'orchestration d'un cadriciel d'informatique en nuage (cloud computing) gère les conteneurs dans lesquels les microservices sont déployés. À mesure que les applications s'étendent sur plusieurs conteneurs déployés sur plusieurs serveurs, leur exploitation devient plus compliquée. Les outils d'orchestration de conteneurs (par exemple, Kubernetes) peuvent aider à coordonner et à planifier de nombreux conteneurs (container). Ils peuvent également aider à faire évoluer les instances de conteneurs pour fournir plus de puissance de calcul. Par exemple, l'outil d'orchestration, représenté comme « Maître » dans la Figure 12.15, déploie les microservices dans des conteneurs (instances uniques, initialement) d'une application sur une ressource informatique.

Un diagramme montre une orchestration de conteneurs. Il comprend des microservices dans des conteneurs, le déploiement, l'extensibilité et les conteneurs réseau.
Figure 12.15 L'orchestration de conteneurs est utilisée pour gérer les microservices dans une application infonuagique native. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

À mesure que la consommation des ressources informatiques par les microservices augmente, des ressources supplémentaires sont ajoutées, et l'outil d'orchestration commencera à ordonnancer et à mettre à l'échelle les microservices. Une plateforme d'orchestration (orchestration platform) aide à planifier les microservices et les conteneurs et optimise l'utilisation de la ressource informatique. En revanche, une application monolithe (monolith) n'est pas conçue pour tirer parti d'une plateforme d'orchestration et nécessite l'utilisation d'équilibreurs de charge. D'autres services, tels que la découverte de services, doivent également être effectués manuellement. Par exemple, si les microservices doivent communiquer entre eux, ils ne peuvent pas trouver les adresses IP de leurs conteneurs respectifs et vérifier s'ils sont en cours d'exécution. Cela est géré automatiquement par la plateforme d'orchestration (c'est-à-dire Microsoft AKS, Amazon AWS EKS, Google GKE). Une plateforme d'orchestration exécute généralement des charges de travail en plaçant les conteneurs correspondants dans des pods qui s'exécutent sur des nœuds (c'est-à-dire une machine virtuelle ou physique). Plusieurs nœuds sont généralement regroupés en grappes pour assurer l'extensibilité. Les pods sont les plus petites unités de calcul déployables ; ils regroupent plusieurs conteneurs, fournissent des ressources de stockage et de réseau partagées, et spécifient comment exécuter les conteneurs. La plateforme d'orchestration fournit un support lorsqu'un pod qui contient un microservice conteneur en cours d'exécution tombe en panne. Dans ce cas, un autre pod est rapidement mis en place et automatiquement intégré au champ d'application de ce service. La Figure 12.16 montre comment les conteneurs de microservices sont mis à l'échelle et gérés en cas de défaillance.

Un diagramme montre une orchestration de conteneurs. Il comprend des microservices dans des conteneurs, le déploiement, l'extensibilité et les conteneurs réseau.
Figure 12.16 L'orchestration de conteneurs est utilisée pour la mise à l'échelle automatique et la vérification de l'état de santé des microservices dans une application infonuagique native mise à l'échelle. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

DevOps Agile et automatisation via CI/CD

DevOps est une méthodologie qui combine le développement logiciel agile et les opérations informatiques pour livrer des logiciels plus rapidement et de meilleure qualité. Parce que DevOps et le cloud natif se concentrent sur différents aspects du processus de développement d'applications, ils se complètent mutuellement en facilitant l'agilité. DevOps se concentre sur les principes et les pratiques utilisés dans le développement et les opérations. Un objectif de DevOps est de s'assurer que tous les membres de l'équipe sont polyvalents, afin qu'ils aient une mentalité unique pour améliorer l'expérience client, répondre plus rapidement aux besoins de l'entreprise et s'assurer que l'innovation est équilibrée avec les besoins de sécurité et opérationnels. Le cloud natif, d'autre part, se concentre sur l'environnement d'application et sur la façon de mettre à l'échelle et de livrer des logiciels plus efficacement.

L'utilisation d'un pipeline DevOps pour migrer une application vers une architecture de microservices permet d'atteindre les objectifs d'automatisation, de discipline et de répétabilité tout en réduisant certains des défis déjà identifiés. À mesure qu'une application infonuagique native (cloud-native application) progresse dans le pipeline DevOps, elle évolue également vers la livraison continue (continuous delivery).

La Figure 12.17 montre l'intégration et le déploiement continus (CI/CD) (continuous integration and continuous deployment (CI/CD)), qui est un ensemble de principes de fonctionnement DevOps qui permettent aux équipes de développement de se concentrer sur des intégrations rapides et fréquentes de nouveau code dans l'application en développement ainsi que sur une livraison ou un déploiement rapide et fréquent de nouvelles itérations de l'application. Cela permet aux équipes de livrer des modifications de code plus fréquemment et de manière plus fiable. Une équipe DevOps établit un pipeline CI/CD, qui est une série d'étapes nécessaires à l'intégration et à la livraison ou au déploiement qui comprend le processus de construction par lequel l'application est compilée, construite, empaquetée et testée. La partie intégration continue (continuous integration) automatise le processus de compilation, de construction, d'empaquetage et de test de l'application, lui permettant de s'exécuter indépendamment des ressources physiques, ce qui permet un processus d'intégration plus cohérent. Cela améliore la communication de l'équipe et conduit à une meilleure qualité logicielle. La partie livraison continue (continuous delivery) va plus loin et automatise également l'étape de déploiement. Au cours de cette phase, l'application est déployée dans des environnements d'infrastructure sélectionnés. Les paquets construits pendant l'IC sont déployés dans plusieurs environnements (par exemple, développement, staging). La construction de l'application subit des tests d'intégration et de performance. Enfin, l'application est déployée en production et mise à la disposition des utilisateurs finaux.

Un diagramme montre un pipeline DevOps. Il montre l'interface utilisateur <-> passerelle API <-> système d'inventaire, système de reporting, système de paiement, service d'expédition, service de panier <-> pipeline DevOps.
Figure 12.17 Un pipeline DevOps est utilisé pour une application infonuagique native à mesure que les mises à jour de son code de microservices y progressent. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Mise à l'échelle élastique et dynamique (montée/descente)

Les applications infonuagiques natives tirent parti de l'élasticité du nuage en mettant à l'échelle les microservices. Les microservices qui nécessitent des ressources supplémentaires peuvent être mis à l'échelle à la demande pour répondre à une capacité accrue. Le microservice peut également être réduit lorsque l'utilisation diminue. Les ressources qui ont été allouées pendant la montée en charge peuvent être désallouées lorsqu'elles ne sont plus nécessaires. Une application infonuagique native peut ainsi s'adapter aux ressources augmentées ou diminuées et s'adapter selon les besoins.

Avantages des applications infonuagiques natives

Les applications infonuagiques natives sont conçues et construites pour tirer parti de la vitesse et de l'efficacité du nuage. Les applications infonuagiques natives sont hautement extensibles, faciles à mettre à jour et tirent parti des plateformes, processus et services infonuagiques pour étendre facilement leurs capacités. Certains des avantages de l'utilisation des applications infonuagiques natives (cloud-native application) sont les suivants :

  • Rentabilité : Les outils d'orchestration peuvent aider à mettre à l'échelle une application infonuagique native en automatisant l'allocation des ressources aux microservices selon les besoins, sans avoir à dupliquer l'application entière. Cela élimine le surprovisionnement de matériel et le besoin d'équilibrage de charge. Les conteneurs peuvent également être utilisés pour réduire la complexité de la gestion des nombreux microservices qui composent une application infonuagique native, ainsi que pour maximiser le nombre de microservices qui s'exécutent sur un hôte, ce qui permet d'économiser du temps, des ressources et de l'argent.
  • Extensibilité : Chaque microservice est logiquement isolé et peut être mis à l'échelle indépendamment sans temps d'arrêt. Les microservices peuvent être mis à l'échelle à la hausse ou à la baisse en allouant plus ou moins de ressources aux services très demandés en réponse à un changement de trafic utilisateur. Si un microservice est modifié pour être mis à l'échelle, les autres ne sont pas affectés. L'extensibilité indépendante facilite également le déploiement ou la mise à jour de n'importe quelle partie de l'application infonuagique native sans affecter l'application entière.
  • Portabilité : Les applications infonuagiques natives sont indépendantes des fournisseurs car les conteneurs dans lesquels les microservices s'exécutent peuvent être déployés n'importe où, évitant ainsi le verrouillage des fournisseurs.
  • Fiabilité et résilience : Si une défaillance se produit dans un microservice, il n'y a aucun effet sur les microservices adjacents car les applications infonuagiques natives utilisent des conteneurs. La résilience est fournie au cœur de l'architecture. Comme pour tout système logiciel, des défaillances peuvent également survenir dans les systèmes distribués et le matériel. Des défaillances transitoires peuvent également survenir dans les réseaux. La capacité d'un système à se remettre des défaillances et à continuer de fonctionner est appelée résilience (resiliency). L'objectif de la résilience est de ramener l'application à un état de fonctionnement complet après une défaillance, en minimisant les temps d'arrêt et la perte de données. Une application est résiliente si elle (1) a une haute disponibilité (high availability), c'est-à-dire la capacité d'une application à continuer de fonctionner dans un état sain sans temps d'arrêt significatif ; et (2) prend en charge la reprise après sinistre (disaster recovery), c'est-à-dire la capacité de l'application à se remettre d'incidents rares mais majeurs : défaillances non transitoires et à grande échelle, telles qu'une interruption de service qui affecte une région entière. Les applications peuvent être rendues résilientes en augmentant la redondance avec des grappes multinœuds, des déploiements multirégion et la réplication de données. D'autres stratégies pour implémenter la résilience incluent les tentatives pour gérer les défaillances réseau transitoires, l'ajout de nœuds à une grappe et l'équilibrage de charge entre eux, la limitation des utilisateurs à volume élevé et l'application de disjoncteurs pour empêcher une application de tenter à plusieurs reprises une opération susceptible d'échouer.
    Les tests de résilience nécessitent de tester la façon dont la charge de travail (workload) de bout en bout se comporte dans des conditions de défaillance qui ne se produisent qu'intermittemment – par exemple, en injectant des défaillances en faisant planter des processus, y compris des certificats expirés, en rendant des services dépendants indisponibles, et ainsi de suite. Des outils et cadriciels de résilience comme Chaos Monkey peuvent être utilisés pour de tels tests de chaos. Par exemple, Netflix utilise Chaos Monkey pour les tests de résilience afin de simuler les défaillances et d'y remédier.
  • Facilité de gestion : Les mises à jour des applications infonuagiques natives et les fonctionnalités ajoutées sont automatisées à mesure qu'elles progressent dans un pipeline DevOps utilisant CI/CD. Cela facilite le suivi des microservices par les développeurs à mesure qu'ils sont mis à jour. Les équipes de développement peuvent se concentrer sur la gestion de microservices spécifiques sans se soucier de la façon dont ils interagiront avec d'autres microservices. Cette architecture permet de choisir des équipes pour gérer des microservices spécifiques en fonction des compétences de leurs membres.
  • Visibilité : Parce qu'une architecture de microservices isole les services, il est plus facile pour les équipes d'apprendre comment les microservices fonctionnent ensemble et d'avoir une meilleure compréhension de l'application infonuagique native dans son ensemble.

Bonnes pratiques pour le développement d'applications infonuagiques natives

Les bonnes pratiques pour la conception d'applications infonuagiques natives sont basées sur le principe DevOps d'excellence opérationnelle pour assurer la livraison en temps voulu de logiciels de qualité. Une architecture infonuagique native n'a pas de règles uniques, et les entreprises aborderont le développement différemment en fonction du problème commercial qu'elles résolvent et du logiciel qu'elles utilisent. En adoptant les principes DevOps pour développer des applications infonuagiques natives, les entreprises obtiennent trois avantages fondamentaux, tels que des logiciels de meilleure qualité publiés plus rapidement, une réactivité accrue aux besoins des clients et un environnement de travail amélioré pour les équipes de développement.

Toutes les conceptions d'applications infonuagiques natives doivent prendre en compte la manière dont l'application sera construite, la manière dont les performances sont mesurées et la manière dont les équipes favorisent l'amélioration continue des performances de l'application, la conformité tout au long du cycle de vie de l'application à un rythme plus rapide et une qualité supérieure. Voici les cinq bonnes pratiques essentielles pour la conception d'applications infonuagiques natives :

  1. Automatisation : Une équipe de développement doit automatiser autant que possible le cycle de vie du développement d'applications infonuagiques natives. L'automatisation aide à réduire les erreurs humaines et à augmenter la productivité de l'équipe. Elle permet également un provisionnement cohérent des environnements d'applications infonuagiques chez plusieurs fournisseurs de services infonuagiques. Avec l'automatisation, l'infrastructure en tant que code (IaC) est utilisée comme une pratique DevOps qui utilise le versionnement et un langage déclaratif pour automatiser le provisionnement des ressources d'infrastructure telles que les services de calcul, les réseaux et le stockage.
  2. Surveillance : Les équipes doivent surveiller l'environnement de développement, ainsi que la façon dont l'application est utilisée. La surveillance garantit que l'application infonuagique native fonctionne sans problème. Les équipes peuvent également renforcer le pipeline CI/CD avec une surveillance continue de l'application, des journaux et de l'infrastructure de support. La surveillance continue peut également être utilisée pour identifier les problèmes de productivité qui pourraient ralentir le pipeline CI/CD.
  3. Documentation : De nombreuses équipes construisent des applications infonuagiques natives avec une visibilité limitée ou nulle sur ce que font les autres équipes. Les équipes ayant des compétences spécifiques sont susceptibles de gérer certains aspects de l'application infonuagique native car les microservices sont construits avec différents langages de programmation et cadriciels dans lesquels les membres de l'équipe sont spécialisés. Il est important de documenter les spécificités des microservices qu'ils gèrent, de suivre les changements et de surveiller les contributions de l'équipe à l'application infonuagique native.
  4. Versions incrémentielles : Les modifications apportées à l'application infonuagique native ou à l'architecture sous-jacente doivent être incrémentielles et réversibles. Avec l'IaC, les développeurs peuvent suivre les modifications dans un dépôt de code source. Les mises à jour doivent être publiées aussi souvent que possible. Les versions incrémentielles réduisent la possibilité d'erreurs et de problèmes d'incompatibilité.
  5. Conception pour la défaillance : Les processus doivent être conçus pour la possibilité de défaillances dans un environnement infonuagique. La mise en œuvre de cadriciels de test pour simuler les défaillances peut atténuer les risques. Ils peuvent également être utilisés pour apprendre des défaillances et pour améliorer la fonctionnalité globale de l'application infonuagique native.

Enjeux mondiaux en technologie

Implications locales et internationales des applications infonuagiques

Bien que les applications infonuagiques natives soient utilisées partout dans le monde, des exigences spécifiques d'internationalisation (I18N) et de localisation (L10N) doivent être respectées pour faciliter la création d'applications que les gens peuvent utiliser. Étant donné que les microservices font partie du dorsal d'une application, ils renvoient généralement des mots-clés qui peuvent être remplacés via un système I18N/L10N au sein du frontal de l'application. Quelle est votre opinion sur la question de savoir si cette approche répond à toutes les exigences I18N/L10N pour les applications infonuagiques natives ?

Outils pour le développement d'applications infonuagiques natives

Plusieurs outils sont utilisés pour le processus de développement d'applications infonuagiques natives. Ensemble, ils créent une pile de développement. Les outils suivants se trouvent généralement dans une pile de développement infonuagique native.

Docker

Docker est une plateforme à code source ouvert qui crée, déploie et gère des conteneurs à l'aide d'un système d'exploitation commun. Il isole les ressources, permettant à plusieurs conteneurs d'utiliser le même système d'exploitation sans conflit. Docker est devenu la norme pour la technologie des conteneurs (container). Un avantage offert par les conteneurs est la portabilité. Les conteneurs Docker peuvent être déployés n'importe où, sur n'importe quelle machine virtuelle physique ou dans le nuage. L'utilisation de Docker aide à réduire la taille du développement et fournit des empreintes plus petites des systèmes d'exploitation dans les conteneurs. Généralement mesurés en mégaoctets, les conteneurs Docker utilisent beaucoup moins de ressources que les machines virtuelles et démarrent presque immédiatement. Les conteneurs Docker sont légers, ce qui les rend facilement extensibles. La Figure 12.18 illustre un aperçu du processus Docker.

Un diagramme avec le flux suivant est présenté : Application -> Dockerfile -> Construire (conteneur inscriptible, ajouter l'image d'application, l'image d'exécution Python, Ubuntu (image de base), fs (noyau) -> Exécuter -> Conteneur.
Figure 12.18 Une image Docker est construite à partir d'un Dockerfile pour déployer une application qui s'exécute dans un conteneur Docker. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Pour déployer des applications à l'aide de Docker, la première étape typique consiste à créer un Dockerfile. Le Dockerfile est un document texte qui contient des instructions pour construire une image Docker. Une image Docker peut être basée sur une autre image avec des personnalisations supplémentaires. Les images Docker sont une collection de couches immuables où chaque instruction d'un Dockerfile crée une couche dans l'image. Une fois construites, les images Docker deviennent des modèles immuables pour la création de conteneurs Docker, qui sont des instances en cours d'exécution de ces images contenant tout le nécessaire pour que l'application fonctionne.

Kubernetes

Kubernetes est une plateforme d'orchestration (orchestration platform) à code source ouvert utilisée pour automatiser le déploiement, la mise à l'échelle et la gestion des charges de travail basées sur des conteneurs. Un exemple de plateforme Kubernetes est présenté à la Figure 12.19.

Un diagramme complexe montrant une application infonuagique native déployée dans un environnement Kubernetes est présenté.
Figure 12.19 Une application infonuagique native est déployée dans un environnement Kubernetes. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

La charge de travail (workload) fait référence à une application exécutée sur Kubernetes. Le nœud maître Kubernetes comprend le plan de contrôle, qui comporte plusieurs composants importants, notamment un contrôleur de services, un contrôleur de nœuds, un contrôleur de points de terminaison, un contrôleur de réplication et un ordonnanceur. Ces composants sont responsables de fonctionnalités telles que l'équilibrage de charge en distribuant efficacement les requêtes réseau entre les conteneurs ; les conteneurs auto-réparateurs en les vérifiant régulièrement pour leur bonne santé et où les conteneurs défaillants sont remplacés ou redémarrés automatiquement ; les conteneurs à mise à l'échelle automatique en les ajoutant ou en les supprimant en fonction de la demande ; le déploiement automatisé pour gérer la configuration et le déploiement des conteneurs dans le nuage ; la gestion du stockage pour gérer les besoins de stockage de tous les conteneurs ; et la gestion du réseau entre les conteneurs.

Le nœud maître Kubernetes comprend plusieurs composants, dont le serveur API Kubernetes, qui joue un rôle crucial dans la gestion des charges de travail basées sur des conteneurs (container). De plus, la grappe Kubernetes se compose de nœuds de travail, chacun contenant un kubelet. Travaillant en tandem avec le nœud maître, le kubelet gère des tâches telles que l'ordonnancement et assure le bon fonctionnement des applications déployées au sein des nœuds de travail. Kubernetes est devenu la plateforme privilégiée pour le déploiement d'applications infonuagiques natives. Dans cet écosystème, les microservices d'une application infonuagique native interagissent sur le réseau, déployés et mis à l'échelle au sein d'une grappe Kubernetes.

Pour déployer une application infonuagique native dans un environnement Kubernetes, les conteneurs de microservices, extraits d'un registre, sont déployés dans des pods. Un pod est une petite unité logique qui exécute un conteneur au sein d'un nœud de travail dans la grappe Kubernetes. Une grappe est un ensemble d'un ou plusieurs nœuds. Les pods sont un groupe d'un ou plusieurs conteneurs avec des ressources de stockage et de réseau partagées et une spécification pour la façon dont les conteneurs sont exécutés. Les conteneurs ne doivent être planifiés ensemble dans un seul pod que s'ils sont étroitement couplés et doivent partager des ressources. Les pods sont éphémères, ce qui signifie qu'ils sont des ressources non permanentes. Kubernetes gère les pods plutôt que les conteneurs directement. Le serveur API sur le nœud maître Kubernetes communique avec le nœud de travail pour déployer le conteneur dans un pod et le démarrer. Les répliques de pods peuvent être augmentées pour mettre à l'échelle le microservice conteneurisé qu'il contient. Si un pod échoue, un nouveau est créé. Kubernetes gère ces déploiements pendant toute la durée du déploiement jusqu'à ce que le pod soit supprimé. En d'autres termes, il garantit que tous les pods et répliques sont en cours d'exécution.

La découverte de services est un autre service important fourni par la plateforme Kubernetes. À mesure que les pods sont ajoutés et répliqués, une adresse IP interne est fournie pour le pod, rendant le conteneur accessible. Les pods sont éphémères, de sorte que les adresses IP peuvent changer à mesure que de nouveaux pods sont créés. Les capacités de registre de services et de découverte de services résolvent ce problème en créant des services Kubernetes. Un service Kubernetes est une abstraction qui définit un ensemble logique de pods et une politique pour y accéder de manière fiable.

Questions de réflexion

Docker et Kubernetes sont-ils trop généralistes ?

Étant donné le fait que de nombreux outils sont disponibles pour la conteneurisation (containerization) et l'orchestration de conteneurs, qu'est-ce qui justifie la large acceptation de Docker et Kubernetes pour gérer ces fonctions respectives ?

Terraform

Terraform est un outil IaC à code source ouvert utilisé pour construire, mettre à jour et versionner les ressources infonuagiques et sur site. Parmi les cas d'utilisation de Terraform, on trouve la gestion des grappes Kubernetes et le provisionnement de ressources dans le nuage, entre autres.

GitLab et GitHub CI/CD

GitLab est une plateforme DevOps basée sur le nuage utilisée pour surveiller, tester et déployer le code d'application. GitLab comprend un dépôt Git basé sur le nuage ainsi que plusieurs fonctionnalités DevOps telles que CI/CD, la sécurité et des outils de développement d'applications. L'outil CI/CD peut être utilisé pour automatiser les tests, le déploiement et la surveillance des applications. GitLab peut également être utilisé pour l'analyse de sécurité, l'analyse statique et les tests unitaires. GitHub est une plateforme de développement basée sur le nuage utilisée pour le développement logiciel, la collaboration et la sécurité. GitHub comprend également un dépôt Git basé sur le nuage et plusieurs fonctionnalités DevOps similaires à GitLab.

Red Hat OpenShift

OpenShift est la plateforme d'applications infonuagiques de Red Hat. Elle comprend plusieurs produits logiciels de conteneurisation, y compris la plateforme de conteneurs OpenShift qui fonctionne sur le système d'exploitation Red Hat Linux et Kubernetes. OpenShift est une plateforme en tant que service (Platform as a Service) (PaaS) qui inclut la plateforme Kubernetes, les images de conteneurs (container) Docker, ainsi que des fonctionnalités exclusives à la plateforme OpenShift. Ces fonctionnalités incluent les définitions de pipeline CI/CD, les outils d'automatisation des conteneurs, l'interface de ligne de commande Kubernetes et les fonctionnalités de sécurité. OpenShift fournit un environnement de développement robuste et multilingue, ainsi que tous les composants logiciels nécessaires pour prendre en charge les applications. OpenShift est une application à code source ouvert et téléchargeable gratuitement qui permet aux développeurs de déployer rapidement des applications web, mobiles et IoT.

Tanzu

Le logiciel d'application infonuagique de VMWare, Tanzu, anciennement connu sous le nom de Cloud Foundry, est une plateforme d'application modulaire qui fournit un riche ensemble d'outils de développement et un chemin pré-établi vers la production pour construire et déployer des applications rapidement et en toute sécurité sur n'importe quel nuage public (public cloud) conforme ou une grappe (cluster) Kubernetes sur site. Tanzu fournit une chaîne d'approvisionnement de résultats opérationnels et de sécurité pour l'environnement de développement via des configurations conçues avec des principes opérationnels et de sécurité afin que les applications puissent être poussées en production rapidement, exécutées et mises à l'échelle en toute sécurité. Ces principes incluent l'exécution du code dans un environnement de test et l'assurance que le code fonctionne correctement, l'application d'une analyse de sécurité afin que l'application qui passe en production soit auditée et conforme aux politiques de sécurité, et le déploiement de l'application dans des environnements de production qui peuvent inclure plusieurs environnements de grappes pouvant s'exécuter et s'adapter en production.

Node

Node est un environnement d'exécution JavaScript côté serveur, multiplateforme et à code source ouvert, qui peut être utilisé pour développer des outils et des applications côté serveur en JavaScript. Parmi les exemples d'applications en temps réel, on trouve les chats, les fils d'actualité et d'autres microservices. Par exemple, Node peut être utilisé pour créer des serveurs virtuels et définir les routes qui connectent les microservices à des API externes telles que les API du système d'exploitation, y compris les bibliothèques HTTP et de système de fichiers, par rapport aux API JavaScript spécifiques aux navigateurs.

L'avenir des applications infonuagiques natives

Les applications infonuagiques natives ont connu une utilisation accrue ces dernières années et sont prédites comme l'avenir du développement logiciel. La Cloud Native Computing Foundation11 a estimé qu'il y avait au moins 6,8 millions de développeurs infonuagiques natifs en 2021, contre 6,5 millions en 2020. Ils ont également estimé qu'il y avait 5,6 millions de développeurs utilisant Kubernetes en 2021, soit une augmentation de 67 % par rapport à l'année précédente.12

Les applications infonuagiques natives résolvent certains des problèmes inhérents à l'informatique en nuage. L'approche infonuagique native est la nouvelle norme pour l'architecture d'entreprise. C'est une façon de concevoir, de construire et d'exécuter des applications dans le nuage. Il a été observé que les entreprises qui adoptent une approche infonuagique native peuvent atteindre des niveaux plus élevés d'innovation, d'agilité et d'extensibilité. Elle offre également de nombreux avantages tels que :

  • la réduction des frais généraux informatiques et des coûts de gestion en fournissant un processus de livraison logicielle rationalisé et une consommation de ressources à la demande
  • la réduction du temps de mise sur le marché et la réduction du risque de déploiement en permettant aux développeurs de construire, tester et déployer rapidement de nouveaux services et des services mis à jour
  • la capacité de réagir plus rapidement sur le marché grâce à la disponibilité constante des ressources
  • la réduction de la complexité
  • un couplage moindre entre les services d'une application

Néanmoins, la migration vers le nuage pour améliorer l'efficacité opérationnelle présente un éventail de défis. Nous avons également souligné précédemment certains des défis rencontrés dans les architectures de microservices. Certains des défis appris précédemment incluent que l'utilisation de microservices nécessite de modifier l'allocation des responsabilités entre les composants, et que la détermination des limites de service des composants pourrait être difficile, le débogage, la journalisation et la surveillance des microservices deviennent également difficiles, pour n'en nommer que quelques-uns.

Lien avec le quotidien

Vie quotidienne et microservices

Il existe une myriade d'applications web que les gens utilisent tous les jours et qui sont basées sur des microservices. Par exemple, les applications météorologiques exploitent généralement des services web qui invoquent des microservices. Des applications plus complexes incluent les sites web de commerce électronique, comme illustré précédemment. Pouvez-vous fournir des scénarios illustratifs supplémentaires qui démontrent comment l'utilisation des microservices aide les gens dans la vie quotidienne ? Vos scénarios ne devraient pas se limiter à décrire comment les microservices sont utilisés, mais devraient plutôt décrire des situations où ces architectures sont appliquées dans des contextes réels.