- Amazon S3 est une technologie cloud apparue en 2006 : elle est solide pour le stockage de fichiers, mais ce n’est pas un système de fichiers qui remplace tel quel l’API de fichiers Unix
- L’API de fichiers Unix ressemble à un module profond qui cache buffering, cache de pages, permissions et ordonnancement des E/S derrière une interface étroite comme
open,read,write,seek,close - S3 paraît simple, centré sur
GetObjectetPutObject, mais il ne permet que les lectures partielles viaRangeet ne prend pas en charge les écritures partielles par écrasement - Les bases de données comme Postgres, SQLite, MySQL, MongoDB et Elasticsearch reposent sur l’écrasement par pages ; déposer tel quel un fichier SQLite ou DuckDB sur S3 ne convient donc guère au-delà de petits jeux de données
- Une forte bande passante en lecture/écriture et une faible charge d’exploitation sont des atouts de S3, mais il faut aussi tenir compte de limites comme l’absence de rename/move, la lenteur du listage, une API uniquement XML et l’absence d’environnement de test local
S3 stocke des fichiers, mais n’est pas un système de fichiers
- S3 est une technologie cloud des débuts, apparue en 2006, et a été appelée « object store » selon l’expression en vogue à l’époque
- En pratique, il est largement utilisé comme stockage de fichiers, mais le comprendre comme un « Amazon Cloud Filesystem » n’est que partiellement juste
- Il stocke bien les fichiers, mais ne remplace pas tel quel le comportement et les attentes d’un système de fichiers classique
L’API de fichiers Unix et les modules profonds
- L’essentiel de l’API de fichiers Unix se résume aux cinq appels suivants
open(filepath): ouvre un fichierfile.read(size=100): lit depuis la position courante et avance cette positionfile.write("hello, world"): écrit à la position courante et avance cette positionfile.seek(94): déplace la position vers un octet donnéfile.close(): ferme le fichier
- Ces appels font partie du cœur des appels système réels et correspondent presque au minimum nécessaire pour lire et écrire des fichiers
- Comme beaucoup de traitements ont lieu derrière une interface étroite, l’API de fichiers Unix peut être vue comme un module profond (deep module)
- buffering et cache de pages
- gestion de la fragmentation
- gestion des permissions
- ordonnancement des E/S
- l’utilisateur bénéficie aussi de fonctions comme le wear-levelling des cartes SD sans avoir à s’en préoccuper directement
Modules superficiels, YAML et ORM
- Un module superficiel expose une surface d’API relativement grande par rapport aux fonctionnalités qu’il prend en charge
- Aujourd’hui, l’un des indices permettant de reconnaître un module superficiel est une interface en YAML
- YAML ressemble à un langage de balisage, mais il est en réalité souvent utilisé comme une syntaxe réutilisable sur laquelle on peut greffer presque n’importe quelle sémantique
- Dans le DevOps, YAML se comporte souvent comme un « langage de programmation »
- Si un mini-langage YAML fournit des structures de répétition, il peut être Turing-complet
- Les modules superficiels ne sont pas toujours mauvais
- Un ORM SQL est par nature une abstraction qui fuit et il est difficile de l’utiliser sans comprendre SQL
- Dans certains cas, un module superficiel peut être la meilleure forme possible
- À conditions égales, un module plus profond est préférable
L’API S3 est simple, mais différente de l’API de fichiers
- L’API de fichiers Unix s’est imposée au début des années 1970 et, pour des raisons de compatibilité, son interface a été conservée tandis que son implémentation interne a changé plusieurs fois
- Amazon S3 ne réimplémente pas l’API d’un système de fichiers Unix
- Les opérations de base de S3 ne correspondent que partiellement à l’API de fichiers Unix
GetObject(Bucket, Key, Range=None): lit tout ou partie d’un objetPutObject(Bucket, Key): écrit un objet entier
- Il existe le concept supplémentaire de bucket, mais si l’on considère le ratio entre fonctionnalités et interface, S3 peut être vu comme plus simple que l’API de fichiers Unix
- La différence décisive est l’absence d’écriture partielle par écrasement
- L’argument
RangedeGetObjectpermet de lire une partie d’un objet - Il est impossible d’écraser seulement une partie d’un objet
- L’écrasement doit se faire sur l’objet complet
- L’argument
- À cause de cette différence, S3 ne convient bien qu’à une partie des usages classiques des fichiers
Les bases de données se transposent difficilement telles quelles sur S3
- Plusieurs bases de données stockent leurs données dans des fichiers placés sur un système de fichiers
- Postgres maintient 2 à 3 fichiers par table, ainsi que plusieurs fichiers de gestion
- SQLite est connu pour stocker toutes ses données dans un seul fichier
- MySQL, MongoDB et Elasticsearch stockent aussi leurs données dans des fichiers
- Le problème est que les bases de données reposent généralement sur des écritures partielles par pages
- Les données sont généralement stockées en pages de 4 Ko ou 8 Ko
- Un fichier heap peut contenir des milliers de pages
- Les pages sont partiellement écrasées pour stocker les données nécessaires
- Si l’on place une base SQLite sur S3, il faut réécrire tout le fichier de base de données à chaque écriture
- S3 peut traiter rapidement de grosses écritures, mais à l’exception des plus petits jeux de données, une stratégie consistant à écraser tout le fichier à chaque fois est difficilement soutenable
- Réécrire à chaque fois le fichier de base de données rend aussi difficile l’utilisation de l’intégrité transactionnelle mise en place par les auteurs de la base
- Sur S3, la dernière écriture gagne
Ce que S3 fait bien et ce qu’il fait moins bien
- Le point fort de S3 est sa bande passante très élevée en lecture et en écriture
- Il n’est pas difficile de trouver en ligne des exemples de lectures ou écritures sur S3 à plus de 10 Go/s
- Il est aussi arrivé qu’une opération d’écriture S3 sature le réseau de bureau d’un client financier
- Au-delà de l’absence d’écritures partielles par écrasement, il existe d’autres contraintes par rapport à un système de fichiers
- S3 ne dispose pas d’opération rename ou move
- Un renommage se fait via
CopyObjectpuisDeleteObject CopyObjectprend un temps linéaire proportionnel à la taille du fichier- Revenir en arrière après avoir écrit beaucoup de fichiers au mauvais endroit est très lent
- Un renommage se fait via
- Le listage des fichiers est lent
- La bande passante en lecture/écriture est très élevée, mais l’énumération des éléments stockés est bien plus lente
- Elle peut même être plus lente que sur un système de fichiers local lent
- En revanche, la charge d’exploitation est plus faible que pour un système de fichiers
- Il suffit de préciser un bucket et un nom de clé, et le cloud s’occupe du reste
- Cela réduit la charge des tâches répétitives comme les sauvegardes, la réplication hors site et le provisionnement
- Le provisionnement concerne aussi bien la capacité que les opérations d’E/S
Les modules profonds sont plus importants aux interfaces entre organisations
- Le fait que S3 ait été la première API cloud populaire est lié aux avantages d’une API profonde
- Une API profonde est utile pour masquer la complexité entre modules au sein d’un même système, et elle l’est encore davantage dans des relations coûteuses comme les interactions entre deux entreprises
- La connexion de systèmes informatiques entre entreprises était traditionnellement appelée integration, et considérée comme synonyme de douleur
- Les grands logiciels d’entreprise comme SAP ne sont pas des modules profonds
- Presque toute l’organisation doit comprendre SAP
- Il faut continuer à l’ajuster aux méthodes de travail existantes
- Les projets d’intégration SAP sont chers, énormes, et les échecs se répètent
- La complexité interne de S3 n’est pas forcément bien moindre que celle d’une installation SAP
- Amazon a appelé S3 « Simple Storage Service », mais la complexité réelle de S3 est élevée
- Elle inclut la théorie des files d’attente, la contention d’E/S, le sharding et de nombreux problèmes gérés par les systèmes de fichiers
- Le « simple » de S3 renvoie davantage à une interface profonde qu’à une simplicité réelle
Les exceptions adaptées à S3 et les contraintes restantes
- Cela n’exclut pas le fait que S3 puisse être coûteux par rapport à certains usages
- Les notions de module profond et de module superficiel viennent de A Philosophy of Software Design de John Ousterhout
- Certaines bases de données ont été conçues dès le départ pour utiliser l’API S3 comme couche de stockage
- Snowflake en est un exemple
- Mais il ne s’agit pas d’un portage transparent : il faut une décision de conception initiale
- Snowflake a pris cette décision très tôt, au moins jusqu’en 2016
- Les bases de données ne sont pas les seules à rencontrer des difficultés sur S3
- De nombreux formats de fichiers supposent un
seekbon marché - Les fichiers Zip sont un exemple typique de format plus performant sur disque que sur S3
- De nombreux formats de fichiers supposent un
Ce qui déçoit avec S3
- L’API S3 est uniquement XML
- JSON existait déjà en 2006, mais XML dominait à l’époque
- Il est regrettable qu’Amazon n’ait pas publié de version JSON lors du passage de SOAP à REST
- Amazon a également cessé de maintenir le schéma XSD
- L’un des grands avantages d’une API XML est le schéma, mais aujourd’hui la documentation standard est le site web
- Amazon ne fournit pas d’environnement de test local
- En Python, on utilise parfois la bibliothèque moto pour effectuer des tests rigoureux
- Même s’il s’agit d’un outil de test pour un service commercial, moto est maintenu par des bénévoles
- Amazon S3 prend en charge les checksums, mais ils ne sont pas activés par défaut
- Amazon avance plusieurs affirmations sur la durabilité
- Je n’ai entendu parler d’aucun problème réel, mais je n’ai pas non plus vu de cas où ces affirmations auraient été testées
- Par le passé, S3 présentait le piège de l’eventual consistency
- Après avoir lu puis écrasé un fichier, une nouvelle lecture pouvait encore renvoyer l’ancien contenu
- Cela survenait parfois pendant un court laps de temps, créant de la confusion
- Les autres implémentations de S3 n’ont pas reproduit cette caractéristique, et Amazon l’a corrigée il y a quelques années avec une strong read-after-write consistency
1 commentaires
Commentaires sur Hacker News
La durabilité de S3 peut sembler exagérée, mais elle est crédible et difficile à comparer à celle d’un système de fichiers traditionnel
La différence ne tient pas seulement au logiciel, mais aussi à l’infrastructure physique et à la culture de la sûreté, et l’isolation des zones de disponibilité d’AWS semble meilleure que celle d’autres clouds
En travaillant sur S3, il fallait souvent comparer les prix avec GCP Blob Storage, mais Google pouvait stocker les données dans le même bâtiment ou dans une autre salle du même bâtiment, ce qui ne constituait pas une comparaison équitable avec la séparation façon AWS
Toute l’organisation était extrêmement obsédée par l’intégrité des données, des checksums étaient ajoutés partout, et même les événements majeurs comme les catastrophes naturelles étaient pris en compte
À l’échelle de S3, il était même possible de détecter du bit rot, comme des inversions de bits aléatoires causées par des rayons gamma frappant les plateaux des disques durs, et les taux de panne étaient mesurés selon le fabricant des disques et la période de production afin de réduire le risque de perte de données même si un lot précis défaillait
Au point de ne pas vouloir stocker des données importantes ailleurs, et ils ont eux-mêmes construit le système de déploiement de S3
Cette explication ressemble un peu à féliciter Cinnabon de faire sa pâte en interne, alors que ce qui est décrit est normalement le genre de choses que fait toute entreprise de stockage
Ajouter des checksums partout est une fonctionnalité de base de nombreux systèmes de fichiers, et si même un ordinateur personnel peut détecter le bit rot et envoyer une alerte, un grand fournisseur de stockage le fait évidemment aussi
Le suivi des taux de panne par fabricant de disque est également courant, certaines entreprises de stockage publient même des rapports, et même une équipe IT de 6 personnes le gérait dans un tableur
En dehors d’AWS aussi, et bien avant la création d’AWS, beaucoup de gens très compétents travaillaient déjà dans le stockage
Le compte geo-redundant de rsync.net existe par exemple avec un stockage principal à Fremont et un stockage secondaire à Denver, donc dans des États ou pays différents
Il n’est pas non plus exact de dire que S3 peut détecter le bit rot grâce à son échelle, car même un serveur personnel sous ZFS détecte très bien le bit rot à petite échelle
[1] siège de he.net
Si ces événements de corruption sont suffisamment nombreux, ils servent probablement aussi de signal pour déplacer des blocs de données individuels vers d’autres machines afin de « guérir » le système
Globalement, ce qui est mentionné ici est assez typique d’un système de stockage et n’a rien de spécifique à S3
D’après la documentation Google Cloud Storage, les données sont répliquées sur plusieurs zones, chaque zone étant mappée à des clusters distincts
https://cloud.google.com/compute/docs/regions-zones/zone-vir...
Je me demande s’il existe un tiers indépendant ayant vérifié la durabilité, l’intégrité et la cohérence de S3 avec une rigueur comparable à Jepsen
Si quelqu’un comparait rigoureusement les stockages cloud compatibles S3, il pourrait en ressortir de gros problèmes assez inquiétants, ou peut-être qu’une telle comparaison existe déjà
Ce qui est vraiment utile dans S3, ce n’est pas tant la vitesse de lecture/écriture que le listing
Dans des buckets sans versioning ou sans marqueurs de suppression, le listing d’un préfixe donné se comporte presque comme du temps constant, ce qui permet de demander, même dans un bucket contenant 100 milliards d’objets, les 1000 clés classées par ordre alphabétique qui suivent une chaîne arbitraire
Utiliser
/comme séparateur n’est qu’une valeur par défaut, on peut employer n’importe quel caractère pour obtenir un ensemble de préfixes communs, et les répertoires n’existent pas réellement : ils donnent seulement cette impression lorsqu’on en a besoinGrâce à cette propriété, on peut partitionner les données de plusieurs façons selon les identifiants nécessaires, sans se soucier des performances
Si le listing était simplement lent, incapable de faire des requêtes par préfixe de fichier, et ralentissait proportionnellement au nombre de clés comme sur un système de fichiers Unix traditionnel, S3 ne serait d’aucune utilité
La capacité à récupérer des clés avant ou après un préfixe est une fonction de base des index de base de données depuis les années 1970, donc ce n’est pas particulièrement impressionnant
Les cas d’usage sont peut-être différents, mais j’ai souvent été gêné par la lenteur du listing de buckets, et dès qu’un bucket grossit un peu, le temps pour énumérer les clés devient supérieur au temps de lecture
De mémoire, le débit du listing était inférieur à 1 Mbps, mais je n’ai pas de gros bucket sous la main pour tester tout de suite
S’il existe
dir1/a/000000àdir1/a/999999ainsi quedir1/b, alors sur un vrai système de fichiers hiérarchique,ls dir1/n’a besoin que de parcourir et renvoyer deux entrées,"a"et"b"En revanche, un store clé-valeur à index de chaînes plat, sans traitement de séparateur, doit parcourir 1 million d’entrées de répertoire allant de
"a/00000"à"a/999999"avant d’atteindre"b"C’est pourquoi une simple hiérarchie plate rend l’énumération du contenu d’un répertoire en
O(tous les enfants récursifs)plutôt qu’enO(enfants directs), ce qui est bien plus lent qu’un vrai système de fichiersEn revanche, si l’algorithme de listing connaît un caractère séparateur comme
/, un trie de préfixes lexical peut ignorer efficacement les sous-arbres au prochain/La documentation Amazon S3 précise aussi dans le champ
CommonPrefixesqu’elle résume et saute des millions de clés imbriquées à des niveaux plus profondshttps://docs.aws.amazon.com/AmazonS3/latest/userguide/using-...
Je n’ai pas testé si l’implémentation réelle économise vraiment les parcours ou si elle parcourt tout puis réduit seulement le résultat, mais j’espère qu’elle les économise
Ils ne ralentissent donc pas proportionnellement au nombre d’entrées, et le listing par préfixe de fichier est lui aussi très rapide
Considérer le listing par préfixe comme la fonctionnalité centrale me semble étrange
Recevoir 1000 clés en un seul appel réseau ne garantit absolument rien sur la complexité côté backend
En retouchant récemment un script de gestion d’actifs S3, j’ai été sidéré par la vitesse de listage.
Un collègue m’a dit qu’il fallait un cache de liste de fichiers et m’a envoyé un cache prérempli ; au début je pensais que ça ne pouvait vraiment pas être nécessaire, mais en vérifiant moi-même, j’ai constaté que si.
Il y a environ 100a0000 répertoires racine pour des actifs individuels, chacun contenant 5 à 6 répertoires et quelques fichiers, avec probablement moins d’un million de fichiers au total et une profondeur maximale d’environ 3 niveaux.
Lister ces fichiers récursivement prend littéralement 15 minutes.
J’ai essayé diverses suggestions de Stack Overflow et ChatGPT pour améliorer la vitesse, mais sans résultat significatif, et je ne comprends pas pourquoi c’est si lent.
Je ne sais pas pourquoi Amazon n’a pas corrigé ça ; vu de l’extérieur, on dirait qu’il suffirait d’ajouter quelques B-arbres à chaque bucket.
Si c’est un problème difficile, j’aimerais entendre pourquoi, parce que ce serait intéressant.
Le fait qu’on puisse voir les objets comme des « répertoires » n’est qu’un filtre par préfixe ; ce n’est pas un système de fichiers et il n’existe même pas de notion de répertoire.
Pour lister les objets le plus rapidement possible dans S3, il n’y a absolument pas besoin de récursion : il suffit de lister tous les objets sous un préfixe donné.
Si on utilise des séparateurs de chemin pour faire passer les clés S3 pour une arborescence de dossiers et qu’on parcourt « dossier par dossier », c’est bien plus lent.
Lors de l’appel à
ListObjectsV2, il ne faut pas passerdelimiter, et tant qu’on n’utilise pas la fonction de séparateur, les « répertoires » et les « niveaux » n’ont aucun impact sur les performances.Pour atteindre le temps total souhaité, il suffit de diviser une opération de listage en listages parallèles sur plusieurs préfixes.
On ne peut pas supprimer un bucket qui contient des objets, et on ne peut pas non plus demander à S3 d’effacer tous les objets d’un coup.
Il faut envoyer une requête d’API de suppression individuelle pour chaque objet, et pour cela il faut aussi envoyer des requêtes de listage des objets par paquets de 1000 ; ces appels de listage prennent du temps et coûtent de l’argent.
Cet article résume bien la situation : https://cloudcasts.io/article/deleting-an-s3-bucket-costs-mo...
Au final, la façon la plus rapide de nettoyer un bucket S3 est de supprimer le compte AWS auquel il appartient.
On peut lister 10a0000 objets par requête, et pour obtenir les 10a0000 suivants il faut le résultat de la requête précédente, donc tout est strictement séquentiel.
Pour lister un million de fichiers, il faut 100 requêtes consécutives, et même avec seulement 50 ms de latence aller-retour, cela fait déjà 5 secondes rien qu’en RTT, sans compter le coût de construction de la liste elle-même dans une itération à plat.
Le coût d’un listage de 10a0000 éléments est comparable à celui d’une écriture, ce qui est déjà assez lent en soi, et chaque listage est peut-être en plus un instantané à cohérence forte, ce qui ajoute encore du coût.
Les B-arbres ne semblent pas d’une grande aide sauf dans le cas d’un parcours de répertoires ; même dans ce cas, le goulot d’étranglement est probablement le travail réseau et l’API exposée à l’extérieur.
Au final, le listage de fichiers n’est pas un cas d’usage si important ; en général, on laisse plutôt S3 effectuer les opérations voulues via des fonctions comme le cycle de vie des objets, afin qu’elles soient traitées efficacement dans la couche interne du système de fichiers.
Ce ne sont que des objets, et l’interface web se contente de présenter joliment les préfixes séparés par des slashs.
Chaque objet a une clé, et cette clé peut contenir des slashs ; pour se faciliter la vie, on peut considérer chaque segment comme un répertoire.
Mais dès qu’on essaie d’y appliquer les opérations qu’on ferait normalement sur un répertoire, l’illusion se brise.
Les gens qui ont créé S3 savaient que ce n’était pas un système de fichiers, et je pense que le terme stockage objet visait précisément à expliquer les différences soulignées dans l’article.
Dire que « les objets étaient populaires » renvoie aux objets comme composants logiciels liant code exécutable et état local, mais les premiers exemples de S3 n’étaient pas du genre « sérialiser un objet vivant puis le désérialiser dans un autre processus ».
Les exemples concernaient tous des choses comme des actifs statiques de sites web, et à l’époque, côté bases de données aussi, l’idée d’objet apparaissait dans des termes comme « binary large object » ou « blob ».
S3 ressemblait davantage à un endroit où stocker ce qu’on met mal dans une base de données, et les cas d’usage de lancement envisagés lors de la conception supposaient que l’index du contenu se trouvait ailleurs ; le fait que le listage soit lent décrit justement bien cette nature.
https://en.wikipedia.org/wiki/Object_storage
D’après l’explication de GCP, le stockage objet est une architecture qui stocke des données non structurées sous forme d’objets dans un environnement de données structurellement plat.
https://cloud.google.com/learn/what-is-object-storage
En d’autres termes, les points clés sont les données non structurées, une organisation plate, et des opérations de lecture et d’écriture sur des éléments complets.
S3 n’est pas un fichier, et encore moins un système de fichiers
Ce qu’on attend de l’abstraction de fichier, c’est la mutabilité : pouvoir modifier une partie d’un fichier, l’agrandir, le réduire, et lire ou écrire à un offset arbitraire.
Une fois le fichier ouvert, on ne devrait pas avoir besoin de remonter à la racine ou à un concept de niveau supérieur, mais S3 ne fournit que des objets immuables au-dessus d’une liste mutable, et pour modifier quelque chose il faut le copier puis le téléverser à nouveau.
L’abstraction de fichier d’origine consiste à retrouver les secteurs d’un disque et à les présenter au client comme un tampon continu, et S3 résout un autre problème.
Beaucoup de gens interprètent à tort la bonne idée UNIX selon laquelle « tout est fichier » comme si cela voulait dire que tout devait être présenté comme un tampon virtuel continu.
Le vrai point essentiel, c’est qu’il existe des nœuds feuilles de base — qu’il s’agisse de fichiers ou d’autres objets que le système veut montrer aux processus —, que tout peut être listé dans des répertoires, y compris les répertoires eux-mêmes, et qu’il y a un arbre récursif.
Ce qui fait un système de fichiers, ce n’est pas le type d’un nœud feuille particulier, mais le répertoire.
Ajouter de nouveaux types de feuilles comme des sockets ou des framebuffers est presque trivial et ne casse pas cette idée, mais ajouter d’autres types de conteneurs comme des listes complexifie la structure du système de fichiers et en brise la cohérence conceptuelle.
S3 ne fait rien de tout cela, et ce n’est pas grave.
Il sert simplement à y mettre des choses qui ne rentrent pas dans une base de données et à espérer qu’il n’y ait pas de bit rot pendant qu’on ne les regarde pas.
À mon avis, le désir de faire de S3 un système de fichiers vient du fait que les clients comprennent mal ce que S3 fait bien, et que le product management n’a pas empêché ce malentendu, mais l’a au contraire entériné.
Une analogie plus juste serait un périphérique de stockage en blocs, sauf qu’il s’agit d’un périphérique en blocs très étrange, avec une taille de bloc arbitraire et auquel on peut attacher des clés.
Un système de fichiers est une abstraction posée au-dessus d’un périphérique de stockage en blocs ; un « système de fichiers S3 » devrait donc être lui aussi une abstraction au-dessus de S3, traité comme stockage en blocs sous-jacent.
Un système de fichiers est une abstraction construite sur un périphérique en blocs.
Un périphérique en blocs fournit un immense tableau d’octets et permet des lectures/écritures par blocs, par exemple « écris ces 300 octets à la position 273041 ».
Le périphérique en blocs lui-même est aussi une abstraction construite sur du matériel réel, si bien que « écris ces 300 octets » se traduit en pratique par des opérations du type « déplace la tête du plateau n°2 à la position n°6 ».
S3 n’est qu’une autre abstraction construite sur du stockage brut, et c’est strictement un stockage clé-objet plat.
Si vous avez besoin de fonctions de système de fichiers, implémentez-les dans l’application ou utilisez un système de fichiers.
Si vous n’avez besoin que d’append, vous pouvez suivre la chaîne d’ajouts dans une base de données et stocker les chunks dans S3 ; si ça ne convient pas, utilisez autre chose.
Si vous avez besoin de copie, vous pouvez créer une nouvelle référence au même objet dans la base de données ; si ça ne convient pas, utilisez autre chose.
S3 convient déjà très bien à beaucoup de gens, donc il ne faut pas essayer d’en faire autre chose.
Il faut aussi arrêter d’essayer de changer le sens d’une terminologie déjà établie dans le domaine : un système de fichiers est un concept expliqué dans les manuels, et S3 n’a jamais prétendu être un système de fichiers.
Étudier un peu la conception des systèmes d’exploitation aide vraiment, et c’est aussi très intéressant.
Il y a eu une discussion comparant l’API
object_stored’Apache Arrow et Apache OpenDAL sur https://github.com/apache/arrow-rs/issues/3888.Apache OpenDAL est une bibliothèque qui fournit une API de type système de fichiers au-dessus de nombreux backends, dont S3 et divers stockages cloud.
Certains systèmes de bases de données, comme GreptimeDB et Databend, utilisent OpenDAL comme un meilleur SDK S3 pour accéder aux données stockées dans le cloud.
Comme autres solutions pour gérer une interface de type système de fichiers au-dessus de S3, il y a aussi Alluxio et JuiceFS, mais contrairement à Apache OpenDAL, ils nécessitent un déploiement séparé et un service de métadonnées interne dédié.
Quand on parle de S3, Backblaze B2 mérite aussi d’être mentionné.
J’aime beaucoup le fait qu’il soit trois fois moins cher que S3, et je n’ai aucun lien avec Backblaze.
Il y a une fenêtre de maintenance de deux heures chaque semaine, le mercredi de 11:30 à 13:30 PST ; il n’y a généralement pas de downtime, mais il arrive parfois qu’une panne totale survienne en plein milieu des heures de bureau aux États-Unis.
Quand le taux d’erreur montait à un niveau rendant le service inutilisable, il fallait ouvrir un ticket de support ; je l’ai vécu environ une fois par an ces dernières années.
Le support se contente de poser une multitude de questions, comme s’il n’avait ni journaux d’erreurs ni visibilité côté interne, sans vraiment examiner le problème.
Il existe aussi de faux succès où l’upload reçoit une réponse de réussite alors qu’en réalité l’objet est enregistré à 0 octet dans le système B2, donc il faut impérativement vérifier les uploads même en cas de code de succès.
En cas de vulnérabilité critique comme la CVE de Log4j2, il peut aussi y avoir de longues interruptions, par exemple 10 heures d’arrêt.
Le prix est excellent, mais ce n’est pas un produit directement comparable à des services de stockage cloud plus matures.
Cela dit, j’estime que deux couches de sauvegarde externe peuvent compenser dans une certaine mesure.
Il est absurde de faire la promotion d’une solution multicloud tout en détruisant en pratique sa viabilité dès lors qu’on se retrouve avec des frais de NAT gateway et d’IPv4 partout.
Dans mon cas d’usage, avec beaucoup de lectures et peu d’écritures, je pouvais encore économiser de l’argent même en payant la bande passante B2, mais ce n’est plus vrai s’il faut passer par une gateway NAT64 ou payer des frais horaires simplement pour accéder à B2.
C’est un bon article, et il m’aurait été utile de le lire avant de me lancer dans l’aventure du montage d’un stockage cloud via FUSE avec rclone mount
Après de nombreuses itérations, rclone s’est doté d’une couche VFS qui adapte des stockages comme S3, Google Cloud Storage, Azure Blob, OpenStack Swift ou Oracle Object Storage en une couche de système de fichiers proche de POSIX, et le code réel de
rclone mountn’est qu’une fine couche au-dessusLa couche VFS propose plusieurs niveaux de compatibilité, et en mode
off, elle ne fait que du cache de répertoiresDans ce mode, comme le dit l’article, on ne peut pas lire et écrire simultanément le même fichier, on ne peut pas écrire au milieu d’un fichier, et les fichiers ne peuvent être écrits que séquentiellement
Étonnamment, malgré ces contraintes, beaucoup de choses fonctionnent plutôt bien
Le niveau suivant,
writes, prend en charge la plupart des fonctionnalités POSIX attendues par les applications, comme la lecture et l’écriture simultanées d’un même fichier ou l’écriture au milieu d’un fichier, mais au prix de créer une copie locale du fichier et de la téléverser de manière asynchrone à la fermetureLa documentation des modes de cache VFS reflète bien les limites décrites dans l’article : https://rclone.org/commands/rclone_mount/#vfs-file-caching
Fondamentalement, S3 n’a même pas de vrais répertoires, donc on ne peut pas avoir de répertoire sans fichier, et les répertoires n’ont pas non plus de métadonnées valides comme l’heure de modification
On peut créer des marqueurs de répertoire, qui sont des fichiers de 0 octet se terminant par
/, et de nombreux outils, dont rclone, les prennent en chargeL’absence de répertoires vides n’est généralement pas un gros problème, car la couche VFS les simule et la plupart des applications y écrivent de toute façon rapidement quelque chose
Au final, transformer quelque chose qui ressemble à S3 en quelque chose qui ressemble à un système de fichiers POSIX demande énormément de travail, et derrière des comportements comme le renommage d’un fichier ouvert ou des cas limites délicats, il y a beaucoup d’astuces
Les commandes bas niveau
move/sync/copyde rclone ne gèrent pas cela et utilisent presque l’API S3 telle quelleSi je pouvais changer une chose dans l’API S3, j’aimerais qu’il existe une option pour lire aussi les métadonnées lors du listing
rclone stocke l’heure de modification des fichiers dans les métadonnées de l’objet, mais comme il n’existe aucun moyen de les lire en masse, il faut faire un
HEADpour chaque objetOu alors, ce serait bien de pouvoir définir le
Last-Modifiedde l’objet lors de l’uploadLa limite de longueur des clés est de 1024, donc la quantité de métadonnées qu’on peut stocker est limitée, mais même en tenant compte du chemin du fichier, cela laisse une marge confortable
On pourrait utiliser un séparateur comme
//, invalide dans un chemin normalisé, pour obtenir quelque chose comme/path/to/file.txt//mtime=1710066090On pourrait toujours récupérer les “répertoires” par préfixe, et récupérer directement le fichier en utilisant
//comme partie du préfixeEn revanche, ce format nuirait probablement fortement à la compatibilité avec les autres logiciels
Dans MinIO, ils ont ajouté un paramètre “secret”
metadata=truequi inclut les métadonnées et les tags dans le listing quand on dispose des autorisations appropriéesComme c’est une extension, on ne peut pas s’y fier de manière stable, mais rclone pourrait toujours essayer et l’utiliser quand c’est possible
Les fichiers de 0 octet se terminant par
/sont possibles, mais on peut aussi considérer les préfixes communs du listing eux-mêmes comme des répertoiresCela a l’avantage et l’inconvénient que les répertoires n’ont pas d’état propre et ne peuvent pas exister s’il n’y a pas d’objet à l’intérieur
Pouvoir définir
Last-Modifiedlors de l’upload réduirait les contraintes côté client, mais l’usage de l’heure du serveur a aussi ses avantagesLes mêmes contraintes doivent aussi être gérées côté client pour la réplication ou la mise en miroir
Personnellement, mon plus grand reproche est l’absence d’un
HeadObjectVersionsqui retournerait les informations de version d’un objet uniqueListObjectVersionsne peut pas savoir si un préfixe donné est un vrai préfixe ou une clé d’objet, donc cela ne peut qu’être une opération portant sur tout le clusterAWS a récemment ajouté
GetObjectAttributes, mais les informations de version, qui y auraient eu toute leur place, n’y figurent pasLe “Simple” de S3 ne veut pas dire “peu profond”, mais plutôt qu’il faut le moins de composants possible pour atteindre l’objectif
Si l’on a besoin d’un stockage objet distribué, centralisé, répliqué, hautement disponible, très durable, à forte bande passante, à faible latence, fortement cohérent, synchrone et extensible, avec en plus une API HTTP REST, je ne pense pas qu’on puisse faire plus simple que S3
AWS S3 a vu s’ajouter beaucoup de fonctionnalités au fil du temps, mais son comportement de base est resté inchangé
Selon A Philosophy of Software Design d’Ousterhout, simple veut dire non complexe, et le “Simple Made Easy” de Rich Hickey va dans le même sens
En revanche, “profond” signifie qu’une petite interface fournit en interne beaucoup de fonctionnalités complexes, et cette description convient mieux à S3 que “simple”
Ce n’est pas la même chose qu’une simplicité au sens où S3 ne ferait pas grand-chose
https://www.infoq.com/presentations/Simple-Made-Easy/