Provisionnement du stockage : capacité et IOPS‏

Niveau : intermédiaire

La plupart du temps, le terme que j'entends en entreprise, c'est "dimensionner" un serveur de stockage.
Ce terme me dérange puisqu'il fait appel à la notion de dimension d'un disque dur, sa capacité.
Pourtant, tant qu'il reste de la place, ce n'est pas l'espace de stockage qui importe, mais ses performances.
Pas assez, et l'infrastructure est directement limitée par les performances des disques durs.
Trop, et l'entreprise jette son argent par la fenêtre.
Je préfère pour ma part le terme "provisionner", c'est à dire mettre à disposition de nouvelles ressources, pour un usage immédiat ou futur.

Si dans un premier temps, l'administrateur apprend à juger des besoins "à l’œil" (un SSD ou un 15K rpm pour une base de données, un 7200 rpm de l'archivage), il est impossible, même pour un senior, d'évaluer les besoins exacts de ses serveurs, d'une façon chiffrée.
Pour faire une évaluation correcte, il faut faire appel à une méthode rationnelle, scientifique, et prendre la peine de mesurer les performances, de les monitorer sur une durée conséquente, tout le long de l'année, pendant les creux, comme pendant les pics d'activité.

"You Can’t Improve What You Can’t Measure" - Stefan Olander, Vice-Président Digital Sports, Nike

Des besoins antagonistes

Lorsque nous avons à dimensionner un espace de stockage, nous pouvons facilement identifier 4 besoins, qui sont par nature antagonistes :
- la capacité
- la vitesse
- l'encombrement de la baie de stockage
- le prix

Un disque avec une grande capacité coûte plus cher, et a tendance à n'être disponible dans un premier temps qu'avec des vitesses de rotation lentes.
Un disque très rapide a par conséquent souvent une plus petite capacité, mais est quand même plus cher qu'un disque lent de grande capacité.
Un disque prend un slot dans l'espace de stockage (serveur, NAS ou SAN), qui en dispose en nombre limité. Plus il y a de disques durs dans une baie, et moins il y a de possibilités d'extension.
Il faut mettre plus de disques de petite capacité (mais performants) que de disques de grande capacité (mais lents), pour obtenir une capacité de stockage équivalente, mais une baie avec de gros disques aura des performances bien moindres.
Multiplier les serveurs, NAS ou SAN, coûte encore plus cher que d'y installer des disques.

Provisionner correctement le stockage, c'est donc trouver le bon compromis entre capacité, vitesse et encombrement, en fonction des besoins, immédiats et futurs, au meilleur prix possible.
Suffisamment pour que les trois besoins fonctionnels soient satisfaits, mais sans extravagance, sinon il y aura gaspillage, et le coût du stockage sera un désavantage de l'entreprise face à ses concurrents.

Tout au long de ma carrière, j'ai vu des administrateurs installer des disques dur lents de 2TO sur des serveurs de bases de données, lorsque celles-ci ne pesaient pas plus d'une centaine de MO.
C'est encore plus le cas lorsque l'on fait appel à un prestataire d'hébergement, type OVH, qui proposait pendant des années des disques les plus volumineux possible ... parce que c'est le seul argument marketing que comprenait le client, à vrai dire !
Alors qu'une capacité moindre et des performances supérieures étaient plus adaptées.

A l'opposé, j'ai vu des jeunes administrateurs remplir une baie avec uniquement des disques durs très rapides, pour servir des fichiers bureautiques.
Pour flatter leur ego, parce qu'ils avaient la baie la plus rapide de l'entreprise / du groupe. Le tout, pour servir des fichiers Word et Excel ...
Comme ils avaient déjà rempli toute la baie en multipliant les disques de petite capacité, ils ne pouvaient plus en ajouter, et le jour où les utilisateurs ont eu le besoin légitime d'avoir plus d'espace, ils n'ont pas eu le choix, il a fallu racheter une nouvelle baie, et de nouveaux disques.
Alors que l'entreprise avait déjà investi une fortune dans la baie précédente, qu'elle avait été vendue par la DSI comme la "solution ultime à tous les problèmes de stockage" =D

Première approximation des besoins

Très rapidement, l'administrateur junior apprend à reconnaitre les besoins selon l'utilisation qui sera faite du stockage :
- pour une base de données, des disques très rapides, de petite capacité, SSD ou 15K rpm
- pour les serveurs web, des disques moyennement rapides, avec une capacité moyenne. Des 10K voire des 7,2K rpm
- pareillement pour les stockages de fichier utilisateurs
- pour un serveur de mails, type Exchange, cela dépend de la politique de l'entreprise : les mails sont stockés sur le serveur, et pour s'assurer de temps de réponse maximaux, mieux vaut utiliser les disques les plus rapides possibles. Mais si les utilisateurs gardent 50GO de courrier, et qu'il y en a beaucoup, le stockage sera très coûteux. C'est donc un compromis entre la capacité et la performance, qui dépendra de l'activité même de l'entreprise, et de l'argent qu'elle est prête à investir dans son système de mails.

