ZFS on Linux - 2


SunFire X4500

Note

La première version date de 2012, donc, les informations présentées ici sont outdated.


Précédent : ZFS on Linux - 1 | Suivant : ZFS on Linux - 3


2.1 - Description du matériel : SunFire X4500

  • 2x "Dual Core AMD Opteron 285" @ 2,6 Ghz (4 processeurs)
  • 16 Go RAM
  • 48x 500 Go SATA (répartis sur 6 controleurs Marvell MV88SX6081 8 ports)
  • 4x Intel Corporation 82546EB Gigabit Ethernet Controller

Mise en service 2006 et 2007. Debian 7 Squeeze jusqu'à Debian 10 Buster

2.2 - Configuration des disques

Sur une machine avec autant de disques (2 pour le système, 46 pour jouer^W les pools), il est fortement conseillé d'utiliser un fichier zdev.conf (qui deviendra vdev_id.conf dans les versions suivantes).

Comme il y a 6 contrôleurs SATA, on listera les disques by-path, afin de pouvoir panacher plus facilement ensuite. Les ¿$%§!£#!! de Virtual USB Devices n'étant pas désactivables (même en intervenant dans le BIOS), il faut nettoyer la liste des disques :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
ls -l /dev/disk/by-path | awk '{print $9 $10 $11}' | grep -v -e "-usb-"

pci-0000:01:01.0-scsi-0:0:0:0->../../sda
pci-0000:01:01.0-scsi-1:0:0:0->../../sdb
pci-0000:01:01.0-scsi-2:0:0:0->../../sdc
pci-0000:01:01.0-scsi-3:0:0:0->../../sdd
pci-0000:01:01.0-scsi-4:0:0:0->../../sde
pci-0000:01:01.0-scsi-5:0:0:0->../../sdf
pci-0000:01:01.0-scsi-6:0:0:0->../../sdg
pci-0000:01:01.0-scsi-7:0:0:0->../../sdh
pci-0000:02:01.0-scsi-0:0:0:0->../../sdi
pci-0000:02:01.0-scsi-1:0:0:0->../../sdk
pci-0000:02:01.0-scsi-2:0:0:0->../../sdl
pci-0000:02:01.0-scsi-3:0:0:0->../../sdm
pci-0000:02:01.0-scsi-4:0:0:0->../../sdn
pci-0000:02:01.0-scsi-5:0:0:0->../../sdo
pci-0000:02:01.0-scsi-6:0:0:0->../../sdp
pci-0000:02:01.0-scsi-7:0:0:0->../../sdq
pci-0000:05:01.0-scsi-0:0:0:0->../../sdr
pci-0000:05:01.0-scsi-1:0:0:0->../../sds
pci-0000:05:01.0-scsi-2:0:0:0->../../sdt
pci-0000:05:01.0-scsi-3:0:0:0->../../sdu
pci-0000:05:01.0-scsi-4:0:0:0->../../sdv
pci-0000:05:01.0-scsi-5:0:0:0->../../sdw
pci-0000:05:01.0-scsi-6:0:0:0->../../sdx
pci-0000:05:01.0-scsi-7:0:0:0->../../sdy
pci-0000:06:01.0-scsi-0:0:0:0->../../sdz
pci-0000:06:01.0-scsi-0:0:0:0-part1->../../sdz1
pci-0000:06:01.0-scsi-0:0:0:0-part2->../../sdz2
pci-0000:06:01.0-scsi-1:0:0:0->../../sdaa
pci-0000:06:01.0-scsi-2:0:0:0->../../sdab
pci-0000:06:01.0-scsi-3:0:0:0->../../sdac
pci-0000:06:01.0-scsi-4:0:0:0->../../sdad
pci-0000:06:01.0-scsi-4:0:0:0-part1->../../sdad1
pci-0000:06:01.0-scsi-4:0:0:0-part2->../../sdad2
pci-0000:06:01.0-scsi-5:0:0:0->../../sdae
pci-0000:06:01.0-scsi-6:0:0:0->../../sdaf
pci-0000:06:01.0-scsi-7:0:0:0->../../sdag
pci-0000:0a:01.0-scsi-0:0:0:0->../../sdah
pci-0000:0a:01.0-scsi-1:0:0:0->../../sdai
pci-0000:0a:01.0-scsi-2:0:0:0->../../sdaj
pci-0000:0a:01.0-scsi-3:0:0:0->../../sdak
pci-0000:0a:01.0-scsi-4:0:0:0->../../sdal
pci-0000:0a:01.0-scsi-5:0:0:0->../../sdam
pci-0000:0a:01.0-scsi-6:0:0:0->../../sdan
pci-0000:0a:01.0-scsi-7:0:0:0->../../sdao
pci-0000:0b:01.0-scsi-0:0:0:0->../../sdap
pci-0000:0b:01.0-scsi-1:0:0:0->../../sdaq
pci-0000:0b:01.0-scsi-2:0:0:0->../../sdar
pci-0000:0b:01.0-scsi-3:0:0:0->../../sdas
pci-0000:0b:01.0-scsi-4:0:0:0->../../sdat
pci-0000:0b:01.0-scsi-5:0:0:0->../../sdau
pci-0000:0b:01.0-scsi-6:0:0:0->../../sdav
pci-0000:0b:01.0-scsi-7:0:0:0->../../sdaw

