Dessine-moi un serveur de miroirs

GNU/Linux Magazine n° 142 | octobre 2011 | Arnaud Gomes do vale
Creative Commons
  • Actuellement 0 sur 5 étoiles
0
Merci d'avoir participé !
Vous avez déjà noté cette page, vous ne pouvez la noter qu'une fois !
Votre note a été changée, merci de votre participation !
Au moment où j'écris ces lignes, la troisième incarnation du serveur mirrors.ircam.fr vient tout juste d'entrer en production. Voyons un peu à quoi elle ressemble.

1. Généralités

Le serveur mirrors.ircam.fr héberge des miroirs de téléchargement pour un certain nombre de projets libres, y compris (mais pas seulement) plusieurs grosses distributions Linux et systèmes BSD. Ces miroirs sont librement accessibles via HTTP, FTP et rsync.

Dans la suite de cet article, je vais principalement décrire la machine d'un point de vue technique. Voici juste un bref rappel concernant le côté social : avant de mettre un miroir en ligne, il convient d'en parler aux responsables du projet concerné (et de s'inscrire à la liste de diffusion idoine quand elle existe, c'est le cas de la plupart des gros projets) et de prévenir les administrateurs du serveur amont (celui à partir duquel on maintient notre propre miroir à jour) s'il ne s'agit pas des mêmes. Notamment, certains gros hébergeurs prévoient de privilégier les miroirs avals par rapport aux clients « normaux » ; c'est par exemple le cas de kernel.org, comme on pourra le voir plus loin.

2. Spécifications

2.1. Les services à fournir

Comme je l'ai écrit plus haut, mirrors.ircam.fr offre des accès FTP, HTTP et rsync à son contenu. Ces trois services devraient suffire à couvrir les besoins des clients sans être trop compliqués à configurer et à sécuriser. On pourrait envisager, par exemple, des accès NFS ou Gopher, mais l'intérêt est au mieux discutable ; un jour peut-être ?

