Mastodonインスタンスと、保存されるデータの話

知っておきたいデータの保存先と節約方法

お約束

この記事はv2.5.2および2018年10月14日のmasterに基づいて書かれています。

非公式のもので、きちんとした資料として内容を保証するものではありません(誤りがあればお知らせ下さい)。

Mastodonについて、知っていると何かの役に立つかもしれないなーという話をつづった、エッセイのようなものです。

正確な情報については、公式のドキュメントや、ソースコードを参照してください。

TL;DR

  • PostgreSQL, Redis, public/system/ or オブジェクトストレージ
  • PostgreSQL大事。バックアップして、たまにvacuumすると吉
  • メディアは定期削除で容量節約。bin/tootctlを、cronに仕掛ける
  • メディアはJPEG変換してサイズと画質を下げれば大幅節約できる

場所と内容、節約方法

Mastodonインスタンスを運営する際、どこにデータが保存され、どのぐらいディスク容量を必要とするのか、やってみないとなかなか判断できないのではないかと思います。以下、概略をご紹介します。

データベース(PostgreSQL)

アカウント、ステータス(投稿)などの主要なデータはすべてここに保存されています。

データベース、超大事です。こいつさえバックアップできていれば、だいたいどうにかなります。

アカウント情報

アカウントには、インスタンスの登録ユーザー(ローカルアカウント)の他、リモートインスタンスのアカウントが随時記録されていきます。
フォローしたり、フォローされたり、お気に入り、ブーストで、どんどん増えていきます。連合リレーに参加していると、さらに増加が加速します。

ローカルアカウントには、秘密鍵が保存されています。データベースが何らかの理由で壊れてしまい、インスタンスを再構築する場合、同じユーザー名でアカウントを作り直しても、この秘密鍵が変わってしまうことで、リモートのインスタンスから「オメー、偽物だろ!」と言われてしまいます。壊してしまわないように気をつけましょう……。

ステータス

こちらもアカウントと同様に、ローカルの投稿の他、リモートの投稿の複製がどんどん増えていきます。データベースの中では、これが一番大きなデータになります。アクセスが早くなるようにインデックスも作成されています。これも決して小さくありません。

データベースを覗いてみる

管理者であれば、インスタンスの管理画面から、pgheloというPostgreSQLのダッシュボードが表示できます。

下記は、実際に稼働しているインスタンスのSpaceを表示したところです。サイズの多い順に並んでいます。ここでは20MB未満のものは省略しました。全体で2.46GBありますね。個々の容量の他、この7日間でどのぐらい増えたのか(7d Growth)も表示されています。

さほど活発なインスタンスの例ではありませんが、ここまででおおよそ1年と5ヶ月経過しての実績です。

実は無駄な領域も生じている

だいぶほったらかしで運用してきましたが、丁度良い機会なので最適化しました。データベースには削除した時に空いている領域が残っているので、それを回収します。vacuumという処理です。詳しくはPostgreSQLの情報をあたってください。

うん、だいぶ小さくなりましたね。1.81GBに縮まりました。7d Growthがマイナスになっていて変化したところがわかります。

バックアップの方法とか

pg_dumpでファイルに吐き出して、自分のパソコンにコピーしておく、というのが基本です。自分のパソコンではなく、どこか信頼できるサーバを別に用意して、そちらにコピーしておいてもいいと思います。これを何世代か保存しておくことで、その時点までロールバックすることができます。

なお、実際に壊れた時に復元できなければ意味がありませんので、バックアップから復元する練習・動作試験をどこかでやっておきましょう。どのぐらいの時間がかかるのか、エラーが発生することはないか、調べておくのです。ここで、データベースの内容に矛盾がある(壊れている)ことが発覚することもあります。

また、バックアップとは別のアプローチになりますが、現在使用しているものとは異なるサーバを用意して、レプリケーションしておくという方法があります。データベースが壊れるような変更が入った場合、レプリケーションは同時に壊れますので、内容のバックアップにはなりません。サーバがすぐに復旧できない場合に、即座にそちらに切り替えて運用を続けることができるという、冗長構成におけるバックアップです。

