Aller au contenu
medium

SeaweedFS : stockage distribué haute performance pour objets et fichiers

23 min de lecture

SeaweedFS est un système de stockage distribué rapide capable de servir des milliards de fichiers avec un accès disque en O(1). Écrit en Go et distribué sous licence Apache 2.0, il fournit un stockage objet (API S3), un système de fichiers distribué (Filer) et un montage FUSE, le tout via un unique binaire weed. Ce guide vous accompagne dans le déploiement d’un cluster 3 nœuds avec master HA (Raft), volume servers, filer et S3 gateway — chaque commande a été testée sur un lab KVM réel.

  • Architecture : comprendre les rôles master, volume server, filer et S3 gateway
  • Déploiement : installer un cluster 3 nœuds avec haute disponibilité (Raft)
  • API S3 : créer des buckets, uploader et télécharger des fichiers
  • Filer : utiliser l’interface fichiers HTTP avec hiérarchie de répertoires
  • Réplication : configurer la réplication inter-rack avec le modèle XYZ

SeaweedFS est un système de stockage distribué inspiré du papier Haystack de Facebook. Son objectif principal : stocker et servir des milliards de petits fichiers (images, documents, logs) avec un accès disque en O(1) — une seule lecture disque par fichier, sans couche de métadonnées intermédiaire.

Analogie : si un système de fichiers classique est une bibliothèque où le bibliothécaire consulte un index puis cherche le livre, SeaweedFS est un entrepôt avec des numéros d’étagère : donnez le numéro, le fichier est récupéré directement sans recherche.

CaractéristiqueDétail
Accès O(1)Seulement 16 octets de métadonnées par blob, une seule lecture disque
Binaire uniqueUn seul exécutable weed pour tous les composants
Multi-interfaceAPI S3, Filer HTTP/gRPC, FUSE, WebDAV
Réplication flexibleModèle XYZ (datacenter/rack/même rack)
Erasure CodingRéduction d’espace pour données froides (10+4 par défaut)
Cloud tieringMigration transparente vers S3/GCS/Azure pour données tièdes
KubernetesDriver CSI officiel pour stockage persistant
CritèreSeaweedFSMinIOGarageCeph
Cas d’usage principalBlobs + fichiersStockage objet S3S3 léger, géo-distribuéStockage unifié
LangageGoGoRustC++
LicenceApache 2.0AGPLv3AGPLv3LGPL
Interface fichiersFiler + FUSENonNonCephFS
API S3Oui (gateway)NatifOuiOui (RGW)
ComplexitéMoyenneSimpleSimpleÉlevée
RAM minimum~128 Mo/composant~512 Mo~256 Mo~4 Go/OSD

SeaweedFS repose sur 4 composants qui peuvent tourner ensemble (mode all-in-one) ou séparément (production).

Architecture SeaweedFS : master cluster Raft, volume servers, filer et S3 gateway

Le master gère la topologie du cluster : il sait quels volume servers sont disponibles, dans quels datacenters et racks. En cluster de 3, les masters utilisent le protocole Raft pour élire un leader et assurer la haute disponibilité.

Rôles du master :

  • Assigner des identifiants de fichiers (file ID) via /dir/assign
  • Localiser les volumes via les lookups
  • Gérer la réplication et l’équilibrage des volumes
  • Port gRPC : 19333 (port HTTP + 10000)

Le volume server stocke les données réelles. Chaque volume server gère plusieurs volumes (fichiers .dat de 30 Go par défaut). Les blobs sont écrits séquentiellement dans ces volumes, ce qui garantit l’accès O(1).

Caractéristiques :

  • 16 octets de métadonnées par fichier (cookie, needle ID, taille)
  • Pas d’index en mémoire pour les lookups — accès direct via offset
  • Compaction automatique pour récupérer l’espace des fichiers supprimés

Le filer ajoute une couche système de fichiers au-dessus des volume servers. Il transforme les file IDs en chemins lisibles (/documents/rapport.pdf). Les métadonnées du filer sont stockées dans un backend configurable : LevelDB (défaut), MySQL, PostgreSQL, Redis, etcd, etc.

Fonctionnalités :

  • API HTTP : upload, download, listing de répertoires
  • FUSE : montage comme un système de fichiers local
  • WebDAV : accès depuis n’importe quel client WebDAV
  • Notifications : événements en temps réel (création, modification, suppression)

Le S3 gateway expose une API compatible AWS S3 au-dessus du filer. Les buckets S3 correspondent à des répertoires dans le filer (/buckets/nom-du-bucket/).

