---
categories: cloud storage
title: Howto DRBD
...

* Documentation : <http://www.drbd.org/en/doc/users-guide-84>

[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_.

## Installation

~~~
# apt install drbd-utils
~~~

~~~
# drbdadm -V
DRBDADM_BUILDTAG=GIT-hash:\ 5474c321d80250cc61d851220503fdc739490ce9\
                  build\ by\ pbuilder@marvin\,\ 2016-01-04\ 12:36:34
DRBDADM_API_VERSION=1
DRBD_KERNEL_VERSION_CODE=0x080403
DRBDADM_VERSION_CODE=0x080902
DRBDADM_VERSION=8.9.2rc1

# modinfo drbd
filename:       /lib/modules/3.16.0-4-amd64/kernel/drivers/block/drbd/drbd.ko
alias:          block-major-147-*
license:        GPL
version:        8.4.3
description:    drbd - Distributed Replicated Block Device v8.4.3
author:         Philipp Reisner <phil@linbit.com>, Lars Ellenberg <lars@linbit.com>
srcversion:     1A9F77B1CA5FF92235C2213
depends:        lru_cache,libcrc32c
intree:         Y
vermagic:       3.16.0-4-amd64 SMP mod_unload modversions
parm:           minor_count:Approximate number of drbd devices (1-255) (uint)
parm:           disable_sendpage:bool
parm:           allow_oos:DONT USE! (bool)
parm:           proc_details:int
parm:           usermode_helper:string
~~~

## 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 
~~~~

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](#ressource-avec-un-seul-volume)). 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 
~~~


## 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](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 :

~~~
# 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](#récupérer-dun-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](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-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_

### 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](HowtoOCFS2) 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.

<img src="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é (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)](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 :

~~~
# 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

<http://www.octetmalin.net/linux/tutoriels/drbd-afficher-et-comprendre-les-differents-etats-des-disques.php>

* `cs` : [Connection State](http://www.drbd.org/en/doc/users-guide-84/ch-admin#s-connection-states) (Connected/WFConnection/Unconnected/StandAlone/PausedSync/etc.)
* `ro` : [Resources roles](http://www.drbd.org/en/doc/users-guide-84/ch-admin#s-roles) (Primary/Secondary/Unknow)
* `ds` : [Disk States](http://www.drbd.org/en/doc/users-guide-84/ch-admin#s-disk-states) (UpToDate/Inconsistent/DUnknown/etc.)
* `A/B/C` : Replication Protocol
* `r-----` : [I/O Flags](http://www.drbd.org/en/doc/users-guide-84/ch-admin#s-io-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](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)


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](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 :

~~~
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](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) :

~~~
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](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)
