NextcloudのデータベースサーバをM1なMac miniにまかせたら死んだ(オレが)

 

Nextcloud便利だけど重い

Nextcloudという「オープンソースのSynology」みたいな、ファイルサーバーベースのウェブアプリケーションスイート("self-hosted productivity platform")があります。

ウチではDropboxの代替として導入したところ、家族用のSlackを内部アプリのTalkで置き換え、Evernote代替のJoplinの保存先として設定し…という感じで順調に依存度を高めてます。

ところが、これが動いてる家庭内サーバが遅い。HP Proliant Microserverという10年くらい前のSOHO用サーバで、NTT-Xストアで2万くらいで買えたために一時期流行ったモノ。ドライブベイが5本あってeSata接続されてるので足回りはそこそこ速いものの、CPUが当時の省電力タイプ(AMD Athlon II)なので、NextCloudみたいな Web サーバ + PHP + DB構成の現代的なサーバープログラムを動かすにはいかにも力不足。*1

PHPのアップデートやキャッシングやJITコンパイラの導入など、できることはやりつくしました。

さすがにもうこのサーバは古すぎるなあ、新しいのほしいけど、この手の部内用サーバってクラウドに置き換えられて絶滅しちゃってるんだよなあ…。

高可用性への道

と思っていたところ、こんなドキュメントを見つけました。

An Insiders Look into scaling Nextcloud by Matthias Wobben

Nextcloud社はサーバをオープンソースで開発しつつ商用サポート版とかを売る商売をやってまして、これはそのセールスエンジニアが書いたプレゼンです。

アーキテクチャ解説の部分に、こんな連続図がありました:

全体の構成



Nextcloudプログラム本体



データベース



ファイル群



分ける

 

ふむふむ・・・と見ていって、9ページでスパッと分かれたのを見たときは、思わず「かっけー!」って叫びましたね。なんかとろくさいと思ってたNextcloudは、実はキレイに分割できるアーキテクチャになっていた。

Nextcloud社では、この形で(さらに負荷分散を加えることで)最大5万から10万ユーザーを実現してるとのこと。プレゼンの後半には実際の導入例とかが載ってました。

いやーすばらしい!

このスケーラビリティは、モダンなウェブアプリなら当然ちゃあ当然…なのかもしれませんが、オレは自分で実用的にいじってるものがきちんと分散できる状況にあったことがなく、むしろ複数のサーバを仮想化で1台にまとめるとかの事例ばかり見てきたわけです。

だから、眼の前のものを分割してパフォーマンスブーストができる、という事例を現実感を持って眺められたことで感動しました。こいつはやってみたい!!

家庭内ロードバランシングしてみる

それで自分ちのことを考えてみると、特に重いのがデータベース。MariaDBというMysqlの派生プロジェクトのやつで、Mysqlより(もちろんSQLiteとかよりはずっと)速いらしいんですが、NextCloudを使っているときにtopで監視してると、

  1. MariaDBがCPUを100%近く使う
  2. 数秒で落ち着くと、いくつも起動してるphp-fpmのチャイルドプロセスがそれぞれ20-50%ずつ使う
  3. 数秒で落ち着くと、手元の表示が出始める

というパターンが頻出します。データベースとphpが足を引っ張ってる。データベースが片方の足を、phpがもう片方の足を引っ張って、思い切り沼に引き込まれてる感じ。

これらのCPU boundな処理を外注できれば高速化できそうです。

んで、データベースサーバは切り出すのに最適です。

まず、

  • もともと分離されてるのが本来の形だから簡単なはず

である上に、

  • 使用容量が小さい
  • CPUとdisk I/Oが重い

というデータベースサーバの条件が、

  • CPUパワーを余らせてる
  • ディスクは250GBで小さすぎ

というM1 Mac miniにピッタリだったから。

mimi(M1 Mac mini の hostname)、キミに決めた! 働いてもらうぜ!

Mac mini M1にMariaDBをインストールして分散

さっそくmimiでport searchしてみるとmariadb-10.8-serverというのが見つかりましたのでインストール。元のサーバのmariadbデータのバックアップを持ってきて流し込み、アクセス権を設定し、元のサーバのNextcloudのnextcloud/config/config.phpを編集して接続できるようにしました。

それで動かしてみたら速い!…?

速いんだけど、思ったほどではないっすね~。php-fpmが処理の大部分の時間を使っていて、こちらのほうが重い。反応時間は2/3くらい。

Mac mini M1にphp-fpmをインストールして分散

それではこのクソ重いphpもmimiにまかせてしまいましょう。mimiにphpをインストールして、Webサーバのnginx.confのlocalhost:9000をMac miniに向ける…ん? 動かない。

オレは勘違いしてました。php-fpmの動いてるマシンにリダイレクトするだけで分散できるんだろうと。この勘違いは、nginx.confのphp-fpmの設定にあります。phpの処理はlocalhostのポート9000に飛ばすようになっている→ということは、データも何もかも一緒に飛ばしてくれるんだよね? と。だってデータベースサーバってそういう分割なんですもん。

ところがphp-fpmは、phpスクリプトを直接処理できないウェブサーバのための機構であり、phpスクリプトとはもともと簡易な動的なページ生成(「ホームページ」を訪れたら中に現在時刻が出てるとか)のためにあります。ここらへんはデータベースサーバとは根本的に違った出自だからしょうがない。

