b-shock. Fortress

PostgreSQLのデータディレクトリに対し、ZFSのスナップショットを撮る

Mastodonの運用…に限らないけど、データベースのバックアップを取る必要がある。 pg_dump を行って rsync なりでリモートに送るのが簡単、実際その方法で1時間ごとに バックアップを取っていた。

Mastodonのデータベースを1年も運用すると、お一人様インスタンスでも1GB超のダンプファイルになる。
この大きさになると、1時間ごとに実行するのは困難。 1時間ごとに pg_dump を実行するお手軽バックアップ、1年にして破綻。
頻度を1日ごとに落とした。

個人的に、正規のバックアップは論理バックアップであるべきと考えており、この1日ごとの pg_dump は 辞められない。
一方で、今まで通りの1時間粒度のバックアップも、やはり続けたいと思っている。

それを実現するアイディアが、ZFSのスナップショット。
地雷運用と言われようとあえてFreeBSDを使い続けてきたが、その真価がついに。

以下の手順、全てroot権限にて。

マウントポイント

FreeBSDで通常のセットアップを行うと、PostgreSQLのデータディレクトリは /var/db/postgres の配下に 置かれるだろう。
ZFSのスナップショットはマウントポイントの単位で行われる為、このディレクトリを独立したマウントポイントに 分ける必要がある。

以下を実行すると、 /var/db/postgres既にあるファイルが削除される。
必要なら、それこそ pg_dump 等でバックアップしてから!

1
2
3
zfs create zroot/postgres
zfs set mountpoint=/var/db/postgres zroot/postgres
zfs set snapdir=visible zroot/postgres

zfstoolsを導入

スナップショットの保存、古いスナップショットの破棄、DBの一時停止等をひと通りやってくれる gemがある。
Mastodonインスタンスが置かれたサーバにRubyがインストールされてないはずはなく、 zfstoolsは以下の手順で導入可能。

1
2
gem install zfstools
zfs set com.sun:auto-snapshot=postgresql zroot/postgres

この手順で、 /usr/local/bin/zfs-auto-snapshot がインストールされる。

実行時ユーザーにsnapshot権限を付与

zfs-auto-snapshot は、OSのpostgresユーザーで実行するのが手っ取り早い。
このユーザーにはZFSのスナップショット作成の権限が与えられてない為、対応が必要。

1
zfs allow postgres snapshot zroot/postgres

追記(2018-09-24)
訂正あり。削除権限の付与も必要。 ZFSスナップショットを削除する

wal_levelを設定

PostgreSQL側で、 wal_level を設定する必要がある。
/var/db/postgres/data96/postgresql.conf 等に以下追記。 (data96のところ、PostgreSQLのバージョンによって変わるから適用に読み替えて)

1
wal_level = replica

反映させる為には、恐らく再起動が必要。

1
service postgresql restart

スナップショットを撮る!

ここまでで準備終わり。以下のコマンドでスナップショットが撮れる。

1
sudo -u postgres /usr/local/bin/zfs-auto-snapshot hourly 24

実際の実行はcron等で。

おまけ

スナップショットの一覧を表示。

1
zfs list -t snapshot

誤って作りまくったスナップショットの破棄。

1
zfs destroy スナップショット名