SeaweedFS utilise un format à 3 chiffres XYZ pour définir la réplication :

ChiffreSignificationPortée
XCopies sur d’autres datacentersInter-DC
YCopies sur d’autres racks (même DC)Inter-rack
ZCopies sur le même rackIntra-rack

Exemples concrets :

ValeurCopies totalesDescription
0001Pas de réplication (développement)
00121 copie sur le même rack
01021 copie sur un rack différent du même DC
10021 copie sur un datacenter différent
20032 copies sur 2 datacenters différents
ServicePort HTTPPort gRPCUsage
Master933319333Topologie, assignation
Volume808018080Stockage données
Filer888818888Système de fichiers
S3 Gateway833318333API S3 compatible
  • 3 machines (physiques ou virtuelles) sous Ubuntu 24.04 avec 2 Go de RAM minimum
  • Accès SSH entre les nœuds
  • AWS CLI v2 installé sur votre poste pour tester l’API S3

Créez un fichier cloud-init.yaml pour provisionner les 3 VMs :

#cloud-config
hostname: seaweedfs-node
users:
- name: bob
groups: sudo
shell: /bin/bash
sudo: ALL=(ALL) NOPASSWD:ALL
ssh_authorized_keys:
- ssh-ed25519 VOTRE_CLE_PUBLIQUE
packages:
- chrony
- wget
runcmd:
- cd /tmp && wget -q https://github.com/seaweedfs/seaweedfs/releases/latest/download/linux_amd64.tar.gz && tar -xzf linux_amd64.tar.gz && mv weed /usr/local/bin/weed && chmod +x /usr/local/bin/weed
- mkdir -p /var/lib/seaweedfs/master /var/lib/seaweedfs/volume /var/lib/seaweedfs/filer

Créez les 3 VMs :

Fenêtre de terminal
for i in 1 2 3; do
sudo virt-install \
--name seaweed${i} \
--ram 2048 --vcpus 1 \
--disk path=/var/lib/libvirt/images/seaweed${i}.qcow2,size=15,backing_store=/var/lib/libvirt/images/ubuntu-24.04-cloud.img,format=qcow2 \
--os-variant ubuntu24.04 \
--cloud-init user-data=cloud-init.yaml \
--network bridge=virbr0 \
--graphics none --noautoconsole --import
done

Vérification : attendez 2 minutes puis récupérez les IP :

Fenêtre de terminal
sudo virsh net-dhcp-leases default

Dans notre lab, les IP sont :

NœudIPRôle
seaweed1192.168.122.187Master + Volume + Filer + S3
seaweed2192.168.122.159Master + Volume
seaweed3192.168.122.144Master + Volume

Configurez les hostnames et /etc/hosts sur chaque nœud :

Fenêtre de terminal
# Sur chaque nœud, ajouter les entrées
sudo tee -a /etc/hosts << EOF
192.168.122.187 seaweed1
192.168.122.159 seaweed2
192.168.122.144 seaweed3
EOF

Vérification : confirmez l’installation du binaire sur chaque nœud :

Fenêtre de terminal
ssh bob@192.168.122.187 "weed version"
# version 30GB 4.13 linux amd64

Pour tester rapidement, SeaweedFS peut démarrer tous les composants avec une seule commande :

Fenêtre de terminal
weed server \
-dir=/var/lib/seaweedfs/volume \
-master.port=9333 \
-volume.port=8080 \
-ip=192.168.122.187 \
-filer \
-s3

Cette commande lance simultanément le master (9333), le volume server (8080), le filer (8888) et le S3 gateway (8333).

Vérification :

