Skip to content

miroir

Replicated block storage for small Kubernetes clusters. CSI driver on top of LVM thin, ZFS, or loopfile backends, with optional synchronous replication (2-3 replicas) via DRBD9.

In practice, miroir turns disks already in your nodes into PersistentVolumes. Each volume is a real block device on the node (an LVM thin volume, a ZFS zvol, or a sparse file behind a loop device), and the CSI driver hands it to pods. When a StorageClass asks for 2 replicas, DRBD (a replication layer built into the Linux kernel) keeps a byte-identical copy on a second node by completing every write on both. If a node dies, pods restart on the surviving node with current data.

A 2-replica volume on a 3-node cluster looks like this (the terminology below defines the words):

flowchart LR
    subgraph node-a
        POD[pod] --> A[("leg A (Primary)")]
    end
    subgraph node-b
        B[("leg B (Secondary)")]
    end
    subgraph node-c
        T["tie-breaker (diskless)"]
    end
    A <==>|synchronous replication| B
    A -. quorum vote .- T
    B -. quorum vote .- T

When to use it

  • You want replicated block storage without running Ceph.
  • You're on 2-3 nodes and either have a spare disk per node (LVM), a ZFS pool (ZFS), or a few GB on the root filesystem (loopfile).
  • You want snapshots that actually work for replicated volumes (both legs cut in lockstep, not whichever finishes first), plus restores, PVC clones, and crash-consistent group snapshots built on them.

When not to use it

  • You need >3 replicas. DRBD9 itself allows up to 32 nodes on a single resource, so this is a scope decision, not a DRBD limit: the controller validates 1..3, metadata reserves --max-peers 7 slots per leg (enough for 2 peer replicas, the tie-breaker, 2 remote clients, and rebuild headroom), and the quorum policies assume 2 data replicas plus a tie-breaker. More than that means redesigning the vote math and recreating on-disk metadata: LINSTOR territory.
  • You need iSCSI targets or a standalone NFS/file server. miroir serves block devices, plus a per-volume NFS export for ReadWriteMany (see ReadWriteMany (RWX)); it is not a general-purpose exporter.
  • You're at fleet scale. Resource groups, automatic eviction and rebalancing, and multi-site replication are LINSTOR's territory; miroir runs the same DRBD9 data plane but deliberately stops at what 2-3 nodes need, with the Kubernetes API as its only control plane.

Terminology

A handful of words recur in these docs. Most come from DRBD; none require DRBD experience:

  • Leg (or replica): one copy of a volume on one node. A 2-replica volume has two legs, each a local block device kept identical by DRBD.
  • Diskful / diskless: whether a leg has a backing device on its node. A diskless leg participates in the volume's replication network without storing any data.
  • Quorum: majority voting among a volume's legs about which side may keep writing when they lose sight of each other. The point is to make it impossible for two disconnected sides to both accept writes.
  • Tie-breaker: a diskless leg added as a third vote so that a 2-replica volume can survive one node loss without risking the two-writers case. It stores nothing and uses no capacity.
  • Client leg: a temporary diskless leg through which a pod on a node without a replica reads and writes the volume over the network.
  • Primary / Secondary: DRBD's roles. The Primary leg is the one serving I/O to a consumer (at most one per volume in miroir); every other leg is Secondary. "Promotion" means becoming Primary.
  • Split-brain: what quorum exists to prevent. Two legs both accepted writes while disconnected and now hold different data. DRBD detects it on reconnect and refuses to merge; an operator picks which side's writes to keep.
  • Resync: DRBD copying blocks from a current leg to a stale one (after a reboot, a replaced disk, a rejoined node) until they are identical again.
  • UpToDate / Degraded: a leg is UpToDate when it holds current data; a volume reads Degraded while any of its legs doesn't (typically: a resync is running).

Where to next