Dockerでやってたら消えちゃった

どっかーに行ってしまったようですね(0点)

Dockerで運用する場合、Dockerの外にデータベース本体を置いておかなければ消えてしまいます。Dockerとはそういうものです。バックアップをとっておらず、もう消えてしまったなら手遅れです。 まだ残っているなら、Dockerの外に移動します。このへんの話は他で十分に語られているので、ここでは省略させていただきます。

データベース(Redis)

直近のタイムラインの状態、バックグラウンドジョブ、その他キャッシュがRedisに保存されています。

Redisはメモリ上で動作する高速なデータベースですが、Mastodonの標準設定では、ストレージにもバックアップをとる設定になっています。そのため、再起動しても内容が復元されます。

さきほど実際のインスタンスのバックアップを覗いてみたところ、1MB程でした。メモリは5MBほど使っているようです。たいしたことありませんね。これは、アクティブなユーザーが多ければもっと多くなります。この例は35人程度です。

メディア

投稿に添付された画像や動画、ユーザーのアバターアイコン、ヘッダイメージ、絵文字、プレビューカード(URLの参照先をプレビュー画像化したもの)などが保存されます。これは非常に大きな容量を必要とします。

投稿に添付された画像や動画については、自分のインスタンスでアップロードされたデータは大事なものなのでずっと保存しておきますが、他のインスタンスでアップロードされたものは、また取りに行けばいいので、古いモノから適当に捨ててしまいます。

普通に使っている場合、 /home/mastodon/live/public/system に保存されます。

オブジェクトストレージを利用する場合、そちらにアップロードされます。

オブジェクトストレージは、保存容量や転送量に応じてお金を払えば、入れ物の大きさを心配せず、データも多重にバックアップされた環境で比較的安全に保持してくれるので、頼りになる存在です。

リモートメディアを定期削除する

mastodonユーザーで、Mastodonのインストールされているディレクトリに移動し、下記のコマンドで7日前までのリモートメディア(キャッシュ)を削除できます。

  • rootでログインしているならsu - mastodon、普通のユーザーからならsudo -su mastodon
  • cd ~/live
  • RAILS_ENV環境変数を.bashrc等で設定していれば、いちいち RAILS_ENV=production は不要
RAILS_ENV=production bin/tootctl media remove  

日付を指定すれば、何日前を削除するか指定できます。

RAILS_ENV=production bin/tootctl media remove --days=1  

これを、cronなどで定期実行することで、常に余分な容量を使わないように節約できます。

運用中のインスタンスでは、しばらく放置してあったので、53GBあったものが、7日分に切り詰めたことで13.5GBに減りました。

画像の品質を下げる

Mastodonは比較的PCで利用しているユーザーの多いSNSだと思いますが、それでも主力はスマートフォンに移行しています。多少品質を下げたところで大差はないので、容量を節約したい場合は、ガッと下げてしまいましょう。

  • 透過でないPNGをJPEGに変換する
  • 画像の最大サイズをより小さな値に変更する
  • JPEGのクオリティ設定を下げて圧縮率を上げる

JPEGへの変換については、先人の知恵を拝借します。アイマストドンの改造を利用させていただきましょう。

アイマストドンの7ヶ月半をgithubのPRベースで振り返る

サイズダウンとクオリティの変更はこのへんです。お好みで加減されると良いでしょう。

https://github.com/noellabo/mastodon/commit/c54ae1ec4791dbba3b77890f181438b73d87fdc2

まぁ、ここまでやると半分以下です。1/3とか、1/4ぐらいになるかもしれません。

こちらの節約方法については、ドン・ゴロツキというインスタンスで実践し、劇的な効果をあげています。

#鯖缶工場に弟子入りし、超小規模インスタンス「ドン・ゴロツキ」をつくった

ログファイル

あまり気にするほどではないのですが、nginxのアクセスログなどが、ずっと蓄積されています。

systemctlで起動しているmastodon-web, mastodon-sidekiq, mastodon-streamingについては、journaldが記録を保持しています。こちらはシステム再起動時に削除される場所に保存されています。