Si c'est une façon simple et prudente de jauger les besoins, elle est incomplète, et se révèle parfois erronée.

Quelles sont les attentes en terme de réactivité de l'infrastructure web, du serveur de mails ?
Combien de personnes utiliseront simultanément les serveurs ?
Comment gérer les pics de trafic pour un site web, ou une pointe d'activité saisonnière pour l'entreprise ?
Quelles sont les perspectives de développement de l'activité visée, selon l'équipe managériale ? A court et à long terme ?
S'il y a déjà un serveur en place et que le stockage est le goulot d'étranglement, quelles sont les performances qu'il faudrait atteindre pour qu'il ne le soit plus ?

Les perspectives de développement

Il faut, selon moi, distinguer les perspectives à court et à long terme.

Autant il est facile de juger les besoins à court terme, puisqu'ils sont presque immédiats, autant les besoins à long terme sont très difficiles à prévoir, puisque l'entreprise se doit d'être agile, et l'informatique, elle aussi, doit pouvoir s'adapter aux changements :
- ajustements de la stratégie et de l'activité
- changements de l'équipe managériale, restructurations
- crise ou boom économique

La tentation d'acheter un serveur de stockage déjà rempli est grande, puisque l'on peut avoir un prix sur le matériel, et le provisionner une fois pour toutes.
Toutefois, cela représente aussi un risque : celui de ne pas pouvoir répondre de manière adéquate dans 6 mois.

Imaginons que l'entreprise décide d'externaliser le service mail. Nous nous retrouverons avec des disques très rapides inutilisés.
Les recycler pour du stockage de fichiers utilisateurs serait du gâchis.
L'entreprise peut aussi décider au contraire d'engager beaucoup d'employés, avec le besoin d'un volume de stockage important.

Si les serveurs de stockage sont déjà pleins, vous devrez en acheter de nouveaux, ou changer les disques existants, ce qui a un coût, en plus de générer des interruptions de service.

De plus, les disques se dévaluent à fur à mesure que le temps passe, et leurs performances / capacité deviennent obsolètes.
Pourquoi payer aujourd'hui les disques dont vous aurez besoin dans 1 ou 2 ans, surtout s'ils n'ont pas forcément les caractéristiques qui conviendront ?

C'est pour cela que le terme "provisionner" me semble très bien adapté : nous achetons des provisions pour un avenir proche, pour avoir quelques réserves, mais nos placards sont suffisamment vides pour y stocker des commissions imprévues.

Performances et IOPS

Dans un contexte grand public, la métrique la plus importante pour les performances, c'est le débit du disque.
Ce qui intéresse avant tout un utilisateur, c'est la capacité. Pouvoir stocker des films, des images, des mp3.
C'est pour cela qu'il va s'attacher à choisir la plus grosse capacité possible pour son disque.
Le grand public a principalement le choix entre trois périphériques avec des performances différentes : les disques mécaniques, de 5400 à 7200 tours / minute, pour les données, et les SSD bas de gamme, pour le système.

Ce qui change, en entreprise, c'est que système de stockage n'est pas exclusivement utilisé par une seule personne, mais par plusieurs.
Des dizaines, des centaines, voire des milliers.
Dans ce cas-là, le cache ne sert pas à grand chose, puisque les données ne seront pas demandées linéairement (séquentiellement), mais aléatoirement.
Il est donc impossible, pour une opération donnée, de prévoir à l'avance quelle sera la prochaine demande, et donc on ne peut pas utiliser le cache pour stocker les données à venir (prefetch), ou pour réutiliser les données déjà présentes.

De plus, un disque dur mécanique peut être vu comme un "tourne disque" moderne : plus il y aura de demandes simultanées, et plus celui-ci va passer de temps à positionner les plateaux sous la tête de lecture, et moins il passera de temps à lire les données elles-mêmes.
En résumé, dans un contexte multi-utilisateur, plus il y aura d'opérations simultanées, et plus les performances (et débits) vont s'écrouler.
Les disques durs sont prévus pour une lecture séquentielle de blocs contigus, et non pas pour des lectures aléatoires, et on ne peut donc pas juger les disques professionnels selon les mêmes critères que les disques grand public, y compris pour du stockage de fichiers.

Dans ce contexte, le cache, le débit nominal, la norme (SATA II, SATA III, SAS, etc), n'ont que peu d'importance.
Ce qui compte, c'est la vitesse de rotation brute du disque dur : en réduisant le temps de recherche et le temps que met la tête de lecture pour parcourir la distance radiale du secteur qui contient la donnée, nous augmentons le débit.
Sauf qu'il y a des limites physiques à la vitesse de rotation, pour des raisons de surchauffe et de stabilité.
Les disques durs ne peuvent maintenir la précision nécessaire au-delà de 15000 tours par minute.

Les SSD n'étant pas mécaniques, mais purement électroniques, ils permettent de faire des lectures / écritures sur des blocs de stockage éloignés (non-contigus).
Mais ils coûtent beaucoup plus cher à capacité équivalente.

Pendant longtemps, nous avons jugé les disques professionnels sur leur vitesse de rotation, mais les SSD n'étant pas mécaniques, il a fallu trouver une caractéristique commune, plus opérationnelle et plus adaptée à l'usage des disques en entreprise : les IOPS (Input/Output operations Per Second).
Plus un disque pourra faire d'IOPS, et plus son débit effectif sera important, et plus il va pouvoir gérer d'opérations simultanées, sans que ses performances ne s'écroulent trop.

En reprenant de valeurs (optimistes), voici une liste d'IOPS par type de périphérique, pour vous donner un ordre d'idée :

TypeCaractéristiquesIOPS
HDD 7,2k rpm 75
HDD 10k rpm 125
HDD 15k rpm 175
SSD MLC de base 400
SSD MLC SanDisk 64GO 8.200
SSD MLC Kingston HyperX 3K 120GO 60.000
SSD SLC Fusion-io IoDrive 140.000
SSD SLC OCZ RevoDrive3 X2 140.000
SSD MLC Fusion-io IoDrive2 290.000



S'il y a effectivement un écart énorme entre les performances, il y a aussi un écart équivalent entre les prix (le "hype" se paie !) : 24000€ HT pour la Fusion-io IoDrive2 640GO.
Pour une capacité de stockage équivalente, vous payerez 40€ TTC Rue Montgallet, pour un disque mécanique 7200 rpm.
Le rapport est de 1 à 714, de quoi faire réfléchir avant d'y stocker des fichiers Word ...

Aller plus loin que la brochure commerciale

Les spécifications techniques fournies sont parfois très optimistes sur le nombre d'IOPS pour les disques, et il n'y a pas vraiment de raisons de s'en priver, puisque personne ne vérifie ces valeurs.
Enfin si ... moi ;-)

Si les fabricants ne sont pas obligés de préciser les différences entre la lecture et l'écriture (et il y en a), ils précisent néanmoins la moyenne entre les deux.
C'est la valeur average disk seek latency, exprimée en ms.
Et nous avons vu que le plateau du disque tournait pour se positionner sous la tête, comme sur un tourne-disques.
C'est la valeur average rotation latency, aussi exprimée en ms.

Les IOPS, c'est donc le nombre de fois que le disque pourra répéter ces deux opérations en une seconde, parce qu'ils correspondent au temps nécessaire au disque pour effectuer 1 IOPS.
La formule est alors :
IOPS = 1000 / (average disk seek latency + average rotation latency)

Vérifions la formule pour un disque dont nous connaissons les spécifications techniques, le "Seagate Cheetah @ 15,7K RPM 450 GO"
IOPS = 1000 / (3,65 + 2)
IOPS = 176,99

Cela correspond à la fourchette que j'ai donné dans la section précédente.

Mesurer les IOPS

Généralités

Maintenant que nous avons une idée des IOPS des disques, s'il l'applicatif à stocker existe déjà, il est possible via SNMP, de connaitre sa consommation en IOPS.
Comme les ingénieurs qui ont conçu SNMP ont fait du bon travail, les compteurs sont organisés par type d'opération (read ou write, parce qu'ils n'ont pas le même coût matériel), par volume physique et logique.
Cela veut dire que vous mesurerez non seulement les IOPS individuels de chaque disque, mais aussi la performance des grappes RAID, puisque c'est la donnée la plus intéressante, d'un point de vue opérationnel.

Il suffit alors d'un simple outil gratuit et léger, SNMP, pour pouvoir enregistrer et analyser les IOPS de chacune de vos grappes via votre logiciel de monitoring / métrologie habituel (Nagios, IPMonitor, Cacti, Collectd, etc)
Il serait donc dommage de ne pas mettre en place cette métrique et de l'archiver, pour pouvoir suivre ses évolutions dans le temps, selon la charge.

Description de la MIB

Nom : UCD-DISKIO MIB
OID : .1.3.6.1.4.1.2021.13.15.1 (Read-Only)

OIDNomType
.1.3.6.1.4.1.2021.13.15.1.1.1 diskIOIndex INTEGER32
.1.3.6.1.4.1.2021.13.15.1.1.2 diskIODevice OCTETSTR
.1.3.6.1.4.1.2021.13.15.1.1.3 diskIONRead COUNTER
.1.3.6.1.4.1.2021.13.15.1.1.4 diskIONWritten COUNTER
.1.3.6.1.4.1.2021.13.15.1.1.5 diskIOReads COUNTER
.1.3.6.1.4.1.2021.13.15.1.1.6 diskIOWrites COUNTER
.1.3.6.1.4.1.2021.13.15.1.1.9 diskIOLA1 INTEGER32
.1.3.6.1.4.1.2021.13.15.1.1.10 diskIOLA5 INTEGER32
.1.3.6.1.4.1.2021.13.15.1.1.11 diskIOLA15 INTEGER32
.1.3.6.1.4.1.2021.13.15.1.1.12 diskIONReadX COUNTER64
.1.3.6.1.4.1.2021.13.15.1.1.13 diskIONWrittenX COUNTER64



