lundi 8 février 2016

La Haute Disponibilité en bref


Le cloud computing, ou plus poétiquement l'informatique dans les nuages, est un sujet d'étude incontournable pour qui souhaite comprendre l'informatique d'aujourd'hui. 

Je prépare quelques articles sur le sujet, toujours avec l'idée d'essayer d'en expliquer les ressorts de la façon simple et compréhensible par le commun des mortels.


 Et j'ai le sentiment que pour arriver à mes fins, il va me falloir déjà parler
  • de la fin : pourquoi le cloud computing, quels sont les apports attendus ?
  • des moyens : quelles sont les avancées techniques, et les modèles économiques, qui en ont favorisé l'essor
Cet article constitue un élément explicatif d'une problématique usuelle en informatique et à laquelle le cloud computing apporte une réponse formidable : il expose les notions de Haute Disponibilité que nous abrégerons en HA par la suite (High Availibility, le terme consacré). 

Il y a des pré-requis. En cas de besoin, commencez par lire la série de 3 articles sur le fonctionnement d'Internet (et des technologies réseau), et l'article d'introduction sur le hardware.

Quels sont les objectifs de la HA ?

Un ordinateur est un dispositif matériel composé pour l'essentiel de circuits électroniques mais également d'éléments mécaniques (les disques durs classiques sont composés d'un moteur, de roulements à bille, de disques, de têtes de lecture ...). Tous ces éléments sont susceptibles de tomber un panne : un composant peut surchauffer et cramer, le moteur d'un disque dur peut casser. 

La fiabilité d'une pièce peut s'exprimer par le MTBF (Mean Time Before Failure, temps moyen avant panne).


Un ordinateur héberge un système d'exploitation. Ce système d'exploitation fait fonctionner des serveurs. Ces serveurs peuvent eux même servir de support à des applications comme un sites web par exemple, 

Tous ces éléments logiciels sont susceptible de rencontrer des bogues et de dysfonctionner. Une simple erreur de programmation dans la gestion de la mémoire peut provoquer une "fuite mémoire" (de la mémoire est allouée, réservée, par le programme qui oublie ensuite de la libérer quand il n'en a plus l'usage) : inévitablement, selon la fréquence à laquelle le programme qui comporte l'erreur est appelé, la quantité de mémoire non libérée, et la quantité de mémoire sur le serveur, il arrivera un moment où il n'y en aura plus de disponible et où le système ne pourra plus répondre à de nouvelles demandes.

Enfin, rappelez vous le fonctionnement du modèle client/serveur : sans que rien ne tombe en panne, un serveur peut recevoir un volume de requêtes qui excède ses capacités de traitement, qui sont finies, et se bloquer ou devenir tellement lent que ça revient au même.

N'importe lequel de ces 3 types d'événement a pour effet de rendre le service rendu indisponible : et selon la criticité dudit service, ce peut être juste ennuyeux, comme très grave ou même dramatique quand des vies humaines sont en jeu.

Le niveau de disponibilité attendu d'un système s'exprime par le pourcentage. Un exemple issu de wikipedia sera plus simple qu'une explication laborieuse :

  • Soit une machine que l'on souhaite utiliser 12 heures par jour, mais qui tombe en panne en moyenne pendant 1 heure chaque jour et a besoin d'une demi-heure de réglages divers pour sa remise en fonctionnement. Sa disponibilité est :
\text{Ai}\ =\ \frac{\text{12 - 1 - 0,5}}{\text{12}}\ =\ \frac{\text{10,5}}{\text{12}}\  =\ \text{87,5}\ \% \!

Pour des systèmes devant tourner en permanence, on utilise parfois le terme 24/7 (24H sur 24, 7 jours sur 7).

L'objectif de la HA est de permettre d'atteindre ces niveaux de disponibilité en dépit de l'inéluctabilité de la survenance de pannes matérielles ou logicielles.

Deux angles d'attaque

La HA peut s'aborder selon deux angles :
  • La capacité de tolérance de panne ou failover est l'ensemble des mécanismes qui permettent de pallier à une panne proprement dite.
  • La capacité à monter en charge ou scalability (parfois traduit en Français par scalabilité) est l'ensemble des mécanismes qui permettent d'adapter la capacité de traitements au volume de requêtes

Failover

Le failover s'obtient principalement par la redondance des éléments matériels et logiciels : par exemple au lieu d'avoir un ordinateur, on en installe deux. Un est présent pour fournir le service (il est up), le second ne fait rien dans un premier temps. Si "on" détecte une panne du premier ordinateur, les requêtes sont redirigées vers le second serveur qui prends le relais du premier ; on dispose ainsi du temps nécessaire pour réparer le premier ordinateur et revenir à une configuration sécurisée. Si le second ordinateur tombe à nouveau en panne avant qu'on ait eu le temps de réparer le premier, on est planté. On peut alors prévoir 3 machines, ou 4, ou 5 ou ...  

Le scénario évoqué est appelé "actif/passif" (un élément actif, un ou plusieurs autres passifs). Il existe aussi des scénarios actif/actif.

On le voit la redondance a un coût qui augmente de façon exponentielle en fonction du niveau de sécurité qu'on veut obtenir (la probabilité d'avoir deux ou trois ou quatre machines en panne en léger différé ne fait que décroître tandis que le coût des matériels augmente de façon linéaire et constante).


