海辺にて

備忘録

カテゴリ「Linux」に属する投稿4件]

2/25にサーバーをイメージから書き換えた後に、ものすごくサーバー負荷が上がりTLが読み込めない・アクセスできないなどのエラーが発生していた。
その原因と修正方法についてメモ。

[症状]
https://minazukey.uk/notes/9q74lznca9m24...
>②①と直接の関連があるか不明だがその上でフォロー関係の有無に関わらず更に一部pleroma/akkoma系サーバーから大量のリクエストが飛んできてお互いの鯖の負荷が地獄になる
症状は夜坂さんのこの投稿にまとまっている。皆尽村が一時HTTP通信状態になったときの投稿が自サーバーにいくつか配送されており、そのときにデータベースに新しくリモートユーザーが作成された。こちらのデーターベース上は1つのアカウントに対して
①ID.アカウント名@ドメイン(HTTP通信以前に作成されていたユーザー) ②アカウント名@ドメイン(HTTP通信時に作成されたユーザー)」のデータが存在する状態になった。①のデータは2/18までの投稿が確認できたが、②のデータはHTTP通信時と思われる2/12分しかなかったことから「①ID.アカウント名@ドメイン」が正しいアカウントだと思う。

[原因]
症状発生時のPostgresqlのエラーは以下。
ERROR:  duplicate key value violates unique constraint "users_nickname_index"
DETAIL:  Key (nickname)=(***@domain.com) already exists.
ERROR:  current transaction is aborted, commands ignored until end of transaction block

ChatGPT先生に聞いたところ、ユーザーのニックネーム(***@domain.com)が重複しているためトランザクション内でエラーが発生し、ロールバックを行ったとのこと。このエラーが1秒間にエグイ数発生しており、相手先(皆尽村)にDDoS攻撃をしているようなものである…本当に申し訳ない。この重複したニックネームのアカウントがデータベース上に2つのユーザーデータがあったアカウントだったので、原因が「分裂したアカウントと自サーバーが何らかの通信を行うとき」ということが分かった。一時的な処置としてこのエラーを止めるにはAkkomaを止めて接続を遮断するしかなさそう。

重複ユーザーはAdmin-FEから目視で探した(もっといい方法があるかもしれないが…)。「①ID.アカウント名@ドメイン」というNameがあれば重複ユーザーだ。私のサーバーでは3人いた。
20240228132130-mizuiro.png
内部のデータベースを見たら以下のような構造になっていた。
20240228135723-mizuiro.png
①ID.アカウント名@ドメイン:名前の更新(updated_at)はされないがステータスの更新(last_status_at)はされる
②アカウント名@ドメイン:名前の更新(updated_at)はされるがステータスの更新(last_status_at)はされない
1つの投稿を取得するたびに2つのユーザーデータが更新されるのがエラーの原因のようだ。②のユーザーデータを消去しただけでは①のnicknameが書き換えられるものか分からないので、以下の手順で直接データを修正することを試みた。
(1)②のユーザーデータを消す
(2) ①のnicknameを元の「アカウント名@ドメイン」に書き換える

[修正]
3/2 追記
ユーザー削除だけだと不十分とのご指摘をいただきました。②アカウント名@ドメインに紐づいていたap_id(http://〜)のデータがactivitiesなどに残ってしまうため、そのあたりまで手を入れないと危なそうなようです。
https://pl.kpherox.dev/notice/AfR8ZLix9U...
https://pl.kpherox.dev/notice/AfR8gA1J48...

試してないのですが、こちらで書かれているnickname入れ替えの方がリスクが少なく、かつ手間もかからなくて良さそうです。
https://pl.kpherox.dev/notice/AfRA8InO8E...

!!データベースを操作するので必ずバックアップを取ってから行ってください!!
(1)Akkomaを止める
sudo service akkoma stop
(2)Postgresqlにログインし、正規ユーザーの内部IDを調べる
sudo -Hu postgres psql -d データベース名
select * from users where nickname='ID.アカウント名@ドメイン';
usersテーブル内のID.アカウント名@ドメインに紐づくデータを取得
idは「001,002...」のようなものではなくもっと複雑で長いです
※アカウント名@ドメインのidを調べるにはもっと良さげな条件式とかありそう
(3)userテーブルから重複ユーザー(アカウント名@ドメイン)を削除する
delete from users where nickname='アカウント名@ドメイン';
(4)正規ユーザーのnicknameを書き換える
update users set nickname='アカウント名@ドメイン' where id='(2)で取得したID';
usersテーブルのidが「(2)で取得したID」のデータのnicknameを「アカウント名@ドメイン」に更新します の意。(2)~(4)を重複したユーザー分行う。
(5)一応Postgresqlを再起動する
sudo systemctl restart postgresql.service
(6)Akkomaを起動する
sudo systemctl start akkoma.service
Admin-FEで該当ユーザーの②アカウント名@ドメインのデータが消えている、①ID.アカウント名@ドメインのNameがアカウント名@ドメインに変わっていればOK。この後、該当ユーザーの投稿の照会や投稿の配送がきちんとされ、自サーバーも皆尽村にもエラーが発生していないことを確認した。
このエラーに対していろいろとご対応していただいた夜坂さん、本当にありがとうございました!

ログを調べたら2/25のイメージ書き換え以前にもデータベースエラーによる大量アクセスが発生していたのだが、自サーバーでの動作には全く影響が出ていなかったので気づいていなかった。今回、いろいろなログの見方や調べ方が分かったのでこれからはこまめにチェックしようと思いました(初心者感)

参考:
データを更新する(UPDATE)
データを削除する(DELETE)
#akkoma
AkkomaサーバーはConoHaのメモリ1GBプランにswap2GBで動かしている。通常一人で使う分には問題なくサクサク動くが、ノーメンテナンスで2週間ほど使っていると動作がもたついてくる。以下を参考にcronで1週間に1回再起動するように設定した。
Linuxで一定時間後にシステムを再起動する方法
【Linux】 定期的な再起動の重要性と実装方法
cronでラズパイを定期的に再起動する

ちゃんと動作しているかlast rebootで確認したところ、設定どおりのタイミングで再起動しているようだった。よかったよかった。
Akkoma設置直後はディスクの使用容量が11~12GBだったのだが、しばらくしたら20GB近くまで増えていた。私の使い方的にそんなにデータベースを使用しているとは思えないので調べてみたら、原因はjournalログのようだった。
そもそもjournalログとは・・・から始めなければならない。
【RHEL】journaldサービスのログについて解説
【全オプション解説】journaldログが削除されない設定とおススメ設定を解説
journaldの使い方

どうやら必要がなかったら消してよさそう。こちらを参考に3日前以前のログを削除、journald.confSystemMaxUseRunMaxUseを1Gに設定してみた。
journalctlログを削除する
df/du コマンドでディスク容量は確認できるけど、もう少し分かりやすく表示してくれるツールを入れた。ディレクトリを移動してファイルを探せるのが便利。
・ncdu - ターミナルで動作するディスク使用量調査ツール  

VPSを借りているConoHaは50GBまで無料でスナップショットが保存できるが、保存するたびに実使用容量よりもモリモリと保存容量が増えていく。追加容量を買わなきゃいけないのか…!?と思っていたら解決方法があった。
・ConoHaのイメージ保存が保存中→ジョブ消失
メモリが1GBでスワップも使っている状態でAkkomaを稼働させているせいか、書き込み作業に数時間かかる。