Diskless
“Less is more” comme disent les inventeurs de buzzwords.
Diskless, sans disques, est une optimisation (radicale) pour gérer un ensemble de serveurs (réels, virtualisés, ou même des conteneurs).
Désagrégation
Un serveur, c’est un ensemble processeur (CPU/GPU) / mémoire / stockage avec du réseau. Les utilisateurs, rien que pour embêter l’hébergeur, ne vont pas vouloir un ratio fixe entre ces ressources matérielles, et même vouloir changer d’avis.
La désagrégation propose d’exploser ses ressources, et de composer un serveur, en piochant dans son pool de ressources.
Spoiler alert, même avec les performances monstrueuses que peuvent atteindre les cartes réseau modernes, on ne peut pas encore généraliser la mémoire désagrégée, même si la norme CXL existe, et des gens s’amusent avec. Mais si c’est techniquement faisable, il n’y a pas d’abstractions magiques et universelles. Les machines multiprocesseurs ont encore des histoires de NUMA, et il est toujours pertinent de profiter de la localité des données et des différents caches. Des abstractions de plus haut niveau ont déjà prouvé leur pertinence, comme Open-MPI, qui évite de lier du code métier à du matériel exotique.
Externaliser le stockage des ordinateurs existe depuis très longtemps, ajouter des boites reliées par des câbles faisant partit des plaisirs simples de l’informaticien.
Débit de disques
Les branchements ont d’abord était cul à cul, puis chainés, switchés, pour enfin utiliser du réseau comme tout le monde.
Les grosses cartes réseaux proposent maintenant de faire plus que du réseau, et mettent à disposition des processeurs ARMs ou du FPGA. On parle de SmartNIC, ou de NPU. Classiquement, la carte propose d’effectuer le chiffrage, les checksums, ou de filer un coup de main pour la virtualisation réseau (comme vSwitch), de prendre en charge le XDP. DPDK propose d’unifier toute cette magie gravée dans le silicium.
Un réseau “normal” est en 10G, sachant que le 100G existe, et que l’on peut agréger les liens pour additionner les bandes passantes.
Vous pouvez mettre ce genre de monstre, 128 * 100Gb, soit 12,8Tb en 4RU comme top of rack, mais bon courage pour connecter les racks avec une bande passante suffisante.
Il est compliqué de comparer les technologies, le débit n’est qu’une des métriques (il peut être symétrique ou asymétrique), les IOPS changent complètement entre les disques à plateaux et SSD, les latences changent d’ordres de grandeur selon les technologies.
Le SATA est encore utilisé pour du stockage massif (comme le propose Backblaze).
L’USB4 intègre Thunderbolt, mais il n’est pas conçu pour les datacenter, il est possible de relier des baies de disques en SAS (en cuivre ou en fibre optique), pour former un gros SAN.
le CXL se base sur PCIe 5.0 et 6.0, mais cible la RAM, pas le stockage.
Samsung arrive à saturer (de peu) les 63G du PCIe 4.0 en x4 avec son SSD PM1735 et donc utilise du x8.
La Pmem (mémoire persistante), est connectée comme une barrette de RAM, en RDIMM. Les performances sont comparables à du PCIe 6.0 en x16. Le chiffre est pour comparer avec les autres technologies, l’intérêt de la Pmem est sa latence, et la proximité avec le cache du processeur.
Technologie | Débit |
---|---|
SATA 3 | 4.8Gbit/s |
HDD 16To lecture séquentielle | 2 Gbit/s |
SAS-5 | 45Gbit/s |
USB4 Gen 3x2 | 40Gbit/s |
USB4 gen 4 | 80Gbit/s |
fibre channel gen 7 | 64Gbit/s |
fibre channel gen 8 | 128Gbit/s |
Infiniband NDR | 106Gbit/s |
PCIe 4.0 x4 | 63Gbit/s |
PCIe 4.0 x8 | 126Gbit/s |
PCIe 6.0 x16 | 968Gbit/s |
Pmem | 1000Gbit/s |
C’est rare que le matériel soit utilisé en 1 seul exemplaire, les benchs SPDK sont faits sur un serveur avec 2 processeurs de 28 cœurs, 14 disques SSD, 4 cartes réseau de 100Gbits, pour un résultat maximal de 330Gbit/s (sur 400 théoriques). Un serveur de stockage à haute densité, c’est 70 disques.
Disque réseau
Un tas de disques utilisé via du réseau par un tas de serveurs s’appelle un SAN, Storage Area Network, et à pendant longtemps nécessité du matériel spécifique (et cher).
Protocoles
iSCSI
L’un des vénérables protocoles de disque dur, SCSI (première version en 1986 quand même), avec ses gros câbles qui changeaient du tout au tout à chaque nouvelle version majeure, a eu droit à son passage au réseau, avec iSCSI, au début des années 2000.
Fibre Channel (fibre et non fiber, pour faire chic) permet (entre autres) de faire passer des commandes SCSI sur un réseau switché (plusieurs ordinateurs peuvent se connecter à plusieurs disques). Fibre channel est luxueux, il nécessite du matériel et des compétences spécifiques.
L’idée du iSCSI est simple, faire passer les messages SCSI en TCP/IP, et permettre ainsi de contrôler des lecteurs de bandes, de changer des cassettes, des CD-ROMs, et aussi des disques durs, sur un réseau classique.
40 ans de SCSI, 20 ans de iSCSI, sa réputation n’est plus à faire, même si les disques SCSI n’ont pas passé l’an 2000 (remplacés par le SAS) avant la déferlante SSD.
NBD
NBD est un protocole vintage, 1997, mais simple, qui permet d’exposer des blocs en TCP/IP. Datant de l’époque des disques à plateaux, il ne propose pas de parallélisation, chose que font très bien les SSDs.
NBD a gagné le statut de format “presque standard” pour exposer des blocs.
go-nbd est fort pratique pour bricoler du bloc avec golang, et je vous recommande ma démo stream-my-root.
QEMU l’utilise pour exposer ses images QCOW2 avec qemu-nbd.
Autre fan de QCOW2, libguestfs propose un projet enthousiaste, nbdkit pour gérer un protocole placide.
Ceph RBD
Ceph se positionne comme la solution ultime et universelle du stockage réseau : il gère les 3 modèles : blocs, fichiers, blobs. Il est rétrocompatible avec l’existant: système de fichiers UNIX, iSCSI, NFS, S3, et avec ses propres protocoles.
Ceph est le service bloc standard des gens qui n’ont pas de SAN iSCSI (Digital Ocean, OVH, Scaleway … Hetzner ?).
NVMeOF
Les premiers SSD avaient une interface SATA, pour faire la transition avec les disques à plateaux, et ont rapidement saturé les performances de ce bus. Le NVMe est un SSD qui utilise directement du PCIe, de manière non bloquante, tous les cœurs d’un CPU peuvent discuter avec le disque. Le NVMe est apparu sous forme de grosses cartes PCIe, puis finalement dans des formats plus pratiques, comme du M.2 pour le grand publique, et du U.2 ou U.3 pour les serveurs (en conservant les racks utilisés par SATA et SAS, et la connexion à chaud).
NVMeOF, comme NVMe Over Fabric, reprend l’astuce du iSCSI et fait passer les messages NVMe prévus pour du PCIe sur du réseau qui lui aussi utilise du PCIe. Le PCIe utilisé par NVMe et le réseau permettent des optimisations redoutables, comme le RDMA, Remote Direct Memory Access, la carte réseau peut exposer un disque NVMe distant, sans passer par le processeur. La communication de carte à carte pouvant être faite en Fibre Channel, Infiniband, ou tout simplement en Ethernet (avec ROCE RDMA Over Converged Ethernet).
NVMeOF peut aussi être géré de manière logicielle (pouvant profiter de l’accélération matérielle de la carte réseau), côté client ou serveur, sous l’égide du projet SPDK, qui centralise tous les efforts NVMe pour Linux.
Du MVMeOF logiciel ne dépend pas de NVMe et peut donc partager un gros disque SATA ou même un disque dynamique.
SPDK a fait de chouettes benchmarks, qui mettent bien en valeur le gain en latence de RDMA face à TCP : 6 fois mieux.
Les blocs du noyau Linux
Le noyau Linux fournit les briques de base pour gérer des disques, que ce soit en espace noyau ou utilisateur, avec sa fascination pour le rangement et le dédoublonnage.
bdev
bdev est la couche de base pour écrire un pilote pour exposer des blocs.
io_uring
Le noyau Linux a galéré pour proposer une API asynchrone pour la gestion du stockage.
Libuv, grand unificateur des API asynchrones, se contente d’un pool de threads pour gérer les accès disques
Il y a eu la tentative AIO, mais sans API équivalente pour les sockets, ça rend les interactions compliquées.
io_uring permet une communication non bloquante avec le stockage avec d’excellente performance.
En juin 2023, Google a constaté que pour l’année 2022, 60% des failles Linux soumises à son bug bounty étaient liées à io_uring, du coup bannissement massif dans l’écosystème Google, suivi par Docker qui en a entrainé d’autres comme Bun.
On attend le retour en grâce du très prometteur io_uring.
ublk
ublk permet aux kernels d’exposer des blocks, en espace utilisateur. Ublk utilise io_uring pour un échange sans interruption entre les espaces noyau et utilisateur. C’est une bonne nouvelle pour les performances, mais il y a eu de grosses failles de sécurité avec io_uring, ce qui lui a valu un bannissement (temporaire) de Google et Docker. Il faut donc attendre la bénédiction d’un acteur majeur avant de pouvoir profiter de cette prometteuse technologie.
ublksrv est le cadriciel en espace utilisateur (le framework en usersapce) pour ublk.
Ublksrv permet par exemple de monter des images QCOW2, et il sera possible de faire du NBD (avec du zero-copy entre le block et le réseau).
Ublk est aux blocs ce que FUSE est aux fichiers.
TCMU
TCM permet de créer une cible SCSI (un serveur) dans le noyau Linux. TCMU est un TCM Utilisateur, et permet donc à une application de se comporter comme un disque SCSI.
FUSE expose des fichiers, ublk des blocs, TCMU une cible SCSI.
TCMU a été utilisé avant l’arrivée de ublk ou vhost-user.
Device mapper
Device Mapper permet de composer sa gestion de blocs en empilant des fonctionnalités plus ou moins exotiques (compression, chiffrage, cache, raid, instantanés, COW …) et même du débug (mesure de performances, ajout de latences…). Device Mapper sert de base à LVM, Logical Volume Manager.
vfio
vfio permet d’exposer en espace utilisateur le DMA d’un périphérique, emballé dans un IOMMU. Le périphérique exposé par VFIO peut être confié à une application, ou même un conteneur.
vDPA
vDPA/VDUSE comme “virtio data path acceleration” et “VDPA Device in USEr space” est une norme pour avoir des drivers en espace utilisateurs qui bénéficient des spécificités d’un drivers (accélérations et délestent proposés par une carte réseau futée (smart NIC/DPU), ou du DMA bordé par un IOMMU). L’idée de conserver l’isolation fournie par une machine virtuelle ou un conteneur, mais de bénéficier des spécificités d’un matériel, sans émulation ou paraphrases. VDUSE permet d’utiliser un périphérique virtio dans le kernel hôte, et de le confier à un conteneur. vDPA permet a QEMU d’utiliser un matériel spécifique, on parle alors de “fast path”, et si l’on souhaite migrer la machine virtuelle sur un hôte sans l’accélération matérielle, il basculera en émulation, on parle de “slow path” (et ça va commencer à ramer sévèrement).
les Virtios de KVM
Virtio normalise (à la hache) des drivers minimalistes pour que les OS invités utilisent des pilotes simple et minimaliste, et quand c’est possible du “passage direct” entre l’invité et l’hôte (du pass through, quoi).
Virtio est utilisé par les différentes solutions de virtualisation basées sur KVM, mais aussi par Xen.
virtio-scsi et virtio-blk
virtio-scsi permet d’exposer du bloc comme un disque SCSI, c’est standard pour l’invité, mais ça tire la longue histoire de SCSI.
virtio-blk se contente d’exposer du bloc.
Par défaut, côté hôte, les services sont statiques et exposent des images disques.
Pour fournir dynamiquement une image disque, il est possible de faire des bricolages honteux, en servant l’image disque via un montage FUSE, comme dans l’article AWS sur le streaming de disque pour firecracker.
vhost-user
vhost-user est le protocole officiel pour exposer un service en espace utilisateur, à un virtio, coté invité. vhost-user utilise un anneau pour discuter sans interruption entre l’hôte et l’invité, de manière comparable à ce qu’utilise io_uring.
vhost-user peut être utilisé pour discuter avec tous les virtio (comme le vhost-device de rust-vmm), mais aussi virtio-blk, et il existe diverses implémentations de backends (comme le documente Firecracker)
- Qemu backend : qemu-storage-daemon
- Cloud Hypervisor backend
- crosvm backend (la VM de ChromeOS, l’un des fondateurs de rust-vmm)
- SPDK backend
Libblkio
libblkio est une bibliothèque rust qui se focalise sur son API C, et propose de brancher tout vers tout : io_uring, NVMe, virtio-blk (vhost-user ou même vhost-vdpa et vfio-pci).
Les blocs du Cloud
Toutes les offres Cloud proposent des disques réseau tellement pratiques à l’usage.
Les gros du cloud ont des outils maison, la plupart des autres utilisent Ceph, sans forcément le préciser, alors que Digital Ocean en profite pour faire de la pub sur le bouquin de leur Mr Ceph
Cinder
Openstack souhaite normaliser le Cloud, ce qui est une idée sympathique, il propose une API normalisée et tous les fabricants de matériel fournisse un pilote.
Cinder est le service de blocs d’Openstack.
Il propose une quantité invraisemblable de pilotes, avec pas mal de SANs, et les grands classiques open sources.
Amazon EBS
AWS aime bien rester nébuleux dans ses pages produits, mais il donne des indices sur son stockage bloc io2, et d’autres infos techniques dans cette présentation re:Invent de 2012 (il faut zapper les présentations produits pour se concentrer sur le techos).
- NVMeOF
- Le réseau (IP) de stockage est isolé du réseau classique
- Pas de TCP, mais du SRD, qui utilise du multipath
- 4Gbps par volume
- Accélération matérielle avec la carte Nitro
Google Cloud Hyperdisk
De manière prévisible, Google donne peu d’informations techniques sur son Hyperdisks, l’OS invité lui cause en SCSI (le virtio-scsi ?) ou en NVMe (du NVMeOF exposé par leur carte SmartNIC gvNIC ?)
Le débit maximum de 24 Gbit/s (avec 5 disques) est assez énorme.
Hyperdisk est fier de découpler les IOPS et bande passante du nombre de CPU, le ratio fixe par CPU est classique pour la RAM ou le disque local, mais là, hyperdisk désagrège le stockage, et l’on peut réserver (IOPS, bande passante) selon un planning, pour ne pas avoir à surdimensionner pour uniquement encaisser les pics d’utilisations.
Azure Elastic SAN
Azure se contente de vendre des tranches de SAN, avec une bande passante par To de stockage. Le partage se fait en iSCSI sur un réseau privé.
Les blocs de l’open source
Les SANs sont hors de prix, les formats sont normalisés, ça fait deux raisons d’avoir des implémentations libres de serveurs de disques en mode blocs.
Open-ISCSI
La RFC3720 est un poil aride, ça utilise de vieux protocoles (comme SLP ou RADIUS), il faut du matériel exotique pour tester la partie RDMA, il n’y a donc pas un enthousiasme fou pour implémenter iSCSI, c’est donc open-isci qui s’y colle, accompagné de tgt pour la partie en espace utilisateur et son daemon.
SPDK
Storage Performance Development Kit est, entre autres, le roi du NVMeOF. Il cause aussi le iSCSI, le vhost (pour virtio), le ublk (pour Linux en espace utilisateur), le CSI de k8s et d’autres trucs exotiques, mais surtout, il a un daemon, spdk_tgt pour configurer tout vers tout, qui discute en JSON-RPC 2.
SPDK met à dispositions des fonctions de plus niveau, comme la gestion des volumes et la création d’instantanés.
SPDK utilisé des modules qui permettent d’ajouter des fonctionnalités comme le “copy on read and write” du bdev_ubi d’Ubicloud, qui permet de cloner une image de base et de l’utiliser tout de suite (attention à la licence non libre)
SPDK est souvent le backend caché derrière des applications de plus haut niveau.
Ceph
Ceph a comme couche basse RADOS (Reliable Autnonomous Distributed Object Store), au-dessus duquel vont être construits des services (utilisant librados pour la plupart) comme RBD ou le NVMeOF de SPDK, et en dessous, il y a des “stores”.
- Filestore, des fichiers sur du XFS, maintenant déprécié.
- BlueStore), du bloc cru (raw block), capable d’utiliser du HDD et de profiter du SSD (et pmem) pour les métadonnées et les journaux.
- Seastore, prochainement, du full NVMe avec SPDK pour avoir une gestion fine du TRIM et proposer du zero copy (avec l’aide de DPDK, pour peu que l’on ait une carte réseau avec du DMA)
- Des travaux sont effectués pour gérer les disques zonés (comme les HDD SMR).
Ceph propose des fonctions avancées comme la création d’instantanés et le COW.
Ceph sait parler le Kubernetes avec ceph-sci.
Débuté lors d’une thèse, le projet a intéressé des scientifiques générant beaucoup de données (Los Almos, le CERN…) avant d’être rachetés par Red Hat, qui a créé une fondation avec d’autres participants de prestige. Suse a d’abord collaboré avant de bouder et mettre en avant son Longhorn.
Sheepdog
Feu Sheepdog était une solution de stockage de blocs distribués, qui s’appuyait sur corosync et Zookeeper. La passerelle iSCSI était assurée par le même tgt utilisé par Open-iSCSI.
Le projet est SUPER STABLE depuis 7 ans. Son fork, sheepdog-ng, est dans le même état.
DRBD / Linstor
Distributed Replicated Block Device est un module de bloc répliqué distant pour le noyau Linux. On écrit sur un bloc local, le noyau réplique (en TCP ou RDMA) l’écriture sur un bloc distant, en synchrone dans le scénario recommandé.
DRDB est une des briques de bases de HA Linux, et permet d’avoir un serveur de secours disponible en cas de défaillance du serveur principal.
Le répliqua n’est pas accessible en lecture, ce qui empêche la répartition de charge en lecture.
Les gens audacieux peuvent utiliser DRBD en multiprimaire, pour peu qu’ils utilisent un système de fichier adapté (comme les exotiques GFS et OCFS2).
Linstor expose un volume DRBD dans différents protocoles (iSCSI via tgt et NVMeOF via SPDK), en assumant la haute disponibilité. Linstor fournit les drivers de haut niveau comme Cinder pour OpenStack ou CIS pour k8s.
OpenEBS
OpenEBS a un logo moche, mais il a plus d’étoiles Github que Longhorn.
OpenEBS est issu de la libération de Mayastor.
Mayastor est maintenant le service utilisé par un agent CIS pour que k8s puisse utiliser des volumes persistants. Mayastor est stateless et cause à différentes sources de blocs, dont l’agent SPDK ou LVM. Mayastor est utilisable par des microconteneurs (Firecracker, Kata), via vhost-user (et donc virtio), et même hors de l’écosystème k8s (pour faciliter le débogage et les migrations).
Longhorn
Longhorn est le service CIS de Rancher.
Rancher se positionne comme le vulgarisateur de Kubernetes et fournit des projets réputés, comme k3s la plus petite des distributions k8s, ou Elemental qui crée des images Linux immutables à partir de fichier Dockerfile.
Rancher est maintenant racheté par Suse.
Dissection de longues cornes
Longhorn, dans sa version actuelle, expose les blocs en iSCSI, via un fork de tgt qui ajoute son propre backstore bs_longhorn, qui se contente de faire le passe-plat, en confiant toutes les commandes lire/écrire/effacer à un service en go, qui lui détient tout le code métier : la réplication, la création d’instantanées, la détection d’incidents et les réparations, comme le détail la documentation secrète.
Le hack de tgtd (repris de Sheepdog), est audacieux, tout comme utiliser un service en golang (avec son ramasse-miette) pour gérer de faibles latences. Autre temps, autres mœurs, en 2016, il n’y avait pas ublk ou même SPDK. Il y a eu une version utilisant TCMU, l’ancêtre de ublk.
Les images disques sont de simples fichiers troués (sparse file), et Longhorn utilise ses sparse-tools, pour ne pas s’embêter avec les trous lors de la création d’instantané, recopie et consolidation. Pour ça, ils s’appuient sur les file extent mapping du noyau Linux (fiemap étant le successeur de fbmap qui lui ne voir que des blocs). Pour bénéficier de fiemap, il faut utiliser un système de fichiers gérant les extents, et pour créer des instantanés, fsfreeze sera utilisé, ce qui ne laisse que XFS et ext4 comme système de fichier utilisable.
La version 2 du moteur de données de Longhorn s’appuie sur SPDK et NVMeOF. Une grosse partie des fonctionnalités sont maintenant assumées par SPDK (accès distant, réplication, instantanés…).
Les gains en performance sont clairs, pas énormément sur la bande passante, mais clairement sur les IOPS et les latences, et la différence est plus flagrante avec un meilleur débit réseau.
La documentation insiste sur ce point : il faut dédier un cœur à spdk_tgt
pour ne pas avoir de fluctuations de performance (jitter).
Au-delà de Longhorn : Harvester
Harverster s’appuie sur LongHorn (et Rancher) pour proposer un service d’infrastructure hyperconvergente (un Proxmox like, quoi).
C’est intéressant de voir une architecture du nouveau monde Kubernetes proposer de la gestion de machines virtuelles (l’ancien monde, donc), auquel on pourra ajouter des conteneurs.
Au-delà des blocs réseau
Un volume réseau est une réponse universelle qui permettra de faire comme avant, sans rien changer, et vous proposera des choses bien pratiques, comme les instantanés, l’agrandissement déraisonnable, ou la déconnexion depuis une machine virtuelle pour se reconnecter vers une autre machine.
Un volume bloc ne sera accessible que depuis un seul client, ou alors il faut mettre les doigts dans gfs2 ou ocfs2. Globalement, un système de fichier distribué aura un comportement différent (et décevant), que ce soit en mode bloc ou fichier.
Réseau
TCP
Le drame de TCP est son ossification, son incapacité à évoluer.
TCP doit faire un compromis sur la taille des paquets, soit des gros pour le débit, soit des petits pour la latence, et il y a encore des drames avec le TCP_NODELAY
pour éviter d’attendre 200ms pour tenter de remplir une trame et limiter le surcout des entêtes.
le reproche principal de TCP est son contrôle de congestion qui attend la perte de paquets pour prévenir la source que le tuyau est saturé.
ECN
La RFC3168 propose d’anticiper l’arrivée d’une congestion, et de ne pas arriver à l’étape fatidique de la destruction de paquet. Pour ça, un champ de l’entête IP, ECN (2 bits), pour Explicit Congestion Notification, est utilisé pour indiquer que la file d’attente a atteint un seuil, et que si ça continue comme ça, il va couper.
Les deux bits ECN sont dans l’octet TOS, qui a eu d’autres usages, et quand on envoie une trame TCP, on ne sait pas si le switch gère l’ECN. S’il le gère, le switch va flipper un des bits, l’autre servant d’annonce de congestion.
Donc, pour bénéficier d’ECN, il faut que les switchs sur le trajet le gèrent, et par exemple, chez AWS, c’est niet.
DCTCP
Le noyau Linux utilise des modules pour le contrôle de congestion, et dctcp (comme DataCenter TCP) utilisé ECN pour anticiper les congestions.
Il y a une RFC, donc Bortzmeyer en parle : 8257
MPTCP
MPTCP propose d’ajouter le multi path à TCP, sans casser Internet, sans modifier les applications.
Même Bortzmeyer dit du bien de la RFC 6182, et explique divers points.
Fort pratique pour les connexions mobiles (4G + Wifi), il peut avoir sa place dans un datacenter, pour profiter de la redondance du réseau. Déjà déployé dans les téléphones, Linux commence à avoir l’outillage nécessaire pour faire correctement du mptcp avec un démon en userspace, mptcpd pour configurer finement le comportement. Les outils se concentrent sur les usages mobiles, ciblant HTTP et SSH, et je n’ai pas vu grand-chose ressemblant aux stratégies ECMP de SRD.
C’est sage de partir sur une technologie compatible avec l’existant, mais je suis curieux de voir comment ça va évoluer dans des réseaux policés comme ceux des datacenters.
Je miserai sur les proxys HTTP, comme premiers déploiements en prod, si votre HAproxy gère mptcp, c’est gagné (il y a d’ailleurs une PR pour mptcp). Golang le gère depuis la 1.21 ça devrait débarquer dans Traefik rapidement (aucune occurrence dans le code, pour l’instant).
En interne, en garantissant l’ordre des paquets, on va subir la latence du pire chemin, même si on peut profiter d’un meilleur débit.
J’ai du mal à voir le bénéfice par rapport à un client qui se connecte directement à une des instances d’une application distribuée, sans passer par un proxy. Pour de l’HTTP, c’est rigolo à coder, je l’ai fait avec le projet Medusa.
BBR v3
Google dit que pendre sur TCP, qui est “ossifié”, et si son QUIC est une alternative efficace, il n’est pertinent que pour l’Internet public, plein de bruit et de fureur.
Plus universel, Google revient à la charge et propose sa troisième itération de BBR, son algorithme de contrôle de congestion. Comme tout le monde, il méprise la perte de paquet comme indicateur de congestion et se concentre sur le classique algorithme AIMD et les informations de délais et ECN. Comme DCTCP, quoi. Google bosse sur le sujet depuis des années, et l’a utilisé chez Youtube, mais surtout pour ses connexions entre datacenter.
Il fournit un module pour le noyau, mais aussi un patch pour ip
et ss
.
Le statut est “test élargi”, du bêta, quoi.
Hystart++
Microsoft bosse aussi sur le contrôle de congestion, et il a spécifié son Hystart++. Cloudflare a fait une implémentation de Hystart++ pour QUIC dans Quiche.
Pour Linux, le hystart sans ++, la version précédente, est intégré comme paramétrage pour le contrôleur CUBIC.
RoCE
La norme ROCE souhaite normaliser le RDMA en mettant de l’Infiniband dans de l’Ethernet, et donc se passer des couteux câbles et switch Infiniband, pour du classique Ethernet (classique, on parle quand même de carte 10G et la plupart du temps de fibre optique).
La version 1, assez naïve, ne fonctionne que dans un même sous réseau, non routable.
RoCE v2 est un véritable protocole Internet, utilisant UDP, routable, mais utilise ECN pour notifier les congestions. Voilà, de l’UDP avec ECN,conçu pour TCP, mais utilisé dans IP, la couche en dessous, du bon gros recyclage. Visiblement, pas tous les switchs le gèrent.
RoCE va envoyer des messages sur le réseau, dans son monde, on parle de “verbe”, mais surtout va envoyer de gros blocs de mémoire de RAM à RAM, sans passer par le CPU, comme le permet le PCIe, du RDMA (Remote Direct Memory Access) et pour ça, il faut une carte réseau qui sache le faire.
SRD
AWS a voulu proposer du réseau en 100G pour son offre de calcul scientifique (HPC). Le monde du HPC est habitué au matériel exotique, et utilise des abstractions aux dessus des couches réseaux, comme Open-MPI comme couche haute, et libfabric comme couche basse.
AWS dit qu’ECN n’est pas adapté à un réseau aussi étendu qu’un datacenter AWS, et donc qu’il est impossible d’utiliser du RoCE v2. Les menaces sont terribles : “Risque de verrou de la mort, épanchement de congestion et blocage en tête de ligne”.
De toute façon, AWS croit très fort au multipath, plutôt que de se contenter d’une route pour se connecter à un serveur, autant utiliser toutes les routes possibles.
Donc, AWS crée SRD, Scalable Reliable Datagram, proche de ce que propose Infiniband (suffisamment pour créer un module libfabric), qui en plus du multipath, ne s’engage pas à livrer les paquets de manières ordonnées.
Le tri des paquets est confié à la couche applicative, qui a à sa disposition bien plus de mémoire qu’une carte réseau, et qui saura prendre des décisions métiers. Le multipath risque d’utiliser des routes plus rapides que d’autres, augmentant les chances de mélanger l’ordre d’arrivée des paquets. Attendre l’arrivée d’un paquet lent va stopper le flot, et péter le débit.
Le classique ECMP est utilisé sur les switchs, mais en lui donnant des indices, et un contrôle de congestion maison est utilisé.
Le réseau est partagé avec les autres, qui se contentent d’une seule route, eux, et pour éviter les tant redoutés de congestions, SRD utilise les RTT pour estimer l’encombrement des routes et s’y adapte. SRD utilise les SmartNICs maison d’AWS, les cartes Nitro, et profite de l’abstraction du pilote EFA pour diverses optimisations comme les accès sans interruption (un ring je présume), du zero copy avec DMA.
L’article est agréable à lire, et les chiffres du monde HPC réveillent en nous le plaisir des gros V8 qui ronronne alors qu’on fait ses trajets en bus diésel.
Mais ça, c’était avant, la dernière itération d’EBS, utilise io2 qui utilise du SRD, et donc les blocs disques utilisent du multipath. La carte Nitro est cité, je présume qu’il y a du NVMe en RDMA (et un gros buffer pour ordonner les paquets).
Snap et Pony express
Google a constaté que développer (et déployer) du code en espace noyau était 4 fois lent qu’en espace utilisateur. Une interruption de 100ms plutôt que de redémarrer la machine, on comprend bien la différence de confort.
Google a choisi une approche maximaliste et utilise snap, un service en espace utilisateur, qui a l’exclusivité sur la carte réseau (une smart NIC qui gère du DMA, Intel est cité), avec un utilisateur non privilégié, mono threadé. Techniquement, c’est un microkernel. Le flot est multipléxé (comme HTTP/2 et QUIC), avec une seule connexion entre deux machines, il gère la congestion à sa sauce. Le document précise juste que ce n’est pas du TCP, ni de l’UDP, on peut supposer que la couche IP est conservée pour avoir du routage. La doc parle de négocier le protocole de transport d’un service, via une connexion TCP, vu que Snap a des mises à jour hebdomadaires, tout le monde ne parle pas la même version. Diverses stratégies sont possibles, mais il est possible de lui dédié un cœur (les processeurs modernes en ont plein), le service consommera donc 100% du CPU, et sera entièrement responsable de la latence, personne (et surtout pas le kernel) n’étant là pour le gêner.
snap
utilise plusieurs modules, avec différentes stratégies fournissant diverses performances (latences, débits) et cout. Le débit par cœur est triplé par rapport à TCP/IP, et les latences en dessous des 10µs.
snap est utilisé pour le réseau des VMs, le peering Internet, et pour le trafic à faible latence au sein d’un datacenter, il y a pony express, qui a divers usages dont la recherche internet et le stockage.
Colossus
Colossus est la technologie de stockage interne de Google, mais aussi la couche basse utilisée par le stockage pour les machines virtuelles, et divers services de stockage (comme Bigtable ou Spanner).
Snap se vante de gérer le stockage, et donc Colossus.
Un énorme pool de stockage utilisant un mix de disque à plateaux et SSD, une gestion pointilleuse du cache (avec CacheSack) et la notion de données chaude (trop de répliqua) puis froide. Chaque client exige des performances, de la redondance, qui peuvent être très variées. Pour maitriser les latences, il n’y a pas de proxy, les échanges se font de point à point, par le chemin le plus court, même le cache est tiré depuis le stockage de référence (le dataplane indiquera alors d’utiliser le cache, plutôt qu’un disque précis).
Bases de données distribuées
Un service complexe de stockage comme une base de données va solliciter fortement le stockage : le log binaire pour pas perdre de données, les données elle-même, avec des réécritures pour bien ranger, la mise à jour des index, ce genre de choses.
Si la réplication a lieu au niveau des blocs, l’amplification d’écriture va être entièrement répliquée, et de manière bloquante. Les bases de données savent (toutes ?) maintenant gérer la réplication au niveau applicatif, en utilisant le flot d’évènements (souvent un WAL), et des quorums pour les réplications, ce qui permet de ne pas attendre les retardataires (outliers), la consolidation se faisant plus tard, en asynchrone.
Aurora a uniformisé ce principe avec Aurora, sur lequel ils utilisent plusieurs bases de données open source (Mysql, Postgresql). Leur article “Conception et considérations pour une base de données relationnelle à haut débit née dans le Nuage et bien plus intéressante que leur infâme page produit. Il ne faut pas oublier que la persistance n’est qu’un des soucis que va gérer une base de données relationnelles, la gestion des transactions en est un autre, et pour ce sujet l’article dédié est “Sur l’évitement du consensus distribué sur les changements dans les entrées/sorties, les transactions et les adhésions”.
Google publie lui aussi des informations sur F1 et Spanner qui s’appuie sur Colossus.
En open source, Neon propose un moteur de persistance pour Postgres, et donc une base de données serverless (?! du dbless ?!).
Plus rigolo, Ceph propose libcephsqlite, un sqlite avec uniquement le stockage distribué, pour un client solitaire.
Dans le même genre, il y a litefs, et litevfs, du sqlite répliqué, avec un bon gros verrou pour arriver à y écrire.
Il existe des bases de données simplissimes qui se concentre surtout sur du clef/valeur (à la rocksdb) et se concentre surtout sur la distribution et la réplication :
- tikv, du CNCF, propose un système de transactions et sert de socle à TiDB
- foundationDB, d’Apple, avec des transactions ACID, des clés ordonnées, des notifications de modification, des opérations atomiques.
- Hive, de Scaleway, crée pour coordonner leur stockage S3 et peut être un jour remplacer etcd.
- Scylladb, un clone de Cassandra, une base orientée colonnes, avec des données typées, un langage de requêtes avec des fonctions utilisateurs. C’est le plus haut niveau de la liste.
On notera que, perfidement, les offres de disques réseaux hautes performances des offres Cloud ciblent les bases de données propriétaires (SQL Server, SAP…), pour contourner les couts de licences (par CPU) ou les surcouts pour le clustering.
Stockage orienté blob
S3 a démontré qu’il savait gérer brutalement une partie des besoins de stockage.
S3 est souvent utilisé en complément à du bloc, pour les sauvegardes par exemple, ou plus récemment comme stockage de flot, pour conserver les flots de réplication.
Ses débits ne sont pas forcément suffisants, on retrouve alors des solutions en pair à pair, soit du bittorrent pour le vaste monde, soit des variations avec des participants de confiance. Déployer des applications et des images de conteneurs font partie des usages violents, mais aussi des données comme des LLM (Large Language Model) pour l’IA ou des données scientifiques, comme des génomes.
DAOS
DAOS reprends les travaux d’openfabrics qui veut désagréger les machines de calcul avec du matériel de rêve (Cray, CXL, RDMA, SCM …).
DAOS propose d’entasser des disques NVMe dans un cluster (on parle de centaines ou de milliers de nœuds), puis d’utiliser tous les moyens possibles pour les saturer : zero copy, RDMA, pmem, accelerations matérielles…
Les modèles de données classiques du calcul scientifique sont exposés (HDF5, Hadoop, MPI-IO, fichiers POSIX…) pour une utilisation simple avec du code existant.
Des primitives sont fournies pour gérer les accès concurrents, avec différents modèles d’organisation des données. L’idée est d’avoir du code métier simple, avec “des applications avec un bon comportement” permettant d’utiliser un “mode relâché”. DAOS est prêt à tout, comme contourner les appels trop lents de FUSE avec LD_PRELOAD
.
Pour le mode bloc, l’incontournable NVMeOF (de SPDK) est utilisé, avec une procédure pour qu’un nœud le monte en RW, écrit, démonte, puis le volume est monté en RO par plusieurs nœuds.
DAOS est un monstre, mais c’est toujours intéressant de voir quels sont les choix pris pour des volumes et des performances extrêmes, et surtout comment fournir des APIs simples et intuitives pour des utilisateurs spécifiques.
La fin de Moore
La taille des disques durs, et les cartes réseau n’ont pas atteint leur plafond, et continue de progresser, alors que la fréquence des CPU est plafonnée.
Le DMA doit permettre de décharger une partie du travail des CPU, mais peut poser des problèmes de sécurité dans des environnements multitenants (comme les environnements virtualisés).
Évolution des abstractions
Le noyau et ses interruptions sont souvent blâmés pour ajouter des latences et empêcher d’utiliser à plein le matériel.
L’espace noyau n’est plus une chasse gardée, le noyau a besoin de déléguer une partie de ses tâches en espace utilisateurs.
Beaucoup de travail est fait dans ce sens pour le kernel Linux, mais il faut du temps pour stabiliser et surtout avoir une sécurité décente (coucou io_uring), puis attendre que ça apparaisse upstream, dans les distributions.
La virtualisation est généralisée, et le domaine est bouillonnant : rust dépoussière kvm, les conteneurs rendent tentant les µconteneurs, et même les unikernels reviennent avec Unikraft. Virtio permet de concentrer les efforts pour que kvm puissent profiter au mieux, de manière la plus transparente, des nouveautés du noyau.
Le bloc de stockage est une abstraction naïve, les stockages ont leur spécificité :
- les seeks des HDD (de pis en pis avec l’augmentation des tailles)
- l’asymétrie des modifications des SSD et son trim
- le stockage zoné pour prolonger la densification des stockages.
- Le RAID a un palier, bon courage pour restaurer votre HDD de 16To.
dm-zoned, ZoneFS F2FS propose des réponses pour le zonage et le trim. Pour le seek, la réponse sera applicative (on écrit pour avoir des réponses séquentielles), et les caches SSD devant un stockage plus lent, dm-cache, bcache, sont imparfaits, le LRU n’aime pas les SSD, et sans indices il est possible de remplacer l’intégralité d’un cache pour des données qui ne seront finalement pas utilisées.
Stateless is the new diskless
Le confort de déployer des services sans états est immense. Ils peuvent facilement être multipliés, déplacés, mis à jour sans crainte de perdre des données.
Pour profiter de cette pureté (pureté promise par le développement fonctionnel), il faut arriver à ranger proprement la gestion de la persistance, en utilisant l’abstraction adéquate.