Howto DRBD
- Installation
- Utilisation basique
- Création de ressources/volumes
- Configuration
- Administration
- Plomberie
- Optimisations
- Monitoring
- FAQ
- Récupérer d’un split-brain
- Unrelated data, aborting
- Vérifier la configuration avec drbdadm verify ?
- Erreur Failure: (127) Device minor not allocated
- Erreur Diskless
- Peut-on avoir plusieurs serveurs ?
- États différents pour les volumes d’une ressource
- Détruire les metadatas
- Migration rsync-like d’un disque existant avec DRBD
- Réplication sans synchronisation de données initiales
- Réplication truck-base
- Supprimer DRBD 9.0
- Documentation DRBD 8.4 : https://linbit.com/drbd-user-guide/users-guide-drbd-8-4/
- Documentation DRBD 9.0 : https://linbit.com/drbd-user-guide/drbd-guide-9_0-en/
DRBD (Distributed Replicated Block Device) est un outil libre pour répliquer des blocs (disques, partitions, volumes LVM…) entre deux serveurs Linux via une connexion réseau. On peut voir cela comme un « RAID1 over TCP/IP ». Nous l’utilisons principalement comme stockage pour de la virtualisation avec KVM, cela permet notamment de réaliser des migrations à chaud de machines virtuelles entre deux hyperviseurs sans dépendre d’un équipement externe de type SAN.
La version 8.4 est intégrée dans le noyau Linux et dans Debian par défaut.
LINBIT (l’entreprise qui développe DRBD) propose aussi la version 9.0 qui permet notamment de faire facilement du DRBD entre trois serveurs Linux, ou encore d’être utilisé par Proxmox par l’intermédiaire de LINSTOR.
Installation
DRBD 8.4
# apt install drbd-utils
# drbdadm -V
DRBDADM_BUILDTAG=GIT-hash:\ 409097fe02187f83790b88ac3e0d94f3c167adab\ reproducible\ build\,\ 2023-01-09\ 14:51:18
DRBDADM_API_VERSION=1
DRBD_KERNEL_VERSION_CODE=0x08040b
DRBDADM_VERSION_CODE=0x091600
DRBDADM_VERSION=9.22.0
# modinfo drbd
filename: /lib/modules/6.1.0-17-amd64/kernel/drivers/block/drbd/drbd.ko
alias: block-major-147-*
license: GPL
version: 8.4.11
description: drbd - Distributed Replicated Block Device v8.4.11
author: Philipp Reisner <phil@linbit.com>, Lars Ellenberg <lars@linbit.com>
srcversion: 488C1124B879DCE7CD031DA
depends: lru_cache,libcrc32c
retpoline: Y
intree: Y
name: drbd
vermagic: 6.1.0-17-amd64 SMP preempt mod_unload modversions
sig_id: PKCS#7
signer: Debian Secure Boot CA
sig_key: 32:A0:28:7F:84:1A:03:6F:A3:93:C1:E0:65:C4:3A:E6:B2:42:26:43
sig_hashalgo: sha256
signature: 0C:85:38:83:85:36:BA:7B:25:BC:00:8A:1A:B6:E5:2F:03:BE:1D:48:
A7:C2:B1:AF:D3:94:6F:AC:28:9A:2F:F4:16:91:A3:6C:F9:67:E3:AF:
3E:70:4F:37:2D:A3:FA:9F:3F:2A:53:DB:87:0B:76:69:E2:9D:F5:F4:
9E:6C:DA:53:C4:79:4B:7E:02:F3:49:6C:A5:72:B3:AC:7C:5A:72:DB:
36:92:5E:A9:4F:60:10:FD:7C:A6:88:BB:E4:AD:0E:F7:27:B1:AB:69:
76:F7:53:BC:5C:97:DF:27:C5:97:5E:B6:6F:DD:36:20:83:25:53:BB:
1C:EF:E6:4B:F0:EC:D2:17:8F:43:E6:13:8A:F6:A6:E6:AA:14:B8:A3:
B6:6A:B2:2F:2A:61:77:81:81:CB:23:9E:B0:90:26:64:3E:45:A1:07:
68:2D:E5:2F:B1:96:D2:9E:20:47:14:1A:0E:49:40:56:68:D5:F7:B5:
89:CA:FA:95:9E:9D:36:58:89:88:11:6C:C7:CA:A3:E1:CE:3C:18:22:
BF:41:DD:1B:0A:5D:FC:EA:AA:83:B5:32:01:C1:00:B2:09:F2:83:55:
94:8F:FA:E8:22:99:2C:84:D6:B7:84:FC:03:6C:E5:79:96:C0:6E:84:
FD:2C:76:67:83:87:F2:92:2E:E5:DD:A2:1D:BA:53:47
parm: allow_oos:DONT USE! (bool)
parm: disable_sendpage:bool
parm: proc_details:int
parm: minor_count:Approximate number of drbd devices (1-255) (uint)
parm: usermode_helper:string
DRBD 9.0
LINBIT fournit un dépôt. Ce qui est étrange c’est que les modules pour DRBD 9 sont dans la suite Proxmox.
On ajoute les clés de LINBIT :
$ wget https://packages.linbit.com/public/linbit-keyring.deb
# dpkg -i « linbit-keyring.deb »
Et voici les sources pour Debian 12 ou Proxmox 8 :
# vim /etc/apt/sources.list.d/drbd.sources
Types: deb
URIs: https://packages.linbit.com/public
Enabled: yes
Suites: proxmox-8
Components: drbd-9
Signed-by: /etc/apt/trusted.gpg.d/linbit-keyring.gpg
et les sources pour Debian 11 ou Proxmox 7 :
# vim /etc/apt/sources.list.d/drbd.sources
Types: deb
URIs: https://packages.linbit.com/public
Enabled: yes
Suites: proxmox-7
Components: drbd-9
Signed-by: /etc/apt/trusted.gpg.d/linbit-keyring.gpg
Et enfin on installe :
# apt install drbd-dkms drbd-utils
# drbdadm -V
DRBDADM_BUILDTAG=GIT-hash:\ ba2ce9037989b6141222c7901d1219cf852949f1\ build\ by\ @buildsystem\,\ 2024-05-06\ 07:39:36
DRBDADM_API_VERSION=2
DRBD_KERNEL_VERSION_CODE=0x09020b
DRBD_KERNEL_VERSION=9.2.11
DRBDADM_VERSION_CODE=0x091c00
DRBDADM_VERSION=9.28.0
~# modinfo drbd
filename: /lib/modules/5.10.0-32-amd64/updates/dkms/drbd.ko
alias: block-major-147-*
license: GPL
version: 9.2.11
description: drbd - Distributed Replicated Block Device v9.2.11
author: Philipp Reisner <phil@linbit.com>, Lars Ellenberg <lars@linbit.com>
srcversion: 954B7260FDB1F57D723507F
depends: lru_cache,libcrc32c
retpoline: Y
name: drbd
vermagic: 5.10.0-32-amd64 SMP mod_unload modversions
parm: enable_faults:int
parm: fault_rate:int
parm: fault_count:int
parm: fault_devs:int
parm: disable_sendpage:bool
parm: allow_oos:DONT USE! (bool)
parm: minor_count:Approximate number of drbd devices (1U-255U) (uint)
parm: usermode_helper:string
parm: protocol_version_min:drbd_protocol_version
parm: strict_names:restrict resource and connection names to ascii alnum and a subset of punct (drbd_strict_names)
Il faut alors charger le nouveau module et redémarrer. On peut
vérifier que c’est bien pris en compte via /proc/drbd
.
Utilisation basique
Sur une installation DRBD on définit :
- des ressources : chaque ressource DRBD a plusieurs paramètres, notamment le second serveur vers qui envoyer/recevoir la réplication
- des volumes : chaque ressource DRBD peut avoir un
ou plusieurs volumes, chaque volume est accessible via un périphérique
unique nommé
/dev/drbdXX
La configuration des ressources DRBD est dans le répertoire
/etc/drbd.d/
; voici un exemple simple d’une ressource
foo avec un volume /dev/drbd42
définie dans un
fichier /etc/drbd.d/foo.res
entre deux serveurs nommés
tic et tac (cet exemple sera repris par la suite)
:
resource "foo" {
volume 0 {
device minor 42;
disk /dev/sdz1;
meta-disk internal;
}
on tic {
address 192.0.2.1:7014;
}
on tac {
address 192.0.2.2:7014;
}
}
Pour voir les volumes configurés et leur statut :
$ cat /proc/drbd
version: 8.4.7 (api:1/proto:86-101)
srcversion: 0904DF2CCF7283ACE07D07A
42: cs:WFConnection ro:Secondary/Unknown ds:Inconsistent/DUnknown C r----s
ns:0 nr:0 dw:0 dr:0 al:8 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:1048508
# drbd-overview
42:foo/0 WFConnection Secondary/Unknown Inconsistent/DUnknown
Attention : Depuis Debian 11 (Bullseye), la commande
drbd-overview
n’est plus disponible. On peut utiliser
drbdadm status [ressource]
ou drbdmon
à la
place.
Il existe aussi drbdmon(8)
qui permet d’avoir un
affichage en temps réel (façon htop(8)
) de l’état des
ressources DRBD.
Pour lister la configuration et vérifier la syntaxe :
# drbdadm dump
drbdadm est l’outil principal pour DRBD, voici quelques commandes utilisables sur une ressource :
# drbdadm dump
# drbdadm create-md [ressource]
# drbdadm attach/detach [ressource]
# drbdadm connect/disconnect [ressource]
# drbdadm adjust/adjust-with-progress [ressource]
# drbdadm primary/secondary [ressource]
On peut également piloter un volume d’une ressource en indiquant la syntaxe [ressource]/[n° de volume], par exemple :
# drbdadm secondary foo/0
drbdadm pilote principalement les commandes bas
niveau drbdsetup
et drbdmeta
. Son mode
« dry-run » est très utile car il va lister les commandes bas niveau
effectuées (sans les appliquer). Par exemple pour voir tous les
changements de configuration non appliqués :
# drbdadm -d adjust all
Création de ressources/volumes
ressource avec un seul volume
Il faut créer /etc/drbd.d/foo.res
sur les deux
serveurs concernés :
resource "foo" {
net {
#allow-two-primaries;
}
volume 0 {
device minor 42;
disk /dev/sdz1;
meta-disk internal;
}
on tic {
address 192.0.2.1:7014;
}
on tac {
address 192.0.2.2:7014;
}
}
Note : les hostnames et adresses IP doivent être corrects car DRBD vérifie qu’ils sont effectivement configurés en local !
On vérifie la syntaxe via :
# drbdadm dump foo
# resource foo on tic: not ignored, not stacked
# defined at /etc/drbd.d/foo.res:1
[…]
On initialise les metadata sur les disques (attention, cela écrit des données à la fin des disk) sur chaque serveur :
tic# drbdadm create-md foo
tac# drbdadm create-md foo
initializing activity log
NOT initializing bitmap
Writing meta data...
New drbd meta data block successfully created.
On utilise la commande drbdadm adjust en mode dry-run sur chaque serveur pour vérifier les actions :
tic# drbdadm -d adjust foo
tac# drbdadm -d adjust foo
drbdsetup-84 new-resource foo
drbdsetup-84 new-minor foo 42 0
drbdmeta 42 v08 /dev/sdz1 internal apply-al
drbdsetup-84 attach 42 /dev/sdz1 /dev/sdz1 internal
drbdsetup-84 connect foo ipv4:192.0.2.1:7014 ipv4:192.0.2.2:7014
Puis on applique cette nouvelle configuration :
tic# drbdadm adjust foo
tac# drbdadm adjust foo
À ce stade, vous devez avoir une ressource Connected avec des données Inconsistent :
# drbd-overview
42:foo/0 Connected Secondary/Secondary Inconsistent/Inconsistent
Il reste à forcer la synchronisation d’un côté :
tic# drbdadm -- --overwrite-data-of-peer primary foo
Et observer cette première synchronisation puis l’état UpToDate de chaque côté :
# drbd-overview
42:foo/0 SyncSource Primary/Secondary UpToDate/Inconsistent
[===>................] sync'ed: 22.3% (818364/1048508)K
# drbd-overview
42:foo/0 Connected Primary/Secondary UpToDate/UpToDate
Si l’on veut être en Primary/Primary il faut avoir configuré
allow-two-primaries;
puis :
tac# drbdadm primary foo
# drbd-overview
42:foo/0 Connected Primary/Primary UpToDate/UpToDate
ressource avec plusieurs volumes
On peut avoir plusieurs volumes pour une même ressource. Cela simplifie la configuration (un seul fichier, un seul port TCP) et la gestion (drbdadm s’applique alors pour tous les volumes d’une même ressource).
Voici un exemple de fichier /etc/drbd.d/foo.res
associé
à un volume pour /dev/drbd43
et un volume pour
/dev/drbd44
:
resource "foo" {
net {
#allow-two-primaries;
}
volume 0 {
device minor 43;
disk /dev/sdz1;
meta-disk internal;
}
volume 1 {
device minor 44;
disk /dev/sdz2;
meta-disk internal;
}
on tic {
address 192.0.2.1:7014;
}
on tac {
address 192.0.2.2:7014;
}
}
Note : attention, les device minor doivent être différents pour chaque volume DRBD sur l’ensemble du serveur car ils vont correspondre à un périphérique unique
/dev/drbd<device minor>
Les étapes sont ensuite similaires à une ressource avec un seul volume (voir détails ci-dessus). En résumé :
tic# drbdadm create-md foo
tac# drbdadm create-md foo
tic# drbdadm adjust foo
tac# drbdadm adjust foo
tic# drbdadm -- --overwrite-data-of-peer primary foo
tac# drbdadm primary foo
# drbd-overview
43:foo/0 Connected Primary/Primary UpToDate/UpToDate
44:foo/0 Connected Primary/Primary UpToDate/UpToDate
ajouter un volume à une ressource existante
Pour ajouter un nouveau volume à une ressource avec des volumes déjà
en production, on utilisera directement les commandes bas niveau
drbdsetup
et drbdmeta
pour ne pas perturber
les autres volumes.
Voici l’exemple du fichier /etc/drbd.d/foo.res
ci-dessus
avec l’ajout d’un 3ème volume /dev/drbd45
:
resource "foo" {
net {
#allow-two-primaries;
}
volume 0 {
device minor 43;
disk /dev/sdz1;
meta-disk internal;
}
volume 1 {
device minor 44;
disk /dev/sdz2;
meta-disk internal;
}
volume 2 {
device minor 45;
disk /dev/sdz3;
meta-disk internal;
}
on tic {
address 192.0.2.1:7014;
}
on tac {
address 192.0.2.2:7014;
}
}
On crée ensuite les metadatas uniquement pour ce nouveau
volume /dev/drbd45
:
tic# drbdmeta 45 v08 /dev/sdz3 internal create-md
tac# drbdmeta 45 v08 /dev/sdz3 internal create-md
Puis on applique cette nouvelle configuration (en observant avant en mode dry-run) :
tic# drbdadm -d adjust foo
tac# drbdadm -d adjust foo
tic# drbdadm adjust foo
tac# drbdadm adjust foo
Et enfin, on force la synchronisation de ce nouveau volume
/dev/drbd45
:
tic# drbdsetup primary 45 --overwrite-data-of-peer
Mise en place de 3 nœuds avec DRBD 9.0
Voici un exemple d’une ressource nommée “foo” :
resource "foo" {
volume 0 {
device minor 42;
disk /dev/sdz1;
meta-disk internal;
}
on tic {
address 192.0.2.1:7014;
}
on tac {
address 192.0.2.2:7014;
}
}
Pour chaque nœud, ajoutez un node-id :
on tic {
address 192.0.2.1:7014;
node-id 0;
}
on tac {
address 192.0.2.2:7014;
node-id 1;
}
on toc {
address 192.0.2.3:7014;
node-id 2;
}
Afin d’énumérer l’ordre de connection de tous les nœuds participants, ajoutez la directive :
connection-mesh {
hosts tic tac toc;
}
Configuration
https://www.drbd.org/en/doc/users-guide-84/re-drbdconf
La configuration générale (directives global et
common) est dans le fichier
/etc/drbd.d/global_common.conf
(inclus par
/etc/drbd.conf
), les ressources sont dans des fichiers
/etc/drbd.d/*.res
(directives resource).
/etc/drbd.conf
├── /etc/drbd.d/global_common.conf
└── /etc/drbd.d/*.res
authentification
Afin de sécuriser un peu les échanges DRBD entre deux serveurs, on peut configurer une authentification dans la section net{} (que l’on peut mettre dans common ou dans chaque directive resource):
net {
cram-hmac-alg "sha1";
shared-secret "PASSWORD";
}
protocoles A/B/C et allow-two-primaries
DRBD dispose de 3 protocoles de réplication/synchronisation : A, B et C.
- A : réplication asynchrone
- B : réplication semi-asynchrone
- C : réplicaton synchrone (c’est le protocole utilisé par défaut),
seul ce mode permet l’option
allow-two-primaries;
On peut configurer le protocole dans la section net{} (que l’on peut mettre dans common ou dans chaque directive resource):
net {
protocol A;
}
net {
protocol B;
}
net {
protocol C;
allow-two-primaries;
}
vitesse de re-synchronisation
https://www.drbd.org/en/doc/users-guide-84/s-configure-sync-rate
La re-synchronisation est l’étape d’échange des données quand un
volume n’est pas/plus en UpToDate/UpToDate (par exemple à la
création d’un nouveau volume). Par défaut, la vitesse de
re-synchronisation est dynamique et limitée à 100Mo/s (soit 800Mb/s).
Ceci est valable depuis DRBD 8.4 même si la
documentation principale n’est pas tout à fait à jour. Les
paramètres par défaut sont
c-plan-ahead 20; c-fill-target 50k; c-min-rate 250k; c-max-rate 100M;
.
Si besoin, on peut fixer temporairement cette vitesse (pour la limiter ou pour l’augmenter) en définissant en Mo/s sur le serveur qui reçoit les données. Par exemple pour forcer à 200 Mo/s :
# drbdadm disk-options --c-plan-ahead=0 --resync-rate=200M <ressource>
Pour reprendre les valeurs des fichiers de configuration :
# drbdadm adjust <ressource>
Si l’on veut modifier ces paramètres de façon définitive, on utilisera la section disk{} (que l’on peut mettre dans common ou dans chaque directive resource) :
disk {
resync-rate 200M;
}
Administration
supprimer une ressource
On peut supprimer une ressource via drbdadm down
(qui
fait un disconnect puis detach) :
# drbdadm down <ressource>
On peut ensuite supprimer le fichier de conf associé et s’assurer que c’est bien pris en compte :
# rm /etc/drbd.d/<ressource>.res
# drbdadm dump <ressource>
supprimer un volume d’une ressource
Dans le fichier /etc/drbd.d/foo.res
on supprime la
section suivante correspondant au volume /dev/drbd45
:
volume 2 {
device minor 45;
disk /dev/sdz3;
meta-disk internal;
}
On utilise ensuite drbdsetup
sur chaque serveur avec le
device minor correspondant au volume à supprimer :
tic# drbdsetup secondary 45
tic# drbdsetup detach 45
tic# drbdsetup del-minor 45
tac# drbdsetup secondary 45
tac# drbdsetup detach 45
tac# drbdsetup del-minor 45
Puis on applique cette nouvelle configuration (en observant avant en mode dry-run) :
tic# drbdadm -d adjust foo
tac# drbdadm -d adjust foo
tic# drbdadm adjust foo
tac# drbdadm adjust foo
passer une ressource en primary/secondary
Pour passer une ressource en primary ou secondary :
# drbdadm primary <ressource>
# drbdadm secondary <ressource>
Note : pour passer en primary il faut s’assurer d’utiliser le protocole C et d’avoir configuré
allow-two-primaries;
Pour passer toutes les ressources en primary ou secondary :
# drbdadm primary all
# drbdadm secondary all
invalider une ressource
Si l’on considère qu’une ressource locale est out-of-sync on va l’invalider, ce qui provoque une resynchronisation immédiate depuis le serveur distant :
# drbdadm invalidate <ressource>
Note : on peut aussi utiliser
drbdadm invalidate-remote
pour invalider une ressource sur le serveur distant
déconnecter/connecter une ressource
Pour des raisons de maintenance, on peut déconnecter une ressource. Attention, il faudra alors éviter un split-brain (notamment ne pas écrire sur les deux serveurs) :
# drbdadm disconnect <ressource>
# drbdadm connect <ressource>
Note : pour toutes les ressources on pourra utiliser drbdadm disconnect all
Resize une ressource
Doc officielle : http://docs.linbit.com/doc/users-guide-84/s-resizing/
À chaud, après avoir étendu le block device associé au volume drbd (par exemple avec LVM).
# drbdadm resize <resource>
Changer le serveur secondaire
Dans le cas où on a besoin de changer la réplication de host1 → host2 à host1 → host3. Cette procédure se fait à chaud.
- sur le nouveau secondaire, s’assurer de recréer le même block device (exactement de même taille) puis configurer la ressource DRBD comme pour une première configuration
- sur les serveurs primaire et secondaire actuels, déconnecter la ressource :
# drbdadm detach <ressource>
# drbdadm disconnect <ressource>
- sur le primaire, mettre à jour les informations de connexion du secondaire dans le fichier de ressource puis appliquer les changements et lancer la synchronisation vers le nouveau secondaire :
# drbdadm adjust all
# drbdadm attach <ressource>
# drbdadm -- --overwrite-data-of-peer primary <ressources>
- sur l’ancien secondaire, le fichier de ressource peut être supprimé.
DRBD et systemd
Bien qu’il n’y ait pas de démon pour DRBD, il y a une unité systemd, mais son utilisation est déconseillée :
systemctl reload drbd
fait un drbdadm adjust all : autant utiliser la commande soi-même (en la testant en dry-run avant)systemctl start drbd
fait tout d’abord un drbdadm adjust-with-progress all : si vous n’avez aucune ressource DRBD, cela échoue avec no resources defined! ; il fait ensuite drbdadm wait-connect all qui sera bloqué infiniment si vos serveurs secondaires ne sont pas encore opérationnels ; enfin, il tente de passer les ressources en Primary ce qu’il est plus prudent de faire manuellementsystemctl stop drbd
est dangereux, il stoppe toutes les ressources en faisant drbdadm down all
DRBD et les filesystem
DRBD réalise une réplication au niveau bloc, il ne tient donc absolument pas compte du filesystem :
- si l’on utilise un filesystem classique (ext4, btrfs etc.) il faut faire attention à ne jamais monter le filesystem à deux endroits à la fois
- si l’on veut lire/écrire les données d’une ressource DRBD depuis les deux serveurs, il faut utiliser un filesystem réseau comme OCFS2 ou GFS2
Plomberie
https://www.drbd.org/en/doc/users-guide-84/p-learn
DRBD est un block device qui se met en proxy devant un périphérique de stockage pour intercepter les requêtes en écriture et les répliquer sur un périphérique distant via un lien réseau.
DRBD a besoin de metadatas
: il les écrit en général à la fin du disque concerné
(option meta-disk internal
)… la taille du block
device final est donc un peu plus petite que le disque concerné. Il
peut aussi gérer ses metadatas à un autre emplacement, ce qui
peut notamment servir à utiliser DRBD avec un disque sans le
modifier.
Les metadatas DRBD contiennent :
- la taille du volume DRBD
- des Generation Identifiers (GI)
- un Activity Log (AL) qui liste les blocs récemment écrits au cas où
- Un quick-sync bitmap qui est une sorte de hash du volume DRBD pour optimiser la re-synchronisation
Les Generation Identifiers (GI) identifient le statut d’un volume DRBD. Concrètement il s’agit de plusieurs UUID auxquels on peut accéder via :
# drbdadm show-gi foo
+--< Current data generation UUID >-
| +--< Bitmap's base data generation UUID >-
| | +--< younger history UUID >-
| | | +-< older history >-
V V V V
0283D46356ABF426:0000000000000000:E55525BF67DFF687:E55425BF67DFF687:1:1:0:1:0:0:0
^ ^ ^ ^ ^ ^ ^
-< Data consistency flag >--+ | | | | | |
-< Data was/is currently up-to-date >--+ | | | | |
-< Node was/is currently primary >--+ | | | |
-< Node was/is currently connected >--+ | | |
-< Node was in the progress of setting all bits in the bitmap >--+ | |
-< The peer's disk was out-dated or inconsistent >--+ |
-< This node was a crashed primary, and has not seen its peer since >--+
flags: Secondary, Connected, UpToDate
meta-data: need apply-al
À propos des protocoles
Il est important de bien comprendre les 3 protocoles de réplication/synchronisation :
A : Réplication asynchrone. Les écritures sur le disque local du nœud primaire sont considérées complètes dès que le disque local a fini. Les paquets de réplication sont placés dans le buffer TCP.
B : Réplication synchronisée en mémoire. Les écritures sur le disque local du nœud primaire sont considérées complètes dès que le disque local a fini et que les paquets de réplication sont reçus sur le second nœud.
C : Réplication synchronisée sur les disques. Les écritures sur le disque local du nœud primaire sont considérées complètes dès que le disque local a fini et sur le disque distant aussi.
Le protocole C est donc le plus sécurisé mais ayant le plus d’impact sur les performances, le protocole A a les meilleures performances (comparables aux performances des disques locaux… si les buffers de réplication ne sont pas saturés) et le protocole B est un compromis entre les deux : il n’est ni sécurisé ni performant…
Bien comprendre /proc/drbd
cs
: Connection State (Connected/WFConnection/Unconnected/StandAlone/PausedSync/etc.)ro
: Resources roles (Primary/Secondary/Unknow)ds
: Disk States (UpToDate/Inconsistent/DUnknown/etc.)A/B/C
: Replication Protocolr-----
: I/O Flags [r/s][-/a][-/p][-/u][-/d/b/n/a][-/s]ns nr dw dr al bm log pe ua ap ep wo oos
: Performance indicators notamment ns/nr (network send/receive), dw/dr (disk write/read), oos (out of sync)
Exemples :
42: cs:WFConnection ro:Primary/Unknown ds:UpToDate/DUnknown C r-----
=> Le nœud attend une reconnexion avec le second serveur pour lui renvoyer les données (re-synchronisation).
42: cs:StandAlone ro:Primary/Unknown ds:UpToDate/DUnknown r-----
=> Il s’agit d’un split-brain, le nœud est en standalone, et n’est plus synchronisé avec le second serveur.
42: cs:Connected ro:Primary/Primary ds:UpToDate/UpToDate C r-----
=> Les serveurs sont bien synchronisés.
42: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r-----
ns:782997 nr:8388524 dw:10158853 dr:684557 al:456 bm:562 lo:0 pe:5 ua:64 ap:0 ep:1 wo:f oos:7780060
[>…] sync'ed: 7.3% (7596/8188)Mfinish: 0:04:29 speed: 28,800 (28,964) K/sec
=> Une re-synchronisation est en cours vers le second serveur.
42: cs:SyncSource ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
ns:73484284 nr:0 dw:64998220 dr:28984421 al:10100 bm:1287 lo:38 pe:20001 ua:0 ap:20001 ep:1 wo:d oos:0
=> Les serveurs sont bien synchronisés (en protocole C) mais un échange intensif de données est en cours, on le voit car les indicateurs pe: (pending) et ap: (application pending) sont à 20001, qui est le max-buffers/max-epoch-size dans ce cas.
Optimisations
disque
DRBD s’assure que les données sont écrites, et notamment que les données sont effectivement écrites sur le disque. Si l’on veut davantage de performance, on peut désactiver ces actions. On conseille notamment de le faire si l’on utilise une carte RAID hardware équipée d’une batterie :
disk {
disk-barrier no;
disk-flushes no;
md-flushes no;
}
On peut synchroniser moins souvent les metadatas :
disk {
al-extents 6433;
}
On peut aussi envisager de modifier le scheduler des disques concernés par DRBD de cfq à deadline et modifier certaines valeurs iosched/*.
réseau
Si possible, on peut activer les Jumbo Frames sur interfaces concernées par DRBD et tous les équipements intermédiaires :
# ifconfig eth4 mtu 9000
On peut augmenter les buffers de chaque volume :
net {
max-buffers 8000;
max-epoch-size 8000;
}
Choix du protocole
Le protocole C utilisé par défaut est le plus sécurisé, mais il
implique qu’une donnée est considérée comme écrite si elle l’a été
également sur le second serveur. Pour éviter cela on peut utiliser le
protocole A ou B tout en gardant en tête que c’est risqué. Le plus
performant (et le plus risqué) est protocol A;
Monitoring
Munin
Il existe un plugin Munin pour avoir des graphes disque/réseau pour chaque volume DRBD :
$ wget https://raw.githubusercontent.com/munin-monitoring/contrib/master/plugins/drbd/drbd
Le plugin drbd nécessite a priori de tourner en root,
/etc/munin/plugin-conf.d/munin-node
:
[drbd]
user root
Nagios
On peut surveiller l’état des volumes DRBD via Nagios via https://exchange.nagios.org/directory/Plugins/Operating-Systems/Linux/check_drbd/details
/usr/local/lib/nagios/plugins/check_drbd -d All -c StandAlone
FAQ
Récupérer d’un split-brain
https://www.drbd.org/en/doc/users-guide-84/s-resolve-split-brain
Un split-brain signifie que des écritures ont été réalisées sur deux volumes primaires et désynchronisés, le seul moyen est de choisir manuellement un volume à réinitialiser !
Sur le serveur en Standalone qu’on veut réinitialiser :
# drbdadm secondary <ressource>
# drbdadm invalidate <ressource>
# drbdadm disconnect <ressource>
# drbdadm -- --discard-my-data connect <ressource>
Sur le serveur primaire où sont les données choisies comme valides :
# drbdadm connect <ressource>
Unrelated data, aborting
block drbd0: Unrelated data, aborting
Si l’on obtient ce message, c’est probablement que les metadatas ont été perdues sur un volume. Il faut alors les recréer…
Vérifier la configuration avec drbdadm verify ?
Attention drbdadm verify
ne vérifie pas la configuration
mais une vérification à chaud des volumes… à ne pas lancer à la légère
en production !
Erreur Failure: (127) Device minor not allocated
Si l’on obtient une erreur du type :
42: Failure: (127) Device minor not allocated
additional info from kernel:
unknown minor
Command 'drbdsetup-84 verify 42' terminated with exit code 10
il faut créer le périphérique avec drbdsetup new-minor
…ou plus simple avec drbdadm adjust
.
Erreur Diskless
Si l’on obtient un état « Diskless » cela peut vouloir dire que la ressource n’est pas ou plus attachée.
Note : Une ressource peut être automatiquement détachée suite à des erreurs d’I/O.
42: cs:WFConnection ro:Primary/Unknown ds:Diskless/DUnknown C r-----
ns:0 nr:932 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:0
On corrigera avec un drbdadm attach
de la ressource en
question.
Cela peut aussi être le cas avec un VG LVM qui serait activé sur un hyperviseur par exemple. On pourra le corriger avec un :
# vgchange -an /dev/<vgname>
Pour éviter que le noyau active le VG voir : https://wiki.evolix.org/HowtoLVM#filter-la-d%C3%A9tection-des-vg
Peut-on avoir plusieurs serveurs ?
Une ressource DRBD doit être définie entre deux serveurs, mais rien n’enpêche d’avoir d’autres ressources liées à différents serveurs.
Si l’on veut répliquer une ressource avec un troisième serveur, une solution est d’empiler deux réplications DRBD
États différents pour les volumes d’une ressource
Les volumes d’une même ressource sont-ils forcément dans le même état primary/secondary ?
Contrairement à ce que l’on pourrait penser, on peut très bien ajuster des volumes d’une même ressource dans des états différents :
tic# drbdsetup primary 43
tic# drbdsetup secondary 44
tac# drbdsetup secondary 43
tac# drbdsetup primary 44
# drbd-overview
43:foo/0 Connected Primary/Secondary UpToDate/UpToDate
44:foo/1 Connected Secondary/Primary UpToDate/UpToDate
Note : cela nécessite d’utiliser le protocole C et d’avoir configuré
allow-two-primaries;
Détruire les metadatas
Pour détruire les metadatas des volumes d’une ressource (attention, c’est évidemment dangereux) :
# drbdadm wipe-md <ressource>
Do you really want to wipe out the DRBD meta data?
[need to type 'yes' to confirm] yes
Wiping meta data...
DRBD meta data block successfully wiped out.
Migration rsync-like d’un disque existant avec DRBD
On peut migrer les données d’un disque existant en créant un volume DRBD avec des metadatas stockées en externe. Par exemple, Gitlab a migré 9To de données en quelques jours.
Voici la configuration d’un volume avec les metadatas en externe :
volume 0 {
device minor 42;
disk /dev/sdz1;
meta-disk /dev/sdx1;
}
Note : meta-disk doit indiquer un périphérique d’une taille suffisante, on peut utiliser /dev/loop*
On démonte le disque, puis comme pour la création d’une ressource avec un seul volume on ajoute la configuration sur chaque serveur, puis on remonte le disque via DRBD (cela doit prendre quelques secondes) :
tic# umount /dev/sdz1
tic# drbdadm create-md foo
tic# drbdadm adjust foo
tic# mount /dev/drbd42 /mnt
On prépare ensuite le second serveur, puis on démarre la réplication depuis le premier serveur :
tac# drbdadm create-md foo
tac# drbdadm adjust foo
tic# drbdadm -- --overwrite-data-of-peer primary foo
La synchronisation va ensuite se faire (et prendre du temps suivant le volume).
Une fois terminé, on pourra choisir son moment pour démounter le disque en production et remounter le volume sans DRBD sur le second serveur (on peut ensuite supprimer tout ce qui est relatif à DRBD) :
tic# umount /dev/drbd42
tic# drbadm secondary foo
tic# drbadm down foo
tic# rm /etc/drbd.d/foo.res
tac# drbadm down foo
tac# mount /dev/sdz1 /mnt
tac# rm /etc/drbd.d/foo.res
Réplication sans synchronisation de données initiales
Une fois les nœuds connectés, au lieu de faire
--overwrite-data-of-peer
sur l’un des serveurs :
tic# drbdadm -- --clear-bitmap new-current-uuid foo
tic# drbdadm primary foo
Réplication truck-base
Plus fort que l’IPoAC, DRBD décrit la réplication truck-based
Supprimer DRBD 9.0
Vous pouvez vouloir supprimer DRBD pour changer sa version (downgrade ou changement majeur). Pour ce faire:
Arrêter et désactiver les services DRBD
sudo systemctl stop drbd
sudo systemctl disable drbd
Décharger les modules DRBD
sudo rmmod drbd
Si le module DRBD ne peut pas être déchargé, cela peut être dû au fait qu’il est en cours d’utilisation. Assurez-vous qu’aucun service ou processus n’utilise DRBD.
Supprimez le fichier du module DRBD manuellement :
sudo rm /lib/modules/$(uname -r)/kernel/drivers/block/drbd.ko (ou .../block/drbd/drbd.ko)
Mettre à jour les dépendances des modules
sudo depmod -a
Désinstallez les packages DRBD :
sudo apt-get remove --purge drbd-utils drbd8-module-source (drbd-module-source pour DRBD9)
Nettoyer les fichiers de configuration restants
sudo find /etc -name "*drbd*" -exec rm -rf {} \;
sudo find /var -name "*drbd*" -exec rm -rf {} \;
Vérifier la suppression
Vérifiez que le module DRBD a bien été supprimé :
ls /lib/modules/$(uname -r)/kernel/drivers/block/ | grep drbd
Redémarrez pour vous assurer que toutes les modifications sont prises en compte.