From 6d02ed0e0e35b6778b246eaa1755fa2643c13886 Mon Sep 17 00:00:00 2001 From: Matt Layher Date: Mon, 14 Feb 2022 16:58:00 -0500 Subject: [PATCH] nixos/servnerr-3: zrepl snapshot/replication from primary to secondary only for now Signed-off-by: Matt Layher --- nixos/servnerr-3/storage.nix | 137 ++++++++++++++++++----------------- 1 file changed, 71 insertions(+), 66 deletions(-) diff --git a/nixos/servnerr-3/storage.nix b/nixos/servnerr-3/storage.nix index 14f0263..fb7d930 100644 --- a/nixos/servnerr-3/storage.nix +++ b/nixos/servnerr-3/storage.nix @@ -3,87 +3,91 @@ let secrets = import ./lib/secrets.nix; - # Make a local zrepl push job from primary to the target zpool. - pushLocal = (zpool: { - name = pushName zpool; - type = "push"; + # Create a local zrepl push job from source to the target zpool. + pushLocal = (source: + (target: { + name = pushName source target; + type = "push"; - # Replicate all of primary locally. - filesystems."primary<" = true; - connect = { - type = "local"; - listener_name = sinkName zpool; - client_identity = "local"; - }; + # Replicate all of the source zpool locally. + filesystems."${source}<" = true; + connect = { + type = "local"; + listener_name = sinkName target; + # Assumes only a single client will ever push locally to sink. + client_identity = "local"; + }; - # Snapshot every 15 minutes. - snapshotting = { - type = "periodic"; - prefix = "zrepl_"; - interval = "15m"; - }; + # Snapshot every 15 minutes. + snapshotting = { + type = "periodic"; + prefix = "zrepl_"; + interval = "15m"; + }; - pruning = { - keep_sender = [ - # Keep snapshots that are not already replicated. - { - type = "not_replicated"; - } - # Keep manual snapshots. - { - type = "regex"; - regex = "^manual_.*"; - } - # Keep time-based bucketed snapshots. - keepGrid - ]; - # Keep the same automatic snapshots as source. - keep_receiver = [ keepGrid ]; - }; - }); + pruning = { + keep_sender = [ + # Keep snapshots that are not already replicated. + { + type = "not_replicated"; + } + # Keep manual snapshots. + { + type = "regex"; + regex = "^manual_.*"; + } + # Keep time-based bucketed snapshots. + keepGrid + ]; + # Keep the same automatic snapshots as source. + keep_receiver = [ keepGrid ]; + }; + })); # Make a local zrepl sink job to the target zpool. sinkLocal = (zpool: { name = sinkName zpool; type = "sink"; root_fs = "${zpool}"; - recv.properties = { - # Inherit any encryption properties. - "inherit" = [ "encryption" "keyformat" "keylocation" ]; - override = { - # Always enable compression. - compression = "on"; + recv = { + # Necessary for encrypted destination with unencrypted source. + placeholder.encryption = "inherit"; - # Do not mount sink pools. - mountpoint = "none"; + properties = { + # Inherit any encryption properties. + "inherit" = [ "encryption" "keyformat" "keylocation" ]; - # Do not auto-snapshot sink pools. - "com.sun:auto-snapshot" = false; - "com.sun:auto-snapshot:frequent" = false; - "com.sun:auto-snapshot:hourly" = false; - "com.sun:auto-snapshot:daily" = false; - "com.sun:auto-snapshot:weekly" = false; - "com.sun:auto-snapshot:monthly" = false; + override = { + # Always enable compression. + compression = "on"; + + # Do not mount sink pools. + mountpoint = "none"; + + # Do not auto-snapshot sink pools. + "com.sun:auto-snapshot" = false; + "com.sun:auto-snapshot:frequent" = false; + "com.sun:auto-snapshot:hourly" = false; + "com.sun:auto-snapshot:daily" = false; + "com.sun:auto-snapshot:weekly" = false; + "com.sun:auto-snapshot:monthly" = false; + }; }; }; + serve = { type = "local"; listener_name = "sink_${zpool}"; }; }); - # Make a local zrepl encrypted sink job to the target zpool. + # Generate the zrepl push job name for a source and target zpool. # - # TODO(mdlayher): unconditionally set this in sinkLocal anyway? - sinkLocalEncrypted = (zpool: - lib.mkMerge [ - (sinkLocal zpool) - { recv.placeholder.encryption = "inherit"; } - ]); - - # Generate the zrepl push job name for a target zpool. - pushName = (zpool: "primary_to_${zpool}"); + # TODO(mdlayher): it would be nice to prefix this with push_ but job renames + # are not possible without major upheaval. See: + # https://github.com/zrepl/zrepl/issues/327. + pushName = (source: (target: "${source}_to_${target}")); # Generate the zrepl sink job name for a target zpool. sinkName = (zpool: "sink_${zpool}"); @@ -207,15 +211,16 @@ in { listen = ":9811"; }]; jobs = [ - # Replicate from primary pool to sinks. - (pushLocal "secondary") - (pushLocal "backup0") - (pushLocal "backup1") + # Replicate from primary to secondary. + # + # TODO(mdlayher): fan-out replication from secondary to backup{0,1}, + # and make smart logic like a udev listener to signal replication when + # the drives are plugged in and spun up. + # https://zrepl.github.io/quickstart/fan_out_replication.html + (pushLocal "primary" "secondary") # Local sink jobs for backups. (sinkLocal "secondary") - (sinkLocalEncrypted "backup0") - (sinkLocalEncrypted "backup1") ]; }; };