Fenêtre de terminal
curl -s http://192.168.122.187:9333/cluster/status
# {"IsLeader":true,"Leader":"192.168.122.187:9333.19333"}
  1. Démarrer les 3 masters (cluster Raft)

    Lancez un master sur chaque nœud avec la liste des pairs :

    Fenêtre de terminal
    # Sur seaweed1
    weed master \
    -mdir=/var/lib/seaweedfs/master \
    -ip=192.168.122.187 \
    -port=9333 \
    -defaultReplication=001 \
    -peers=192.168.122.187:9333,192.168.122.159:9333,192.168.122.144:9333
    Fenêtre de terminal
    # Sur seaweed2
    weed master \
    -mdir=/var/lib/seaweedfs/master \
    -ip=192.168.122.159 \
    -port=9333 \
    -defaultReplication=001 \
    -peers=192.168.122.187:9333,192.168.122.159:9333,192.168.122.144:9333
    Fenêtre de terminal
    # Sur seaweed3
    weed master \
    -mdir=/var/lib/seaweedfs/master \
    -ip=192.168.122.144 \
    -port=9333 \
    -defaultReplication=001 \
    -peers=192.168.122.187:9333,192.168.122.159:9333,192.168.122.144:9333

    Vérification : après ~10 secondes, un leader est élu via Raft :

    Fenêtre de terminal
    curl -s http://192.168.122.144:9333/cluster/status
    # {
    # "IsLeader": true,
    # "Leader": "192.168.122.144:9333.19333",
    # "Peers": [
    # "192.168.122.159:9333.19333",
    # "192.168.122.187:9333.19333"
    # ]
    # }
  2. Démarrer les volume servers

    Lancez un volume server sur chaque nœud, dans des racks différents pour la réplication :

    Fenêtre de terminal
    # Sur seaweed1
    weed volume \
    -dir=/var/lib/seaweedfs/volume \
    -ip=192.168.122.187 -port=8080 \
    -mserver=192.168.122.187:9333,192.168.122.159:9333,192.168.122.144:9333 \
    -max=10 -dataCenter=dc1 -rack=rack1
    Fenêtre de terminal
    # Sur seaweed2
    weed volume \
    -dir=/var/lib/seaweedfs/volume \
    -ip=192.168.122.159 -port=8080 \
    -mserver=192.168.122.187:9333,192.168.122.159:9333,192.168.122.144:9333 \
    -max=10 -dataCenter=dc1 -rack=rack2
    Fenêtre de terminal
    # Sur seaweed3
    weed volume \
    -dir=/var/lib/seaweedfs/volume \
    -ip=192.168.122.144 -port=8080 \
    -mserver=192.168.122.187:9333,192.168.122.159:9333,192.168.122.144:9333 \
    -max=10 -dataCenter=dc1 -rack=rack3

    Vérification : la topologie montre les 3 volume servers :

    Fenêtre de terminal
    curl -s http://192.168.122.144:9333/vol/status | python3 -m json.tool
    # "DataCenters": {
    # "dc1": {
    # "rack1": { "192.168.122.187:8080": [...] },
    # "rack2": { "192.168.122.159:8080": [...] },
    # "rack3": { "192.168.122.144:8080": [...] }
    # }
    # }
  3. Démarrer le filer

    Le filer s’installe sur un ou plusieurs nœuds (ici seaweed1) :

    Fenêtre de terminal
    # Sur seaweed1
    weed filer \
    -ip=192.168.122.187 \
    -port=8888 \
    -master=192.168.122.187:9333,192.168.122.159:9333,192.168.122.144:9333

    Vérification :

    Fenêtre de terminal
    curl -s -H "Accept: application/json" http://192.168.122.187:8888/ | python3 -m json.tool
    # {"Path":"/","Entries":[...],"EmptyFolder":false}
  4. Démarrer le S3 gateway

    Créez d’abord le fichier de credentials S3 :

    {
    "identities": [
    {
    "name": "admin",
    "credentials": [
    {
    "accessKey": "seaweedadmin",
    "secretKey": "seaweedadmin123"
    }
    ],
    "actions": ["Admin", "Read", "Write", "List", "Tagging", "Lock"]
    },
    {
    "name": "readonly",
    "credentials": [
    {
    "accessKey": "seaweedread",
    "secretKey": "seaweedread123"
    }
    ],
    "actions": ["Read", "List"]
    }
    ]
    }

    Enregistrez-le dans /etc/seaweedfs-s3.json, puis lancez le S3 gateway :

    Fenêtre de terminal
    weed s3 \
    -port=8333 \
    -filer=192.168.122.187:8888 \
    -config=/etc/seaweedfs-s3.json

    Vérification :

    Fenêtre de terminal
    curl -s http://192.168.122.187:8333/ | head -5
    # <?xml version="1.0" encoding="UTF-8"?>

Pour un déploiement persistant, créez des fichiers de service systemd.

[Unit]
Description=SeaweedFS Master
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/weed master \
-mdir=/var/lib/seaweedfs/master \
-ip=ADRESSE_IP_DU_NOEUD \
-port=9333 \
-defaultReplication=001 \
-peers=IP1:9333,IP2:9333,IP3:9333
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target

L’API native de SeaweedFS fonctionne en 2 étapes : assigner un identifiant, puis uploader vers le volume server.

