MisskeyのDBをマネージドに移行した時の振り返り(AWS)
この記事は、みすてむず いず みすきーしすてむずアドベントカレンダー3枚目の12/11の記事です。 みすてむずというMisskeyサーバーにいる人々だけでアドベントカレンダー4枚以上(!)が埋まる大活況、多種多様な記事が公開されており読みごたえ抜群です。
前日の記事⇒Linuxの日本語入力のはなし byカノン氏 翌日の記事⇒cdktf触ってみた記事を…書けるかなあ… byyutaro氏
はじめに
ぷろろーぐと申します。MisskeyというSNSを今年初めくらいから始めて、(アカウント自体はMisskey.ioにかなり昔に取ってあった)みすてむずというサーバーなどに定住したあげく自分でりずみすきーというサーバーを建てて、9カ月程度(記事執筆時点)運営している者です。
りずみすきーは、リズムゲームを嗜む方々向けのオンライン人数50-100人規模(記事執筆時点)のサーバーです。
本記事では、2023年5月、りずみすきーのDBをマネージドに移行した時の振り返りを行いたいと思います。
2023年の宿題の一環です。
しかし、もう半年以上も前になってしまっていて記憶がおぼろげなので、当時のメモをもとに書いていきます。
背景
りずみすきーはAWSを使用しています。
なぜVultrなどお得なIaaSがあるのにAWSかというと、私の趣味と勉強を兼ねているからです。
そして、移行前(2023/5以前)の構成は、
- t2.largeにMisskey、Redis、PostgresDBが全部入り
- 余談ですが、t系は人が増えてくるとCPUのバーストクレジットが枯渇して不安定になるため、普通にm5とかの汎用インスタンス使いましょう。
-
Ubuntu版詳細説明をもとに作成した
- dockerとかシェルスクリプトとか便利なものを使っておらず手作業で全部入れたあたたかみのあるサーバー
というものでした。見切り発車でMisskeyサーバーを建てた人あるあるかと思います。
また、当時、以下の問題がありました。
- DBのバックアップが自動化できていない
- MisskeyのDBは全データが格納されているので定期的にバックアップした方が良い、というか普通定期的にバックアップする
- バージョンアップの際に毎回手動でやっていて、嫌な気分になっていた
- cronでDBのバックアップを定期的に作成するやり方が鯖管内では話題になっていたが、ローテーションとか設計するのちょいめんどくて手が出せなかった
- この辺とかに先人の一例があるがこれはOracleだからそのまま適用できないしうーんという感じだった
- スケールアウトとか視野に入れたいのでコンポーネントを分離したい
- しかし、今なおスケールアウトできる構成にはできてない&人増えないので必要がないのでこれは夢にすぎない
この辺のモチベと、後はRDSの練習をしてみたかったというのもあり、RDSに移行することにしました。
なお、コスト面で言うとすごい勢いで上昇しますので、マネージドDBへの移行は、サーバー管理を趣味の道楽でやっているなど正気を喪った人間以外あまりお勧めではないです。
移行の手順
全くDB移行のノウハウはなかったので、以下の手順でやりました。
- 調査
- テストDBサーバーに移行してみる
- サーバーを止め、本番DBサーバーに移行を実施
調査
-
AWS DMSというマネージドサービスがあるらしいことがわかる
- 折角だからマネージドで完結させてみようという気が起こる
- ただ、2023/5時点だとMisskeyのバックエンドで動いているPostgresDB 15は未対応だったので不採用
- 今(2023/12)見たらできるって書いてあるから今は多分できると思われる
-
Amazon EC2 インスタンスから PostgreSQL データベースをインポートするで愚直にインポートすることに
- AWS公式ドキュメントは日本語訳とかおかしかったりするけど安牌だと思っています
- Copying PostgreSQL database to another serverの手順でできたら楽そうなので次のテストDBサーバーへの移行で試してみることにした
テストDBサーバーに移行
いきなり本番やってうまくいくはずがないので、一度移行作業の手順を試してみました。
テストDBサーバー作成
- テストなのでお金がかからない設定でめっちゃ小さいDBサーバー作った
- EC2コンピューティングリソースに接続⇒移行前のEC2と接続をしてDBのdumpが移行できるようにした
- 大抵クラウドで適当に環境構築するとセキュリティグループ等の問題でつながらなくて困るんだけど特に困った形跡がないからこれで全部勝手にやってくれたはず
コマンド1つで行けるか?
You don't need to create an intermediate file. You can do
pg_dump -C -h localhost -U localuser dbname | psql -h remotehost -U remoteuser dbname
or
pg_dump -C -h remotehost -U remoteuser dbname | psql -h localhost -U localuser dbname
- Stack Overflowにあった楽そうな手順をまずやった
- You don't need to create an intermediate file.だって~すごいな~コマンド1つで行けるなんて本当かな~?⇒できませんでした
- 普通に私の環境だとまずなんかsudoしないとpostgresにアクセスできなくて、その関係でパーミッションとか色々面倒だった
AWSのドキュメントに従う
# ダンプファイルを生成する
sudo -u postgres pg_dump dbname=mk1 >mk1dump.sql
# DBつくらないとだめだということが分かったのでとりあえずpostgres OWNERで作ってるけどこれはダメパターン
CREATE DATABASE mk1 OWNER postgres;
# ダンプファイルをもとに移行先にDBを作成
psql \
-f mk1dump.sql \
--host saikyou-no-test-rds-instance.ap-northeast-1.rds.amazonaws.com \
--port 5432 \
--username postgres \
--password \
--dbname mk1
- ERROR role "misskey" does not existが出た
- usernameは前と後で合わせないといけない
- でも当時の私はここまでやってなんか雰囲気つかめたから最後まで確認しないで本番作業ヨシ!したらしい
- CREATE ROLE misskeyすればいけるやろと思ったらしい
- 適当すぎるだろ
- 時間なかったのかな
作業計画を立て、本番の準備をしました。
作業計画
- RDSインスタンス作る
- ユーザーmisskeyを作る
- 構成変更後のconfigを作成しておく
- Misskey落とす
- pg_dumpを作る
- 移行前のデータベースの情報を取得する
- psqlコマンドでDBを移行
- 移行を確認する(テーブル名に問題ないか、件数あってるかCOUNTで確認
- OKであれば、Misskeyのconfig/defalt.ymlを切り替える
- Misskeyをrestartして問題ないか確かめる
本番
構成
- t2.large⇒t3.medium+db.t3.mediumに変更。
- DBを分離した分スペック低くても大丈夫かなという淡い期待
- しかし、AP側サーバーはt3.mediumだとダメだったので結局t3.largeになりました
※2023/12現在の構成ではなく、2023/5時点での構成です。現在はもう少しスペックを上げています。
DBサーバーの作成
- PostgreSQL 15.2-R2
- 本番稼働用、単一のDBインスタンス
- db.t3.medium⇒のちにdb.t4g.mediumにしました、安いため
- 汎用SSD(gp2)30GiB
- これが小さいせいで後々やばいことになる。お楽しみに
- EC2コンピューティングリソースに接続⇒Misskeyサーバー
- 自動バックアップ有効
- バックアップ保持期間は7日間
- その他の細かい設定は省略
- インスタンスだけで大体85.90 USD。プラスバックアップの分
- その後ストレージを増やしたのでDBの費用は大体120 USDになっています
移行作業
- ユーザーmisskeyを作る。
- postgresの権限関係は難しい、このときかなり調べたけどあまりわかっていない
- 特権ユーザーでログインして権限を与える必要があったりなど
- postgres沢山触るひとならよく分かっている話かも、私はわからない
- postgresの権限関係は難しい、このときかなり調べたけどあまりわかっていない
CREATE ROLE misskey LOGIN CREATEDB PASSWORD 'POYOPOYOMECHATSUYOPASSWORD';
CREATE DATABASE mk1 OWNER misskey;
# 以下1行これをやってなかったから権限不足でMisskeyアプデするときに問題が起きました
GRANT USAGE, CREATE ON SCHEMA public TO misskey;
- その後の作業
sudo systemctl stop misskey
sudo -u postgres psql --dbname=mk1
select relname, n_live_tup from pg_stat_user_tables where schemaname='public' ORDER BY relname;
→テキストにコピーする
SELECT COUNT(1) FROM note;
count
---------
4541372
(1 row)
sudo -u postgres pg_dump dbname=mk1 >mk1dump.sql
psql \
-f mk1dump.sql \
--host saikyou-no-rds-instance.ap-northeast-1.rds.amazonaws.com \
--port 5432 \
--username postgres \
--password \
--dbname mk1
psql --host=saikyou-no-rds-instance.ap-northeast-1.rds.amazonaws.com --port=5432 --username=misskey --password --dbname=mk1
select relname, n_live_tup from pg_stat_user_tables where schemaname='public' ORDER BY relname;
\d
SELECT COUNT(*) FROM note;
count
---------
4541372
(1 row)
SELECT COUNT(*) FROM __chart__notes;
count
-------
1511
(1 row)
SELECT COUNT(*) FROM drive_file;
count
--------
712032
(1 row)
SELECT COUNT(*) FROM note_reaction;
count
---------
2665210
(1 row)
色々見たけど大丈夫そう。
sudo su - misskey
cd misskey/.config
vi default.yml
以下を書き換え
# PostgreSQLの設定。
db:
host: saikyou-no-rds-instance.ap-northeast-1.rds.amazonaws.com
port: 5432
db : mk1
user: misskey
pass: POYOPOYOMECHATSUYOPASSWORD
ほぞんする
sudo systemctl start misskey
sudo systemctl status misskey
動作確認
落ちた。にゃーん
- 生ログですがIPは胡乱な数字にかえています
May 6 09:47:30 ip-256-256-256-256 misskey[3666321]: ERR *#011[core nest]#011error: no pg_hba.conf entry for host "256.256.256.256", user "misskey", database "mk1", no encryption
May 6 09:47:30 ip-256-256-256-256 misskey[3666321]: at Parser.parseErrorMessage (/home/misskey/misskey/node_modules/.pnpm/pg-protocol@1.6.0/node_modules/pg-protocol/dist/parser.js:287:98)
May 6 09:47:30 ip-256-256-256-256 misskey[3666321]: at Parser.handlePacket (/home/misskey/misskey/node_modules/.pnpm/pg-protocol@1.6.0/node_modules/pg-protocol/dist/parser.js:126:29)
May 6 09:47:30 ip-256-256-256-256 misskey[3666321]: at Parser.parse (/home/misskey/misskey/node_modules/.pnpm/pg-protocol@1.6.0/node_modules/pg-protocol/dist/parser.js:39:38)
May 6 09:47:30 ip-256-256-256-256 misskey[3666321]: at Socket.<anonymous> (/home/misskey/misskey/node_modules/.pnpm/pg-protocol@1.6.0/node_modules/pg-protocol/dist/index.js:11:42)
May 6 09:47:30 ip-256-256-256-256 misskey[3666321]: at Socket.emit (node:events:513:28)
May 6 09:47:30 ip-256-256-256-256 misskey[3666321]: at addChunk (node:internal/streams/readable:324:12)
May 6 09:47:30 ip-256-256-256-256 misskey[3666321]: at readableAddChunk (node:internal/streams/readable:297:9)
May 6 09:47:30 ip-256-256-256-256 misskey[3666321]: at Readable.push (node:internal/streams/readable:234:10)
May 6 09:47:30 ip-256-256-256-256 misskey[3666321]: at TCP.onStreamRead (node:internal/stream_base_commons:190:23): no pg_hba.conf entry for host "256.256.256.256", user "misskey", database "mk1", no encryption
色々調べた結果、下記のようにするとOK
- Misskeyリポジトリのexample.ymlにもちょろっと書いてあるけどsslの設定が必要
- rejectUnauthorized: falseも必要だった
- https://pote-chil.com/blog/postgresql-no-pg-hba-conf ←ありがとうございます
db:
host: saikyou-no-rds-instance.ap-northeast-1.rds.amazonaws.com
port: 5432
db : mk1
user: misskey
pass: POYOPOYOMECHATSUYOPASSWORD
extra:
ssl:
require: true
rejectUnauthorized: false
こうしてDB移行は問題なく終わったかに見えた・・・
移行後の問題点
移行した後当然のごとくいくつか問題が発生しました。
1. Misskeyアプデ時にpnpm run migrateが上手くいかない
- 下記エラーがでた。うわあああああああ
query failed: CREATE TABLE "user_memo" ("id" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, "targetUserId" character varying(32) NOT NULL, "memo" character varying(2048) NOT NULL, CONSTRAINT "PK_e9aaa58f7d3699a84d79078f4d9" PRIMARY KEY ("id")); COMMENT ON COLUMN "user_memo"."userId" IS 'The ID of author.'; COMMENT ON COLUMN "user_memo"."targetUserId" IS 'The ID of target user.'; COMMENT ON COLUMN "user_memo"."memo" IS 'Memo.'
error: error: permission denied for schema public
query: ROLLBACK
Error during migration run:
QueryFailedError: permission denied for schema public
- こういうことらしい
- 解決するためにはuser misskeyでcreate tableできるようにする必要があった
- user postgresでDBにログインして以下で解決
GRANT USAGE, CREATE ON SCHEMA public TO misskey;
2. 急にアクセス数が増加した時、DBのバーストバランスがやばくなった
- ストレージに汎用SSD(gp2)を使用していると発生する問題
- 許容されるIOPSがDBのボリュームサイズにより決まっている
- 汎用SSD(gp2)30GiBだとベースラインのIOPSは100IOPS
The gp2 storage type also has a base IOPS that is set when the volume is created. However, you don’t provide a value for the IOPS directly—instead, IOPS is a function of the size of the volume. The IOPS for a gp2 volume is the size of the volume in GiB x 3, with a minimum of 100 IOPS and a maximum of 10K IOPS.
- ベースラインのIOPSを超えた分はクレジットを消費してバーストすることで対応するが、慢性的にIOPSを超える状況になるとクレジットが枯渇する
- 枯渇するとIOPSがベースラインに制限され、アプリケーションは不安定になる
- 2023/7のTwitter騒動でMisskeyに人が流れ込んできたとき、急にIOPSが増えてバーストバランスがほぼ枯渇しそうに
- IOPSみつつストレージを200 GiBに上げたところ、バーストバランスがV字回復した
- ストレージ増やした分コストが増えました
- こういう場合ストレージ増やして対応するのがベストなのかは自信がない
- ギリセーフの図
移行してダメなところ
- コストが倍になります
- ざっくり$100⇒$200になりました
- t2.large⇒t3.large+db.t3.medium
- 趣味でやってる場合以外は許されないコスト増
- ざっくり$100⇒$200になりました
移行してよかったところ
- 上記以外特に大変なことが起こっていない
- DBのチューニングをやらなくてすんでいる
- バックアップについて考えなくてすんでいる
- メトリクスがコンソールから見れて楽
- DBのインスタンスタイプ変えたいってなった時すごい楽
- db.t3.medium⇒db.t4g.mediumはコンソールでポチポチしたらダウンタイムなしでできた気がする(記憶が確かなら)
- cpuをx64⇒arm64に変える系のインスタンス変更でも簡単にできるのはPaaSのいいところだと思う
- db.t3.mediumよりDBサーバーのスペックを上げないで済んでいる
- 今のところどちらかというとMisskeyサーバー側のCPUのスペックがボトルネックになりがちでした(私のサーバーの場合)
まとめ
- コストはかかるけどMisskeyのDBをマネージドに任せるのも悪くないよ
- EC2に置いてたPostgresDBからAWS RDSへの移行がどうにかこうにかうまくいったよ
アドカレにはもう1つ登録しておりまして、12/25、「Misskeyサーバー運用(運用開始〜これまで)の全体的な振り返り」でまたよろしくお願いします。
今回はDB移行に絞りましたが、全体の振り返りを書きます。
Discussion