[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_.
- 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`
**drbdadm** pilote principalement les commandes bas niveau `drbdsetup` et `drbdmeta` : son mode _dry-and-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 :
Pour ajouter un volume à une ressource existante 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` :
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 et surtout pour éviter des erreurs de manipulation, on peut configurer une authentification dans la section _net{}_ (que l'on peut mettre dans _common_ ou dans chaque directive _resource_):
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 :
Si l'on veut modifier des paramètres de façon définitive, on utilisera la section _disk{}_ (que l'on peut mettre dans _common_ ou dans chaque directive _resource_) :
Bien qu'il n'y ait pas de démon pour DRBD, il y a une unité [systemd](HowtoSystemd), 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-and-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 stop all`
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, brtfs 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](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éplique sur un périphérique distant via un lien réseau.
<imgsrc="https://www.drbd.org/ug/users-guide-8.4/drbd-in-kernel.png"alt="Architecture de DRBD"/>
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é (`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 resynchronisation
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é 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œeud.
C : Réplication synchronisé 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.
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/*_.
### réseau
Si possible, on peut activer les _Jumbo Frames_ sur interfaces concernées par DRBD et tous les équipements intermédiaires :
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;`
On peut surveiller l'état des synchronisations DRBD via Nagios via <https://exchange.nagios.org/directory/Plugins/Operating-Systems/Linux/check_drbd/details>
Un _split-brain_ signifie que des écritures ont été réalisées sur deux volumes primaires et desynchronisés, le seul moyen est de choisir manuellement un volume à réinitialiser !
Sur le serveur en _Standalone_ qu'on veut réinitialiser :
il faut créer le périphérique avec `drbdsetup new-minor` …ou plus simple avec `drbdadm adjust`.
### Peut-on avoir plusieurs serveurs ?
Une ressource DRBD doit être définie entre deux serveurs, mais rien n'enpêche d'avoir d'autres resssources 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](https://www.drbd.org/en/doc/users-guide-84/s-three-way-repl)
### é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 :
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)
### Détruire les _metadatas_
Pour détruire les _metadatas_ des volumes d'une ressources (dangereux) :
~~~
# drbdadm wipe-md <ressource>
Do you really want to wipe out the DRBD meta data?