[DRBD](http://www.drbd.org) (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](HowtoKVM), 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_.
**Attention :** A partir de Debian 11 (Bullseye), la commande `drbd-overview` n'est plus disponible. Cette page n'a pas été mise à jour depuis. On peut utiliser `drbdadm status [ressource]` ou `drbdmon` à la place.
- 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) :
**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 :
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).
> *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>`
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.
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_).
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_):
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](https://www.drbd.org/en/doc/users-guide-84/re-drbdconf). [Les paramètres par défaut sont](https://www.drbd.org/en/doc/users-guide-84/s-recent-changes-defaults#s-recent-changes-defaults-variable-rate-sync) `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 :
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_) :
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 :
Pour des raisons de maintenance, on peut déconnecter une ressource. Attention, il faudra alors éviter un [split-brain](#récupérer-dun-split-brain) (notamment ne pas écrire sur les deux serveurs) :
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 :
*`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 manuellement
*`systemctl stop drbd` est dangereux, il stoppe toutes les ressources en faisant _drbdadm down all_
* 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](HowtoOCFS2) ou _GFS2_
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](https://www.drbd.org/en/doc/users-guide-84/ch-internals#s-metadata) : 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 [Generation Identifiers (GI)](https://www.drbd.org/en/doc/users-guide-84/s-gi) identifient le statut d'un volume DRBD. Concrètement il s'agit de plusieurs UUID auxquels on peut accéder via :
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…
*`ns nr dw dr al bm log pe ua ap ep wo oos` : [Performance indicators](http://www.drbd.org/en/doc/users-guide-84/ch-admin#s-performance-indicators) notamment ns/nr (network send/receive), dw/dr (disk write/read), oos (out of sync)
=> 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.
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 :
On peut aussi envisager de modifier le _scheduler_ des disques concernés par DRBD de _cfq_ à **_deadline_** et modifier certaines valeurs _iosched/\*_.
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;`
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 !
Si l'on veut répliquer une ressource avec un troisième serveur, [une solution est d'empiler deux réplications DRBD](https://www.drbd.org/en/doc/users-guide-84/s-three-way-repl)
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](https://about.gitlab.com/2015/03/09/moving-all-your-data/).
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](https://www.drbd.org/en/doc/users-guide-84/ch-internals#s-meta-data-size), on peut utiliser /dev/loop*
On démonte le disque, puis comme pour la [création d'une ressource avec un seul volume](#ressource-avec-un-seul-volume) on ajoute la configuration sur chaque serveur, puis on remonte le disque via DRBD (cela doit prendre quelques secondes) :
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) :
Plus fort que l'[IPoAC](https://fr.wikipedia.org/wiki/IP_over_Avian_Carriers), DRBD décrit la [réplication truck-based](https://www.drbd.org/en/doc/users-guide-84/s-truck-based-replication)