というわけで、これは処理部分だけ飛ばすわけにはいかず、プログラムやデータの入ったファイルシステムが見えている必要があります。(上の分割図でいうところのWebサーバ部分)。

Mac mini M1でファイルサーバからnfsマウントして分散

で、元のサーバからこのあたりをnfsエクスポートしてmimiでマウントして実験してみると…なんかファイルシステムが見えない。index.phpを処理しに行ったphp-fpmプロセスが返ってきません。

しかもここでトラブル発生。mimiのmariadbがCPUを使い切って暴走してます。元のサーバからのアクセスをそのままにして実験したのが悪かった? しかしデータベースなんて複数マシンから同時アクセスされるのが普通じゃないの??

とりあえずmimiのnginxを止めて、mariadbは再起動。

諦めてデータベースサーバの分散だけでよしとする…だがしかし

とりあえず調子良く動いているので安心していたところ、夜になって急にNextcloudの反応がなくなりました。504 Bad Gatewayとか出る。

nginxのログを見てみるとphp-fpmがタイムアウトしてます。これはデフォルト60秒なので、Nextcloudのアップデート時なんかには出ることがあるエラー。

そんなに負荷が高いのかと思って、サーバでtopを見てみると…静かなもんです。いつもよりぜんぜん使われてないというか、php-fpmが上に来てない。

ps auxw | grep phpで見るとphp-fpmのプロセス自体は動いてる。なのにnginxに処理が戻らない。なんか起きてますな…。

変わったことといえばmariadbの分散…というわけでmimiを見てみると、なんかMariadbの負荷が高いですね…。ちょっと再起動してみる。反応変わらず。

とりあえずこの時点でデータベースのバックアップを取ってみる。テーブルが壊れてるとかならバックアップもまともに取れないだろうから、そのときは移行したときのバックアップまで巻き戻す…あれ? 普通にバックアップ取れる。データベースじゃないのか…。

php-fpmのエラーログを見ても、特にエラーは出てない模様。php.iniかなんかでログレベルをdebugまで上げてやると、チャイルドプロセスの展開状況を毎秒知らせてくるレベルでログを吐くんですが、これをやっても出ない。

サーバの環境がなにかぶっ壊れたかなあ、とphpを一旦アンインストールして再インストールしてみたり、はては

freebsd-update upgrade

までやってみたけど、やっぱりphp-fpmの処理が返ってこない状況は変わりません。

やっぱりやっぱりデータベースじゃないの?と思ってmysqlコマンドで接続してみると、普通に接続できる。やっぱりデータベースじゃないのか…と諦めて寝ました。

データベースをWindowsに移してみる

もともと24/7でまったく止まらずにちゃんと動いていたものが急に調子が悪くなり、しかも原因不明となれば、変えたところがおかしいに決まっているわけです。

しかし負荷分散してアプリを軽くする実験を後退させたくもない。

そしてデータベースサーバは本当に何にでもインストールできる。

というわけで翌朝。これもわりに遊んでるくせに高速な、図書室のWindows 10マシンにMariadbをインストールしてみました。管理の作法がいろいろ違っててめんどくさかったけど、サクッと入って快調に動作。

(軽くハマったのはデータベース本体の管理。「データベースサーバプログラムに接続できるように設定する」ということと「特定のデータベースに接続できるように設定する」ということって違うのね…。mimiに入れたときもやったはずだけど、まだ慣れてない)

それでこちらのデータベースに接続してみると…Nextcloud復活したよ!!

macOS is not UNIX!!

大人しくしてればいいものを実験を続けました。せめてphpを分散できないかなあと。

しかしMacのnginxがNFSマウントしたボリュームの中のファイルを全く読めない。

これはphp-fpmとの絡みを考えたくなかったので静的ファイルで実験したり、macOS特有のファイルアクセス制限を逃れるために置き場(nginxのdocument root)をいろいろ変えたりしたんだけど、どうしても読めないんですね。nginxの設定そのものがおかしい?と思って/Users/me/Public/の下にindex.htmlを作ってやるとあっさり読めるんですが、同じファイルがNFSの中に入ると読めない。

しかもこれ、エラーはPermission DeniedではなくOperation not permittedが出る。

そうはいってもやっぱり権限問題なんじゃない?と思って sudo _www cat index.html とやると普通に読める…。

サーバ側の設定がおかしいのかもなあ…と思って、Pop!_OS(Ubuntu派生のたいへん使いやすいデスクトップLinux)の入ったノートPCでnfsマウントしてみると、めちゃめちゃあっさりnginxから読めるw

というわけで、ブン投げました。Macはサーバにならん。

さらに頑張ってなんとか動かしたとしても、またAppleが破壊的な変更をやってくるだろうということが容易に予想がつくので、学習資源が再利用不能すぎるんですよね。

なのでmimiはそういうことに使わないでよし。です。php-fpmの処理だけならRasPi4とかでも現行サーバよりは軽くなるはず。

ふりかえり

mimiのMariadbは最新版を入れたんですが、マシンがM1であることを考えると、バージョンが新しすぎたかも。次に実験するときは、よく枯れたやつを入れてみます。それでも十分速いはずだし、謎のエラーが出なくなるなら素晴らしい…しかし出なくなるかなw

*1:CPU Markは478とかで、10万オーバーな最新のRyzen Threadripper PRO 5995WXの1/200とかしかありません。何だよ10万オーバーて。ベジータ様か。