Il faut retirer les disques bootable d'id 0 (pci-0000:06:01.0-scsi-0:0:0:0) et 1 (pci-0000:06:01.0-scsi-4:0:0:0) de cette liste.

En essayant de panacher les disques et les contrôleurs, afin de répartir au moins pire les I/O, voici un fichier zdev.conf résultant (il est possible de faire mieux) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# X4500 - zdev.conf, raidz1 panachés sur les controleurs sata

# pci-0000:03:04.0-usb-0:1:1.0-scsi-0:0:0:0 -> sr0
# pci-0000:03:04.1-usb-0:1:1.0-scsi-0:0:0:0 -> sdj

# pci-0000:06:01.0-scsi-0:0:0:0 -> sdz  (OS 0)
# pci-0000:06:01.0-scsi-4:0:0:0 -> sdad (OS 1)

# bloc A
A1  pci-0000:01:01.0-scsi-0:0:0:0 # sda
A2  pci-0000:01:01.0-scsi-3:0:0:0 # sdd
A3  pci-0000:01:01.0-scsi-7:0:0:0 # sdh
A4  pci-0000:02:01.0-scsi-2:0:0:0 # sdl
A5  pci-0000:02:01.0-scsi-6:0:0:0 # sdp
A6  pci-0000:05:01.0-scsi-2:0:0:0 # sdt

# bloc B
B1  pci-0000:05:01.0-scsi-6:0:0:0 # sdx
B2  pci-0000:01:01.0-scsi-1:0:0:0 # sdb
B3  pci-0000:01:01.0-scsi-4:0:0:0 # sde
B4  pci-0000:01:01.0-scsi-5:0:0:0 # sdf
B5  pci-0000:02:01.0-scsi-3:0:0:0 # sdm
B6  pci-0000:02:01.0-scsi-7:0:0:0 # sdq

# bloc C
C1  pci-0000:05:01.0-scsi-3:0:0:0 # sdu
C2  pci-0000:01:01.0-scsi-2:0:0:0 # sdc
C3  pci-0000:02:01.0-scsi-0:0:0:0 # sdi
C4  pci-0000:02:01.0-scsi-4:0:0:0 # sdn
C5  pci-0000:05:01.0-scsi-0:0:0:0 # sdr
C6  pci-0000:05:01.0-scsi-4:0:0:0 # sdv

# bloc D
D1  pci-0000:06:01.0-scsi-3:0:0:0 # sdac
D2  pci-0000:01:01.0-scsi-6:0:0:0 # sdg
D3  pci-0000:02:01.0-scsi-1:0:0:0 # sdk
D4  pci-0000:02:01.0-scsi-5:0:0:0 # sdo
D5  pci-0000:05:01.0-scsi-1:0:0:0 # sds
D6  pci-0000:05:01.0-scsi-5:0:0:0 # sdw

# bloc E
E1  pci-0000:06:01.0-scsi-2:0:0:0 # sdab
E2  pci-0000:06:01.0-scsi-6:0:0:0 # sdaf
E3  pci-0000:0a:01.0-scsi-2:0:0:0 # sdaj
E4  pci-0000:0a:01.0-scsi-6:0:0:0 # sdan
E5  pci-0000:0b:01.0-scsi-2:0:0:0 # sdar
E6  pci-0000:0b:01.0-scsi-6:0:0:0 # sdav

# bloc F
F1  pci-0000:06:01.0-scsi-7:0:0:0 # sdag
F2  pci-0000:0a:01.0-scsi-3:0:0:0 # sdak
F3  pci-0000:0a:01.0-scsi-7:0:0:0 # sdao
F4  pci-0000:0b:01.0-scsi-3:0:0:0 # sdas
F5  pci-0000:05:01.0-scsi-7:0:0:0 # sdy
F6  pci-0000:0b:01.0-scsi-5:0:0:0 # sdau

# bloc G
G1  pci-0000:0a:01.0-scsi-0:0:0:0 # sdah
G2  pci-0000:0a:01.0-scsi-4:0:0:0 # sdal
G3  pci-0000:0b:01.0-scsi-0:0:0:0 # sdap
G4  pci-0000:0b:01.0-scsi-4:0:0:0 # sdat
G5  pci-0000:06:01.0-scsi-1:0:0:0 # sdaa
G6  pci-0000:06:01.0-scsi-5:0:0:0 # sdae

# spares
SP1 pci-0000:0a:01.0-scsi-1:0:0:0 # sdai
SP2 pci-0000:0a:01.0-scsi-5:0:0:0 # sdam
SP3 pci-0000:0b:01.0-scsi-1:0:0:0 # sdaq
SP4 pci-0000:0b:01.0-scsi-7:0:0:0 # sdaw

Pour que le fichier /etc/zfs/zdev.conf soit pris en compte, il faut utiliser la commande suivante :

1
udevadm trigger /etc/zfs/zdev.conf

Un ls -l dans /dev/disk/zpool/ (ou /dev/disk/by-vdev/) confirmera la bonne prise en compte de cette configuration.

On peut, bien évidemment, panacher autrement. 8 disques par contrôleurs et 6 contrôleurs : Plein de possibilités !

On restera contraint avec les disques bootables (id 0 et id 1) qui sont sur le contrôleur 6.

2.3 - Création d'un pool manuel

2.3.1 pool unique

Un pool unique de 46 disques n'est pas recommandé. Mais ça fonctionne :

1
2
3
4
5
6
zpool create -f data raidz2 /dev/sda /dev/sdb /dev/sdc /dev/sdd /dev/sde /dev/sdf \
/dev/sdg /dev/sdh /dev/sdi /dev/sdj /dev/sdk /dev/sdl /dev/sdm /dev/sdn /dev/sdo \
/dev/sdq /dev/sdr /dev/sds /dev/sdt /dev/sdu /dev/sdv /dev/sdw /dev/sdx /dev/sdaa \
/dev/sdab /dev/sdac /dev/sdae /dev/sdaf /dev/sdag /dev/sdah /dev/sdai /dev/sdaj \
/dev/sdak /dev/sdal /dev/sdam /dev/sdan /dev/sdao /dev/sdap /dev/sdaq /dev/sdar \
/dev/sdas /dev/sdat /dev/sdau /dev/sdav spare /dev/sdaw /dev/sdy

Cela offre un espace utile d'environ 22 To. Mais, en raidz1, un seul disque qui pète, vous perdez l'ensemble. En raidz2, il faut deux disques en panne pour perdre le pool. Statistiquement, avec 48 disques, c'est vite arrivé...

2.3.2 pool compartimenté

En respectant les bonnes pratiques, on crée ici un assemblage de 7 grappes raidz1 de 6 disques chacun, plus 4 disques "hot-spare" globaux.

1
2
3
4
5
6
7
8
9
zpool create -f -o autoreplace=on -m /data data \
raidz1 /dev/sda /dev/sdb /dev/sdc /dev/sdd /dev/sde /dev/sdf \
raidz1 /dev/sdg /dev/sdh /dev/sdi /dev/sdj /dev/sdk /dev/sdl \
raidz1 /dev/sdm /dev/sdn /dev/sdo /dev/sdq /dev/sdr /dev/sds \
raidz1 /dev/sdt /dev/sdu /dev/sdv /dev/sdw /dev/sdx /dev/sdaa \
raidz1 /dev/sdab /dev/sdac /dev/sdae /dev/sdaf /dev/sdag /dev/sdah \
raidz1 /dev/sdai /dev/sdaj /dev/sdak /dev/sdal /dev/sdam /dev/sdan \
raidz1 /dev/sdao /dev/sdap /dev/sdaq /dev/sdar /dev/sdas /dev/sdat \
spare /dev/sdaw /dev/sdy /dev/sdau /dev/sdav

Vérification (l'assemblage des différentes grappes raidz1 est mis en valeur naturellement) :

1
2
3
4
zpool list

NAME   SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
data  19,0T   561G  18,5T     2%  1.00x  ONLINE  -
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
zpool status

  pool: data
 state: ONLINE
  scan: scrub repaired 0 in 0h14m with 0 errors on Tue Apr 10 09:18:52 2012
config:

    NAME        STATE     READ WRITE CKSUM
    data        ONLINE       0     0     0
      raidz1-0  ONLINE       0     0     0
        sda     ONLINE       0     0     0
        sde     ONLINE       0     0     0
        sdi     ONLINE       0     0     0
        sdm     ONLINE       0     0     0
        sdq     ONLINE       0     0     0
        sdu     ONLINE       0     0     0
      raidz1-1  ONLINE       0     0     0
        sdy     ONLINE       0     0     0
        sdb     ONLINE       0     0     0
        sdf     ONLINE       0     0     0
        sdj     ONLINE       0     0     0
        sdn     ONLINE       0     0     0
        sdr     ONLINE       0     0     0
      raidz1-2  ONLINE       0     0     0
        sdv     ONLINE       0     0     0
        sdc     ONLINE       0     0     0
        sdk     ONLINE       0     0     0
        sdo     ONLINE       0     0     0
        sds     ONLINE       0     0     0
        sdw     ONLINE       0     0     0
      raidz1-3  ONLINE       0     0     0
        sdd     ONLINE       0     0     0
        sdh     ONLINE       0     0     0
        sdl     ONLINE       0     0     0
        sdp     ONLINE       0     0     0
        sdt     ONLINE       0     0     0
        sdx     ONLINE       0     0     0
      raidz1-4  ONLINE       0     0     0
        sdac    ONLINE       0     0     0
        sdag    ONLINE       0     0     0
        sdak    ONLINE       0     0     0
        sdao    ONLINE       0     0     0
        sdas    ONLINE       0     0     0
        sdaw    ONLINE       0     0     0
      raidz1-5  ONLINE       0     0     0
        sdah    ONLINE       0     0     0
        sdal    ONLINE       0     0     0
        sdap    ONLINE       0     0     0
        sdat    ONLINE       0     0     0
        sdaa    ONLINE       0     0     0
        sdae    ONLINE       0     0     0
      raidz1-6  ONLINE       0     0     0
        sdai    ONLINE       0     0     0
        sdam    ONLINE       0     0     0
        sdaq    ONLINE       0     0     0
        sdau    ONLINE       0     0     0
        sdab    ONLINE       0     0     0
        sdaf    ONLINE       0     0     0
    spares
      sdaj      AVAIL
      sdan      AVAIL
      sdar      AVAIL
      sdav      AVAIL

errors: No known data errors

Cette configuration offre un bon rapport espace/panne : 19 To pour 7 + 4 disques qui peuvent tomber en panne, avant de perdre le pool. On peut aussi faire la même configuration en raidz2, pour encore plus de résilience à la panne disque.

2.4 - Création d'un pool avec zdev.conf

Toujours en respectant les bonnes pratiques, mais en utilisant cette fois-ci les alias du fichier /etc/zfs/zdev.conf, on peut largement simplifier la commande du § précédent :

1
2
3
4
5
6
7
8
9
zpool create -f -o autoreplace=on -m /data data \
raidz1 A1 A2 A3 A4 A5 A6 \
raidz1 B1 B2 B3 B4 B5 B6 \
raidz1 C1 C2 C3 C4 C5 C6 \
raidz1 D1 D2 D3 D4 D5 D6 \
raidz1 E1 E2 E3 E4 E5 E6 \
raidz1 F1 F2 F3 F4 F5 F6 \
raidz1 G1 G2 G3 G4 G5 G6 \
spare SP1 SP2 SP3 SP4

Vérification (7 grappes raidz1 de 6 disques chacune, et 4 disques hot-spare globaux) :

1
2
3
4
zpool list

NAME   SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
data  19,0T   561G  18,5T     2%  1.00x  ONLINE  -
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
zpool status

  pool: data
 state: ONLINE
  scan: none requested
config:

    NAME        STATE     READ WRITE CKSUM
    data        ONLINE       0     0     0
      raidz1-0  ONLINE       0     0     0
        A1      ONLINE       0     0     0
        A2      ONLINE       0     0     0
        A3      ONLINE       0     0     0

        [OK, vous avez compris...]

        G4      ONLINE       0     0     0
        G5      ONLINE       0     0     0
        G6      ONLINE       0     0     0
      spares
        SP1     AVAIL
        SP2     AVAIL
        SP3     AVAIL
        SP4     AVAIL

errors: No known data errors

2.5 - Tuning spécifique

La SunFire X4500 est un veau : Pas assez de processeurs, pas assez de mémoire. Cependant, il est possible d'améliorer un peu son comportement avec quelques réglages.

2.5.1 Forcer l'affinité des interruptions par CPU

Dans /etc/rc.local, on force l'association entre processeur et contrôleur SATA :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# fixer les irq sata/cpu
# cat /proc/interrupts pour trouver les bonnes interruptions
# (ici : 24,32,38,46,68 et 76 = 6 controleurs SATA)
# pour le processeur 0 : 2^0=1
echo "1" > /proc/irq/24/smp_affinity
echo "1" > /proc/irq/32/smp_affinity
# pour le processeur 1 : 2^1=2
echo "2" > /proc/irq/38/smp_affinity
echo "2" > /proc/irq/46/smp_affinity
# pour le processeur 2 : 2^2=4
echo "4" > /proc/irq/68/smp_affinity
echo "4" > /proc/irq/76/smp_affinity
# le dernier processeur (3) est laissé tranquille

Note

Edit 2019 : Sur une machine, ou une distribution, plus récente, il faut utiliser irqbalance plutôt que s'embêter avec smp_affinity.

2.5.2 Ordonnanceur

Pour changer l'ordonnanceur (ou scheduler), on peut simplement le fixer au démarrage de la machine (dans default/grub). Mais c'est brutal (ce qui va bien pour ZFS n'est pas forcément pertinent pour le réseau ou les I/O RAM).

Dans /etc/default/grub:

1
GRUB_CMDLINE_LINUX_DEFAULT="elevator=deadline"

Sinon, dans /etc/rc.local, disque par disque :

1
2
3
for device in /dev/sd? /dev/sda? ; do
  echo deadline > /sys/block/$disk/queue/scheduler   # noop, deadline, cfq
done

Note

Edit 2019 : Depuis les versions 3 et 4 des noyaux linux, l'ordonnanceur cfq donne de bien meilleures performances.

2.5.3 Slab limit et ARC min/max

Sous solaris, par défaut, ZFS n'était pas limité dans son usage de la mémoire, mais on pouvait lui fixer quelques limites. Pour retrouver le même comportement sous Linux, il faut passer des paramètres aux modules chargés dans le noyau.

Dans /etc/modprobe.d/zfs.conf :

1
2
3
4
5
6
options spl spl_kmem_cache_slab_limit=16384

# ARC à 8G => 8589934592 bytes
options zfs zfs_vdev_scheduler=deadline zfs_arc_min=8589934592 \
zfs_arc_max=8589934592 zfs_vdev_min_pending=1 zfs_vdev_max_pending=3 \
zfs_prefetch_disable=1 zfs_txg_synctime_ms=2000 zfs_txg_timeout=5 zfs_nocacheflush=0

En 2019, on peut presque se limiter à fixer zfs_arc_max (de 1/3 à 1/2 de la RAM) :

1
2
3
4
options spl spl_kmem_cache_slab_limit=16384

# ARC à 8G => 8589934592 bytes
options zfs zfs_vdev_scheduler=cfq zfs_arc_max=8589934592

Le CBP maintient encore quelques vaillantes SunFire X4500 en production.


Précédent : ZFS on Linux - 1 | Suivant : ZFS on Linux - 3