先日書いた、CoreOSでバックアップを取っていなかったためデータを飛ばした話の続きである。

前回fleetを使うという話をしたのだけれど、自分が今使っている環境はシングルホストだしsystemdを使うことにした。最もfleetはsystemdを分散クラスタ上で管理するためのツールのようなので、実際やることは変わらないだろう。

まず、Postgresからデータを取り出すためのイメージを作った。中身は単純にPostgres公式イメージ上でpg_dumpを実行するだけのシロモノである。 dumpしたファイルは volumeとして取り込んだホスト側の領域に吐き出される。 上記イメージを実行するコマンドをシェルスクリプトでラップし、実行ファイルとした。

pg-backup.sh

BACKUP_DIR=バックアップファイル置き場
docker run --rm -ti --link -v $BACKUP_DIR:/var/pg_dump \
  my-postgres-container:pg postgres-backup-image

次にこのスクリプトをsystemdのサービスとして登録する。 systemdではユニットという単位でOS上の様々なものを管理する。 サービスもユニットの一種という扱いのようだ。 これらのユニットを管理するための設定ファイルとしてユニットファイルを書くとsystemd側でロード、起動を実行してくれる。 ユニットファイルはCoreOSのデフォルトだと、/etc/systemd/systemに置く。 上のスクリプトのユニットファイルは以下のようになる。

pg-dump.service

[Unit]
Description=Dump data from Postgres container
Requires=docker.service

[Service]
ExecStart=/opt/docker/scripts/pg-backup/pg-backup.sh

Descriptionはユニットの説明を、Requiresは依存関係(この場合dockerサービス)を表している。 ExecStartには実際に実行されるコマンドを置く。

次に、ジョブスケジューリングのためのユニットファイルを書く。systemdではタイマーイベントもユニットとして扱うことが出来る。

pg-dump.timer

[Unit]
Description=daily Postgres backup

[Timer]
OnCalendar=*-*-* 20:00:00

[Install]
WantedBy=default.target

OnCalendarで起動時刻を指定する。この辺りはCronとおなじ感覚だ。 .serviceと.timerが同じ名前であれば、起動するサービス名は指定しなくてよい。

あとはsudo systemctl start pg-backup.timerで実行すれば、タイマーイベントとして登録される。

タスクスケジューラとしてsystemdを使ってみた感想としては、最初の印象ほどややこしくはなかったが、このぐらいのタスクであればcronの方が楽かもしれない。 依存関係などを考えるようになると真価を発揮するのではないかと思っている。