La détection fiable de la panne du premier ordinateur (le fameux "on") est une des problématiques à résoudre. 

On aborde ici un (vaste) sujet de l'informatique : la supervision qui est l'ensemble des moyens matériels / logiciels / humains qui permettent de surveiller le bon fonctionnement des matériels et logiciels en temps réel ou quasi-réel. 

Cette supervision se fait généralement via des sondes matérielles ou logicielles  qui mesurent la "santé" d'un ordinateur. Une bonne image est celle d'un malade en salle de réanimation dans un hôpital branché sur des appareils qui surveillent sa pression artérielle, le fonctionnement de ses poumons etc. et émettent des alertes en cas de problème.


La redirection du trafic entrant (les requêtes émises par les clients) vers la machine numéro 2 (qui passe d'un rôle passif à actif)  au lieu de la machine 1 (qui passe d'un rôle passif à un rôle actif) est fréquemment effectuée grâce à des mécanismes réseau de bas niveau qui permettent d'associer le FQDN du service appelé à une adresse IP virtuelle. 

Cette IP est dite virtuelle car elle n'a aucune correspondance physique avec une carte réseau : au lieu de cela, elle est affectée dynamiquement à la machine active (qui a une carte réseau et une vraie adresse IP)



Quand la machine 1 est en panne, on redirige les requêtes sur la machine 2, et on "répare" la machine 1. Si c'est une panne logicielle, il suffit généralement de rebooter la machine. Si c'est une panne matérielle c'est beaucoup plus ennuyeux, il est parfois possible de changer rapidement une pièce défectueuse si on a du stock mais on trouve vite les limites pratiques. Du coup, la solution consiste généralement à avoir la machine complète en spare (en pièce de rechange) : ça a un coût, il faut stocker le matériel, qui peut très bien être en panne aussi ... vous commencez peut être à percevoir l'intérêt de la virtualisation ? Nous reviendrons sur ceci.

Scalability

La scalabilité se décline sous deux formes :
  • scalabilité horizontale : elle s’obtient en multipliant le nombre d’instance du service à mettre en HA et en plaçant en amont un mécanisme de répartition de charge (load-balancer)
  • scalabilité verticale : elle s’obtient par l’ajout de ressources physiques au niveau de l’infrastructure (disques durs, mémoire, processeurs etc.).

Dans le cas de la scalabilité horizontale, le FQDN du service en HA est associé à l'IP du load-balancer. 

Ce dernier se charge d'envoyer la requête à une des machines qui s'exécutent en parallèle selon un algorithme. 

Cet algorithme peut être très simple et adresser alternativement et successivement chacune des machines (on parle de round-robin) ou être plus sophistiqué et tenir compte de l'état de santé des différentes machines pour cibler celle qui est la plus en forme, et éviter d'envoyer du trafic à une machine en panne. On retrouve la nécessité de sondes pour ce cas.

C'est ce type de scalabilité qui est le plus employé. La scalabilité verticale consiste simplement à upgrader un matériel pour lui ajouter des capacités (de la mémoire, du disque, un processeur supplémentaire sur une machine multi-processeur etc.).