Fenêtre de terminal
# Étape 1 : demander un file ID au master
curl -s http://192.168.122.144:9333/dir/assign
# {"fid":"4,031c0dfc08","url":"192.168.122.187:8080","publicUrl":"192.168.122.187:8080","count":1}
# Étape 2 : uploader le fichier sur le volume server
echo "Hello SeaweedFS!" > /tmp/test.txt
curl -F file=@/tmp/test.txt http://192.168.122.187:8080/4,031c0dfc08
# {"name":"test.txt","size":17,"eTag":"c76e4f38","mime":"text/plain"}
Fenêtre de terminal
# Télécharger via le volume server
curl http://192.168.122.187:8080/4,031c0dfc08
# Hello SeaweedFS!
# Supprimer
curl -X DELETE http://192.168.122.187:8080/4,031c0dfc08
# {"size":51}
Fenêtre de terminal
# Réplication inter-rack (010)
curl -s "http://192.168.122.144:9333/dir/assign?replication=010"
# Le master choisit un volume répliqué sur un rack différent

Le filer expose une interface fichiers avec chemins hiérarchiques via HTTP.

Fenêtre de terminal
# Uploader un fichier dans /documents/
curl -F file=@/tmp/rapport.txt http://192.168.122.187:8888/documents/
# {"name":"rapport.txt","size":18}
# Lister le contenu (HTML par défaut)
curl http://192.168.122.187:8888/documents/
# Lister en JSON
curl -H "Accept: application/json" http://192.168.122.187:8888/documents/
# {"Path":"/documents","Entries":[{"FullPath":"/documents/rapport.txt",...}]}
Fenêtre de terminal
curl http://192.168.122.187:8888/documents/rapport.txt
# (contenu du fichier)
Fenêtre de terminal
export AWS_ACCESS_KEY_ID=seaweedadmin
export AWS_SECRET_ACCESS_KEY=seaweedadmin123
export AWS_DEFAULT_REGION=us-east-1
Fenêtre de terminal
# Créer un bucket
aws --endpoint-url http://192.168.122.187:8333 s3 mb s3://mon-bucket
# make_bucket: mon-bucket
# Lister les buckets
aws --endpoint-url http://192.168.122.187:8333 s3 ls
# 2026-03-01 10:57:44 mon-bucket
# Uploader un fichier
echo "Fichier via S3" > /tmp/s3-test.txt
aws --endpoint-url http://192.168.122.187:8333 s3 cp /tmp/s3-test.txt s3://mon-bucket/documents/
# upload: ./s3-test.txt to s3://mon-bucket/documents/s3-test.txt
# Uploader un gros fichier (multipart automatique)
dd if=/dev/urandom of=/tmp/bigfile.bin bs=1M count=10 2>/dev/null
aws --endpoint-url http://192.168.122.187:8333 s3 cp /tmp/bigfile.bin s3://mon-bucket/data/
# upload: ./bigfile.bin to s3://mon-bucket/data/bigfile.bin
# Lister le contenu récursivement
aws --endpoint-url http://192.168.122.187:8333 s3 ls s3://mon-bucket --recursive
# 2026-03-01 10:58:00 10485760 data/bigfile.bin
# 2026-03-01 10:57:59 15 documents/s3-test.txt
# Télécharger
aws --endpoint-url http://192.168.122.187:8333 s3 cp s3://mon-bucket/documents/s3-test.txt /tmp/download.txt
cat /tmp/download.txt
# Fichier via S3
# Générer une URL présignée (valide 1 heure)
aws --endpoint-url http://192.168.122.187:8333 s3 presign s3://mon-bucket/documents/s3-test.txt --expires-in 3600
Fenêtre de terminal
# Supprimer un objet
aws --endpoint-url http://192.168.122.187:8333 s3 rm s3://mon-bucket/data/bigfile.bin
# Supprimer un bucket (doit être vide)
aws --endpoint-url http://192.168.122.187:8333 s3 rb s3://mon-bucket
# Forcer la suppression (bucket + contenu)
aws --endpoint-url http://192.168.122.187:8333 s3 rb s3://mon-bucket --force
Fenêtre de terminal
# Statut du cluster (identifier le leader)
curl -s http://IP_MASTER:9333/cluster/status
# Statut des volumes
curl -s http://IP_MASTER:9333/vol/status
# Version
weed version

SeaweedFS fournit un shell interactif pour l’administration :

Fenêtre de terminal
weed shell -master=192.168.122.144:9333

Commandes utiles dans le shell :

