Plus de machines, des services

La virtualisation n’était qu’une étape.

Le besoin de virtualisation

La virtualisation est apparue pour en finir avec l’ajout sans cesse de machines dans les salles serveur. Pour pouvoir garantir de la qualité, limiter la portée des incidents, permettre des cycles de vies différents, il est important de pouvoir isoler les services. La virtualisation permet de découper des serveurs physiques. En regroupant des services sur un serveur plus gros, on gagne en efficacité, en consommation d’énergie, et en souplesse pour réorganiser l’ensemble (il est possible de migrer une machine virtuelle sur une autre machine physique).

Abstraction matérielle

Cette nouvelle couche d’abstraction n’a pas été indolore, mais des optimisations sont arrivées rapidement. Les processeurs se sont adaptés en rajoutant des jeux d’instructions spécifiques (Intel VT et AMD-V). L’augmentation du nombre de coeurs au sein d’une même puce, et l’augmentation constante de la quantité de RAM disponible permet de passer en force. La virtualisation pure et dure est rapidement passée à la paravitualisation, l’OS invité devant faire quelques efforts d’adaptation en échange d’un gain en performance important.

Techniquement, il est possible de mélanger les OS (Linux, Windows, FreeBSD…), mais rester sur du tout Linux, en se contentant de mélanger les versions ou les distributions, simplifie beaucoup de choses.

Il est possible de redimensionner ou de déplacer une VM, mais concrètement peu d’hébergeurs le proposent, à part Gandi Cloud, peut-être. Le redimensionnement à froid est plus simple, et souvent, la migration vers une VM plus grosse est préconisée.

Augmenter la densité

Un serveur physique met à disposition un certain nombre de ressources (Processeur, RAM, réseau, stockage…). La virtualisation permet d’en mutualiser certaines (Openstack parle d’un ratio, pour la RAM, on peut monter péniblement à 1.5:1, en mettant en commun des plages de mémoire. Dans les cas les plus courant, la mémoire est partagée à 1:1, et ce sont les accès disques qui sont bloquants. Un ordonnanceur essaye de répartir équitablement les ressources, mais le phénomène du voisin bruyant est bien connu des utilisateurs d’AWS.

La plus petite tranche possible

Pour pouvoir profiter d’un minimum de parallélisme, il faut au moins avoir 2 CPUs dans une VM. Le ratio RAM/CPU et de 1:1 pour les offres basses (VPS OVH, Digital Ocean par exemple) pour monter à 3.75:1 pour de l’Amazon Web Service et Google Cloud, et grimper autour de 7:1 pour des VMs spécialisées. Ce qui fait quand même presque 8Go de RAM comme unité de base. Quand on est plus petit que Netflix ou Twitter, ça fait quand même une grosse tranche, surtout si l’on veut doubler le nombre de machine pour avoir de la redondance.

Découper différemment

Les machines virtuelles sont une bonne réponse, mais quelle est la question, déjà?

Pouvoir isoler des services.

Les besoins d’isolations sont finalement divers et négociables :

  • Répartir au plus juste la consommation des ressources (CPU, RAM, stockage, réseau).
  • Isoler les différents utilisateurs qui vont utiliser des ressources physiques communes (CPU, RAM, stockage, réseau)
  • Réstreindre les capacités des utilisateurs, pour limiter les possibilités de faire des bêtises, et donc les surfaces d’attaques.

Ces différentes possibilités ont été explorées, en patchant directement le noyau Linux. Vserver et OpenVZ pour le confinement, GRSec pour la sécurité.

Ces pistes, prometteuses, mais intrusives, ont permis la création de nouveaux modules dans le noyau Linux, permettant ensuite la création de produits, sans avoir besoin d’un noyau patché.

Les capabilities définissent les actions privilégiées que peut faire un process. Pour isoler des processus, il y a maintenant les namespaces, pour répartir les ressources, Google à offert les CGroups, pour la sécurité, les Linux Security Modules permettent avec quelques polémiques de brancher Apparmor, SELinux (cadeau de la NSA) ou des choses plus exotiques comme Tomyo ou Smack. Seccomp (issu de Google Chrome) permet de créer des règles de sandboxing (par thread) en BPF. BPF est la toute nouvelle machine virtuelle universelle pour Linux qui permet de définir des règles en user space, qui seront utilisées en kernel space, sans avoir à faire d’aller-retour. Libseccomp propose une interface de plus haut niveau pour définir ces règles de sécurité.

Les solutions de conteneurs officiels sont des assemblages de ces différents outils :

Les conteneurs sont une approche grandboutiennes, il est toujours possible d’avoir une approche petiboutiste, plus spécifique et du coup plus adapté, comme le propose uwsgi, un serveur d’application.

De toute façon ces outils se démocratisent rapidement, l’invasion Systemd amène avec lui les Cgroups (et donc les namespaces), et Apparmor est installé par défaut sur Ubuntu depuis la 7.10.

Découper le découpage

Il est possible de découper à grandes tranches avec de la paravirtualisation, qui pour l’instant est la seule à garantir une isolation forte, puis de confier ensuite la finition à un kernel Linux récent.

Simplifier le découpage

Une fois la démarche de conteneurisastion amorcée, il est tentant d’optimiser la pile en enlevant la couche de paravirtualisation. C’est la démarche qu’à fait Google, ils ont basculé vers le tout container. Google ne fait pas tourner de code dont ils n’ont pas confiance, ce qui facilite largement le passage au tout container. Au pire, ils peuvent avoir du code bête, mais pas du code méchant. LMCTFY, leur solution maison, utilise quand même Apparmor. Par contre, pour leur offre d’hébergement, Google Cloud, utilise toujours KVM.

Découper quoi?

Une machine virtuelle a une taille minimale plutôt conséquente. Il n’est pas possible d’empiler trop de machines virtuelles sur une machine physique. Tout pousse à utiliser les machines virtuelles comme des machines physiques, en y faisant cohabiter différents services. Certains services étant des prérequis (syslog, ntpd, dnsd, cron, atd…) d’autres étant un regroupement de services pour ne pas gâcher la place.

Découper des services

Un service peut être rendu par une ou plusieurs machines. Les services distribués peuvent utiliser le classique pattern master/slave ou des choses plus égalitaires, à base de Paxos ou de Raft.

Il est possible de redimensionner (confier plus ou moins de ressource) un service, ou d’en ajouter des instances, s’il supporte la distribution.

Utiliser des services

Un service est ce que va utiliser un développeur, il se fiche un peu des détails d’implémentation ou de paramétrages. Son application, qui n’est finalement qu’un service, va utiliser d’autres services pour fonctionner, et en bout de chaine, consommer des ressources.

Un développeur va utiliser des services, qui seront dimensionnés en fonction de la demande et du budget disponible.

Ces services pourront être classique, comme du stockage, du backup, une base de données relationnelle, mais aussi plus abstrait comme de l’antispam (Akismet…), le stockage distribué de S3, la proximité d’un CDN, la surveillance d’un pingdom, la consolidation des erreurs d’un Sentry (un projet libre), l’analyse de performance d’un Newrelic… la liste évolue de jour en jour.

L’informatique est maintenant de plain-pied dans l’ère des services.

blogroll

social