Faisons un tour rapide de son contenu sur un serveur de fichiers Linux (résultats tronqués) :

snmpwalk -v 2c -c public localhost .1.3.6.1.4.1.2021.13.15.1

UCD-DISKIO-MIB::diskIOIndex.26 = INTEGER: 26
UCD-DISKIO-MIB::diskIOIndex.27 = INTEGER: 27
UCD-DISKIO-MIB::diskIOIndex.28 = INTEGER: 28
UCD-DISKIO-MIB::diskIOIndex.29 = INTEGER: 29
UCD-DISKIO-MIB::diskIOIndex.30 = INTEGER: 30
UCD-DISKIO-MIB::diskIOIndex.31 = INTEGER: 31
UCD-DISKIO-MIB::diskIOIndex.32 = INTEGER: 32
UCD-DISKIO-MIB::diskIOIndex.33 = INTEGER: 33
UCD-DISKIO-MIB::diskIODevice.26 = STRING: sda
UCD-DISKIO-MIB::diskIODevice.27 = STRING: sda1
UCD-DISKIO-MIB::diskIODevice.28 = STRING: sda2
UCD-DISKIO-MIB::diskIODevice.29 = STRING: sdb
UCD-DISKIO-MIB::diskIODevice.30 = STRING: sdc
UCD-DISKIO-MIB::diskIODevice.31 = STRING: sdd
UCD-DISKIO-MIB::diskIODevice.32 = STRING: sde
UCD-DISKIO-MIB::diskIODevice.33 = STRING: dm-0
UCD-DISKIO-MIB::diskIONRead.26 = Counter32: 353321984
UCD-DISKIO-MIB::diskIONRead.27 = Counter32: 351671296
UCD-DISKIO-MIB::diskIONRead.28 = Counter32: 942080
UCD-DISKIO-MIB::diskIONRead.29 = Counter32: 78040064
UCD-DISKIO-MIB::diskIONRead.30 = Counter32: 1172064256
UCD-DISKIO-MIB::diskIONRead.31 = Counter32: 114206720
UCD-DISKIO-MIB::diskIONRead.32 = Counter32: 811008
UCD-DISKIO-MIB::diskIONRead.33 = Counter32: 1363399680
UCD-DISKIO-MIB::diskIONWritten.26 = Counter32: 3063009280
UCD-DISKIO-MIB::diskIONWritten.27 = Counter32: 3061895168
UCD-DISKIO-MIB::diskIONWritten.28 = Counter32: 1114112
UCD-DISKIO-MIB::diskIONWritten.29 = Counter32: 160157696
UCD-DISKIO-MIB::diskIONWritten.30 = Counter32: 303570944
UCD-DISKIO-MIB::diskIONWritten.31 = Counter32: 126849024
UCD-DISKIO-MIB::diskIONWritten.32 = Counter32: 96735232
UCD-DISKIO-MIB::diskIONWritten.33 = Counter32: 687312896
UCD-DISKIO-MIB::diskIOReads.26 = Counter32: 194057
UCD-DISKIO-MIB::diskIOReads.27 = Counter32: 193703
UCD-DISKIO-MIB::diskIOReads.28 = Counter32: 206
UCD-DISKIO-MIB::diskIOReads.29 = Counter32: 18124
UCD-DISKIO-MIB::diskIOReads.30 = Counter32: 285559
UCD-DISKIO-MIB::diskIOReads.31 = Counter32: 27760
UCD-DISKIO-MIB::diskIOReads.32 = Counter32: 178
UCD-DISKIO-MIB::diskIOReads.33 = Counter32: 332862
UCD-DISKIO-MIB::diskIOWrites.26 = Counter32: 1279722
UCD-DISKIO-MIB::diskIOWrites.27 = Counter32: 1279517
UCD-DISKIO-MIB::diskIOWrites.28 = Counter32: 205
UCD-DISKIO-MIB::diskIOWrites.29 = Counter32: 10002
UCD-DISKIO-MIB::diskIOWrites.30 = Counter32: 57345
UCD-DISKIO-MIB::diskIOWrites.31 = Counter32: 978366
UCD-DISKIO-MIB::diskIOWrites.32 = Counter32: 16637
UCD-DISKIO-MIB::diskIOWrites.33 = Counter32: 1094193
UCD-DISKIO-MIB::diskIONReadX.26 = Counter64: 4648289280
UCD-DISKIO-MIB::diskIONReadX.27 = Counter64: 4646638592
UCD-DISKIO-MIB::diskIONReadX.28 = Counter64: 942080
UCD-DISKIO-MIB::diskIONReadX.29 = Counter64: 78040064
UCD-DISKIO-MIB::diskIONReadX.30 = Counter64: 1172064256
UCD-DISKIO-MIB::diskIONReadX.31 = Counter64: 114206720
UCD-DISKIO-MIB::diskIONReadX.32 = Counter64: 811008
UCD-DISKIO-MIB::diskIONReadX.33 = Counter64: 1363399680
UCD-DISKIO-MIB::diskIONWrittenX.26 = Counter64: 28832813056
UCD-DISKIO-MIB::diskIONWrittenX.27 = Counter64: 28831698944
UCD-DISKIO-MIB::diskIONWrittenX.28 = Counter64: 1114112
UCD-DISKIO-MIB::diskIONWrittenX.29 = Counter64: 4455124992
UCD-DISKIO-MIB::diskIONWrittenX.30 = Counter64: 26073374720
UCD-DISKIO-MIB::diskIONWrittenX.31 = Counter64: 511227957248
UCD-DISKIO-MIB::diskIONWrittenX.32 = Counter64: 8686669824
UCD-DISKIO-MIB::diskIONWrittenX.33 = Counter64: 550443126784

Les disques qui nous intéressent sont le disque système (sda), ainsi que les 4 disques physiques supplémentaires (sdb à sde), et le volume logique dm-0, qui est le RAID5 formé des disques sdb à sde.
Vous remarquerez que les volumes logiques sont aussi comptabilisés, et que vous pouvez donc monitorer les IOPS non seulement sur des disques physiques ou des grappes RAID, mais aussi sur des partitions, ce qui peut sauver la vie de l'administrateur : on imagine très bien le cas de figure dans lequel vous avez un problème d'entrées / sortie, et que les appels sont faits sur une partition particulière (système, swap, données).

Grâce à UCD-DISKIO-MIB::diskIODevice, nous identifions le nom du périphérique, et son numéro d'index UCD-DISKIO-MIB::diskIOIndex correspondant.
Dans le cas de "sdc", le 3e disque, c'est 30.
Les compteurs UCD-DISKIO-MIB::diskIOReads et UCD-DISKIO-MIB::diskIOWrites vous donnent le nombre d'opérations de lecture et d'écriture depuis le dernier boot.

Les compteurs UCD-DISKIO-MIB::diskIONRead et UCD-DISKIO-MIB::diskIONWritten ne sont pas franchement pertinents, c'est le nombre d'octets lus ou écrits depuis le dernier boot.
Ces derniers ne sont pas très pertinents parce que le débit varie fortement selon les IOPS.

Peu d'IOPS, et le débit sera faible, le disque n'est pas sollicité.
Trop d'IOPS par rapport aux performances du disque, et le débit sera faible aussi (le débit s'écroule parce que les IOPS demandées sont trop importantes par rapport à celles qu'il peut fournir)
Un disque surchargé de demandes peut donc avoir un débit faible !

Le débit ne permet donc aucunement de juger de la sollicitation d'un disque, seules les IOPS peuvent permettre de détecter la surcharge d'activité.

Si nous avons des compteurs en valeur absolue, il est alors très simple d'avoir les IOPS : nous faisons la différence entre les compteurs, toutes les secondes.
Ou si nous interrogeons les compteurs moins souvent, nous faisons la différence entre les compteurs, et nous la divisons par le délai entre les deux interrogations (en secondes).

Monitoring avec Nagios

Maintenant que nous savons précisément ce que l'on cherche, nous allons automatiser la surveillance via Nagios, par exemple.

J'ai traité cette partie dans un article à part, que vous trouverez ci-dessous :
Monitorer les IOPS via Nagios

IOPS d'une grappe RAID

Maintenant que nous avons un ordre de grandeur pour les disques et les grappes RAID déjà en production, il nous reste à apprendre à calculer les performances d'une grappe RAID, pour un nouvel applicatif, ou pour remplacer une grappe dont les performances sont insuffisantes.

Il faut bien garder à l'esprit un point très important : si le niveau le nombre brut d'IOPS possibles pour un disque ne change pas lorsqu'il est intégré dans une grappe, le nombre effectif d'IOPS que pourra fournir la grappe RAID, lui, varie, et n'est pas la somme des IOPS des disques la composant.
Le RAID permet la mise en commun des ressources et la redondance, via des "astuces" dans la distribution de données.
Et ceux-ci ont des avantages mais aussi un coût.

Nous parlons alors de pénalité RAID.
Chaque niveau de RAID ayant des mécanismes internes différents, la pénalité RAID variera.

Pour un descriptif des niveaux de RAID, un petit rappel, vous y trouverez aussi les définitions du chunk (bloc) et du stripe (bande) :
RAID (informatique) - Wikipédia

La lecture

Quelque soit le niveau de RAID, il n'y a pas de pénalité associée à la lecture.