# Lister les volumes
volume.list
# Vérifier la santé du cluster
cluster.check
# Équilibrer les volumes
volume.balance
# Compacter un volume (récupérer l'espace)
volume.vacuum
# Forcer la réplication d'un volume
volume.fix.replication

Pour les données froides, l’Erasure Coding (EC) remplace la réplication par un codage 10+4, réduisant l’espace de 300 % (réplication 3x) à 140 % :

Fenêtre de terminal
# Dans weed shell
ec.encode -collection=archive -fullPercent=95
ec.rebuild -force
SymptômeCause probableSolution
no leader lors du démarrageRaft n’a pas convergéVérifier que les 3 masters sont démarrés et joignables (port 9333 et 19333)
no writable volumesVolumes non assignés ou max atteintAugmenter -max sur les volume servers ou compacter avec volume.vacuum
connection refused sur 8888Filer non démarréLancer weed filer avec les bons -master
Upload S3 échoue avec InvalidAccessKeyIdCredentials S3 non configurésVérifier -config=/etc/seaweedfs-s3.json ou utiliser les flags env AWS_ACCESS_KEY_ID
Bucket “already exists”Répertoire préexistant dans le filerLes buckets S3 correspondent à /buckets/nom/ dans le filer
-ip invalide pour weed s3Le flag correct est -ip.bindUtiliser weed s3 -ip.bind=IP au lieu de -ip=IP
Fenêtre de terminal
# Vérifier les processus
ps aux | grep weed
# Vérifier les ports ouverts
ss -tlnp | grep -E '9333|8080|8888|8333'
# Consulter les logs master
journalctl -u seaweedfs-master -f
# Topologie complète avec volumes
curl -s http://IP_MASTER:9333/vol/status | python3 -m json.tool
# Vérifier le leader Raft
for ip in IP1 IP2 IP3; do
echo -n "$ip: "
curl -s http://${ip}:9333/cluster/status
echo ""
done

Créez des identités avec le minimum de droits nécessaires :

{
"identities": [
{
"name": "app-backend",
"credentials": [
{
"accessKey": "app-key-xxxxx",
"secretKey": "secret-xxxxx"
}
],
"actions": ["Read:mon-bucket", "Write:mon-bucket", "List:mon-bucket"]
}
]
}

Les actions peuvent être restreintes à un bucket spécifique avec la syntaxe Action:bucket.

  • Isolez le réseau interne : les ports 9333 et 8080 ne doivent pas être exposés sur Internet
  • Exposez uniquement le S3 gateway (8333) derrière un reverse proxy avec TLS
  • TLS natif : SeaweedFS supporte les certificats via -cert.file et -key.file
Fenêtre de terminal
# Volume server avec chiffrement au repos
weed volume -dir=/var/lib/seaweedfs/volume -encryptVolumeData
  • Masters : 3 instances minimum pour le quorum Raft (nombre impair)
  • Volume servers : au moins autant que le facteur de réplication
  • Filer : 1 ou 2 instances (avec un backend de métadonnées externe pour la HA)
  • RAM : 128 Mo par composant minimum, 512 Mo recommandé
  • Un rack par nœud physique : pour que la réplication 010 protège contre la perte d’un serveur
  • Datacenters : utilisez -dataCenter pour identifier les sites géographiques
  • Collections : groupez les données par type (-collection=images, -collection=logs) pour faciliter la maintenance
  • SSD pour les masters : les écritures Raft bénéficient de la faible latence
  • HDD pour les volume servers : l’accès séquentiel exploite bien les disques mécaniques
  • -max : définissez le nombre maximum de volumes par serveur selon l’espace disque disponible (1 volume = 30 Go par défaut)
  • Compaction : exécutez volume.vacuum régulièrement pour récupérer l’espace des fichiers supprimés
  • SeaweedFS est un stockage distribué haute performance avec accès O(1) par fichier, idéal pour les blobs et petits fichiers
  • Le binaire unique weed exécute tous les composants : master, volume, filer, S3
  • Les masters Raft (3 minimum) assurent la haute disponibilité ; les volume servers stockent les données réelles
  • Le filer ajoute une couche système de fichiers avec hiérarchie, FUSE et WebDAV
  • La réplication XYZ (000, 001, 010, 100, 200) contrôle finement la distribution des copies
  • L’API S3 compatible AWS permet d’utiliser aws s3, s3cmd et tout SDK S3 existant
  • Pour la production : déployez chaque composant séparément, utilisez -dataCenter et -rack, et configurez des services systemd
  • L’Erasure Coding (10+4) réduit considérablement l’espace pour les données froides par rapport à la réplication 3x

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn