UUIDから学ぶDRBDデータ同期の仕組み
はじめに

DRBD(Distributed Replicated Block Device)は、Linux環境における高可用性(HA)クラスタの構築に欠かせない、ブロックデバイスレベルのレプリケーションソフトウェアです。DRBDがデータを正確に同期し、障害発生時にデータを守るためには、UUID と呼ばれるメタデータが重要な役割を果たしています。
本記事では、このDRBDの「データの番人」であるUUIDが、ノード間の接続状態やデータ不整合(スプリットブレイン)の際にどのように変動し、DRBDの状態を決定しているのかを、具体的な検証ログに基づいて解説します。
DRBDのUUIDとは
DRBDにおけるUUIDは、データセットの状態と履歴を追跡するための4つの要素からなる識別子です。このUUIDをピアノード同士で比較することで、データの整合性や同期の方向を決定します。
| 要素 | 名称 | 役割 |
| 第1要素 | Current UUID | 現在のデータセットのユニークなID。データ更新があるたびに変化する。 |
| 第2要素 | Bitmap UUID | 前回同期(リシンク)が行われた時点の Current UUID。通常はゼロ。 |
| 第3要素 | History UUID | 自身のディスクが保持していた過去の Current UUID。 |
| 第4要素 | History UUID | ピア(対向ノード)のディスクが保持していた過去の Current UUID。 |
UUIDの比較ルール: DRBDは、この4つのUUID要素を複雑なルールに基づいて比較し、「どちらのノードが最新か」「同期が必要か」「スプリットブレインか」を判断します。
単純な回線断の場合の例
ここでは、DRBDノード間の接続が一時的に切断され、その後再接続された際のUUIDの動作を確認します。
node1とnode2の2台のサーバのディスクをDRBDで同期して、node1をPrimaryにします。

操作:
- node2で
drbdadm disconnect r0を実行して、ただちにdrbdadm connect r0を実行します。
結果:
node1がPrimary、node2がSecondaryの状態で接続が一時切断された後、両ノードでデータの更新がないまま再接続する。