Prenons un disque 10k RPM, à 125 IOPS.
Dans le cas d'un RAID0, les données sont distribuées sur les deux disques : le système lira en alternance les données sur les deux disques, et les IOPS en lecture d'un RAID0 seront alors à 250 IOPS.
Dans le cas d'un RAID1, les données sont dupliquées sur chaque disque : pareillement, le système pourra lire les données sur les deux disques, puisqu'ils ont le même contenu.
Les données sont distribuées, dans les cas des RAID5 (une chunk de parité) et RAID6 (deux chunks de parité). Les données sont distribuées sur l'intégralité des disques.
S'il y a 5 disques 125 IOPS dans une grappe RAID5 ou RAID6, les IOPS effectifs en lecture seront de 625 IOPS.
Pour les RAIDs complexes, type 10, 50 ou 60, la règle est la même, puisque ce ne sont que des RAID 1, 5, 6 que l'on a mis en RAID0.

Pour la lecture, quelque soit le niveau de RAID, la formule est la suivante : IOPS effectifs lecture = nombre de disques dans la grappe x IOPS d'un disque
On dit que la pénalité RAID est de 1.

L'écriture

Dans un RAID0, les données ne sont pas redondées, et au détriment de la sécurité, stockées indépendamment les unes des autres.
Il n'y a donc pas d'impact sur les performances, on dit que la pénalité RAID est de 1, parce qu'une opération d'écriture système correspond à une opération d'écriture sur les disques.

Dans un RAID1, les données sont dupliquées sur deux disques, une écriture système correspond à deux opérations d'écriture, une sur chaque disque.
Un RAID1 de deux disques 125 IOPS, les IOPS effectifs en lecture de la grappe seront de 250 IOPS, mais les IOPS effectifs en écriture seront toujours de 125.
Cela ne veut pas dire que les opérations "disparaissent" par magie ou que les disques ne travaillent pas, cela veut dire que 50% des opérations totales d'écriture ne sont pas employées à des fins utiles, mais à des fins "internes", pour la construction de la redondance !
On dit alors que la pénalité RAID est de 2.

Pour le RAID5, les choses se compliquent ...
Pour écrire un bloc (chunk), il faut d'abord lire le chunk avant modification, lire le chunk de parité de la bande (stripe), calculer la valeur de la parité sans le chunk à modifier, recalculer la parité avec le contenu du nouveau chunk (opération XOR), écrire le chunk demandé, et écrire la nouvelle parité du stripe dans le chunk prévu à cet effet.
Les calculs de la nouvelle parité permettent heureusement de ne pas avoir à lire tous les chunks du stripe, sinon, l'écriture en serait encore plus pénalisée, croissante avec le nombre de disques, donc de chunks dans le stripe ...
Ce calcul XOR ne concerne pas directement le disque, il se fait au niveau du CPU système ou de la carte contrôleur via des circuits spécialisés, et on considère qu'il a un impact négligeable, même s'il induit une très légère latence.
Toutefois, il y a bien 4 opérations (2 lectures et 2 écritures) au niveau des disques, pour une seule demande d'écriture !
Sur une grappe de 5 disques à 125 IOPS, les IOPS effectifs en lecture seront de 625 IOPS, mais seulement de 156,25 pour l'écriture, soit à peine plus d'un disque.
On dit que la pénalité RAID du RAID5 est de 4.

Pour le RAID6, il y a deux parités différentes, ce qui permet de pallier à la perte de deux disques.
Une opération d'écriture d'un chunk donne alors lieu, selon le même principe que le RAID5, à la lecture du chunk d'origine, des 2 chunks de parité, de 4 calculs de parité, 2 écritures supplémentaires de parité, et enfin, de l'écriture du chunk lui-même.
2 méthodes différentes sont utilisées pour les calculs de parité, une opération XOR simple, et un algorithme plus complexe, celui de Reed-Solomon.
Au niveau disque, cela nous fait 6 opérations, 3 lectures, 3 écritures.
Sur un RAID6 de 5 disques, les IOPS effectifs seront de 625 IOPS en lecture et de 104,16 en écriture, soit un peu moins qu'un disque.
On dit que la pénalité RAID du RAID6 est de 6.

Les niveaux de RAID combinés, RAID 10, 50 et 60, ne sont qu'un RAID1, 5 ou 6, sur lequel nous avons appliqué du RAID0.
Il auront alors les pénalités du RAID1, 5 ou 6, puisque le RAID0 n'apporte aucune pénalité.

Résumé des pénalités RAID

S'il est utile mais un peu compliqué de comprendre les différents niveaux de RAID, ce qu'il faut retenir, c'est que si la lecture sur les grappes est nettement plus performante, les pénalités d'écriture sont, quant à elles, très lourdes, et croissent avec le niveau du RAID.
Dans une situation professionnelle, nous utiliserons heureusement juste les valeurs de pénalité RAID, pour gagner du temps et ne pas faire griller notre cerveau !

Un tableau synthétique :

RAIDPénalité de lecturePénalité d'écriture
RAID0 1 1
RAID1 et 10 1 2
RAID5 et 50 1 4
RAID6 et 60 1 6

Calcul global des IOPS

Nous connaissons les IOPS des disques individuels.
Nous avons appris grâce au chapitre "Mesurer les IOPS" à monitorer et à évaluer les IOPS pour chaque serveur, chaque type d'application.
Certains usages vont faire surtout appel à la lecture (fichiers bureautiques, serveurs web), certains vont faire lourdement appel à l'écriture (serveurs de logs, systèmes transactionnels), et certains vont mixer lectures et écritures.
Grâce au monitoring, nous connaissons les mesures individuelles d'IOPS pour la lecture et l'écriture, et le rapport entre les deux.

Nous pouvons donc maintenant calculer précisément les performances d'une grappe RAID, en fonction des disques, du niveau de RAID et de la répartition des lectures/écritures.

Si l'on additionne les capacités IOPS de chaque disque, nous obtenons les performances "brutes" de la grappe :
Total IOPS brut = IOPS d'un disque x Nombre de disques

Le Total IOPS effectif = ((Total IOPS brut x % Reads) / Read Penality) + ((Total IOPS brut x % Writes) / Write Penality)
Comme vu précédemment, le Read Penality est toujours à 1 !

Prenons un cas concret :
sur un RAID 5 de 5 disques 10k RPM 125 IOPS, avec un ratio de 80% de lectures typique d'une base de données web, nous aurons :
Total IOPS effectif = ((625 x 0,8) / 1) + ((625 x 0,2) / 4) = 500 + 31,25 = 531,25 IOPS.

Avec 100% de lectures et 0% d'écritures, nous aurions :
Total IOPS effectif = ((625 x 1) / 1) + ((625 x 0) / 4) = 625 + 0 = 625 IOPS.

Avec 0% de lectures et 100% d'écritures, nous aurions :
Total IOPS effectif = ((625 x 0) / 1) + ((625 x 1) / 4) = 156,25 IOPS.

Nous retrouvons bien les chiffres théoriques des sections précédentes !

Il faut bien garder en tête que si les IOPS globaux sont utiles, votre application va quant à elle demander des IOPS en lecture et en écriture minimaux, et que ce sont les deux valeurs qu'il faudra vérifier lorsque vous voudrez provisionner correctement votre stockage.
Si la grappe RAID arrive à traiter 531,25 IOPS, mais que c'est un serveur de logs qui demande 400 IOPS en écriture qui est stocké dessus, il va ralentir TRES fortement, vos disques seront saturés !

