Zálohy jsou zásadní a důležitou součástí každého plánu obnovy po havárii. Zálohování produkční databáze je také základní a důležitou součástí administrace PostgreSQL. DBA však často neověřují, zda jsou tyto zálohy spolehlivé.
Každá organizace přijímá zálohy databáze PostgreSQL v různé formě, některé mohou provádět zálohu souborového systému (fyzickou) datových adresářů PostgreSQL (pomocí nástrojů jako Barman, PGBackRest), zatímco jiné mohou provádět pouze logické zálohy (pomocí pg_dump) a dokonce i jiní mohou pořizovat snímky na úrovni bloku pomocí nástrojů jako EBS nebo VMWare snapshot.
V tomto blogu vám ukážeme, jak ověřit zálohu PostgreSQL obnovením zálohy do kontejneru Docker pomocí nástroje pgBackRest pro převzetí a obnovení zálohy. Předpokládáme, že již máte znalosti o tom, jak používat PostgreSQL, Docker a pgBackRest.
Proč byste měli používat Docker?
Docker zjednodušuje automatizaci a také usnadňuje integraci naší úlohy PostgreSQL Backup Validation do nástrojů CI/CD, jako jsou CircleCI, Travis, GitLab nebo Jenkins. Používáním Dockeru se vyhnete času a zdrojům, které musíme vynaložit na zavedení nového prostředí pro testování zálohy.
Nastavení ukázky
Hostitel | Role | Instalováno Balíčky | Crontab |
uzel-1 192.168.0.111 CentOS-7 | Primární instance Posgresql-11. Vytvořen uživatel a databáze „pgbench“ a inicializovány tabulkami pgbench. | postgresql-11, pgbackrest-2.15 | Spuštění pgbench každých 5 minut pro simulaci pracovní zátěže. |
uzel-2 | Testovací stroj – na tomto hostiteli spustíme ověření Dockeru. | docker-ce-18.06, pgbackrest-2.15 | |
uzel-3 192.168.0.113 CentOS-7 | Hostitel úložiště pgBackRest | pgbackrest-2.15 | Spuštění pgbackrest pro zálohování Incr každé 4 hodiny Rozdíl zálohování každý den Úplné zálohování týdně |
Aby pgbackrest fungoval, nastavil jsem mezi těmito uzly přístup SSH bez hesla.
Uživatel „postgres“ na node-1 a node-2 se může přihlásit bez hesla k uživateli „pgbackrest“ na node-3.
[[email protected] ~]$ sudo -u postgres ssh [email protected] uptime
13:31:51 up 7:00, 1 user, load average: 0.00, 0.01, 0.05
[[email protected] ~]$ sudo -u postgres ssh [email protected] uptime
13:31:27 up 7:00, 1 user, load average: 0.00, 0.01, 0.05
Uživatel „pgbackrest“ na node-3 se může přihlásit bez hesla k uživateli „postgres“ na node-1 a node-2.
[[email protected] ~]$ sudo -u pgbackrest ssh [email protected] uptime
13:32:29 up 7:02, 1 user, load average: 1.18, 0.83, 0.58
[[email protected] ~]$ sudo -u pgbackrest ssh [email protected] uptime
13:32:33 up 7:01, 1 user, load average: 0.00, 0.01, 0.05
Přehled ověření zálohy
Níže je stručný přehled kroků, kterými se budeme řídit při ověřování záloh PostgreSQL.
- Pomocí příkazu pgbackrest restore načteme nejnovější zálohu z hostitele úložiště pgBackRest (uzel-3) do adresáře Test Machine (node-2) /var/lib/pgsql/11/data
- Během běhu dockeru připojíme adresář hostitelského počítače (node-2) /var/lib/pgsql na kontejner dockeru a spustíme démona postgres/postmaster z připojeného adresáře. Zpřístupnili bychom také port 5432 z kontejneru na port 15432 hostitelského počítače.
- Jakmile se spustí kontejner dockeru, připojíme se k databázi PostgreSQL přes uzel-2:15432 a ověříme, že jsou obnoveny všechny tabulky a řádky. Také bychom zkontrolovali protokoly PostgreSQL, abychom se ujistili, že během obnovy není žádná zpráva ERROR a instance také dosáhla konzistentního stavu.
Většina kroků ověření zálohy bude provedena na hostitelském uzlu-2.
Vytvoření obrázku Docker
Na node-2 vytvořte Dockerfile a vytvořte docker image „postgresql:11“. V níže uvedeném souboru Dockerfile použijeme následující změny oproti základnímu obrázku centos:7.
- Instalace postgresql-11, pgbackrest a openssh-clients. Pro pgbackrest je potřeba Openssh-clients.
- Konfigurace pgbackrest – Pro testování PITR potřebujeme konfiguraci pgbackrest v obrazu, bez konfigurace pgbackrest by restore_command selhal. Jako součást konfigurace pgbackrest
- Přidáváme hostitelskou ip úložiště pgbackrest (192.168.0.113) do konfiguračního souboru /etc/pgbackrest.conf.
- Potřebujeme také přístup SSH bez hesla mezi kontejnerem dockeru a hostitelem úložiště pgbackrest. Za tímto účelem zkopíruji SSH_PRIVATE_KEY, který jsem již vygeneroval, a také jsem přidal jeho veřejný klíč do hostitele úložiště pgbackrest ([email protected]).
- VOLUME ["${PGHOME_DIR}"] – Definuje adresář kontejneru /var/lib/pgsql jako bod připojení. Při spuštění příkazu docker run určíme hostitelský adresář uzlu 2 k tomuto přípojnému bodu.
- USER postgres – Jakýkoli příkaz spuštěný na kontejneru bude proveden jako uživatel postgres.
$ cat Dockerfile
FROM centos:7
ARG PGBACKREST_REPO_HOST
ARG PGHOME_DIR=/var/lib/pgsql
## Adding Postgresql Repo for CentOS7
RUN yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
## Installing PostgreSQL
RUN yum -y install postgresql11 postgresql11-server postgresql11-devel postgresql11-contrib postgresql11-libs pgbackrest openssh-clients
## Adding configuration for pgbackrest, needed for WAL recovery and replication.
RUN echo -ne "[global]\nrepo1-host=${PGBACKREST_REPO_HOST}\n\n[pgbench]\npg1-path=/var/lib/pgsql/11/data\n" > /etc/pgbackrest.conf
## Adding Private Key to the Docker. Docker container would use this private key for pgbackrest wal recovery.
RUN mkdir -p ${PGHOME_DIR}/.ssh && chmod 0750 ${PGHOME_DIR}/.ssh
COPY --chown=postgres:postgres ./SSH_PRIVATE_KEY ${PGHOME_DIR}/.ssh/id_rsa
RUN chmod 0600 ${PGHOME_DIR}/.ssh/id_rsa
RUN echo -ne "Host ${PGBACKREST_REPO_HOST}\n\tStrictHostKeyChecking no\n" >> ${PGHOME_DIR}/.ssh/config
## Making "/var/lib/pgsql" as a mountable directory in the container
VOLUME ["${PGHOME_DIR}"]
## Setting postgres as the default user for any remaining commands
USER postgres
Nyní máme dva soubory, Dockerfile používaný sestavením dockeru a SSH_PRIVATE_KEY, který se zkopíruje do obrazu dockeru.
$ ls
Dockerfile SSH_PRIVATE_KEY
Spusťte níže uvedený příkaz na node-2 a vytvořte náš docker image. V příkazu jsem zmínil hostitelskou IP repozitáře pgbackrest a tato IP bude použita v parametru pgbackrest „repo-host“.
$ docker build --no-cache -t postgresql:11 --build-arg PGBACKREST_REPO_HOST=192.168.0.113 .
Sending build context to Docker daemon 230.4kB
Step 1/12 : FROM centos:7
---> 9f38484d220f
Step 2/12 : ARG PGBACKREST_REPO_HOST
---> Running in 8b7b36c6f151
Removing intermediate container 8b7b36c6f151
---> 31510e46e286
Step 3/12 : ARG PGHOME_DIR=/var/lib/pgsql
...
Step 4/12 : RUN yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
...
...
Step 12/12 : USER postgres
---> Running in c91abcf46440
Removing intermediate container c91abcf46440
---> bebce78df5ae
Successfully built bebce78df5ae
Successfully tagged postgresql:11
Ujistěte se, že byl obrázek úspěšně vytvořen, a zkontrolujte, zda byl obrázek „postgresql:11“ vytvořen nedávno, jak je uvedeno níže.
$ docker image ls postgresql:11
REPOSITORY TAG IMAGE ID CREATED SIZE
postgresql 11 2e03ed2a5946 3 minutes ago 482MB
Obnovení zálohy PostgreSQL
Nyní obnovíme naši zálohu PostgreSQL udržovanou v hostitelském uzlu-3 záložního úložiště pgbackrest.
Níže je konfigurační soubor pgbackrest přítomný na hostitelském uzlu-2 a uzel-3 jsem uvedl jako hostitel úložiště pgbackrest. Adresář zmíněný v param pg1-path je místo, kde by se datový adresář PostgreSQL obnovil.
[[email protected] ~]$ cat /etc/pgbackrest.conf
[global]
log-level-file=detail
repo1-host=node-3
[pgbench]
pg1-path=/var/lib/pgsql/11/data
Pomocí níže uvedeného příkazu pgbackrest restore bude datový adresář postgresql obnoven na node-2:/var/lib/pgsql/11/data.
Pro ověření PITR pomocí zálohy pgbackrest jsem nastavil --type=time --target='2019-07-30 06:24:50.241352+00', takže obnova WAL se zastaví před zmíněný čas.
[[email protected] ~]$ sudo -u postgres bash -c "/usr/bin/pgbackrest --type=time --target='2019-07-30 06:24:50.241352+00' --target-action=promote --recovery-option='standby_mode=on' --stanza=pgbench restore"
Výše uvedený příkaz může chvíli trvat v závislosti na velikosti zálohy a šířce pásma sítě. Po obnovení ověřte velikost datového adresáře a také zkontrolujte recovery.conf.
[[email protected] ~]$ sudo -u postgres du -sh /var/lib/pgsql/11/data
2.1G /var/lib/pgsql/11/data
[[email protected] ~]$ sudo -u postgres cat /var/lib/pgsql/11/data/recovery.conf
standby_mode = 'on'
restore_command = '/usr/bin/pgbackrest --stanza=pgbench archive-get %f "%p"'
recovery_target_time = '2019-07-30 06:24:50.241352+00'
Zakázat režim archivace pro kontejner dokovacího zařízení PostgreSQL.
[[email protected] ~]$ sudo -u postgres bash -c "echo 'archive_mode = off' >> /var/lib/pgsql/11/data/postgresql.auto.conf"
Spusťte kontejner dockeru s obrázkem „postgresql:11“. V příkazu jsme
-
Nastavení názvu kontejneru jako „pgbench“
-
Připojování adresáře hostitele dockeru (uzel-2) /var/lib/psql do adresáře kontejneru dockeru /var/lib/psql
-
Vystavení portu kontejneru 5432 portu 15432 v uzlu 2.
-
Spuštění démona postgres pomocí příkazu /usr/pgsql-11/bin/postmaster -D /var/lib/pgsql/11/data
[[email protected] ~]$ docker run --rm --name "pgbench" -v /var/lib/pgsql:/var/lib/pgsql -p 15432:5432 -d postgresql:11 /usr/pgsql-11/bin/postmaster -D /var/lib/pgsql/11/data
e54f2f65afa13b6a09236a476cb1de3d8e499310abcec2b121a6b35611dac276
Ověřte, zda je kontejner „pgbench“ vytvořen a spuštěn.
[[email protected] ~]$ docker ps -f name=pgbench
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e54f2f65afa1 postgresql:11 "/usr/pgsql-11/bin/p…" 34 seconds ago Up 33 seconds 0.0.0.0:15432->5432/tcp pgbench
Ověřování PostgreSQL
Protože je hostitelský adresář /var/lib/pgsql sdílen s kontejnerem dockeru, protokoly generované službou PostgreSQL jsou viditelné také z uzlu-2. Ověřte dnešní protokol, abyste se ujistili, že se PostgreSQL spustil v pořádku bez jakékoli CHYBY, a ujistěte se, že níže uvedené řádky protokolu jsou přítomny.
[[email protected] ~]$ sudo -u postgres tailf /var/lib/pgsql/11/data/log/postgresql-Tue.csv
..
2019-07-30 06:38:34.633 UTC,,,7,,5d3fe5e9.7,5,,2019-07-30 06:38:33 UTC,1/0,0,LOG,00000,"consistent recovery state reached at E/CE000210",,,,,,,,,""
2019-07-30 06:38:34.633 UTC,,,1,,5d3fe5e9.1,2,,2019-07-30 06:38:33 UTC,,0,LOG,00000,"database system is ready to accept read only connections",,,,,,,,,""
2019-07-30 06:38:35.236 UTC,,,7,,5d3fe5e9.7,6,,2019-07-30 06:38:33 UTC,1/0,0,LOG,00000,"restored log file ""000000010000000E000000CF"" from archive",,,,,,,,,""
2019-07-30 06:38:36.210 UTC,,,7,,5d3fe5e9.7,7,,2019-07-30 06:38:33 UTC,1/0,0,LOG,00000,"restored log file ""000000010000000E000000D0"" from archive",,,,,,,,,""
...
2019-07-30 06:39:57.221 UTC,,,7,,5d3fe5e9.7,37,,2019-07-30 06:38:33 UTC,1/0,0,LOG,00000,"recovery stopping before commit of transaction 52181192, time 2019-07-30 06:25:01.576689+00",,,,,,,,,""
...
2019-07-30 06:40:00.682 UTC,,,7,,5d3fe5e9.7,47,,2019-07-30 06:38:33 UTC,1/0,0,LOG,00000,"archive recovery complete",,,,,,,,,""
Zpráva "konzistentní stav obnovení dosažen na E/CE000210" znamená, že se záložním datovým adresářem pgbackrest jsme byli schopni dosáhnout konzistentního stavu.
Zpráva "obnovení archivu dokončeno" znamená, že jsme schopni přehrát soubor WAL zálohovaný pgbackrest a obnovit jej bez problémů.
Připojte se k instanci postgresql přes místní port 15432 a ověřte tabulky a počty řádků.
[[email protected] ~]$ sudo -iu postgres /usr/pgsql-11/bin/psql -p 15432 -h localhost -U pgbench
Password for user pgbench:
psql (11.4)
Type "help" for help.
pgbench=> \dt
List of relations
Schema | Name | Type | Owner
--------+------------------+-------+---------
public | pgbench_accounts | table | pgbench
public | pgbench_branches | table | pgbench
public | pgbench_history | table | pgbench
public | pgbench_tellers | table | pgbench
(4 rows)
pgbench=> select * from pgbench_history limit 1;
tid | bid | aid | delta | mtime | filler
-----+-----+---------+-------+----------------------------+--------
98 | 3 | 2584617 | 507 | 2019-07-30 06:20:01.412226 |
(1 row)
pgbench=> select max(mtime) from pgbench_history ;
max
----------------------------
2019-07-30 06:22:01.402245
(1 row)
pgbench=> select count(1) from pgbench_history ;
count
-------
90677
(1 row)
pgbench=> select count(1) from pgbench_accounts ;
count
----------
10000000
(1 row)
Nyní jsme obnovili naši zálohu PostgreSQL na kontejneru dockeru a také ověřili PITR. Po ověření zálohy můžeme zastavit kontejner a odstranit datový adresář.
[[email protected] ~]$ docker stop pgbench
pgbench
[[email protected] ~]$ sudo -u postgres bash -c "rm -rf /var/lib/pgsql/11/data && mkdir -p /var/lib/pgsql/11/data && chmod 0700 /var/lib/pgsql/11/data"
Závěr
V tomto blogu jsem demonstroval ověření zálohy pomocí malé databáze na malém virtuálním počítači VirtualBox. Z tohoto důvodu bylo ověření zálohy dokončeno během několika minut. Je důležité si uvědomit, že v produkci budete muset vybrat správný VM s dostatkem paměti, CPU a disku, aby bylo možné úspěšně dokončit ověření zálohy. Můžete také automatizovat celý proces ověřování pomocí bash skriptu nebo dokonce integrací s CI/CD potrubím, abyste mohli pravidelně ověřovat naše zálohy PostgreSQL.