21 juin 2011

multi-tenancy

"Java EE 7 sera Cloud"
Voilà une annonce pleine de bonnes intentions, mais qu'en est-il concrètement ?

Les démos, comme celle de Spring/VMWare lors de What's Next pour CloudFoundry ne nous montrent que l'abstraction faite sur la gestion des infrastructures, OS et middlewares : truc app dans une console, et hop j'ai une appli en ligne, truc db et hop, j'ai une base MySQL... Les utilisateurs de Heroku doivent bien rigoler de nous voir admiratifs devant ce spectacle !

Il y a un second aspect qui est nettement plus délicat à percevoir, qui du coup fait moins l'objet des démos, et qui sera - j'espère - au centre des discutions de l'expert group Java EE 7, que Spike Washburn (celui qui a conçu RUN@Cloud) va rejoindre : la gestion multi-tenant. Je fais mon savant là mais je n'ai compris ce concept que récemment lorsque mes collègues de CloudBees m'ont fait une explication de texte ;)

Pour expliquer ce concept, nous allons ensemble - virtuellement - construire un SaaS. Je vais donc dérouler les différentes variantes de ce que j'ai pu mettre en oeuvre.

1. Serveur mutualisé

Dans le but de réduire les coûts de mise en oeuvre et d'administration, c'est la première chose qu'on met en place. Dans mon cas, un proxy Internet pour les dépendances Maven. On réserve donc une bonne bécane et on installe un repository manager, Archiva dans mon cas (je participais à son développement à cette époque).

Avantage : une seule instance, c'est simple à comprendre et à administrer
Inconvénients : pollution mutuelle entre utilisateurs, qui ont tous une librairie machin à installer. En gros, on impose à tous une logique commune, ce qui fait préférer à certains d'avoir leur propre dépôt et de le gérer eux-même pour retrouver une certaine liberté même s'il faut payer le coup de mise en place.

Je ferais un parallèle avec SVN vs Git : le fonctionnement du système centralisé s'impose à tous et devient pénalisant.


2. Clonage de VM

Ici on met à disposition un environnement type qu'on est en mesure de mettre en place en quelques minutes. L'utilisateur peut alors adapter à ses besoins un canevas de base, qu'on aura éventuellement bridé si nécessaire, ou au moins préparé avec les pratiques généralement acceptées. Exemple type, une image VM Linux avec Git/svn + Nexus + Jenkins + Sonar + Java/Ant/Maven préinstallés.


Avantage : on démarre en quelques minutes, et chacun peut faire ce qu'il veut
Inconvénients : la mise à jour des instances existantes reste une tâche d'administration pénible.  Le clonage des VM ne permet pas de mutualiser / centraliser ces opérations. Lorsqu'une nouvelle version de Jenkins arrive, qui fera la mise à jour ? Qui pourra valider son fonctionnement. On s'attendrais à ce qu'une phase de qualification permette ensuite de déployer la nouvelle version sur toutes les VM clonées, avec peut être possibilité de débrayer cet update automatique. 

Le parallèle qui me vient à l'esprit ici c'est la gestion du parc de PC, souvent basée sur le clonage d'image système puis création du compte utilisateur à la main. Sauf que nos administrateurs disposent de Windows Update pour assurer la maintenance, sans quoi il faudrait toutes les semaines venir faire la queue à la logistique pour obtenir les correctifs adéquats.




3. Création automatisée des VM

On monte d'un cran et on exploite les outil de déploiement continu pour construire nos images de VM à partir de "recettes" (pour reprendre le vocabulaire de Chef). La mise à jour d'une recette se traduit par une mise à jour de toutes les instances, et l'élimination de la redondance dans les tâches d'administration. Autre avantage par rapport au clone, il est possible d'utiliser un OS différent vu qu'on a scripté l'installation.


Avantage : gestion centralisée et automatisée
Inconvénients : sur-consommation de ressources. Je ne l'ai pas évoqué ci-dessus, mais nos VM par projet consomment de nombreuses ressources sur la machine physique de notre data-center. Même si l'hyperviseur fait de son mieux pour répartir la charge, chaque instance "up" consomme mémoire, cpu et I/O. 