La scalabilité horizontale peut être gérée dynamiquement simplement en démarrant une nouvelle machine et en informant le répartiteur de charge. On peut même si on pousse l'idée plus loin, ajouter et enlever des machines automatiquement selon les besoins : c'est ce qu'on appelle l'élasticité (une notion clé des solutions cloud comme nous le verrons). Ici aussi, vous devez percevoir l'intérêt de la virtualisation : en effet, à moins d'avoir des robots ou des armées d'ouvriers, comment pourrait on installer et dé-installer dynamiquement des ordinateurs physiques ?

La scalabilité verticale conserve son intérêt. Quand on choisit un serveur chez un fournisseur, on a tout intérêt à se préoccuper de la capacité d'évolutivité de la machine en question. En effet, il ne faut pas perdre de vue que si on virtualise les moyens informatique, il faut quand même des serveurs physiques pour faire tourner les systèmes virtuels, et que ce sont eux qui vont devoir encaisser un accroissement d'activité généré par la multiplication d'ordinateurs virtuels dans le cas d'une scalabilité horizontale. Et ils deviendront à leur tour un facteur limitant si vous devez les changer ou les immobiliser pour ajouter des processeurs, des disques, des interfaces réseau etc. Les serveurs spécialisés professionnels prennent tout leur intérêt avec de fortes capacité d'extension à chaud sans interruption de service.

SPOF

Encore un acronyme comme on les aime en informatique : Single Point Of Failure. Ce terme désigne le maillon faible d'une architecture, celui qui en cas de défaillance met en panne l'ensemble du système.

Dans notre exemple précédent, on parlait de mettre un répartiteur de charge devant n serveurs pour assurer la scalabilité horizontale. 

C'est super mais que se passe il si notre répartiteur de charge tombe en panne ? On aura beau avoir 100 serveurs mega-puissants derrière, on l'aura dans le coin coin. Le répartiteur constitue ici un SPOF.

Comment améliorer les choses ?

On a deux types de répartiteurs de charges : logiciels et matériels. Préférer un répartiteur matériel améliorera les choses : ils sont extrêmement robustes et très peu susceptibles de tomber en panne : mais ça arrive quand même (et en outre ça coûte très cher). Les marques les plus connues sont F5 et Alteon

Pour supprimer le SPOF, il faudra simplement un mécanisme de failover sur le load-balancer : si on met deux répartiteurs physiques en actif/passif par exemple, les probabilités de panne seront très très très faibles (mais pas nulles, le mécanisme qui fournit l'IP virtuelle en amont peut défaillir).

Quoi d'autre ?

Dans tous les exemples ci-dessus, nous avons parlé de HA au sujet d'ordinateurs en nous focalisant sur la ressource "capacité de traitement" du système informatique, qui est assurée bien entendu par le CPU des ordinateurs (en collaboration avec la RAM).

Mais d'autres éléments sont mis en oeuvre :
- de l'espace de stockage
- des communications réseau

Dans les infrastructures de production conséquentes, les ordinateurs n'ont souvent pas de disque et la gestion des disques est effectuée sur des périphériques de stockages dédiés et accessibles via le réseau.

Différents systèmes existent : le NAS est en gros un ordinateur qui héberge un service de serveur de fichiers auquel font appel les serveurs "cpu" (dans l'idée c'est comme un partage réseau sur un ordinateur de bureau), le SAN est un mécanisme beaucoup plus sophistiqué, coûteux et performant.

Tous ces "trucs" (ordinateur, load-balancer, NAS, SAN ...) communiquent par le réseau. Or un réseau ça implique aussi du matériel : switch pour cloisonner différents réseaux virtuels (switch administrable niveau 3), routeur pour l'interconnexion à Internet ou à d'autres réseaux étendus, firewall ...

Tous ces éléments sont également amenés à être supervisés et installés dans une configuration HA car leur défaillance ou surcharge est également critique pour l'ensemble du système.

Et, oui ... ces éléments peuvent également être virtualisés (ça devient un peu compliqué).

Au niveau logiciel

J'ai parlé ici de la HA au niveau matériel et système. Mais on retrouve les mêmes concepts au niveau logiciel. Je vais ici mettre le focus sur les architectures web, et les serveurs d'application mis en oeuvre pour assurer le rendu des pages des sites web dynamiques.

De nombreux serveurs d'applications offrent des solutions pour regrouper des serveurs autonomes en ensembles cohérents, pour l'administration et le déploiement des applications, mais également pour la mise en oeuvre de la haute disponibilité : load-balancing, failover.

Les serveurs d'application JEE (plateforme Java) en particulier sont riches en ce domaine que ce soit IBM Websphere, Oracle Weblogic, Redhat Jboss ...

Les architectures web ont cependant longtemps présentées une contrainte particulière : la gestion d'une session utilisateur se faisant dans la mémoire du serveur sur lequel l'utilisateur s'est initialement authentifié, le load-balancing qui a comme conséquence de le diriger vers un serveur de façon aléatoire ne peut pas être mis en oeuvre. Et si le serveur dans lequel sa session est gérée redémarre, les données de sa session sont perdues (en tant qu'utilisateur, vous perdez vos données mémorisées et vous devez vous authentifier à nouveau).

