Mastodon用S3バケットに不完全なマルチパートアップロードが大量に残っていた
公開日:
経緯
先日Kagoya VPSへの移行作業をして以降、数年ぶりにMastodonメンテ意識が高まったので手を入れられそうな部分をあれこれ確認していたところ、メディア周りについて数年放置していたのを思い出した。
弊Mastodonサーバーではメディア用ストレージとしてAWS S3を使っている。今使っているバケットは2019年末頃作成してそこから使い続けているもの。6年と8か月くらい。
ちなみに外部からメディアを見る時はCloudFrontを通すようにしている。
事前カウント
% docker compose exec web bin/tootctl media usage
Object Total Local
Attachments 13.2GB 6.57GB
Custom Emoji 4.58GB 1.25MB
Avatars 4.63GB 247KB
Headers 9.47GB 265KB
Preview Cards 176MB
Backups 0バイト
Settings 87.9KB
remove-orphansとremove –prune-profiles実行後
% docker compose exec web bin/tootctl media usage
Object Total Local
Attachments 13.3GB 6.57GB
Custom Emoji 4.58GB 1.25MB
Avatars 294MB 247KB
Headers 693MB 265KB
Preview Cards 177MB
Backups 0バイト
Settings 87.9KB
まぁ良さそう。普通の容量って感じ。
ただこれ、AWS側のバケットメトリクスを見ると全然違う値が出ていた。

一日1回更新なので上記の削除作業前のカウントになるが、AWSコンソールから見ると74GBくらい。
tootctl media usageから見えるのは大体作業前32GBくらい作業後18GBくらい。
怖くなったのでrcloneでmastodonに渡してあるのと同じIAMを使って見てみた
% rclone size {ここにバケットとか認証情報}
Total objects: 476.893k (476893)
Total size: 24.810 GiB (26639839976 Byte)
明らかにおかしい。
おかしいのは2点
- tootctl media usageから見えない+rcloneからも見えないオブジェクトが40GBくらいある
- media usageからは見えない+rcloneからは見えてるオブジェクトが7GBくらいある
両方調べたい所だが、一旦前者を中心に調査した。
調査
まずはmastodonの事を忘れて、rcloneやawscliとS3事だけ考えてみよう。
API経由のこういうカウントでぱっと見容量として算出されないがメトリクスには出るものとなると、すぐ思いつくのはバケット側でバージョニングを有効化している場合。
これはDBの定期バックアップを送り付けてるS3バケットでは有効化しているので思いつけたが、今回の対象バケットでは有効にしていない。(し、オブジェクトクラスを自動で移動するみたいな機能も使ってない)
ちょっと思いつかなかったので検索したりAIに聞きまくったりした結果どうにもきれいに完了しなかったマルチパートアップロードの残骸が残っている場合があるらしい。
今まで意識したことが無かった機能だったのでrcloneのオプションを調べて確認してみた。(S3 API叩くツール側が吸収してくれる場合が多いと思う)
% rclone backend list-multipart-uploads {ここにバケットとか認証情報}
出てくるわ出てくるわでシェルをおっかけるのが無理なくらい出てきた。
% rclone backend list-multipart-uploads {ここにバケットとか認証情報} > list-multipart-uploads-20260816.json
みたいにパイプしてjsonをこねこねしてカウントしてみたら1200件ほど残っていた。
おそらく動画系だろうし、1200件って多分マルチパートが1200件っていうよりもマルチパートアップロードしようとしたオブジェクトが1200件で、パート自体はもっとたくさんありそう。そこまではちゃんと確認してないけど。
対処
rcloneで確認できたのでrcloneで消してみよう。
% rclone cleanup {ここにバケットとか認証情報}
大体2分くらいでプロンプトが戻ってきた。
% rclone backend list-multipart-uploads {ここにバケットとか認証情報}
{
"バケット名": []
}
この後rcloneやawscliでまた容量を確認してみたが、特にこのcleanup作業前と変わらず25GBくらいだった。(作業前からマルチパートアップロードの残りカスはカウントされてなかったから当たり前)
Mastodonに渡しているIAMでも、他の管理者的な権限があるIAMでAWS CloudShellからawscliを使って確認してみても、どっちでも数字は変わらなかったので権限的な問題は無い事が確認できている。
二日後の確認
S3のバケットメトリクスは一日一回更新だが、具体的に何時ごろのデータが更新されるかは公開されていない。
今回のバケットの場合大体いつもJSTで朝方に更新されているが、更新されたデータは大体12時間くらい前のものな場合が今までは多かった。(体感だけど)
一応cleanupをした次の日の朝にメトリクスを見たが予想通り容量は74GB程度のまま変わっていなかったので次の日もう一度確認した。

バケットメトリクス上は26GBくらいになっている。

tootctl media usage上と管理画面上では18GBくらい。これは前と変わらず。
awscliから見ても(rcloneのコマンドメモから消えてどっかいってもうたのでhistory見るのだるいからこっちで)、メトリクスとほぼ同じだった。
% aws s3 ls "s3://$S3_BUCKET" --recursive --summarize | tail -3
Total Objects: 475962
Total Size: 26018507613
不完全なマルチパートアップロードをcleanupしただけで中々の量が消えたことになる。S3への課金でも数ドル減らせそうでとても嬉しい。
ライフサイクルルールで自動化
うまく行ったとはいえcleanup作業を都度都度行うのは面倒なので、ライフサイクルルールで自動化しよう。
対象のS3バケットに対してこんなルールを設定した。

最初「有効期限切れのオブジェクト削除マーカーまたは不完全なマルチパートアップロードを削除」って、後ろだけで良いんだけどなんで両方なんだよだるいなぁ…って思ったけどその項目にチェック入れたらその下にオブジェクト削除マーカーと不完全なマルチパートアップロードが別々に出てきてなんだこのクソUIはとなった
三日でも一日でも一週間でもなんでもいいだろうここは。
最後に
tootctl media usageから見える18GBとS3メトリクスの26GBの差分、7~8GBが一体何なのかは結局分かっていない。
rcloneやawscliから見てもメトリクスと同じなので、多分Mastodon側がカウントをミスってると思うけどちゃんと調査はしてない。(これ正直昔からずっとだし…)
今だったら、codexとかclaude codeなんかに調査させるのが良いかな?とも思ったけどめんどくさくてやってない。この程度の差だと年間$5とか$10くらいにしかならないんじゃねえかな。
一応他にも可能性はあって、2019年末にCloudflare通してた頃の都合でS3バケットを作り直している。(この頃も確かrcloneでwasabiかどっかから移してきたはず)
その影響で、何か妙なファイルが残ってるんじゃねえかなぁ、と。
ただそれだったらremove-orphansで消えろよって話なんだけど、勿論実行済みで残っている差分なのでどうしようもない。

