Cette série d'articles a pour objectif de présenter l'évolution des techniques et des métiers de l'hébergement Web du milieu des années 2000 à nos jours. Ces techniques concernent la manière dont on rend visible une application Web à ses utilisateurs sur Internet: quels matériels, quelles configurations, quels problèmes rencontre-t-on ? On montrera que le moteur de cette évolution est de minimiser les efforts et les investissements à engager pour servir toujours plus d'utilisateurs. On commencera par l'arrivée du Cloud avec AWS en 2006 et la machine virtuelle comme plateforme de référence, puis l'arrivée des containers Docker en 2013 et de Kubernetes deux ans plus tard, puis l'explosion des services managés pour les bases de données, le stockage, l'observabilité, et finalement pour le code applicatif côté serveur, avec Cloud Run en 2019.
L'évolution des techniques d'hébergement Web est une longue histoire. Si on commence à l'éclatement de la bulle Internet au début des années 2000 et qu'on avance jusqu'à nos jours, on peut dire qu'elles n'ont cessé de se transformer pour, dans un sens, se faire oublier.
Une double contrainte s'applique aux infrastructures d'hébergement, celle d'abord de servir toujours plus d'utilisateurs finaux (ceux qui utilisent l'application), pour les servir plus vite pour moins cher, de manière fiable et en engageant le moins d'effort possible de la part de l'équipe technique. La contrainte aussi de servir ceux qui font l'application, les développeurs, qui ont leurs propres attentes vis-à-vis de l'infrastructure. Ils doivent pouvoir déployer et tester leurs mise-à-jour rapidement sans être contraint dans le développement du produit par les limites techniques de l'infrastructure.
À la fin, quand le système est bien rodé, c'est toute l'entreprise qui y gagne : on se démarque en répondant plus vite que ses concurrents aux attentes des utilisateurs finaux parce qu'on déploie plus vite que les autres les fonctionnalités attendues, et on accueille les nouveaux utilisateurs sur le produit, quel que soit leur nombre, en leur offrant la même qualité du service que les autres. Tout ça sans devoir toucher à son infrastructure. Le paradis.
Comment espérer sinon une croissance annuelle à trois chiffres pour les startups SaaS s'il fallait revoir son infrastructure à chaque nouvelle dizaine de milliers d'utilisateurs pour le B2C, ou faire patienter les nouveaux arrivants chèrement acquis par le marketting le temps d'allouer plus de ressources ?
Une double contrainte de simplicité et de rapidité à passer à l'échelle quand le volume d'utilisateurs augmente donc, et de souplesse d'utilisation pour déployer des mises-à-jour pour les développeurs.
Pour illustrer la première contrainte, imaginez-vous que Google fonctionne sur votre ordinateur personnel. Quand quelqu'un fait une recherche sur Internet, c'est votre ordinateur qui réfléchit et qui lui répond. Vous sentez sans doute que pour quelques utilisateurs votre ordinateur pourra s'en sortir. Mais passer un certain seuil cela risque de ralentir, et peut être de se bloquer.
Ce qui limite les capacités d'un système à servir plus d'utilisateurs in fine c'est toujours soit la puissance du processeur, soit la taille de la mémoire, soit la vitesse de lecture/écriture vers les disques ou le réseau.
Alors pour répondre à ce problème on peut envisager deux approches :
Sous des apparences simplistes, c'est en réalité ce que l'on fait lorsqu'on veut servir plus d'utilisateurs. Soit l'une, soit l'autre, soit un mélange des deux.
On appelle la première scalabilité verticale : on garde la même base mais on lui donne plus de ressources. Et la seconde scalabilité horizontale : on rajoute une nouvelle machine à côté de la première pour former un cluster.
La scalabilité verticale est en général l'approche la plus simple : on éteint la machine, on lui donne plus de ressource, on la relance, et voilà. Mais cette approche a aussi ses limites. On pourra peut-être trouver un processeur 2 fois plus puissant que l'original, peut-être 10 fois même, mais 10000 fois, sans doute que non.
Il faut donc trouver une autre solution, et ça sera la scalabilité horizontale. On sent qu'avec cette approche on pourra réunir s'il le faut 10,000 machines pour les faire fonctionner ensemble, mais la question alors c'est de les coordonner pour qu'elles travaillent ensemble le plus efficacement possible, sans perdre trop de temps à se coordonner justement, ce qu'on pourrait résumer d'une manière générale par échanger de l'information efficacement.
Et ça, ce n'est pas si facile.
Une première raison à cela c'est que d'échanger de l'information entre machines, c'est beaucoup plus lent que de communiquer entre les organes d'une même machine. Pour illustrer:
L1 cache reference (intra CPU) | 0.5 ns |
Main memory reference | 100 ns |
Send 1K bytes over 1 Gbps network | 10,000 ns |
Read 4K randomly from SSD* | 150,000 ns |
Round trip within same datacenter | 500,000 ns |
Send packet CA->Netherlands->CA | 150,000,000 ns |
Référence ici, chiffres 2012, un peu datés donc, mais les ratio reste les mêmes.
Ce qu'on peut déduire de ce tableau c'est que la plupart des opérations qui se déroulent à l'intérieur d'une machine, hors IO-disque (L1 Cache et memory read, ~100 ns), sont 5000 fois plus rapides qu'une communication aller-retour entre deux machines dans un datacentre.
Une autre raison pour laquelle la scalabilité horizontale ce n'est pas si facile, c'est qu'il va falloir rajouter à son système des composants d'infrastructure pour diviser le travail entre les machines et leur permettre de se coordonner donc.
Imaginez. Avec la scalabilité verticale, je rajoute de la RAM à une machine A. Après l'opération je n'ai toujours qu'une machine. Même configuration réseau, même configuration de l'OS, même place dans le datacentre. Facile.
Maintenant avec deux machines il va falloir que je rajoute de quoi répartir les requêtes des utilisateurs entre elles (un loadbalancer), puis il ne faudrait pas qu'une machine garde pour elle seule de l'information donnée par l'utilisateur (une mise à jour de son profil par exemple) à une autre, il nous faut donc du stockage partagé. Et vous comprendrez, plus de machines = plus de pannes potentielles ! Il va donc nous falloir qu'on sache les détecter et rectifier la configuration du load-balancer en conséquence, quand une de nos machines nous aura fait faux bond.
Puis si on pousse le bouchon, on comprend que si veut rajouter une troisième machine il va là aussi falloir mettre à jour nos configurations, installer notre application, tenir cette nouvelle machine à jour pour s'éviter des failles de sécurité... Bref, de bons moments en perspective pour notre équipe IT pre-serverless :-)
Mais rassurez vous, on peut dire que ça c'était avant. Mais il fallait bien commencer par quelque chose. Dans le cas où l'entreprise choisissait d'investir dans sa propre infrastructure, c'est à dire d'acheter ses serveurs, son loadbalanceur, son matériel réseau, il lui fallait aussi un administrateur système et un administrateur réseau pour s'occuper de tout cela.
La première étape vers plus simplicité c'était d'ouvrir un compte chez un fournisseur de Cloud, prenons AWS à partir de 2006, et de cliquer au bon endroit sur leur interface web pour obtenir exactement les mêmes ressources, le tout en quelques minutes, et sans administrateur réseau ni système. Il vous aurait sans doute toujours fallu un administrateur système pour la suite, faire vivre le système, mais pour l'administrateur réseau, c'est moins sûr.
Nous nous arrêterons là pour ce premier article, et irons regarder de plus près ce que c'est que de servir une application Web dans le prochain !