mirror of
https://github.com/zrepl/zrepl.git
synced 2025-01-22 06:09:45 +01:00
docs/tutorial: switch to push setup & use mutual TLS (2 machines)
This commit is contained in:
parent
a62b475f46
commit
0b8c19c620
@ -6,7 +6,7 @@ Tutorial
|
||||
========
|
||||
|
||||
|
||||
This tutorial shows how zrepl can be used to implement a ZFS-based pull backup.
|
||||
This tutorial shows how zrepl can be used to implement a ZFS-based push backup.
|
||||
We assume the following scenario:
|
||||
|
||||
* Production server ``prod`` with filesystems to back up:
|
||||
@ -17,12 +17,12 @@ We assume the following scenario:
|
||||
|
||||
* Backup server ``backups`` with
|
||||
|
||||
* Filesystem ``storage/zrepl/pull/prod`` + children dedicated to backups of ``prod``
|
||||
* Filesystem ``storage/zrepl/sink/prod`` + children dedicated to backups of ``prod``
|
||||
|
||||
Our backup solution should fulfill the following requirements:
|
||||
|
||||
* Periodically snapshot the filesystems on ``prod`` *every 10 minutes*
|
||||
* Incrementally replicate these snapshots to ``storage/zrepl/pull/prod/*`` on ``backups``
|
||||
* Incrementally replicate these snapshots to ``storage/zrepl/sink/prod/*`` on ``backups``
|
||||
* Keep only very few snapshots on ``prod`` to save disk space
|
||||
* Keep a fading history (24 hourly, 30 daily, 6 monthly) of snapshots on ``backups``
|
||||
|
||||
@ -31,74 +31,70 @@ Analysis
|
||||
|
||||
We can model this situation as two jobs:
|
||||
|
||||
* A **source job** on ``prod``
|
||||
* A **push job** on ``prod``
|
||||
|
||||
* Creates the snapshots
|
||||
* Keeps a short history of snapshots to enable incremental replication to ``backups``
|
||||
* Accepts connections from ``backups``
|
||||
* Keeps a short history of local snapshots to enable incremental replication to ``backups``
|
||||
* Connects to the ``zrepl daemon`` process on ``backups``
|
||||
* Pushes snapshots ``backups``
|
||||
* Prunes snapshots on ``backups`` after replication is complete
|
||||
|
||||
* A **pull job** on ``backups``
|
||||
* A **sink job** on ``backups``
|
||||
|
||||
* Connects to the ``zrepl daemon`` process on ``prod``
|
||||
* Pulls the snapshots to ``storage/zrepl/pull/prod/*``
|
||||
* Fades out snapshots in ``storage/zrepl/pull/prod/*`` as they age
|
||||
|
||||
|
||||
Why doesn't the **pull job** create the snapshots before pulling?
|
||||
|
||||
As is the case with all distributed systems, the link between ``prod`` and ``backups`` might be down for an hour or two.
|
||||
We do not want to sacrifice our required backup resolution of 10 minute intervals for a temporary connection outage.
|
||||
|
||||
When the link comes up again, ``backups`` will catch up with the snapshots taken by ``prod`` in the meantime, without a gap in our backup history.
|
||||
* Accepts connections & responds to requests from ``prod``
|
||||
* Limits client ``prod`` access to filesystem sub-tree ``storage/zrepl/sink/prod``
|
||||
|
||||
Install zrepl
|
||||
-------------
|
||||
|
||||
Follow the :ref:`OS-specific installation instructions <installation>` and come back here.
|
||||
|
||||
Configure server ``backups``
|
||||
----------------------------
|
||||
|
||||
We define a **pull job** named ``pull_prod`` in ``/etc/zrepl/zrepl.yml`` or ``/usr/local/etc/zrepl/zrepl.yml`` on host ``backups`` : ::
|
||||
|
||||
jobs:
|
||||
- name: pull_prod
|
||||
type: pull
|
||||
connect:
|
||||
type: tcp
|
||||
address: "192.168.2.20:2342"
|
||||
root_fs: "storage/zrepl/pull/prod"
|
||||
interval: 10m
|
||||
pruning:
|
||||
keep_sender:
|
||||
- type: not_replicated
|
||||
- type: last_n
|
||||
count: 10
|
||||
keep_receiver:
|
||||
- type: grid
|
||||
grid: 1x1h(keep=all) | 24x1h | 30x1d | 6x30d
|
||||
regex: "^zrepl_"
|
||||
interval: 10m
|
||||
|
||||
The ``connect`` section instructs the zrepl daemon to use plain TCP transport.
|
||||
Check out the :ref:`transports <transport>` section for alternatives that support encryption.
|
||||
|
||||
.. _tutorial-configure-prod:
|
||||
|
||||
Configure server ``prod``
|
||||
Generate TLS Certificates
|
||||
-------------------------
|
||||
|
||||
We define a corresponding **source job** named ``source_backups`` in ``/etc/zrepl/zrepl.yml`` or ``/usr/local/etc/zrepl/zrepl.yml`` on host ``prod`` : ::
|
||||
We use the `TLS client authentication transport <transport-tcp+tlsclientauth>` to protect our data on the wire.
|
||||
To get things going quickly, we skip setting up a CA and generate two self-signed certificates as described :ref:`here <transport-tcp+tlsclientauth-2machineopenssl>`.
|
||||
Again, for convenience, We generate the key pairs on our local machine and distribute them using ssh:
|
||||
|
||||
.. code-block:: bash
|
||||
:emphasize-lines: 6,13
|
||||
|
||||
openssl req -x509 -sha256 -nodes \
|
||||
-newkey rsa:4096 \
|
||||
-days 365 \
|
||||
-keyout backups.key \
|
||||
-out backups.crt
|
||||
# ... and use "backups" as Common Name (CN)
|
||||
|
||||
openssl req -x509 -sha256 -nodes \
|
||||
-newkey rsa:4096 \
|
||||
-days 365 \
|
||||
-keyout prod.key \
|
||||
-out prod.crt
|
||||
# ... and use "prod" as Common Name (CN)
|
||||
|
||||
ssh root@backups "mkdir /etc/zrepl"
|
||||
scp backups.key backups.crt prod.crt root@backups:/etc/zrepl
|
||||
|
||||
ssh root@prod "mkdir /etc/zrepl"
|
||||
scp prod.key prod.crt backups.crt root@prod:/etc/zrepl
|
||||
|
||||
|
||||
Configure server ``prod``
|
||||
----------------------------
|
||||
|
||||
We define a **push job** named ``prod_to_backups`` in ``/etc/zrepl/zrepl.yml`` on host ``prod`` : ::
|
||||
|
||||
jobs:
|
||||
- name: source_backups
|
||||
type: source
|
||||
serve:
|
||||
type: tcp
|
||||
listen: ":2342"
|
||||
clients: {
|
||||
"192.168.2.10" : "backups"
|
||||
}
|
||||
- name: prod_to_backups
|
||||
type: push
|
||||
connect:
|
||||
type: tls
|
||||
address: "backups.example.com:8888"
|
||||
ca: /etc/zrepl/backups.crt
|
||||
cert: /etc/zrepl/prod.crt
|
||||
key: /etc/zrepl/prod.key
|
||||
server_cn: "backups"
|
||||
filesystems: {
|
||||
"zroot/var/db:": true,
|
||||
"zroot/usr/home<": true,
|
||||
@ -108,39 +104,69 @@ We define a corresponding **source job** named ``source_backups`` in ``/etc/zrep
|
||||
type: periodic
|
||||
prefix: zrepl_
|
||||
interval: 10m
|
||||
pruning:
|
||||
keep_sender:
|
||||
- type: not_replicated
|
||||
- type: last_n
|
||||
count: 10
|
||||
keep_receiver:
|
||||
- type: grid
|
||||
grid: 1x1h(keep=all) | 24x1h | 30x1d | 6x30d
|
||||
regex: "^zrepl_"
|
||||
|
||||
.. _tutorial-configure-prod:
|
||||
|
||||
Configure server ``prod``
|
||||
-------------------------
|
||||
|
||||
We define a corresponding **sink job** named ``sink`` in ``/etc/zrepl/zrepl.yml`` on host ``prod`` : ::
|
||||
|
||||
jobs:
|
||||
- name: sink
|
||||
type: sink
|
||||
serve:
|
||||
type: tls
|
||||
listen: ":8888"
|
||||
ca: "/etc/zrepl/prod.crt"
|
||||
cert: "/etc/zrepl/backups.crt"
|
||||
key: "/etc/zrepl/backups.key"
|
||||
client_cns:
|
||||
- "prod"
|
||||
root_fs: "storage/zrepl/sink"
|
||||
|
||||
The ``serve`` section whitelists ``backups``'s IP address ``192.168.2.10`` and assigns it the client identity ``backups`` which will show up in the logs.
|
||||
Again, check the :ref:`docs for encrypted transports <transport>`.
|
||||
|
||||
Apply Configuration Changes
|
||||
---------------------------
|
||||
|
||||
We need to restart the zrepl daemon on **both** ``prod`` and ``backups``.
|
||||
This is :ref:`OS-specific <usage-zrepl-daemon-restarting>`.
|
||||
We use ``zrepl configcheck`` before to catch any configuration errors: no output indicates that everything is fine.
|
||||
If that is the case, restart the zrepl daemon on **both** ``prod`` and ``backups`` using ``service zrepl restart`` or ``systemctl restart zrepl``.
|
||||
|
||||
|
||||
Watch it Work
|
||||
-------------
|
||||
|
||||
Run ``zrepl status`` on ``prod`` to monitor the replication and pruning activity.
|
||||
|
||||
Additionally, you can check the detailed structured logs of the `zrepl daemon` process and use GNU *watch* to view the snapshots present on both machines.
|
||||
To re-trigger replication (snapshots are separate!), use ``zrepl signal wakeup prod_to_backups`` on ``prod``.
|
||||
|
||||
If you like tmux, here is a handy script that works on FreeBSD: ::
|
||||
|
||||
pkg install gnu-watch tmux
|
||||
tmux new-window
|
||||
tmux split-window "tail -f /var/log/zrepl.log"
|
||||
tmux split-window "gnu-watch 'zfs list -t snapshot -o name,creation -s creation | grep zrepl_'"
|
||||
tmux select-layout tiled
|
||||
tmux new -s zrepl -d
|
||||
tmux split-window -t zrepl "tail -f /var/log/messages"
|
||||
tmux split-window -t zrepl "gnu-watch 'zfs list -t snapshot -o name,creation -s creation | grep zrepl_'"
|
||||
tmux split-window -t zrepl "zrepl status"
|
||||
tmux select-layout -t zrepl tiled
|
||||
tmux attach -t zrepl
|
||||
|
||||
The Linux equivalent might look like this: ::
|
||||
|
||||
# make sure tmux is installed & let's assume you use systemd + journald
|
||||
tmux new-window
|
||||
tmux split-window "journalctl -f -u zrepl.service"
|
||||
tmux split-window "watch 'zfs list -t snapshot -o name,creation -s creation | grep zrepl_'"
|
||||
tmux select-layout tiled
|
||||
tmux new -s zrepl -d
|
||||
tmux split-window -t zrepl "journalctl -f -u zrepl.service"
|
||||
tmux split-window -t zrepl "watch 'zfs list -t snapshot -o name,creation -s creation | grep zrepl_'"
|
||||
tmux split-window -t zrepl "zrepl status"
|
||||
tmux select-layout -t zrepl tiled
|
||||
tmux attach -t zrepl
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
Loading…
Reference in New Issue
Block a user