Compare commits

...

4 Commits

Author SHA1 Message Date
Christian Schwarz 66946df756 docs: continous_server_backup: simplify by removing need for recv.placeholder 2022-01-09 12:51:00 +01:00
Andrew Gunnerson 556fac3002 docs: document fan-out replication & add quick-start guide
closes https://github.com/zrepl/zrepl/pull/552
fixes https://github.com/zrepl/zrepl/issues/551

Signed-off-by: Andrew Gunnerson <chillermillerlong@hotmail.com>
Co-authored-by: Christian Schwarz <me@cschwarz.com>
2022-01-09 12:45:09 +01:00
Christian Schwarz 1ad7df2df3 docs: badges & links to Matrix chat room
fixes https://github.com/zrepl/zrepl/issues/488
2022-01-09 12:05:19 +01:00
Christian Schwarz a3d010c5f0 util/optionaldeadline: disable scheduler latency-sensitive tests in CircleCI 2021-12-30 14:41:06 +01:00
12 changed files with 240 additions and 19 deletions
+3 -2
View File
@@ -1,11 +1,12 @@
[![GitHub license](https://img.shields.io/github/license/zrepl/zrepl.svg)](https://github.com/zrepl/zrepl/blob/master/LICENSE)
[![Language: Go](https://img.shields.io/badge/language-Go-6ad7e5.svg)](https://golang.org/)
[![Language: Go](https://img.shields.io/badge/lang-Go-6ad7e5.svg)](https://golang.org/)
[![User Docs](https://img.shields.io/badge/docs-web-blue.svg)](https://zrepl.github.io)
[![Support me on Patreon](https://img.shields.io/badge/dynamic/json?color=yellow&label=Patreon&query=data.attributes.patron_count&suffix=%20patrons&url=https%3A%2F%2Fwww.patreon.com%2Fapi%2Fcampaigns%2F3095079)](https://patreon.com/zrepl)
[![Support me on Patreon](https://img.shields.io/badge/dynamic/json?color=yellow&label=Patreon&query=data.attributes.patron_count&url=https%3A%2F%2Fwww.patreon.com%2Fapi%2Fcampaigns%2F3095079)](https://patreon.com/zrepl)
[![Donate via GitHub Sponsors](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&style=flat&color=yellow)](https://github.com/sponsors/problame)
[![Donate via Liberapay](https://img.shields.io/liberapay/patrons/zrepl.svg?logo=liberapay)](https://liberapay.com/zrepl/donate)
[![Donate via PayPal](https://img.shields.io/badge/donate-paypal-yellow.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=R5QSXJVYHGX96)
[![Twitter](https://img.shields.io/twitter/url/https/github.com/zrepl/zrepl.svg?style=social)](https://twitter.com/intent/tweet?text=Wow:&url=https%3A%2F%2Fgithub.com%2Fzrepl%2Fzrepl)
[![Chat](https://img.shields.io/badge/chat-matrix-blue.svg)](https://matrix.to/#/#zrepl:matrix.org)
# zrepl
zrepl is a one-stop ZFS backup & replication solution.
@@ -9,7 +9,4 @@ jobs:
key: "/etc/zrepl/backups.key"
client_cns:
- "prod"
recv:
placeholder:
encryption: inherit # use 'off' if sender uses send.encrypted
root_fs: "storage/zrepl/sink"
@@ -9,8 +9,8 @@ jobs:
key: /etc/zrepl/prod.key
server_cn: "backups"
filesystems: {
"zroot/var/db": true,
"zroot/usr/home<": true,
"zroot<": true,
"zroot/var/tmp<": false,
"zroot/usr/home/paranoid": false
}
snapshotting:
@@ -0,0 +1,59 @@
jobs:
# Separate job for snapshots and pruning
- name: snapshots
type: snap
filesystems:
'tank<': true # all filesystems
snapshotting:
type: periodic
prefix: zrepl_
interval: 10m
pruning:
keep:
# Keep non-zrepl snapshots
- type: regex
negate: true
regex: '^zrepl_'
# Time-based snapshot retention
- type: grid
grid: 1x1h(keep=all) | 24x1h | 30x1d | 12x30d
regex: '^zrepl_'
# Source job for target B
- name: target_b
type: source
serve:
type: tls
listen: :8888
ca: /etc/zrepl/b.example.com.crt
cert: /etc/zrepl/a.example.com.crt
key: /etc/zrepl/a.example.com.key
client_cns:
- b.example.com
filesystems:
'tank<': true # all filesystems
# Snapshots are handled by the separate snap job
snapshotting:
type: manual
# Source job for target C
- name: target_c
type: source
serve:
type: tls
listen: :8889
ca: /etc/zrepl/c.example.com.crt
cert: /etc/zrepl/a.example.com.crt
key: /etc/zrepl/a.example.com.key
client_cns:
- c.example.com
filesystems:
'tank<': true # all filesystems
# Snapshots are handled by the separate snap job
snapshotting:
type: manual
# Source jobs for remaining targets. Each one should listen on a different port
# and reference the correct certificate and client CN.
# - name: target_c
# ...
@@ -0,0 +1,30 @@
jobs:
# Pull from source server A
- name: source_a
type: pull
connect:
type: tls
# Use the correct port for this specific client (eg. B is 8888, C is 8889, etc.)
address: a.example.com:8888
ca: /etc/zrepl/a.example.com.crt
# Use the correct key pair for this specific client
cert: /etc/zrepl/b.example.com.crt
key: /etc/zrepl/b.example.com.key
server_cn: a.example.com
root_fs: pool0/backup
interval: 10m
pruning:
keep_sender:
# Source does the pruning in its snap job
- type: regex
regex: '.*'
# Receiver-side pruning can be configured as desired on each target server
keep_receiver:
# Keep non-zrepl snapshots
- type: regex
negate: true
regex: '^zrepl_'
# Time-based snapshot retention
- type: grid
grid: 1x1h(keep=all) | 24x1h | 30x1d | 12x30d
regex: '^zrepl_'
+38 -3
View File
@@ -248,7 +248,7 @@ Limitations
Multiple Jobs & More than 2 Machines
------------------------------------
The quick-start guides focus on simple setups with a single sender and a single receiver.
Most users are served well with a single sender and a single receiver job.
This section documents considerations for more complex setups.
.. ATTENTION::
@@ -288,11 +288,46 @@ This section might be relevant to users who wish to *fan-in* (N machines replica
**Working setups**:
* N ``push`` identities, 1 ``sink`` (as long as the different push jobs have a different :ref:`client identity <overview-passive-side--client-identity>`)
* **Fan-in: N servers replicated to one receiver, disjoint dataset trees.**
* ``sink`` constrains each client to a disjoint sub-tree of the sink-side dataset hierarchy ``${root_fs}/${client_identity}``.
* This is the common use case of a centralized backup server.
* Implementation:
* N ``push`` jobs (one per sender server), 1 ``sink`` (as long as the different push jobs have a different :ref:`client identity <overview-passive-side--client-identity>`)
* N ``source`` jobs (one per sender server), N ``pull`` on the receiver server (unique names, disjoing ``root_fs``)
* The ``sink`` job automatically constrains each client to a disjoint sub-tree of the sink-side dataset hierarchy ``${root_fs}/${client_identity}``.
Therefore, the different clients cannot interfere.
* The ``pull`` job only pulls from one host, so it's up to the zrepl user to ensure that the different ``pull`` jobs don't interfere.
.. _fan-out-replication:
* **Fan-out: 1 server replicated to N receivers**
* Can be implemented either in a pull or push fashion.
* **pull setup**: 1 ``pull`` job on each receiver server, each with a corresponding **unique** ``source`` job on the sender server.
* **push setup**: 1 ``sink`` job on each receiver server, each with a corresponding **unique** ``push`` job on the sender server.
* It is critical that we have one sending-side job (``source``, ``push``) per receiver.
The reason is that :ref:`zrepl's ZFS abstractions <zrepl-zfs-abstractions>` (``zrepl zfs-abstraction list``) include the name of the ``source``/``push`` job, but not the receive-side job name or client identity (see :issue:`380`).
As a counter-example, suppose we used multiple ``pull`` jobs with only one ``source`` job.
All ``pull`` jobs would share the same :ref:`replication cursor bookmark <replication-cursor-and-last-received-hold>` and trip over each other, breaking incremental replication guarantees quickly.
The anlogous problem exists for 1 ``push`` to N ``sink`` jobs.
* The ``filesystems`` matched by the sending side jobs (``source``, ``push``) need not necessarily be disjoint.
For this to work, we need to avoid interference between snapshotting and pruning of the different sending jobs.
The solution is to centralize sender-side snapshot management in a separate ``snap`` job.
Snapshotting in the ``source``/``push`` job should then be disabled (``type: manual``).
And sender-side pruning (``keep_sender``) needs to be disabled in the active side (``pull`` / ``push``), since that'll be done by the ``snap job``.
* **Restore limitations**: when restoring from one of the ``pull`` targets (e.g., using ``zfs send -R``), the replication cursor bookmarks don't exist on the restored system.
This can break incremental replication to all other receive-sides after restore.
* See :ref:`the fan-out replication quick-start guide <quickstart-fan-out-replication>` for an example of this setup.
**Setups that do not work**:
+4 -3
View File
@@ -5,7 +5,7 @@
.. |GitHub license| image:: https://img.shields.io/github/license/zrepl/zrepl.svg
:target: https://github.com/zrepl/zrepl/blob/master/LICENSE
.. |Language: Go| image:: https://img.shields.io/badge/language-Go-6ad7e5.svg
.. |Language: Go| image:: https://img.shields.io/badge/lang-Go-6ad7e5.svg
:target: https://golang.org/
.. |User Docs| image:: https://img.shields.io/badge/docs-web-blue.svg
:target: https://zrepl.github.io
@@ -13,13 +13,14 @@
:target: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=R5QSXJVYHGX96
.. |Donate via Liberapay| image:: https://img.shields.io/liberapay/patrons/zrepl.svg?logo=liberapay
:target: https://liberapay.com/zrepl/donate
.. |Donate via Patreon| image:: https://img.shields.io/badge/dynamic/json?color=yellow&label=Patreon&query=data.attributes.patron_count&suffix=%20patrons&url=https%3A%2F%2Fwww.patreon.com%2Fapi%2Fcampaigns%2F3095079
.. |Donate via Patreon| image:: https://img.shields.io/badge/dynamic/json?color=yellow&label=Patreon&query=data.attributes.patron_count&url=https%3A%2F%2Fwww.patreon.com%2Fapi%2Fcampaigns%2F3095079
:target: https://www.patreon.com/zrepl
.. |Donate via GitHub Sponsors| image:: https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&style=flat&color=yellow
:target: https://github.com/sponsors/problame
.. |Twitter| image:: https://img.shields.io/twitter/url/https/github.com/zrepl/zrepl.svg?style=social
:target: https://twitter.com/intent/tweet?text=Wow:&url=https%3A%2F%2Fgithub.com%2Fzrepl%2Fzrepl
.. |Matrix| image:: https://img.shields.io/badge/chat-matrix-blue.svg
:target: https://matrix.to/#/#zrepl:matrix.org
.. |serve-transport| replace:: :ref:`serve specification<transport>`
.. |connect-transport| replace:: :ref:`connect specification<transport>`
+2 -1
View File
@@ -5,7 +5,7 @@
.. include:: global.rst.inc
|GitHub license| |Language: Go| |Twitter| |Donate via Patreon| |Donate via GitHub Sponsors| |Donate via Liberapay| |Donate via PayPal|
|GitHub license| |Language: Go| |Twitter| |Donate via Patreon| |Donate via GitHub Sponsors| |Donate via Liberapay| |Donate via PayPal| |Matrix|
zrepl - ZFS replication
@@ -137,5 +137,6 @@ Table of Contents
pr
changelog
GitHub Repository & Issue Tracker <https://github.com/zrepl/zrepl>
Chat: Matrix <https://matrix.to/#/#zrepl:matrix.org>
supporters
+1
View File
@@ -33,6 +33,7 @@ Keep the :ref:`full config documentation <configuration_toc>` handy if a config
quickstart/continuous_server_backup
quickstart/backup_to_external_disk
quickstart/fan_out_replication
Use ``zrepl configcheck`` to validate your configuration.
No output indicates that everything is fine.
+5 -5
View File
@@ -9,13 +9,13 @@ This config example shows how we can backup our ZFS-based server to another mach
* Production server ``prod`` with filesystems to back up:
* ``zroot/var/db``
* ``zroot/usr/home`` and all its child filesystems
* **except** ``zroot/usr/home/paranoid`` belonging to a user doing backups themselves
* The entire pool ``zroot``
* except ``zroot/var/tmp`` and all child datasets of it
* and except ``zroot/usr/home/paranoid`` which belongs to a user doing backups themselves.
* Backup server ``backups`` with
* Backup server ``backups`` with a dataset sub-tree for use by zrepl:
* Filesystem ``storage/zrepl/sink/prod`` + children dedicated to backups of ``prod``
* In our example, that will be ``storage/zrepl/sink/prod``.
Our backup solution should fulfill the following requirements:
+93
View File
@@ -0,0 +1,93 @@
.. include:: ../global.rst.inc
.. _quickstart-fan-out-replication:
Fan-out replication
===================
This quick-start example demonstrates how to implement a fan-out replication setup where datasets on a server (A) are replicated to multiple targets (B, C, etc.).
This example uses multiple ``source`` jobs on server A and ``pull`` jobs on the target servers.
.. WARNING::
Before implementing this setup, please see the caveats listed in the :ref:`fan-out replication configuration overview <fan-out-replication>`.
Overview
--------
On the source server (A), there should be:
* A ``snap`` job
* Creates the snapshots
* Handles the pruning of snapshots
* A ``source`` job for target B
* Accepts connections from server B and B only
* Further ``source`` jobs for each additional target (C, D, etc.)
* Listens on a unique port
* Only accepts connections from the specific target
On each target server, there should be:
* A ``pull`` job that connects to the corresponding ``source`` job on A
* ``prune_sender`` should keep all snapshots since A's ``snap`` job handles the pruning
* ``prune_receiver`` can be configured as appropriate on each target server
Generate TLS Certificates
-------------------------
Mutual TLS via the :ref:`TLS client authentication transport <transport-tcp+tlsclientauth>` can be used to secure the connections between the servers. In this example, a self-signed certificate is created for each server without setting up a CA.
.. code-block:: bash
source=a.example.com
targets=(
b.example.com
c.example.com
# ...
)
for server in "${source}" "${targets[@]}"; do
openssl req -x509 -sha256 -nodes \
-newkey rsa:4096 \
-days 365 \
-keyout "${server}.key" \
-out "${server}.crt" \
-addext "subjectAltName = DNS:${server}" \
-subj "/CN=${server}"
done
# Distribute each host's keypair
for server in "${source}" "${targets[@]}"; do
ssh root@"${server}" mkdir /etc/zrepl
scp "${server}".{crt,key} root@"${server}":/etc/zrepl/
done
# Distribute target certificates to the source
scp "${targets[@]/%/.crt}" root@"${source}":/etc/zrepl/
# Distribute source certificate to the targets
for server in "${targets[@]}"; do
scp "${source}.crt" root@"${server}":/etc/zrepl/
done
Configure source server A
-------------------------
.. literalinclude:: ../../config/samples/quickstart_fan_out_replication_source.yml
Configure each target server
----------------------------
.. literalinclude:: ../../config/samples/quickstart_fan_out_replication_target.yml
Go Back To Quickstart Guide
---------------------------
:ref:`Click here <quickstart-apply-config>` to go back to the quickstart guide.
@@ -9,9 +9,11 @@ import (
"github.com/stretchr/testify/require"
"github.com/zrepl/zrepl/util/chainlock"
"github.com/zrepl/zrepl/util/zreplcircleci"
)
func TestContextWithOptionalDeadline(t *testing.T) {
zreplcircleci.SkipOnCircleCI(t, "test relies on predictably low scheduler latency")
ctx := context.Background()
cctx, enforceDeadline := ContextWithOptionalDeadline(ctx)
@@ -72,6 +74,7 @@ func TestContextWithOptionalDeadlineNegativeDeadline(t *testing.T) {
}
func TestContextWithOptionalDeadlineParentCancellation(t *testing.T) {
zreplcircleci.SkipOnCircleCI(t, "test relies on predictably low scheduler latency")
pctx, cancel := context.WithCancel(context.Background())
cctx, enforceDeadline := ContextWithOptionalDeadline(pctx)