バックアップユーティリティ barman 2.0 の新機能について

この記事は[PostgreSQL Advent Calendar 2016](http://qiita.com/advent-calendar/2016/postgresql)の7日目の記事です。

# はじめに
直前まで何書くか全然決めていなかったのですが、PGConf.Asia 2016(12/1～12/3)に参加し、[Magnusさんの講演](http://www.pgconf.asia/JP/day-2/#A2)でbarmanに興味を持ったので、今回調べてみることにしました。
ちなみにbarmanとは2ndQuadrantがGithubで[公開](https://github.com/2ndquadrant-it/barman)しているPostgreSQL専用のバックアップ/リカバリ管理ツールです。

barmanの基本的な機能紹介等については、PGEConsの[報告書](https://www.pgecons.org/wp-content/uploads/PGECons/2015/WG3/PGECons_2015_WG3_DBTools.pdf)が参考になるかもしれません。興味のあるかたはご一読ください。

# 1.barman 2.0の新機能
最新版の2.0が2016年9月にリリースされました。
どういった機能が実装されたのか詳細は[リリースノート](https://github.com/2ndquadrant-it/barman/blob/master/NEWS)をご確認ください。
多くの更新が入っていますが、主な新機能としては以下の4つぐらいでしょうか。
本当は全部やるつもりだったのですが、今回は時間がなかったので個人的に響いた項番3についてのみ確認してみました。

|項番|概要|備考|
|:--:|:--|:--|
| 1  |レプリケーションスロットに対応|receive-walコマンドで--create-slotと--drop-slotコマンドがサポート|
| 2  |PG96から導入された新しいバックアップAPIをサポート|9.2～9.5まではスタンバイからのバックアップ取得にpgespressoが必要だったが今後は不要。|
| 3  |同期スタンバイとしてのWALストリーミング機能をサポート|この機能によりRPO=0（どの時点にでも復旧可能）となる。|
| 4  |barman-wal-restoreオプションでWALファイルのリモートパラレルフェッチをサポート|たぶん、リストアが早くなるという話と思われる。（要確認）|

「見せてもらおうか、barmanの新機能の実力とやらを！」

# 2.環境構築

本作業は以下の条件で実施します。

- 構成
    - マスタ(node_yama)＋バックアップサーバ(node_umi)の2台構成
- 製品
    - barman 2.0
    - PostgreSQL 9.6.1 （RPMでインストールされた状態を前提とする。）
        - バックアップサーバにもPostgreSQLをインストールする必要あり。pg_basebackupや[pg_receivexlog](http://www.postgresql.jp/document/9.6/html/app-pgreceivexlog.html)を使用するため。
    - CentOS 7.2


![streaming_barman](https://d17oy1vhnax1f7.cloudfront.net/items/370H0l0p1p1D1Q3z2j1i/streaming_barman.PNG "streamning_barman")

PostgreSQLのパラメータは以下の点を変更します。

```$PGDATA/postgresql.conf
wal_level = 'replica'
max_wal_senders = 3
max_replication_slots = 3
synchronous_standby_names = 'barman_receive_wal'
```

## 2-1. DBサーバでの作業（node_yamaで実施）

### barmanが管理で使用するためのROLEを作成する。

barmanからPostgreSQLに接続する際のROLEを作成する。

```
[postgres@node_yama]$ createuser -s barman
```

続いて、Streaming Replicationを用いたバックアップを行うためのROLEを作成する。

```
[postgres@node_yama]$ createuser --replication streaming_barman
```

## 2-2. バックアップサーバでの作業（node_umiで実施）

### barmanのインストール
DBサーバとは別のマシンにインストールします。
python系のRPMと依存関係があるので、yumで入れてしまうのが手っ取り早いです。

```
[root@node_umi]# wget https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-7-x86_64/pgdg-centos96-9.6-3.noarch.rpm
[root@node_umi]# rpm -ivh pgdg-centos96-9.6-3.noarch.rpm
[root@node_umi]# yum install barman
[root@node_umi]# su - barman
[barman@node_umi]$ barman --version
2.0 Barman by 2ndQuadrant (www.2ndQuadrant.com)
```

### barmanを設定する

気にしないといけないのはざっくりと以下の設定ファイルです。

barman全体の設定ファイル：/etc/barman.conf 
barmanでバックアップされる各サーバの設定：/etc/barman.d/＜ノード名＞.conf

テンプレートファイルがあるので、それを参考にしながら書いてみます。

```
# cd /etc/barman.d/
# cp streaming-server.conf-template node_yama.conf  
```

```/etc/barman.d/node_yama.conf
[node_yama]
description =  "Example for Advent Calendar"
conninfo = host=node_yama user=barman dbname=postgres
streaming_conninfo = host=node_yama user=streaming_barman

; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Backup settings (via pg_basebackup)
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
backup_method = postgres
;streaming_backup_name = barman_streaming_backup

; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WAL streaming settings (via pg_receivexlog)
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
streaming_archiver = on
slot_name = barman_slot
;streaming_archiver_name = barman_receive_wal
;streaming_archiver_batch_size = 50
```

### レプリケーションスロットを作成する

barmanから対象のDBサーバでレプリケーションスロットを作成することができます。

```
$ barman receive-wal --create-slot node_yama
Creating physical replication slot 'barman_slot' on server 'node_yama'
Replication slot 'barman_slot' created
```

### barmanの設定確認

以下のコマンドでバックアップ取得先との状態等を確認できます。

```
$ barman check node_yama                                                        
Server node_yama:
        WAL archive: FAILED (please make sure WAL shipping is setup)
        PostgreSQL: OK
        superuser: OK
        PostgreSQL streaming: OK
        wal_level: OK
        replication slot: FAILED (slot 'barman_slot' not initialised: is 'receive-wal' running?)
        directories: OK
        retention policy settings: OK
        backup maximum age: OK (no last_backup_maximum_age provided)
        compression settings: OK
        failed backups: OK (there are 0 failed backups)
        minimum redundancy requirements: OK (have 0 backups, expected at least 0)
        pg_basebackup: OK
        pg_basebackup compatible: OK
        pg_basebackup supports tablespaces mapping: OK
        pg_receivexlog: OK
        pg_receivexlog compatible: OK
        receive-wal running: FAILED (See the Barman log file for more details)
        archiver errors: OK
```

WAL archive、replication slot、receive-wal runningが「FAILED」になっています。
後ろ2つが失敗しているのは、まだpg_receivexlogを起動していないので、ごもっとも。

WAL archiveの項目ですが、一旦は無視してOKです。
これはbarmanコマンドを実行した際に作成されるxlog.dbファイル（/var/lib/barman/node_yama/wals/xlog.db）のファイルサイズが0でないことを確認しており、まだバックアップも何もしていないので、この段階ではFAILDになります。

以上で環境構築は終わりです。


# 3.barmanによるバックアップ取得

## barman経由でのpg_receivexlog起動

```
[barman@node_umi]$ barman receive-wal node_yama
Starting receive-wal for server node_yama
node_yama: pg_receivexlog: starting log streaming at 0/10000000 (timeline 1)
```

※ちなみにこのプロセスはフォアグラウンドで動きます！

## WALの手動切り替え

自分の環境だとこの手順を入れないとうまく行きませんでした。
理由はよくわからず。。。xlog.dbと関連があるとは思うのですが。。。

```
[barman@node_umi]$ barman switch-xlog node_yama
Switch to 000000010000000000000011 for server 'node_yama'
```

pg_receivexlogで受信ができていれば、「node_yama: pg_receivexlog: finished segment at 0/11000000 (timeline 1)」が新しくコンソールに出力されるはずです。


## ベースバックアップ取得

```
[barman@node_umi]$ barman backup node_yama
Starting backup using postgres method for server node_yama in /var/lib/barman/node_yama/base/20161207T132607
Backup start at xlog location: 0/11000060 (000000010000000000000011, 00000060)
Copying files.
Copy done.
Finalising the backup.
This is the first backup for server node_yama
WAL segments preceding the current backup have been found:
        000000010000000000000010 from server node_yama has been removed
Backup size: 171.6 MiB
Backup end at xlog location: 0/13000000 (000000010000000000000012, 00000000)
Backup completed
Processing xlog segments from streaming for node_yama
        000000010000000000000011
```

これでバックアップの取得は完了です。
ちなみにこの状態でcheckコマンドを実行すると以下のようになります。

```
[barman@node_umi]$ barman check node_yama                                                        
Server node_yama:
        PostgreSQL: OK
        superuser: OK
        PostgreSQL streaming: OK
        wal_level: OK
        replication slot: OK
        directories: OK
        retention policy settings: OK
        backup maximum age: OK (no last_backup_maximum_age provided)
        compression settings: OK
        failed backups: OK (there are 0 failed backups)
        minimum redundancy requirements: OK (have 1 backups, expected at least 0)
        pg_basebackup: OK
        pg_basebackup compatible: OK
        pg_basebackup supports tablespaces mapping: OK
        pg_receivexlog: OK
        pg_receivexlog compatible: OK
        receive-wal running: OK
        archiver errors: OK
```

バックアップの取得状況については以下のコマンドで確認することができます。
何度かバックアップを取得したりしているとこんな感じで増えていきます。

```
[barman@node_umi]$ barman list-backup node_yama
node_yama 20161207T144606 - Wed Dec  7 14:46:06 2016 - Size: 187.6 MiB - WAL Size: 0 B
node_yama 20161207T144354 - Wed Dec  7 14:43:54 2016 - Size: 187.6 MiB - WAL Size: 64.0 MiB
node_yama 20161207T140602 - Wed Dec  7 14:06:02 2016 - Size: 187.6 MiB - WAL Size: 48.0 MiB
node_yama 20161207T132607 - Wed Dec  7 13:26:07 2016 - Size: 187.6 MiB - WAL Size: 128.0 MiB
```

# 4.新機能3の確認

「新機能3：同期スタンバイとしてのWALストリーミング機能をサポート」がPostgreSQL上からどのように見えるか確認します。
以下のように、レプリケーションスロットを利用したbarmanへのWALストリーミングが同期モードで動いていることを確認できました。

```
[postgres@node_yama]$ psql postgres -c "select pid,usename,application_name,client_addr,state,sync_state from pg_stat_replication"                                                                
  pid  |     usename      |  application_name  | client_addr |   state   | sync_state 
-------+------------------+--------------------+-------------+-----------+------------
 17770 | streaming_barman | barman_receive_wal | 192.168.1.3 | streaming | sync
(1 row)

[postgres@node_yama]$ psql postgres -c "select slot_name,slot_type,active_pid from pg_replication_slots"
  slot_name  | slot_type | active_pid 
-------------+-----------+------------
 barman_slot | physical  |      17770
(1 row)
```

確認があっさりしすぎ？

# 5.リストア
バックアップしたものはリストアできなくては意味がない。
というわけで上記で取得したバックアップをリストアしてみます。

pg_receivexlogの効果を見るためにも、以下の手順でやります。

1. データを1件INSERT
2. DB停止、$PGDATA削除
3. リストア
4. DB起動、手順1のデータが復旧できたか確認

## データを1件INSERT

```
[postgres@node_yama]$ psql postgres -c "CREATE TABLE bar(v varchar)"
[postgres@node_yama]$ psql postgres -c "INSERT INTO bar VALUES ('gakki')"
```

## DB停止、$PGDATA削除

```
[barman@node_yama]$ pg_ctl stop
[barman@node_yama]$ rm -rf $PGDATA
```

## リストア

```
[barman@node_umi]$ mkdir ~/data
[barman@node_umi]$ barman recover node_yama latest ~/data                                        
Starting local restore for server node_yama using backup 20161207T153302
Destination directory: /var/lib/barman/data
Copying the base backup.
Copying required WAL segments.
Generating archive status files
Identify dangerous settings in destination directory.

Your PostgreSQL server has been successfully prepared for recovery!
[barman@node_umi]$ barman get-wal node_yama --output-directory ./data/pg_xlog 0000000100000000000
00008
[barman@node_umi]$ cp node_yama/streaming/000000010000000000000009.partial data/pg_xlog/000000010000000000000009
[barman@node_umi]$ scp -r data postgres@node_yama:/var/lib/pgsql/9.6
```

ちょっと調べきれていないのですが、上記の手順だとstreamingしていたWALは別途手作業でbarmanから取り出しています。
本当だとbarmanがここらへんもよろしくやってくれそうな気がするけど・・・（要確認）

## DB起動、手順1のデータが復旧できたか確認

```
[postgres@node_yama]$ pg_ctl -D /var/lib/pgsql/9.6/data start                                    
server starting
[postgres@node_yama]$ 2016-12-07 16:07:37.906 JST [21729] LOG:  redirecting log output to logging collector process
2016-12-07 16:07:37.906 JST [21729] HINT:  Future log output will appear in directory "pg_log".

[postgres@node_yama]$ psql postgres -c "SELECT * FROM bar"
   v   
-------
 gakki
(1 row)
```

無事にリストアできていることを確認できました。


# さいごに
barman2.0についてですが、着目すべきは以下の点と考えます。

- barman管理下でのリアルタイムWALアーカイブが可能になった
    - リアルタイムでWALが同期されているのでPITRする際、どの時点にでも復旧が可能
- レプリケーションスロットとの連携により、WALのローテートを気にしないくてよくなった

最近、バックアップについて考えることが多いので、継続してbarmanについて見ていこうと思います。
なんかちゃんと魅力を伝えきれていない気がする。。。
時間が空いたタイミングで適宜修正していきます。