La tarification d'Amazon EC2 en est d'ailleurs le reflet : on paye certes à la minute, mais une instance de serveur web qui reste démarrée est facturée pour un temps plein, car un serveur web qui ne fait rien ... consomme tout de même cpu, mémoire et I/O ! Ceux qui ont démarré une instance EC2 pour faire un test et ont "oublié" de l'éteindre en ont eu pour leurs frais :P La virtualisation a cet effet pervers qu'on a tendance à laisser tourner des VM sans réaliser ce qu'elle coûtent réellement, et par voie de conséquence d'obliger à surdimensionner les machines physiques (ou la facture).

Le parallèle cette fois ce serait un serveur sur lequel on fait tourner 100 instances de Tomcat avec le war Jenkins déployé, consommant 100 fois la mémoire nécessaire malgré les effort de l'OS pour swapper les processus inactifs, et obligeant l'admin à commander quelques Go de mémoire supplémentaire.

Imaginons à présent la même machine avec un seul Tomcat musclé et 100 webapps déployées dans des contextes dédiés. On économiserait au moins l'empreinte mémoire du serveur et de la JVM. Le problème serait alors d'assurer l'indépendance, la performance et l'étanchéité de chaque webapp pour qu'elle ne voit pas "par erreur" les données de sa voisine. Sans parler de l'empreinte mémoire de nos 100 instances de la même webapp qui pèse tout de même 80Mo à grand coup de Spring+Hiberante+CXF+<votre-framework-préféré>. D'où le concept de ...

4. Application mutli-tenant

Le cas le plus connu de multi-tenant c'est la notion de virtual-host dans Apache HTTPD : le même serveur web gère les requêtes de plusieurs sites web (du point de vue de l'utilisateur) et détermine ce qu'il doit faire en fonction du nom de serveur invoqué.

Imaginons que notre serveur JavaEE soit étendu pour proposer une fonctionnalité bien spécifique : une seule application jenkins.war est déployée, mais en fonction du virtualhost par lequel les requêtes HTTP arrivent "monAppli.serveur.com", il va basculer dynamiquement les ressources vers un répertoire dédié /var/lib/jenkins/monAppli. Il va faire de même pour notre DataSource qui pointera vers jdbc/monAppli, nos files JMS, nos fichiers de log, etc.

Ce serveur JavaEE++ magique, c'est un serveur prêt pour le Cloud ! En installant une instance de ce type en frontal nous serons en mesure de gérer la diversité de nos instances du même service, puis de distribuer la charge de travail sur un pool de machines (ce que propose déjà Jenkins via ses esclaves, et qui du coup le rend particulièrement éligible à cette évolution, comme le prouve DEV@Cloud).

C'est cela qu'on attend de la norme Java EE 7 lorsqu'on parle de "multi-tenancy". 

Pour le développeur, cela signifiera très probablement quelques aménagements. aussi il est important de comprendre ce concept si vous voulez suivre les débats du JCP sur le sujet (la liste de discussion est accessible en lecture seule à tous ceux qui veulent prendre le temps de la suivre).

Si ce sujet vous intéresse, poursuivez la lecture via cette série d'articles :

2 commentaires:

waddle a dit…

J'aimerais bien comprendre (et pourtant, ça en fait des articles sur le cloud et le multi-tenancy que je lis) quelle différence cela fait par rapport à une gestion de droits/preferences/theme au sein d'une application. On l'a toujours fait et ca marche très bien.

On peut par ailleurs conclure que par exemple GMail (GApps en général) c'est le cloud (en SaaS) et qu'il est multi-tenancy. Je vois mal la valeur ajoutée de tous ces buzz words, surtout dans Java EE...

nicolas deloof a dit…

Si ton appli gère des droits, préférences, thèmes, et ACL sur les données tu as en effet les éléments de base du multi-tenant. Mais tu dois tout monter avec tes petites mains. gApps est en effet multitenant.

Dans le cadre de Java EE en effet l'intérêt est particulièrement peu évident. J'attends de voir moi aussi ce que ça va donner