De préférence, sur un stockage qui demande des performances en lecture, nous allons préférer le RAID5 et le RAID50 (permet plus de disques et de capacité), mais sur un stockage qui demande des performance en écriture, ce sera le RAID1 et le RAID10 (pénalité RAID d'écriture moindre).

Mais est-ce tout ?

Non, le point restant ne concerne pas directement le provisionnement des disques physiques, mais leur configuration.
Les performances d'un système de stockage dépendent aussi du chunk size, la taille des blocs qui composent le stripe RAID qu'aura crée l'administrateur, et de la taille des opérations de lecture / écriture.

Nous avons vu auparavant que ce qui importait, dans le monde de l'entreprise, au contraire du grand public, c'était avant tout de pouvoir répondre aux requêtes en parallèle, dans les meilleurs délais, et non pas forcément d'avoir du débit.
On ne peut traiter de la même façon des lectures / écritures de petits fichiers, des serveurs de bases de données, ou du streaming vidéo.

Dans le premier cas et le deuxième cas, la taille des E/S sera petite.
Peu importe le débit final, ce qui compte, c'est que les nombreuses requêtes soient satisfaites le plus rapidement possible.

Dans le troisième cas, la taille des E/S sera grande. Ce qui compte, c'est que l'utilisateur ait le plus de débit possible au niveau de la grappe.
Le débit sera privilégié par rapport au nombre de requêtes parallèles.

Or, les disques mécaniques doivent positionner leur tête de lecture, parcourir les plateaux.
Ensuite, ils doivent traiter la demande elle-même (notons au passage que la lecture d'un bloc et l'écriture induisent des temps de latence différents)
Même si les disques SSD n'ont pas de parties mécaniques, ils ont eux aussi un temps de latence, très inférieur aux disques classiques, tout comme la mémoire vive, mais existant.
Lui aussi sera différent pour la lecture et l'écriture.

IOPS et chunk size

Il en découle alors deux stratégies différentes pour le stockage des données :

S'il s'agit de traiter le plus de petites requêtes en parallèle, mieux vaut cantonner une opération donnée E/S sur un seul disque de la grappe.
De cette façon, chaque disque de la grappe pourra traiter une requête différente, et la grappe fournira au final plus d'IOPS.
La taille du chunk doit alors être immédiatement supérieure à la taille moyenne de la requête.
Si la taille de la requête dépasse la taille du chunk, un autre disque sera mobilisé pour l'opération, alors qu'il pourrait répondre à d'autres demandes ...

La valeur idéale lorsque l'on privilégie les IOPS effectifs sur le débit, c'est une taille de chunk suffisante pour contenir la moyenne des I/O.
Le chunk size doit être plutôt grand.

S'il s'agit d'obtenir du débit, au détriment des IOPS effectifs, la stratégie consistera à mobiliser tous les disques qui composent la grappe dans le traitement d'une seule I/O système.
Si l'opération E/S à traiter est de grande taille, nous ferons en sorte que la taille du stripe soit immédiatement supérieure à la taille moyenne de la requête, et non pas la taille du chunk, comme dans la stratégie précédente.
Si la taille de la requête est inférieure à la taille du stripe, il est possible que tous les disques (chunks) ne soient pas utilisés pour traiter la requête, et l'on perdra du débit.
Le chunk size doit être plutôt petit.

Profilage des E/S

Les choses se compliquent sérieusement, puisqu'à ma connaissance, il n'existe pas d'OID SNMP ou de sonde Nagios qui permettent de profiler correctement la taille moyenne des I/O.
Chaque logiciel serveur un tant soit peu sérieux devrait avoir un outil de profilage des E/S, soit de base, soit via des plugins (gratuits ou payants).
Néanmoins, cela suppose pas mal de recherches, puisque c'est un domaine plutôt spécialisé.
Certains NAS et surtout les SAN proposent aussi des outils de profilage, puisque ce type d'optimisation entre directement dans les compétences d'un ingénieur spécialiste du stockage.

Nous pouvons toutefois noter, pour Linux, la présence du paquet sysstat, qui fournit l'utilitaire iostat.
Il se place au niveau du système, et non pas au niveau de l'applicatif.
Si vous avez placé les données de l'application sur une partition à part, vous aurez tout de même la possibilité d'avoir des informations sur la taille des I/O.

apt-get install sysstat
root@mysql1:/# iostat -x /dev/sda1
Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda1              0,01     0,17    0,03    0,32     0,75     4,55    30,24     0,00    2,73    5,14    2,54   0,32   0,01

Ici, c'est la variable avgrq-sz (average sectors per request) qui nous permet de profiler les I/O.

Conclusion

Le but de ce chapitre n'est pas de vous apprendre à profiler des I/O (c'est une vraie discipline, à part), mais uniquement de vous sensibiliser.

Parce qu'il est courant qu'un administrateur provisionne des grappes très rapides, mais que les équipes applicatives remontent quand même des problèmes de performance.
Au-delà des erreurs basiques (la grappe ne dispose pas suffisamment d'IOPS en lecture ou en écriture), le problème est souvent lié à la taille des blocs RAID, et témoigne d'une mauvaise coordination (ou d'une absence de communication) entre les équipes système et applicatif !

C'est plus particulièrement flagrant lorsque le problème concerne les bases de données, puisqu'elles sont très fortement limitées par les E/S, et doivent traiter beaucoup de requêtes en simultané, avec une latence minimale.
Une mauvaise taille de bloc va alors carrément faire s'écrouler les performances de la base !

Conclusion générale

Nous avons vu dans cet article les critères qu'il faut considérer lorsqu'on choisit un stockage, la notion des IOPS pour les disques individuels, mais aussi pour les grappes RAID, les avantages et inconvénients de chaque niveau de RAID, comment monitorer le stockage existant, et comment prévoir les performances des systèmes dès l'achat, et non pas une fois qu'ils seront mis en place.
Et quels étaient les possibilités d'optimisation d'une grappe, en jouant sur la taille des blocs et bandes RAID (chunks et stripes).

C'est beaucoup d'informations d'un coup si vous débutez, mais c'est la somme de connaissances nécessaire pour provisionner intelligemment des disques.
En dessous, et vous vous exposez à des approximations, voire à des erreurs, surtout si vous travaillez en production.
S'il y a bien un domaine dans lequel le manque de rigueur et le "maraboutage" peuvent se révéler catastrophiques, c'est bien celui-là.
Car tout simplement l'infrastructure applicative n'avancera jamais plus vite que son composant le plus lent, et c'est dans la majorité des cas le stockage !

Pour aller plus loin

Un calculateur pour vos grappes RAID, qui permet d'effectuer automatiquement les calculs que vous venez de voir (IOPS d'un disque, IOPS d'une grappe RAID, débit, etc).
http://www.wmarow.com/strcalc/strcalc.html

Partager l'article

Submit to FacebookSubmit to Google PlusSubmit to Twitter

Vous n'avez pas le droit de poster des commentaires

A propos de l'auteur

Milosz SZOTMilosz SZOT est ingénieur systèmes & réseaux spécialisé dans Linux et l'hébergement de sites web à fort trafic.

En savoir plus