ログの詳細:
node1の/var/log/messagesは次のようになりました。
Nov 12 11:04:29 node1 kernel: drbd r0 node2: Handshake to peer 0 successful: Agreed network protocol version 122
Nov 12 11:04:29 node1 kernel: drbd r0 node2: Feature flags enabled on protocol level: 0x7f TRIM THIN_RESYNC WRITE_SAME WRITE_ZEROES RESYNC_DAGTAG
Nov 12 11:04:29 node1 kernel: drbd r0: Preparing remote state change 2906424402: 0->1 role( Secondary ) conn( Connected )
Nov 12 11:04:29 node1 kernel: drbd r0/0 drbd0 node2: drbd_sync_handshake:
Nov 12 11:04:29 node1 kernel: drbd r0/0 drbd0 node2: self 7E42409FAE235AB0:0000000000000000:E210827503590C26:6A4DC2791796CB16 bits:0 flags:120
Nov 12 11:04:29 node1 kernel: drbd r0/0 drbd0 node2: peer 7E42409FAE235AB0:0000000000000000:6A4DC2791796CB16:2288D9C85D962AC2 bits:0 flags:1120
Nov 12 11:04:29 node1 kernel: drbd r0/0 drbd0 node2: uuid_compare()=no-sync by rule=reconnected
Nov 12 11:04:29 node1 kernel: drbd r0 node2: Committing remote state change 2906424402 (primary_nodes=2)
Nov 12 11:04:29 node1 kernel: drbd r0 node2: conn( Connecting -> Connected ) peer( Unknown -> Secondary ) [remote]
Nov 12 11:04:29 node1 kernel: drbd r0/0 drbd0 node2: repl( Off -> Established ) [remote]
Nov 12 11:04:29 node1 kernel: drbd r0/0 drbd0 node2: cleared bm UUID and bitmap 7E42409FAE235AB0:0000000000000000:E210827503590C26:6A4DC2791796CB16
Nov 12 11:04:29 node1 kernel: drbd r0/0 drbd0 node2: pdsk( Outdated -> UpToDate ) [peer-state]
Nov 12 11:04:29 node1 kernel: drbd r0 node2: helper command: /sbin/drbdadm unfence-peer
Nov 12 11:04:29 node1 kernel: drbd r0 node2: helper command: /sbin/drbdadm unfence-peer exit code 1 (0x100)UUIDの動作:
- 再接続時のハンドシェイクで、両ノードの Current UUID (第1要素) が一致していることを確認します。
- データが更新されていないため、DRBDはデータの一貫性が保たれていると判断し、リシンクは発生しません。
ログが示すこと:
drbd r0/0 drbd0 node2: uuid_compare()=no-sync by rule=reconnected- このメッセージは、「UUID比較の結果、再接続ルールにより同期は不要である」と判定されたことを示しており、UUIDに変更がない状態からの正常な復旧であることを裏付けます。
スプリットブレインの場合の例
スプリットブレイン(Split Brain)は、ノード間の通信が途絶した間に、両ノードが Primary に昇格し、互いに独立してデータが更新されてしまう、最も危険な状態です。
1.スプリットブレインの発生
node1がPrimaryのまま、node2もPrimaryにしてみます。node2で強制昇格(--force primary)後にデータ更新を行い、UUIDを意図的に乖離させてから再接続を実行します。
操作:
以下の操作を行って、スプリットブレインを発生させます。
- node2で
drbdadm disconnect r0を実行します。 - node2でdrbdam
--force primaryr0を実行します。 - node2でデバイスをマウントします。(mount /dev/drbd0 /mnt)
- マウントによりnode2のデータが更新されます。
- node2でマウントを解除します。(umount /dev/drbd0)
- node2で
drbdadm connect r0を実行します。
ログの詳細:
この時のnode1の/var/log/messagesは次のようになります。
Nov 12 11:05:55 node1 kernel: drbd r0: Preparing remote state change 3623628693: 0->1 conn( Disconnecting ) disk( Outdated )
Nov 12 11:05:55 node1 kernel: drbd r0 node2: Committing remote state change 3623628693 (primary_nodes=2)
Nov 12 11:05:55 node1 kernel: drbd r0 node2: conn( Connected -> TearDown ) peer( Secondary -> Unknown ) [remote]
Nov 12 11:05:55 node1 kernel: drbd r0/0 drbd0 node2: pdsk( UpToDate -> Outdated ) repl( Established -> Off ) [remote]
Nov 12 11:05:55 node1 kernel: drbd r0 node2: Terminating sender thread
Nov 12 11:05:55 node1 kernel: drbd r0 node2: Starting sender thread (peer-node-id 0)
Nov 12 11:05:55 node1 kernel: drbd r0 node2: Connection closed
Nov 12 11:05:55 node1 kernel: drbd r0 node2: helper command: /sbin/drbdadm disconnected
Nov 12 11:05:55 node1 kernel: drbd r0 node2: helper command: /sbin/drbdadm disconnected exit code 0
Nov 12 11:05:55 node1 kernel: drbd r0 node2: conn( TearDown -> Unconnected ) [disconnected]
Nov 12 11:05:55 node1 kernel: drbd r0 node2: Restarting receiver thread
Nov 12 11:05:55 node1 kernel: drbd r0 node2: conn( Unconnected -> Connecting ) [connecting]
Nov 12 11:06:58 node1 kernel: drbd r0 node2: Handshake to peer 0 successful: Agreed network protocol version 122
Nov 12 11:06:58 node1 kernel: drbd r0 node2: Feature flags enabled on protocol level: 0x7f TRIM THIN_RESYNC WRITE_SAME WRITE_ZEROES RESYNC_DAGTAG
Nov 12 11:06:58 node1 kernel: drbd r0: Preparing remote state change 1720572940: 0->1 role( Secondary ) conn( Connected )
Nov 12 11:06:58 node1 kernel: drbd r0/0 drbd0 node2: drbd_sync_handshake:
Nov 12 11:06:58 node1 kernel: drbd r0/0 drbd0 node2: self 7E42409FAE235AB0:0000000000000000:E210827503590C26:6A4DC2791796CB16 bits:0 flags:120
Nov 12 11:06:58 node1 kernel: drbd r0/0 drbd0 node2: peer 27E90B577DB7AA86:7E42409FAE235AB0:6A4DC2791796CB16:2288D9C85D962AC2 bits:514 flags:1120
Nov 12 11:06:58 node1 kernel: drbd r0/0 drbd0 node2: uuid_compare()=target-use-bitmap by rule=bitmap-peer
Nov 12 11:06:58 node1 kernel: drbd r0/0 drbd0 node2: I shall become SyncTarget, but I am primary!
Nov 12 11:06:58 node1 kernel: drbd r0 node2: Aborting remote state change 1720572940
Nov 12 11:06:58 node1 kernel: drbd r0 node2: conn( Connecting -> Disconnecting ) [receive-disconnect]
Nov 12 11:06:58 node1 kernel: drbd r0 node2: Terminating sender thread
Nov 12 11:06:58 node1 kernel: drbd r0 node2: Starting sender thread (peer-node-id 0)
Nov 12 11:06:58 node1 kernel: drbd r0 node2: Connection closed
Nov 12 11:06:58 node1 kernel: drbd r0 node2: helper command: /sbin/drbdadm disconnected
Nov 12 11:06:58 node1 kernel: drbd r0 node2: helper command: /sbin/drbdadm disconnected exit code 0
Nov 12 11:06:58 node1 kernel: drbd r0 node2: conn( Disconnecting -> StandAlone ) [disconnected]
Nov 12 11:06:58 node1 kernel: drbd r0 node2: Terminating receiver threadUUIDの動作:
強制昇格により、node2は自身の Current UUID (第1要素) を新しい値に更新しました。この状態で再接続すると、両ノードの Current UUID が異なってしまうため、DRBDはどちらのデータセットが正当か判断できません。
ログが示すこと:
drbd r0/0 drbd0 node2: self 7E42409FAE235AB0:...(node1のCurrent UUID)drbd r0/0 drbd0 node2: peer 27E90B577DB7AA86:...(node2の新しいCurrent UUID)drbd r0/0 drbd0 node2: I shall become SyncTarget, but I am primary!- このログは、「お互いのUUIDが食い違っており、どちらを同期元/同期先とするか判断できない」という矛盾(Primary/Primary 判定)が生じたため、接続を断ち切ったことを示しています。
2.スプリットブレインの解消とUUIDの同期
スプリットブレインを修復するために、node2のデータを破棄してnode1のデータで上書きします。
操作:
- node1のデータを正として、node2で
drbdadm connect --discard-my-data r0を実行。 - node1(Primary)からnode2(Secondary)へ強制的にリシンクが開始される。
ログの詳細:
この時のnode1の/var/log/messagesは次のようになります。
Nov 12 11:28:14 node1 kernel: drbd r0 node2: conn( StandAlone -> Unconnected ) [connect]
Nov 12 11:28:14 node1 kernel: drbd r0 node2: Starting receiver thread (peer-node-id 0)
Nov 12 11:28:14 node1 kernel: drbd r0 node2: conn( Unconnected -> Connecting ) [connecting]
Nov 12 11:28:15 node1 kernel: drbd r0 node2: Handshake to peer 0 successful: Agreed network protocol version 122
Nov 12 11:28:15 node1 kernel: drbd r0 node2: Feature flags enabled on protocol level: 0x7f TRIM THIN_RESYNC WRITE_SAME WRITE_ZEROES RESYNC_DAGTAG
Nov 12 11:28:15 node1 kernel: drbd r0: Preparing remote state change 213972305: 0->1 role( Secondary ) conn( Connected )
Nov 12 11:28:15 node1 kernel: drbd r0/0 drbd0 node2: drbd_sync_handshake:
Nov 12 11:28:15 node1 kernel: drbd r0/0 drbd0 node2: self 7E42409FAE235AB0:0000000000000000:E210827503590C26:6A4DC2791796CB16 bits:0 flags:120
Nov 12 11:28:15 node1 kernel: drbd r0/0 drbd0 node2: peer 27E90B577DB7AA86:7E42409FAE235AB0:6A4DC2791796CB16:2288D9C85D962AC2 bits:514 flags:1121
Nov 12 11:28:15 node1 kernel: drbd r0/0 drbd0 node2: uuid_compare()=target-use-bitmap by rule=bitmap-peer
Nov 12 11:28:15 node1 kernel: drbd r0/0 drbd0 node2: Resync direction reversed by --discard-my-data. Reverting to older data!
Nov 12 11:28:15 node1 kernel: drbd r0 node2: Committing remote state change 213972305 (primary_nodes=2)
Nov 12 11:28:15 node1 kernel: drbd r0 node2: conn( Connecting -> Connected ) peer( Unknown -> Secondary ) [remote]
Nov 12 11:28:15 node1 kernel: drbd r0/0 drbd0 node2: pdsk( Outdated -> Consistent ) repl( Off -> WFBitMapS ) [remote]
Nov 12 11:28:15 node1 kernel: drbd r0/0 drbd0 node2: send bitmap stats [Bytes(packets)]: plain 0(0), RLE 23(1), total 23; compression: 100.0%
Nov 12 11:28:15 node1 kernel: drbd r0/0 drbd0 node2: pdsk( Consistent -> Outdated ) [peer-state]
Nov 12 11:28:15 node1 kernel: drbd r0/0 drbd0 node2: receive bitmap stats [Bytes(packets)]: plain 0(0), RLE 28(1), total 28; compression: 100.0%
Nov 12 11:28:15 node1 kernel: drbd r0/0 drbd0 node2: helper command: /sbin/drbdadm before-resync-source
Nov 12 11:28:15 node1 kernel: drbd r0/0 drbd0 node2: helper command: /sbin/drbdadm before-resync-source exit code 0
Nov 12 11:28:15 node1 kernel: drbd r0/0 drbd0 node2: pdsk( Outdated -> Inconsistent ) repl( WFBitMapS -> SyncSource ) [receive-bitmap]
Nov 12 11:28:15 node1 kernel: drbd r0/0 drbd0 node2: Began resync as SyncSource (will sync 2056 KB [514 bits set]).
Nov 12 11:28:15 node1 kernel: drbd r0/0 drbd0 node2: Resync done (total 1 sec; paused 0 sec; 2056 K/sec)
Nov 12 11:28:15 node1 kernel: drbd r0/0 drbd0 node2: pdsk( Inconsistent -> UpToDate ) repl( SyncSource -> Established ) [resync-finished]
Nov 12 11:28:15 node1 kernel: drbd r0 node2: helper command: /sbin/drbdadm unfence-peer
Nov 12 11:28:15 node1 kernel: drbd r0 node2: helper command: /sbin/drbdadm unfence-peer exit code 1 (0x100)node2の方は次のようになります。
Nov 12 11:27:59 node2 kernel: drbd r0 node1: conn( StandAlone -> Unconnected ) [connect]
Nov 12 11:27:59 node2 kernel: drbd r0 node1: Starting receiver thread (peer-node-id 1)
Nov 12 11:27:59 node2 kernel: drbd r0 node1: conn( Unconnected -> Connecting ) [connecting]
Nov 12 11:28:15 node2 kernel: drbd r0 node1: Handshake to peer 1 successful: Agreed network protocol version 122
Nov 12 11:28:15 node2 kernel: drbd r0 node1: Feature flags enabled on protocol level: 0x7f TRIM THIN_RESYNC WRITE_SAME WRITE_ZEROES RESYNC_DAGTAG
Nov 12 11:28:15 node2 kernel: drbd r0: Preparing cluster-wide state change 213972305: 0->1 role( Secondary ) conn( Connected )
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: drbd_sync_handshake:
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: self 27E90B577DB7AA86:7E42409FAE235AB0:6A4DC2791796CB16:2288D9C85D962AC2 bits:514 flags:121
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: peer 7E42409FAE235AB0:0000000000000000:E210827503590C26:6A4DC2791796CB16 bits:0 flags:1120
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: uuid_compare()=source-use-bitmap by rule=bitmap-self
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: Resync direction reversed by --discard-my-data. Reverting to older data!
Nov 12 11:28:15 node2 kernel: drbd r0: State change 213972305: primary_nodes=2, weak_nodes=FFFFFFFFFFFFFFFC
Nov 12 11:28:15 node2 kernel: drbd r0: Committing cluster-wide state change 213972305 (21ms)
Nov 12 11:28:15 node2 kernel: drbd r0 node1: conn( Connecting -> Connected ) peer( Unknown -> Primary ) [connected]
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0: disk( UpToDate -> Outdated ) [connected]
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: pdsk( Outdated -> UpToDate ) repl( Off -> WFBitMapT ) [connected]
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0: Disabling local AL-updates (optimization)
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0: Setting exposed data uuid: 7E42409FAE235AB0
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: receive bitmap stats [Bytes(packets)]: plain 0(0), RLE 23(1), total 23; compression: 100.0%
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: send bitmap stats [Bytes(packets)]: plain 0(0), RLE 28(1), total 28; compression: 100.0%
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: helper command: /sbin/drbdadm before-resync-target
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: helper command: /sbin/drbdadm before-resync-target exit code 0
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0: disk( Outdated -> Inconsistent ) [receive-bitmap]
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: repl( WFBitMapT -> SyncTarget ) [receive-bitmap]
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: Began resync as SyncTarget (will sync 2056 KB [514 bits set]).
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: Resync done (total 1 sec; paused 0 sec; 2056 K/sec)
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: updated UUIDs 7E42409FAE235AB0:0000000000000000:7E42409FAE235AB0:E210827503590C26
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0: disk( Inconsistent -> UpToDate ) [resync-finished]
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: repl( SyncTarget -> Established ) [resync-finished]
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: helper command: /sbin/drbdadm after-resync-target
Nov 12 11:28:15 node2 kernel: drbd r0/0 drbd0 node1: helper command: /sbin/drbdadm after-resync-target exit code 0UUIDの動作:
--discard-my-data オプションは、ローカルノード(node2)の全てのデータとUUIDを破棄し、ピアノード(node1)のUUIDを強制的に受け入れることを指示します。これにより、DRBDは同期方向を決定し、リシンクが始まります。
ログが示すこと:
drbd r0/0 drbd0 node2: Resync direction reversed by --discard-my-data. Reverting to older data!drbd r0/0 drbd0: Setting exposed data uuid: 7E42409FAE235AB0(node1のUUIDに合わせる)drbd r0/0 drbd0 node1: updated UUIDs 7E42409FAE235AB0:0000000000000000:7E42409FAE235AB0:E210827503590C26- 同期完了後、node2のUUIDは完全にnode1のUUID値に上書きされ、両ノード間でUUIDの一貫性が回復しました。
まとめ
DRBDの運用において、データの信頼性はUUIDによって担保されています。
- 正常な運用: UUIDが一致していることを確認し、リシンクなしで接続を維持します。
- 障害・不整合時: UUIDの比較結果に基づいて、同期の必要性や方向を決定します。
- スプリットブレイン時: UUIDの乖離が検出された場合、手動で
--discard-my-dataコマンドを使用し、どちらのUUIDを「正」とするかを明示的に指定しなければ、システムは復旧できません。
このUUIDの動作原理を理解することで、HAクラスタ運用時のトラブルシューティングがより的確に行えるようになります。