En pratique, les téléchargements sont beaucoup plus nombreux en HTTP qu'en FTP. À titre d'exemple, la dernière semaine d'activité de l'ancien serveur a vu moins de 40000 fichiers téléchargés en FTP, contre plus de neuf millions de requêtes en HTTP. Sur ces neuf millions, près de sept se sont soldées par un code de retour 200 (correspondant à des pages d'index ou à des vrais fichiers téléchargés), et un peu plus d'un million par un code de retour 206 (téléchargement partiel) indiquant probablement l'utilisation d'un « accélérateur de téléchargement ».

Enfin, sur la même semaine, le serveur rsync a émis un peu moins de deux millions de fichiers, à destination de moins de 120 clients. Le faible nombre de clients pour une telle quantité de fichiers s'explique assez bien par la nature même du protocole rsync ; de plus, je sais qu'un certain nombre d'autres serveurs de miroirs viennent régulièrement se synchroniser sur mirrors.ircam.fr, ce qui ne peut que renforcer la tendance.

2.2. Dimensionnement

Le choix d'une architecture matérielle relève souvent d'un compromis entre le prix et les performances. Dans mon cas, il me fallait une machine capable de stocker une petite dizaine de To de fichiers et d'exploiter un lien à 1 Gbps vers Internet, le tout pour un prix pas trop prohibitif et avec des possibilités d'évolution pour les années à venir.

J'ai opté pour un serveur très ordinaire, construit autour d'un processeur Xeon à 4 coeurs de milieu de gamme. Les deux points sensibles sont les disques et la mémoire.

À l'heure actuelle, le serveur contient un peu moins de 8 To de données. J'ai donc opté pour un RAID logiciel construit sur six disques SATA de 2 To, sur lesquels j'héberge tant le système (en RAID1) que les données (en RAID5). En lecture séquentielle, ce genre de configuration est largement capable de saturer une interface réseau 1 Gbps. Malheureusement, dans des conditions réelles, le serveur doit supporter beaucoup d'accès concurrents qui font chuter les performances. On peut bien sûr compenser en ajoutant beaucoup de disques, si possible avec une redondance assez forte (typiquement en RAID10), et en utilisant plutôt des disques SAS. Toutefois, on arrive rapidement à des prix prohibitifs.

La solution la plus simple à ce problème de performances est de prévoir un cache assez gros pour contenir toutes les données utiles et ne pas avoir à toucher les disques lors des pics de charge. Concrètement, ça signifie quelques dizaines de Go de mémoire, ce qui correspond par exemple à la taille d'une version de Fedora (la sortie d'une nouvelle version induit presque toujours un pic d'une journée ou deux). Pour chiffrer un peu tout ça, l'ancien serveur dispose de 10 Go de mémoire, ce qui ne lui permet pas de dépasser 600 à 650 Mbps de bande passante effective sur des périodes de plus de quelques minutes, sauf cas exceptionnels (essentiellement un client téléchargeant des gros fichiers est capable d'occuper la bande passante à lui seul ; dans ce cas, la machine peut fournir plus de 950 Mbps, c'est-à-dire en pratique saturer son interface). Le nouveau dispose de 48 Go, j'espère que ça sera suffisant. Ce point est important : d'une part, pour ce genre d'application, ajouter de la mémoire peut améliorer les performances, mais il faut ajouter assez de mémoire pour arriver à faire une vraie différence ; d'autre part, je n'ai jamais trouvé de bon moyen de tester les performances du serveur à part l'essai en conditions réelles.

Et si ça n'est pas suffisant, me direz-vous ? La carte mère du nouveau serveur est équipée d'une interface SAS et j'ai pris soin de garder deux emplacements libres pour ajouter des disques. Si besoin est, je prévois de m'en servir pour ajouter un cache HTTP (probablement à base de mod_cache, à moins que je me penche sur Varnish) sur deux disques rapides en RAID0.

Reste un problème que je n'ai pas mentionné : l'espace disque n'est au final pas très abondant. J'envisage deux solutions à cela :

- la plus simple, remplacer mes disques de 2 To par d'autres, plus gros, quand le problème se posera réellement ;

- plus efficace, ajouter du stockage externe, probablement en iSCSI ; la machine dispose d'une deuxième interface ethernet gigabit qui peut être utilisée de cette façon, et je dois pouvoir trouver de la place sur mes baies existantes.

Contrairement aux très gros hébergeurs (j'ai déjà cité kernel.org), le trafic de mirrors.ircam.fr est assez modéré pour être supporté par une seule machine. Si le besoin s'en fait sentir, je pense pouvoir augmenter la bande passante disponible jusqu'à 2 ou 3 Gbps sans trop de difficultés ; par contre, le passage à 10 Gbps n'est probablement pas sérieusement envisageable avec du matériel PC actuel. On en est de toute façon encore loin ; pour fixer les idées, la figure 1 montre le trafic réseau de la machine sur une semaine ordinaire.

Figure 1

2.3. Configuration du stockage

Comme je l'écrivais plus haut, à terme, les fichiers des miroirs pourraient être répartis entre plusieurs systèmes de stockage. Malgré tout, il va s'avérer utile de rassembler ces fichiers sous une racine unique, même si on pourrait techniquement faire autrement au moins pour HTTP et pour rsync. À ce sujet, j'ai opté pour une racine unique pour tous les services, mais on pourrait parfaitement envisager une racine par service, je n'en vois simplement pas l'utilité à l'heure actuelle. Cette racine se trouve sous /var/ftp pour des raisons historiques (le tout premier mirrors.ircam.fr n'hébergeait au début de sa carrière qu'un serveur FTP).

D'autre part, il est indispensable de pouvoir travailler sur le stockage sans incidence sur les fichiers visibles de l'extérieur. Le cas le plus évident est celui de la mise en place d'un nouveau miroir, qu'il vaut mieux peupler avant de le publier ; on peut aussi penser au déplacement d'un miroir d'un système de fichiers vers un autre, qui doit être le plus transparent possible.

Au final, la solution que j'ai retenue consiste à monter le stockage local sous /srv/mirrors, puis les éventuels systèmes de fichiers supplémentaires sous /srv/mirrors2 et autres si besoin (l'ancien serveur avait un /srv/mirrors2 sur un volume iSCSI). Les différents répertoires utiles sont ensuite montés à leur place sous /var/ftp/pub avec l'option --bind de mount. Une fois traduit dans /etc/fstab, ça donne quelque chose comme ça :

/dev/vg00/mirrors /srv/mirrors      ext4 rw,noatime 1 2

/srv/mirrors/CPAN /var/ftp/pub/CPAN none rw,bind    0 0

Dans le cas d'un système de fichiers réseau (par exemple en iSCSI), il ne faudrait pas oublier d'ajouter l'option _netdev partout :

/dev/vg01/mirrors2 /srv/mirrors2     ext4 rw,noatime,_netdev 1 2

/srv/mirrors2/CTAN /var/ftp/pub/CTAN none rw,bind,_netdev    0 0

Le lecteur avisé remarquera sans aucun doute que j'utilise le système de fichiers ext4. C'est le cas sur la machine en production, mais après une nouvelle série de mesures (à base de time curl http://mirrors.ircam.fr/un/repertoire/avec/beaucoup/de/fichiers/), il se pourrait bien que je change pour ext3, nettement plus performant tant que les données ne sont pas dans le cache. Et dire que je voulais vérifier que je n'avais pas eu tort de ne pas utiliser XFS...

3. Le logiciel

Avant de se lancer dans le détail des différents services, un petit mot à propos du système d'exploitation, en l'occurrence Scientific Linux 6 (http://www.scientificlinux.org/). Il s'agit d'un clone approximatif de Red Hat Enterprise Linux (comprendre que ses développeurs ne s'interdisent pas d'y ajouter des logiciels absents de RHEL) qui présentait au moment du choix le gros avantage d'exister, alors qu'on attendait toujours CentOS 6.

Je n'ai pas tant fait ce choix pour des raisons techniques que pour des raisons culturelles, puisque les clones de Red Hat constituent la grande majorité de notre parc, que nous disposons donc de tout un tas de configurations à peu près standardisées et que je n'avais pas de raison particulière de choisir autre chose.

3.1. Le serveur rsync

Par expérience, les connexions rsync ont tendance à être longues et surtout relativement peu nombreuses. On peut donc faire tourner le serveur comme un service de xinetd sans se poser trop de questions ; le coût d'établissement d'une connexion ne fera pas de grosse différence.

Dans le détail, voici la partie pertinente de la configuration de xinetd (le fichier /etc/xinetd.d/rsync) :

service rsync

{

        disable = no

        socket_type     = stream

        wait            = no

        user            = root

        server          = /usr/bin/rsync

        server_args     = --daemon

        log_on_failure += USERID

}

et un extrait du fichier /etc/rsyncd.conf :

motd file = /etc/motd.rsync

syslog facility = local6

[pub]

comment = Ircam free software mirrors

path = /var/ftp/pub

use chroot = true

read only = true

list = true

ignore nonreadable = true

transfer logging = true

refuse options = c

dont compress = *

[atrpms]

comment = ATrpms

path = /var/ftp/pub/atrpms

use chroot = true

read only = true

list = true

ignore nonreadable = true

transfer logging = true

refuse options = c

dont compress = *

Chaque section (il y en a plus que les deux qui apparaissent ci-dessus, mais elles sont toutes similaires) correspond à un « module » au sens rsync ; le module pub est un fourre-tout où l'on retrouve tout le contenu du serveur, tandis que chacun des autres modules en reprend une partie. Au final, voici ce qu'on voit quand on se connecte au serveur avec un client rsync :

% rsync mirrors.ircam.fr::           

pub             Ircam free software mirrors

atrpms          ATrpms

CentOS          CentOS Linux

CPAN            Comprehensive Perl Archive Network

CTAN            Comprehensive TeX Archive Network

dag             RPMForge

debian          Debian GNU/Linux

debian-non-US   Debian GNU/Linux non-US

fedora-epel     Fedora EPEL

fedora-linux    Fedora Linux

opensuse        OpenSUSE

openvz          OpenVZ

planetccrma     PlanetCCRMA

proftpd         ProFTPD

pure-ftpd       Pure FTPD

Vous remarquerez que la configuration ci-dessus impose le transfert de données non compressées ; le serveur disposant d'une bande passante réseau confortable, il vaut mieux ne pas charger son processeur inutilement, d'autant que la majorité du contenu est déjà compressée (il s'agit principalement d'archives compressées ou d'images ISO en contenant).

3.2. Le serveur FTP

Pas grand-chose de particulier de ce côté. J'ai opté pour Pure-FTPD, essentiellement parce que je le connaissais un peu et que je l'avais sous la main ; les fonctionnalités utilisées ici sont assez basiques, il s'agit uniquement d'accès anonyme en lecture seule. La plupart des options de configuration ont des valeurs « évidentes » ; voici juste un petit extrait du fichier /etc/pure-ftpd/pure-ftpd.conf pour la route :

BrokenClientsCompatibility no

MaxClientsNumber            200

Daemonize                   yes

MaxClientsPerIP             2

AnonymousOnly               yes

DontResolve                 yes

MaxLoad                     4

En gros, il s'agit d'une configuration un peu optimisée, mais limitée aux faibles charges (c'est le sens de la directive MaxLoad). C'est un parti-pris avant tout politique ; le protocole FTP est suffisamment mal conçu (pardon, on dit « chargé d'histoire ») et fragile (par rapport à HTTP) pour que je préfère ne pas trop encourager son utilisation.

3.3. Le serveur HTTP

J'en entends déjà réfléchir à voix haute : serveur Web, fichiers statiques, fortes charges, mais c'est bien sûr : nginx ! Eh bien non, la bonne réponse est Apache. En effet, un certain nombre de projets utilisent des fichiers .htaccess avec des vrais morceaux de mod_rewrite et autres apacheries dedans et je n'ai pas envie de passer du temps à me battre contre nginx pour récupérer les fonctionnalités manquantes, à supposer que ce soit possible.

Contrairement à ce qu'on peut entendre ici ou là, Apache lui-même n'est pas spécialement lourd ni lent. Par contre, il est assez généraliste, et l'adapter à un type de charge particulier (ce qui est le cas ici) peut demander un peu de travail.

La modification de configuration la plus rentable, et de très loin, est l'utilisation du MPM worker à la place du traditionnel prefork que nous connaissons tous. Là où prefork engendre autant de processus que de connexions simultanées, worker utilise des threads pour traiter plusieurs dizaines de connexions par processus. Nous verrons un peu plus bas le détail de sa configuration.

Le premier gros pic de charge de mirrors.ircam.fr a eu lieu lors de la sortie de la version 0.9 de VLC. À l'époque, Apache était configuré, un peu au doigt mouillé, pour accepter 5000 connexions simultanées avec le MPM prefork (j'ai déjà parlé de la difficulté de tester le serveur en laboratoire). La machine s'est donc allègrement offert un load average de 5000. Je peux maintenant parler d'expérience : un Linux peut se remettre d'une telle charge, mais ce n'est pas tout à fait instantané. Pour chiffrer un peu, je parle d'une petite demi-heure entre l'ouverture de la connexion SSH et l'obtention d'un shell en état de marche, et d'une vingtaine de minutes entre le killall httpd et la mort du dernier processus d'Apache. À titre de comparaison, le record de load average depuis le passage au MPM worker doit être de l'ordre de 50 ou 60 ; en tout cas, pas suffisamment élevé pour être vraiment mémorable.

Bien entendu, ce gain de performances ne va pas sans quelques contraintes ; typiquement, worker ne permet pas l'utilisation de mod_php (on peut toujours faire tourner un interpréteur PHP comme processus FastCGI, mais l'étroitesse de la marge de cet article ne me permet pas de développer, d'autant que ce n'est pas le sujet). Dans le cas présent, ce problème n'en est pas vraiment un vu qu'il n'était de toute façon pas vraiment question d'utiliser PHP.

Voyons un peu la configuration proprement dite. Contrairement aux autres modules Apache, les MPM sont compilés en dur dans le binaire httpd. Heureusement, Red Hat et les distributions dérivées sont conçues en conséquence ; le paquet httpd contient, outre le binaire compilé avec le MPM prefork, deux autres binaires, httpd.event et httpd.worker, compilés avec les MPM correspondants. Le choix du binaire à lancer se fait en positionnant la variable HTTPD dans le fichier /etc/sysconfig/httpd ; dans notre cas, voici son contenu utile (hors commentaires) :

HTTPD=/usr/sbin/httpd.worker

Attention, il vaut mieux arrêter Apache avant d'éditer ce fichier, sinon le script /etc/init.d/httpd risque fort de ne pas retrouver ses petits.

Je ne vais pas donner ici la totalité de la configuration du serveur ; en voici tout de même quelques morceaux choisis. J'insiste, il s'agit ici d'une configuration « qui marche », mais probablement pas optimale, d'autant que je n'ai pas encore vraiment pu tester la nouvelle machine en conditions réelles. Pour commencer, la configuration du MPM worker lui-même :

<IfModule worker.c>

ServerLimit          1000

StartServers           10

MaxClients           4000

MinSpareThreads        25

MaxSpareThreads       200

ThreadsPerChild        32

MaxRequestsPerChild   500

</IfModule>

Ici, les deux directives importantes sont ThreadsPerChild (le nombre de threads par processus) et MaxClients (le nombre maximum de clients simultanés). Si vous faites le calcul, vous vous rendrez compte qu'ici 125 processus suffisent à servir le nombre maximum de clients. Pourquoi, alors, cette ServerLimit plus élevée ? En lisant la documentation d'Apache, ça ressemble à une bonne idée car ça permet de modifier les deux directives précédentes sans forcer un redémarrage complet du serveur ; dans la vraie vie, ça ne m'a jamais servi à rien mais ça ne coûte pas grand-chose.

La deuxième optimisation importante consiste à indiquer à Apache qu'il peut utiliser l'appel système sendfile(2). Ça lui permet de copier directement le contenu d'un fichier sur une socket réseau en économisant une copie en mémoire et un changement de contexte. Je vous conseille tout de même de vous reporter à la documentation d'Apache (http://httpd.apache.org/docs/2.2/) qui indique quelque cas où il vaut mieux ne pas utiliser sendfile(2). Par défaut, il est activé sur les systèmes qui le supportent (ce qui est le cas de Linux depuis quelques années) ; l'activer explicitement ne peut pas faire de mal.

EnableSendfile on

On tombe ensuite dans des optimisations plus classiques. D'abord, ne pas perdre de temps à résoudre les noms des clients (un programme d'analyse de logs pourra toujours le faire plus tard si besoin est) :

HostnameLookups Off

Ensuite et surtout, n'activer que les modules Apache potentiellement utiles (sur un serveur de miroirs, ce n'est le cas ni de mod_php, ni de mod_ssl, par exemple) :

LoadModule authz_host_module modules/mod_authz_host.so

LoadModule log_config_module modules/mod_log_config.so

LoadModule setenvif_module modules/mod_setenvif.so

LoadModule mime_module modules/mod_mime.so

LoadModule autoindex_module modules/mod_autoindex.so

LoadModule negotiation_module modules/mod_negotiation.so

LoadModule dir_module modules/mod_dir.so

LoadModule alias_module modules/mod_alias.so

LoadModule rewrite_module modules/mod_rewrite.so

LoadModule status_module modules/mod_status.so

Le dernier de la liste, mod_status, est utilisé par un outil de monitoring ; il n'est pas utile à l'activité « serveur de miroirs » en tant que telle.

Il y a probablement moyen de faire mieux que cette configuration en y passant du temps ; en attendant, elle donne déjà de très bons résultats.

4. Peuplement et mise à jour des miroirs

Pour commencer, j'ai créé un utilisateur mirror qui est propriétaire de tous les sous-répertoires de /srv/mirrors*/ (mais pas des répertoires /srv/mirrors*/ en tant que tels). C'est lui qui a la charge de maintenir les miroirs. J'ai aussi créé un répertoire /etc/mirrors et deux sous-répertoires, rsync et ftp, qui contiennent la configuration des différents miroirs et les scripts qui vont avec.

Vous remarquerez que cette configuration nécessite une intervention de root pour ajouter ou supprimer un miroir. Ce n'est pas spécialement gênant, dans la mesure où il devra de toute façon intervenir pour ajouter un point de montage dans /var/ftp/pub.

4.1. Par rsync

J'utilise rsync pour tenir à jour la plupart des miroirs. J'ai écrit une paire de scripts pour l'invoquer à peu près proprement (en plaçant des verrous pour éviter les exécutions concurrentes). Le premier de ces scripts, run-mirrors, est invoqué depuis la crontab de l'utilisateur mirror :

*/15 * * * * /etc/mirrors/rsync/run-mirrors 15minutes

1 * * * * /etc/mirrors/rsync/run-mirrors 1hour

# .../...

23 23 * * * /etc/mirrors/rsync/run-mirrors nightly

L'argument passé au script run-mirrors correspond à un sous-répertoire de /etc/mirrors/rsync qui contient un fichier de configuration par miroir correspondant à la périodicité concernée. Ces fichiers ne sont rien d'autre que des morceaux de scripts shell qui initialisent quelques variables. En voici un exemple simple, 1hour/ubuntu-releases :

source=rsync://rsync.mirrorservice.org/releases.ubuntu.com/

dest=/srv/mirrors/ubuntu/releases

Et voilà la version à peu près complète, 4hour/fedora :

source=rsync://monlogin@mirrors3.kernel.org/t2fedora-enchilada/linux/

dest=/var/ftp/pub/fedora/linux

excludes=debug

password=tucroispasquejevaislemettreenclair?

postcmd=/usr/bin/report_mirror

Le cœur du script run-mirrors ressemble à ça (j'en ai enlevé le gros du traitement d'erreur pour simplifier) :

#!/bin/bash

adminmail='mirrormaster@ircam.fr'

dorun="$(dirname $0)/do-run"

cd $(dirname $0)

instance="$1"

logdir=/home/mirror/logs

mkdir -p "$logdir/$instance"

for f in $instance/*

do

        [ -f "$f" ] || exit 0

        ( echo "$f" | egrep -q '(~|-DISABLED)$' && continue

                logfile="$logdir/$instance/$(basename $f).$(date +%Y%m%d).$(date +%H%M%S).$$"

                timeout 8h "$dorun" "$f" >> "$logfile" 2>&1

                fgrep -q 'rsync error' "$logfile" && ( egrep '^rsync: ' "$logfile" ; echo ; echo 'Full log file follows:' ; echo ; cat "$logfile" ) | mail -s "[$(basename $f)] rsync errors" "$adminmail"

                gzip "$logfile"

        ) &

        sleep 120

done

Vous remarquerez que le script se contente normalement d'écrire ses logs dans un fichier ; il envoie un mail à l'administrateur des miroirs en cas d'erreur, et uniquement dans ce cas. Depuis qu'il est en place, ma boîte à lettres mirrormaster est passée d'une paire de centaines de messages par jour à quelques dizaines par semaine tout au plus, sachant que la plupart des erreurs sont bénignes (notamment des téléchargements en cours sur le serveur amont, qui se traduisent par des accès refusés tant que les fichiers ne sont pas complets).

J'en profite pour glisser un mot sur l'utilisation de la commande mail dans un script destiné à être lancé par cron. Elle n'est certes pas indispensable, puisque ce dernier peut envoyer la sortie standard du script par mail à l'utilisateur ; elle permet simplement de gérer un peu plus finement les destinataires du message et de le doter d'un sujet un peu plus explicite (et lisible !) que Cron <mirror@lamachine> la commande.

Manque juste le moteur, le script do-run ; encore une fois, je l'ai simplifié en enlevant le gros du traitement d'erreurs :

#!/bin/bash

rsync="/usr/bin/rsync -arvH --delete-after --delay-updates"

f=$1

piddir=/home/mirror/.lock       # la coutume est d'utiliser /var/run

                                # mais il faut etre root

pidfile=${piddir}/rsync-$(basename $f).pid

shellflags=$-

set -o noclobber

{ echo "$$" >$pidfile ; } 2>/dev/null || {

    echo >&2 "$* already running"

    exit 1

}

set -$shellflags

# destruction automatique du fichier à la fin

trap "rm -f $pidfile" EXIT

unset source dest excludes password precmd postcmd

source $f

if [ "$source" = "" -o "$dest" = "" ];

then

        echo "E: $f missing source or dest."

        exit 1

fi

echo "$source" | egrep -q '/$' || source="$source/"

echo "$dest" | egrep -q '/$' || dest="$dest/"

cmd="$rsync"

[ "$excludes" ] && for e in $excludes

do

        cmd="$cmd --exclude $e"

done

cmd="$cmd $source $dest"

[ "$password" ] && cmd="env RSYNC_PASSWORD=$password $cmd"

[ "$precmd" ] && cmd="$precmd ; $cmd"

[ "$postcmd" ] && cmd="$cmd ; $postcmd"

cmd="echo +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; date ; $cmd"

eval "$cmd"

Vous avez du même coup la liste des variables utilisables dans les fichiers de configuration.

J'ai fini par opter pour cette approche (verrouillage tâche par tâche, exécution en parallèle et utilisation de la commande timeout(1)) après avoir connu quelques problèmes avec rsync qui décidait de bouder et de ne jamais s'arrêter en cas de hoquet de sa connexion ; jusqu'à présent, elle donne des résultats satisfaisants.

4.2. Par FTP

Je ne m'attarderai pas sur cette méthode qui ne sert que pour la petite poignée de projets, dont ni le site de téléchargement principal, ni les principaux miroirs ne sont accessibles en rsync. Juste un mot sur le logiciel que j'utilise pour suivre ces quelques projets, il s'agit de fmirror. Il ne semble plus maintenu depuis quelques années, je ne suis pas certain qu'il ait ne serait-ce qu'un site de distribution officiel (le plus proche que j'ai pu trouver, ftp://ftp.guardian.no/pub/free/ftp/fmirror/, est inaccessible au moment où j'écris ces lignes), mais il marche mieux que les autres logiciels similaires que j'ai pu essayer.

5. Et ensuite ?

Dans l'immédiat, l'essentiel de l'activité « miroirs » va consister à observer le comportement du serveur et décider d'un éventuel ajout de cache, et de la forme qu'il pourrait prendre (Varnish ou mod_cache ?). Je vais aussi étudier les possibilités d'extension du stockage ; je n'exclus pas de convertir des serveurs déclassés en baies iSCSI, quitte à n'y stocker que des grosses quantités de données peu utilisées.

À plus long terme, j'étudierais bien les problématiques de haute disponibilité et de montée en charge, qui sont assez liées entre elles ; toutefois, j'ai peur que mon architecture « bon marché » montre très vite ses limites dans ce cadre. On verra ça pour la prochaine génération, d'ici 5 ans. :-)

Références

- Colm MacCárthaigh, Scaling Apache 2.x beyond 20,000 concurrent downloads : http://www.stdlib.net/~colmmacc/Apachecon-EU2005/scaling-apache-handout.pdf

- Olivier Thauvin, Mettre en place un miroir public : http://2010.rmll.info/IMG/pdf/RMLL2010-AdminSys-Miseenplacemiroirpublic.pdf