La session, pour les non spécialistes du web, c'est simplement la mémorisation des données spécifiques à un internaute entre deux requêtes, comme par exemple la liste de son panier d'achat (rappelons que le protocole http est sans état).

Pour pallier à ces deux soucis, il existe différentes solutions que j'expose rapidement :
  • on configure le load-balancer dans un mode particulier appelé "affinité de session" (sticky mode) qui permet de toujours rediriger un même utilisateur sur le même serveur Cependant, si ça permet de concilier load-balancing et session serveur, ça ne couvre pas le failover.
  • on configure le serveur d'application pour qu'il enregistre les données de session en base de données (sessions persistantes). On a ainsi le load-balancing et le failover mais les inconvénients sont très nombreux : le stockage des données de session en base est très lent et implique l'investissement dans du matériel très coûteux pour héberger le SGBDR, il y a des contraintes de programmation, on introduit un SPOF au niveau du SGBDR et si on veut l'éliminer il faut passer par des solutions techniques (réplication) également très coûteuses et qui ne sont pas sans inconvénient, en particulier au niveau de l'exploitation
  • on peut mettre en oeuvre des solutions qui permettent de stocker la session en mémoire mais de façon répartie, rapidement, avec de la redondance qui apporte le failover. C'est sans doute la meilleure solution mais ça implique l'achat de licences pour ces solutions (et leur apprentissage). A réserver pour les gros sites, avec des investisseurs au portefeuille garni.

Ceci étant dis, le mieux est probablement de bâtir une architecture dans laquelle on n'a pas de gestion de la session utilisateur côté serveur.

On qualifie ces architectures de stateless (sans état) et elles constituent l'état de l'art actuel, du moins à humble avis.

Ces architectures sont généralement basées sur des communications asynchrones en http effectuées par du code javascript s'exécutant dans le navigateur (technique de base du web 2.0, parfois encore appelé ajax). On parle de style d'architecture REST (bien que souvent, on soit plutôt sur du simple RPC over HTTP avec de la sérialisation au format JSON).

Explications du jargon : RPC ça veut juste dire "appel de procédure distante" (Remote Procedure Call) ce qui est le cas puisqu'on a un code javascript sur le client qui appelle une procédure sur le serveur ; over HTTP qu'on utilise le protocole HTTP pour faire cet appel de procédure (donc tout bêtement qu'on fait une requête http) : JSON, c'est "Javascript Notation", un format de sérialisation de données, ce qui en bon Français veut juste dire une façon de représenter des données de façon textuelle (dans un format qui en outre est directement compréhensible par un interpréteur EcmaScript, donc par javascript). Ces éléments sont présents et essentiels dans la définition d'une architecture REST qui nécessite cependant le respect d'autres points souvent ignorés par des développeurs qui font du coup du "presque-REST" (la confusion est fréquente).

Ce style d'architecture rencontre un grand engouement actuellement, bien au delà des applications web d'ailleurs, et combiné avec les outils et pratiques DevOps et les techniques de virtualisation moderne remet au gout du jour le SOA dans une variante désormais appelée micro-services.

Explications du jargon : SOA (Service Oriented Architecture) est un style d'architecture répartie qui a été très à la mode malgré une lourdeur certaine dans ses premières implémentations (SOAP pour ceux à qui ça parle), et qui revient actuellement sur le devant de la scène grâce à ce "nouveau" (en fait rien de nouveau pour les vieux briscards, mais bon passons) mode de mise en oeuvre basé sur REST, beaucoup plus simple et léger. Cette facilité d'implémentation, plus l'essor du mouvement DevOps qui rapproche les équipes de développements et d'exploitation et met l'accent sur des solutions techniques légères (comparativement aux serveurs d'application JEE cités plus haut qui sont des usines à gaz redoutables) favorise donc une nouvelle "saveur" de SOA rebaptisé "micro-services" pour faire oublier aux DSI les millions engloutis dans des projets SOA ayant explosé en vol (en partie du fait de la lourdeur des choix techniques initiaux, bien que les écueils de ces projets étaient bien souvent liés à des problèmes organisationnels).

