GitBucketを複数台構成で動かす方法を考えてみる

GitBucketはもともと学習用途やスモールチーム用と割り切っていたことと、またGitの絡みでRDBだけでなくファイルシステムが切っても切り離せないこともあり、これまで複数台構成で動かすことは想定していなかったのですが、Giteaでは共有ファイルシステムを使って複数台での稼働を一応サポートしているようなのでGitBucketでもできないかなと思い試してみました。

github.com

具体的に障害になりそうなのは

それぞれ具体的に見ていきます。

RDB

GitBucketはデフォルトでは組み込みモードのH2を使用しますが、外部DBとしてMySQL/MariaDBPostgreSQLをサポートしていますので、各GitBucketインスタンスを外部DBに接続するよう設定すればOKです。

ただし、GitBucketはアップグレード時に自動でDBのマイグレーションを行う機能があるため、この点だけは留意が必要です。多くのケースでは普通に各インスタンスをローリングで更新し、最初に更新したインスタンスにDBマイグレーションを行わせるでうまくいくと思うのですが、場合によってはスキーマの不一致によって未アップデートのインスタンスでエラーになってしまう可能性があります。安全を考えるといったんサービスを停止した状態でアップグレードした方がよさそうです。

HTTPセッション

GitBucketはServletのHTTPセッションを使用していますので、複数台構成にする際はアプリケーションサーバ側でセッションをレプリケーションするように設定しておく必要があります。ここは各アプリケーションサーバに依存する部分ですが、GitBucketのスタンドアロンモードであれば --save_sessions というオプションでセッション情報をディスクにシリアライズすることができますので、このディレクトリを共有することで複数サーバでセッションを共有できます。

ただ、将来的にはHTTPセッションに依存しないようにした方がよいのかもしれません。

キャッシュ

GitBucketは取得するのに重い処理が必要な一部のGitリポジトリ関連の情報をメモリ上にキャッシュしています。このキャッシュの中にはgit pushされた際に破棄する必要があるものも含まれているのですが、複数台構成にするとリクエストを受け付けたサーバ以外ではキャッシュが破棄されず古い情報を返し続けてしまいます。

とりあえず --disable_cache というオプションを追加してキャッシュ自体を使わないようにできるようにしてみましたが、将来的にはmemcachedに対応してもよいかもしれません。

ローカルファイル

GitBucketはGitリポジトリや添付ファイルなどをローカルファイルシステムに保存しています。ここはGiteaを倣って共有ファイルシステムを使います。以下のディレクトリ(要するにpluginsディレクトリ以外)を共有すれば大丈夫だと思います。

  • <GITBUCKET_HOME>/repositories
  • <GITBUCKET_HOME>/data
  • <GITBUCKET_HOME>/sessions
  • <GITBUCKET_HOME>/tmp

JGitはS3をサポートしているので、将来的にはローカルファイルシステムの代わりにS3を使えるようにするのもありかもしれませんが、GitBucketをイントラで立てるようなケースだとAWSなどは使えない可能性もあると思うのでユースケースに合うかは微妙な気もしています。

また、GitBucketにはもう1つローカルファイルシステムに依存する機能として、ダッシュボードにアクティビティログを表示するという機能があります。アクティビティログは<GITBUCKET_HOME>/activity.logに書かれており、このログを加工してダッシュボードに表示しているのですが、当然各サーバは自分でリクエストを受け付けた分のログしか持っていません。そこでひとまずダッシュボードにアクティビティログを表示しないようにする --disable_news_feed というオプションを追加しました。

もともとアクティビティログはRDBに入れていたものをサイズが大きくなりすぎるのでファイルに移行したという経緯があるのですが、それが裏目に出てしまいました。将来的にはログは各サーバに書きつつ、表示に必要な分のデータだけRDBに入れるといった工夫が必要かもしれません。

プラグイン

複数台構成での動作を想定していない一部のプラグイン(CIプラグインなど)は正しく動作しません。これはもう仕方ないところです。

また、使用するプラグインによっては追加で共有しないといけないディレクトリがあります。たとえばGistプラグイン<GITBUCKET_HOME>/gistを使用しますのでこのディレクトリも共有する必要があります。

まとめ

こんな感じでやっつけ感はあるものの、やろうと思えば複数台構成にすることはできそうです。ただ、実際の運用を考えるとバージョンアップ時のデータベースのマイグレーションは問題がありそうです。

また、やはりGitリポジトリを共有ファイルシステムに置くとなるとそこがスケールの限界になります。スケールアウトを考えるとGitリポジトリのシャーディングは必須になるかと思いますが、GitBucketは小規模での利用を想定しているという点については変わりありませんので、まあそこまでは頑張らなくてもいいかなというところです。