Dapr, un outil pour les applications Cloud Native distribuées
Avec la vague d’adoption du Cloud aujourd’hui, il y a un changement important dans le développement Cloud Native, qui utilise le plus souvent les architectures de microservices.
Piliers du Cloud Native by Microsoft Azure
Contrairement à des applications monolithiques migrées vers le cloud, les applications cloud-natives sont conçues pour le cloud dès leur naissance. Elles s'exécutent dans des containers (ou microVM, WASM), sont déployées dans le cadre de microservices et sont gérées à l'aide de méthodologies DevOps et Agiles.
Pour plus d'informations sur le concept Cloud Native, je vous invite à lire cet article:
https://docs.microsoft.com/fr-fr/dotnet/architecture/cloud-native/definition
Pour ceux qui n’auraient pas la motivation de lire l’article en entier, voici la définition officielle de ce concept fournie par la Fondation Cloud Native Computing :
“Les technologies Cloud-natives permettent aux organisations de créer et d’exécuter des applications évolutives dans des environnements dynamiques et modernes, tels que des clouds publics, privés et hybrides. Les conteneurs, les maillages de service, les microservices, l’infrastructure immuable et les API déclaratives illustrent cette approche.”
Fondation Cloud Native Computing
IDC prévoit que plus de 35% de toutes les applications de production seront cloud natives d'ici la fin de l’année 2022. Le cloud natif devient alors rapidement la nouvelle façon de développer des applications modernes.
Cette architecture de microservices a été adoptée pour plus de résilience, d’observabilité, maintenabilité, et pour répondre à des concepts importants du DevOps qui sont réduire le Time-to-Market et le Time-to-Value.
Toutefois, cette approche peut être très coûteuse en compréhension et en compétences sur des systèmes distribués. Ainsi, alors qu’un développeur peut être à l'aise avec l'architecture basique des applications Web et des bases de données, une expertise spécifique est à acquérir pour maîtriser le développement des systèmes distribués, nécessaire pour créer ces applications Cloud Native. Dans la pratique, le développeur doit toujours répondre aux mêmes problématiques présentes dans les applications distribuées comme la gestion des événements, la gestion des états, etc. Par ailleurs, de nombreux runtimes de programmation sont souvent limités dans la prise en charge de différents langages de programmation, ce qui rend plus complexe la création d’architectures en microservices.
Pour aider les développeurs et répondre à tous ces besoins (diminuer la complexité, faciliter le support des runtimes, etc.), Microsoft lance en octobre 2019 Dapr (Distributed Application Runtime). Ce projet fournit une plateforme de modèle de programmation de microservices, facilitant la fabrication d’applications distribuées. Il est portable, piloté par des évènements et simplifie la création de microservices. Dapr est désormais, depuis février 2021, disponible en V1.
Utilisable avec de multiples langages et frameworks (Python, JavaScript, Go, Java, .Net), il consiste en des blocs de construction, Building blocks (appel de service, gestion d’état, publication/abonnement de messagerie, liaison de ressources basées sur des évènements) accessibles par des API standards gRPC ou HTTP. Indépendant de la plateforme, il peut être exécuté en local ou dans un cluster Kubernetes et inclut une interface de ligne de commande.
Qu'est ce qui rend Dapr utile ?
Les applications modernes de microservices sont souvent composées de services écrits par différentes équipes, internes ou externes à l’entreprise, et la main-d'œuvre informatique nécessite de plus en plus de mobilité. Il est souvent difficile que chaque développeur opte pour le même langage de programmation.
Aujourd’hui, dans le monde du développement d'applications web, nous devons adopter la variété et chercher des moyens pour que les développeurs, ayant des compétences, des préférences et des styles de travail différents puissent travailler et avancer ensemble.
Vous l’aurez compris, grâce à Dapr, les Devs et les Ops peuvent choisir d’utiliser les services de leurs choix et qui correspondent mieux au contexte de développement actuel.
Dapr est conçu comme un hub de blocs de construction, et non comme un cadre autonome qui fournit tout de A à Z. Cela permet à Dapr de proposer de nouvelles fonctionnalités aux développeurs avec une grande agilité.
De plus, dans l'écosystème Dapr il existe une grande communauté qui contribue à ajouter de nouvelles fonctionnalités et à les améliorer, afin de répondre de mieux en mieux à ces besoins. La communauté se regroupe sur Discord, et cela permet à toute personne de s’y connecter, de poser des questions, d’aider les autres et/ou se faire aider par les autres.
En bref Dapr c'est quoi ?
Dapr est tout d’abord un environnement d’exécution pour permettre de construire des applications distribuées de type microservices.
Les avantages sont nombreux:
- Cloud agnostic
- Portable
- Event-Driven
- Supporte de nombreux langages et frameworks
- Intégré nativement avec Kubernetes
- Supporté par une large communauté de développeurs (Plus de 700 contributeurs au début de 2021)
- Un CLI utile pour le déploiement et le debugging
Dapr se compose d’un ensemble de blocs préconçus (building blocks) en API ouverte (accessible en HTTP/gRPC). Par conséquent vous pouvez faire appel à ses blocs depuis n’importe quel langage de programmation (Framework compris). Chacun de ses building blocks est indépendant, donc vous pouvez choisir d’y faire appel ou non dans votre code.
Vue d'ensemble de Dapr
En quoi consiste l'architecture de Dapr ?
1. Les buildings blocks
Lors de la mise en place d’une infrastructure microservices il y a de nombreuses considérations à prendre en compte (le stockage des données, la communication entre services et les appels de leurs méthodes, etc…). Dapr a mis en place des blocs préconçus sur la plupart des fonctionnalités communes aux applications microservices.
Blocs de construction Dapr
En outre, voici un certain nombre de modules fournis par le runtime de Dapr. Ces derniers permettent surtout d’implémenter des bonnes pratiques de développement.
Pour la Web Application que j’ai conçue pendant mon stage, je n’ai utilisé qu’un seul building block, celui du Service-to-service invocation. Ce building block est une API d'appel de service, c’est à dire qu'un service peut communiquer de manière fiable et sécurisée avec d'autres services à l'aide des protocoles gRPC ou HTTP standard. Cette API agit comme une combinaison d'un reverse proxy avec un DNS, tout en tirant parti des métriques, de la gestion des erreurs, du chiffrement et plus encore.
Pour appeler une application à l'aide de Dapr, vous utilisez l'invokeAPI sur n'importe quelle instance Dapr. Le modèle de programmation Sidecar encourage chaque application à communiquer avec sa propre instance de Dapr.
Dapr propose sur son site des quickstarts, des exemples de code, et des explications détaillées pour chaque bloc de construction.
Mais le Sidecar qu’est-ce que c’est ?
2. Architecture de Dapr et principe du Sidecar
Ce qu’il faut comprendre c’est que Dapr utilise le principe du Sidecar, cela signifie qu’un processus ou un container va s’exécuter juste à côté de votre module applicatif. Autrement dit le Sidecar Dapr est attaché à votre application (application parent) et fournit à celle-ci des fonctionnalités auxquelles elle peut faire appel (ici ce sont les building blocks). À noter que le sidecar contenu dans un container et votre module applicatif contenu dans un autre container sont tous les deux contenus dans un seul et même pod. L’avantage ici est de ne pas détricoter la solution existante, de permettre à chaque container (Sidecar et Service/Application) d’avoir son propre environnement d’exécution et de se reposer sur différentes plateformes de programmation.
Principe du Sidecar
Dapr interagit sous le déclenchement d’événements et communique avec les autres APIs Dapr avec les protocoles standards HTTP/gRPC. Les demandes de l’API HTTP sont envoyées en tant que texte (JSON) et peuvent être lues et créées par des humains. Pour améliorer les performances, les développeurs peuvent appeler les blocs de construction Dapr avec gRPC.
gRPC est une infrastructure moderne et hautement performante qui fait évoluer le protocole d'appel de procédure distante (RPC). gRPC utilise HTTP/2 pour son protocole de transport, ce qui apporte de nettes améliorations en matière de performances par rapport au service HTTP RESTFul.
Enfin, le runtime Dapr supporte la gestion des états mais aussi les architectures stateless.
On peut donc comparer notre application à la moto et le Sidecar à un bloc qui va nous offrir des fonctionnalités en plus qui seront attachées à la moto, et que l’on aura à notre disposition.
3. Environnement d'hébergement
Dapr peut être hébergé dans différents environnements, y compris auto-hébergé sur une machine Windows/Linux/macOS, ou sur Kubernetes.
En mode auto-hébergé, Dapr s'exécute comme un processus annexe distinct, que votre code de service peut appeler via HTTP ou gRPC. Ce mode est surtout utilisé pour le développement en local car c’est le moyen le plus simple de commencer. Chaque service en cours d'exécution dispose d'un processus d'exécution Dapr (ou sidecar) qui est configuré pour utiliser les state stores, le pub/sub, les composants de liaison et les autres blocs de construction.
Dapr en mode auto-hébergé
Dans les environnements d'hébergement de containers tels que Kubernetes, Dapr s'exécute en tant que container sidecar avec le container d'applications dans le même pod. Les services "dapr-sidecar-injector" et "dapr-operator" fournissent une intégration de première classe pour lancer Dapr en tant que container sidecar dans le même pod que le container de services et fournissent des notifications sur les mises à jour des composants Dapr provisionnées dans le cluster.
Déployer et exécuter une application compatible Dapr dans votre cluster Kubernetes est aussi simple que d'ajouter quelques annotations aux schémas de déploiement. Les concepts de Dapr sous Kubernetes restent le même que Dapr en local mis à part quelques différences.
Sous Kubernetes vous devez injecter dans votre cluster 4 pods Dapr :
- Actor placement
- Sidecar injector
- Sentry
- Operator
Les pods Sidecar injector et Operator permettent de lancer Dapr en tant que container sidecar dans le même pod que le container de votre application et permet de fournir des notifications des mises à jour des composants Dapr du cluster. Sentry est une autorité de certification, pour les authentifications. C'est grâce à ces éléments que le sidecar de chaque microservice de votre application va communiquer avec les différents composants (building blocks).
Dapr en mode Kubernetes
4. Mon expérience avec Dapr
J’ai découvert Dapr pendant mon stage de fin d’études, que j’ai effectué chez OCTO Technology. L’objectif de mon stage était de développer un mini Google Drive intelligent s’appuyant sur une architecture event-driven, en utilisant l’outil Dapr et des services de Machine Learning fournis par des Cloud Providers. Pour rentrer un peu plus dans le détail, vous verrez ci-dessous l’architecture de mon projet.
Architecture de ma Web App “Google Drive à ma façon”
Le point négatif de l’architecture ci-dessus, avec des APIs en Python appelées grâce au building block Service to Service Invocation de Dapr depuis notre frontend, est que l'on doit à chaque fois passer par le frontend. Alors que le but, si on veut rester dans l’univers des applications Cloud Natives serait de séparer au maximum le frontend du backend. J’ai alors pensé à utiliser le building block Bindings and Triggers afin de reproduire le même schéma d’architecture qu’avec les cloud functions. Cependant Dapr étant un outil très récent, toutes les fonctionnalités ne sont pas encore entièrement développées. Le building block "Binding and Triggers" possède un trigger permettant de déclencher un service lorsque l’on dépose un fichier dans un Bucket uniquement avec le cloud provider Microsoft et pas encore avec GCP.(cf. lien de la doc Dapr).
Comparaison architecture Dapr VS GCP
Dans l’architecture de droite sur le schéma ci-dessus, dès qu’un fichier arrive sur le bucket de stockage, un trigger intelligent de GCP va venir déclencher la cloud function Detect Label. Une fois cette cloud function exécutée, elle va déclencher automatiquement une autre cloud function _Add To Collection_. C’est cette architecture là que j’aurais aimé implémenter avec Dapr, mais ce n’est qu’une question de temps pour que cette fonctionnalité soit proposée par Dapr.
Conclusion
Pour conclure, je vais vous partager mon avis sur mon expérience personnelle avec Dapr.
Comme vous l'aurez compris, pendant mon stage j’ai pu utiliser qu’un seul building block, celui du ***\Service to Service Invocation*. Par conséquent, mon point de vue n'est pas exhaustif. Selon moi l'utilisation de Dapr nécessite un minimum de connaissances d’ops, car vous serez surement amené à déployer des clusters Kubernetes (par exemple). Dapr s’adresse donc à des équipes mélangeant les Devs et les Ops. Dans ce contexte là, Dapr peut s'avérer utile dans le sens où, vous l’aurez compris, cet outil va leur faciliter la vie quand à la création de web app Cloud Native en architectures microservices et de se concentrer sur la logique métier de l’application.
Un problème que j’ai pu soulever pendant mon stage est, comme je vous l’ai expliqué dans la partie précédente, que certaines fonctionnalités ne sont pas encore toutes disponibles pour tous les cloud providers. En ce sens, Dapr peut alors s’avérer plus intéressant dans un contexte Multi Cloud que dans l’utilisation d’un seul cloud provider (comme j’ai pu le faire dans mon projet en utilisant uniquement GCP).