Oui, mais si on a absolument besoin d'un session du fait des fonctionnalités et de l'ergonomie (un panier d'achat pour un site ecommerce par exemple) ? Hé bien, la session est gérée côté client. A un moment, il faudra bien renvoyer le paquet de données au serveur mais ça ne devrait pas constituer un facteur limitant dans 99% des cas. Et les frameworks javascript modernes facilitent désormais la programmation de ce genre de cas.

Comme on le voit, les choix d'implémentations ont donc aussi un impact fort sur la facilité plus ou moins grande à mettre en oeuvre une architecte HA.

Pour le fun : virtual hosting

Juste pour le fun. Si vous avez compris tout ceci, vous devez pouvoir comprendre comment fonctionne le virtual hosting dans un serveur http.

Le virtual hosting est la capacité pour un serveur http à héberger non pas un, non pas deux, non pas trois mais un nombre potentiellement très élevé de sites web. C'est la technique utilisée par les hébergeurs web pour leurs offres d'hébergement mutualisé (un serveur web partagé par n sites).

Mais comment est ce possible puisque chaque site web a un FQDN différent ? Et que chaque FQDN est censé pointer sur son serveur web dédié, via son IP spécifique ?

Hé bien, tous les noms de machines pointent sur la même adresse IP, celle du serveur web. C'est donc le serveur Web qui reçoit toutes les requêtes pour tous les sites. Exactement comme notre load-balancer tout à l'heure. D'ailleurs, on peut configurer un serveur web en tant que load-balancer, c'est l'alternative gratuite à l'utilisation des coûteux boitiers F5./Alteon évoqués (qui sont par contre infiniment plus performants vu que l'algorithme est implémenté au niveau matériel). Ici, le serveur web est configuré en reverse-proxy : comme son nom l'indique il fait l'inverse de ce que fait un proxy (qui rappelons le, reçoit les requêtes en sortie et les réémet) : il reçoit les requêtes en entrée et les adresse vers le bon destinataire en se basant sur le nom (FQDN) avec lequel il a été appelé. Sa configuration consiste à activer la fonctionnalité et à décrire les règles de mise en correspondance entre un FQDN et un répertoire racine d'un site web statique ou une adresse et un protocole de communication d'un serveur d'application pour un site web dynamique.

J'avais évoqué dans l'article sur le fonctionnement d'Internet la possibilité d'héberger plusieurs serveurs web à son domicile malgré le fait que notre box Internet ne dispose que d'une seule IP publique. Hé bien, c'est à cette technique que je faisais allusion : une règle de NAT au niveau de la box pour envoyer le trafic entrant sur le port 80 vers votre serveur http hébergé en interne et qui met en oeuvre du virtual hosting pour relayer le trafic vers n serveurs (http ou serveur d'application) de votre réseau interne. Vous voilà hébergeur !

Conclusion

Bon, j'ai écrit tout ça d'une traite après une nuit blanche (je vais me relire un petit coup quand même). Je n'avais rien produit depuis un moment, je suis en train de voir pour démarrer une activité en indépendant et je passe un temps insensé à chercher les infos à jour sur les mécanismes fiscaux et de protection sociale... bien plus compliqué que l'informatique croyez moi ! Et j'ai fait des études de gestion (j'ose pas imaginer la galère pour celui qui n'y connait rien).

La suite c'est de parler rapidement des solutions de virtualisation, puis de décrire les modèles économiques  du cloud computing (SAAS, PAAS, IAAS et même DAAS), et rebondir ensuite sur les solutions techniques de gestion de cloud et le mouvement/outils DevOps. J'ai toute la trame en tête , faudra juste que je prenne le temps.