クラウド時代のWebアプリケーション・スマートフォンアプリを開発・運用する会社です。 03-4577-8680 03-6673-4950

GitLab 9.1.2 (MySQL) を 11.4.0 (PostgreSQL) にアップグレード

2018-10-30

弊社ではかなり前からGitLab(CE)を自社環境で運用しているのですが、ふと気付くと、バージョンがだいぶ先に行ってしまっていました。
とくに最近のバージョンでは Auto DevOps なども使えるようになっていたりするので、さすがにそろそろキャッチアップしたいと考えたわけです。

現行の環境は次の通りです:

  • GitLab 9.1.2
    • sameersbn/gitlab 使用
  • MySQL 5.6
    • Google CLoud SQL
    • Cloud SQL Proxy Dockerを経由してGCP
    • https://cloud.google.com/sql/docs/mysql/connect-docker
  • Redis
    • sameersbn/redis 使用

で、ある程度予想はしてたんですが、ただ単純にGitLabコンテナをバージョンアップしただけでは起動しなかったのです。
問題は結局次の7点ありました。

  1. PostgreSQLへ移行しなければならないパターンが発生
  2. PostgreSQLへの移行ツールの問題
  3. GitLab公式に記載された移行方法が実行できない
  4. PostgreSQL 10で起動に失敗する件
  5. GitLab 10.0でのDBマイグレーションで発生する問題
  6. DBマイグレーション実行後のGitLab起動失敗
  7. GitLab起動後にDBが初期化される

経緯を追うと長くなりそうですが、おそらくこれだけ見ると意味がわからないので、それぞれできるだけ短く記載していきます。

1. PostgreSQLへ移行しなければならないパターンが発生

GitLab 9.3 で、MySQLでのサブグループ機能が廃止されました。
https://docs.gitlab.com/ce/user/group/subgroups/index.html#database-requirements
もともと対応環境として「PostgreSQL推奨/MySQLも可」とはなっていましたが、状況によってはMySQLでのDBマイグレーションが通らないようなので、あきらめてPostgreSQLへの移行を決意しました。

2. PostgreSQLへの移行ツールの問題

さてではどのようにPostgreSQLへ移行するか、ということですが、GitLab公式ドキュメントで pgloader を推奨しているようです。
https://docs.gitlab.com/ee/update/mysql_to_postgresql.html

2018-10月現在の最新版は 3.5.2 のようですが、これが Control stack exhausted とエラーが表示されて動作しませんでした。
同様のIssueがあり、3.5.1を使用することとします。
https://github.com/dimitri/pgloader/issues/810

3. GitLab公式に記載された移行方法が実行できない

さて、公式リファレンスに書かれた手順で pgloader をテスト実行してみましたが、どうやら WITH オプションのどれかが通らないようです。
リファレンスでは pgloader 3.4.1+ と書かれているので、3.4.1 では動くのかもしれません。
試行錯誤の結果、 WITH オプションは WITH preserve index names だけがあればとりあえず問題が無いようです。
(この点は保証がありません)

4. PostgreSQL 10で起動に失敗するパターンがある件

移行後のDBとしてPostgreSQLを用意し、GitLabと仮接続して確認してみたところ、
いくつかの操作でGitLab内のエラーが発生しました。
念のため確認してみたところ、PostgreSQL 10は対応環境外とされているようですね。
https://gitlab.com/gitlab-org/gitlab-ce/issues/42047
ということで、 PostgreSQLは9.6を使用することとしました。

5. GitLab 10.0でのDBマイグレーションで発生する問題

GitLab 9.1.2のデータをMySQLからPostgreSQLに入れ替え、GitLab 11.4.0でDBマイグレーションを実行してみたところ、失敗し中断しました。
エラーメッセージを追ってみたところ、9.x から 10.0 の間のDBマイグレーションに問題があるようです。
https://gitlab.com/gitlab-org/gitlab-ce/issues/38283

PostgreSQLにデータを移行しなおしてから、events テーブルのINDEXを見ると、確かにプライマリキーのINDEX名が idx_xxxxx_primary のようになっているので、PostgreSQL上で
ALTER INDEX '(eventテーブルのプライマリキーのINDEX名)' RENAME TO 'events_pkey';
と実行すると、DBマイグレーションが通るようになりました。

6. DBマイグレーション実行後のGitLab起動失敗

sameersbn/gitlab のドキュメントにあるように、GitLabコンテナを稼働させる前に、rake:migrate を実行してDBマイグレーションを実行したところ、GitLabコンテナが起動中しなくなりました。
条件・原因がいまいちパっとわからない状況ではあったのですが、 sameersbn/gitlab の起動時の挙動を追うと、起動時に自動的にDBマイグレーションも走るようだったので、事前に実行せず、起動時処理に任せることにしました。

7. GitLab起動後にDBが初期化される

GitLabコンテナを起動したところ、「管理者パスワードの変更画面」が表示されました。
これはGitLabをクリーンインストールした場合の状態のはずですので、PostgreSQLのデータを確認してみると、やはりデータが初期化されています。

ソースを追ってみたところ、GitLab起動時に毎回、「(PostgreSQLの場合)public スキーマ内のテーブルの数をカウントし0である場合はクリーンインストール」する挙動となっていることがわかりました。

ということはつまり、 pgloader でのデータ移行時に、テーブルが public スキーマ以外に作成されているということになります。
改めてPostgreSQLを初期状態に戻し、 pgloader でデータ移行しなおしてからPostgreSQL内を見てみると、データベース名と同じスキーマ名になっています。

ということでどうやら、pgloaderのデフォルト挙動では、データベース名と同名のスキーマを新規追加するようです。
この状況を防ぐためには、 pgloader のオプションとして ALTER schema '(データベース名)' rename to 'public' が必須となります。
https://github.com/dimitri/pgloader/issues/645


ということで、手順ベースでまとめると:

  • MySQLからPostgreSQLへ、pgloaderでデータ移行
  • events テーブルのINDEX名を手動で変更
  • 11.4.0のGitLabコンテナを起動

ずいぶんシンプルになってしまいますね…。

なお、実際にアップグレードを実行する際には、いくつか注意が必要です。

既存GitLabのディレクトリ(gitレポジトリなどが配置されている)はまるごと全てバックアップしておく必要があります。
(マイグレーションの一環として、このディレクトリの構造が変化してしまうため)
こういうとき、GCPなどスナップショットが保存できる環境だと楽ですね。

当然ながら、既存DBのバックアップは、絶対にx3必須です。

実際にPostgreSQLにデータを入れる際は、安全のため次のような手順で実施しています。

  • ローカルにDockerコンテナ環境を構築
  • 本番環境からMySQLのダンプを取得
  • コンテナ間でデータ移行
  • PostgreSQLコンテナで完全に確認できたらダンプを取得
  • 本番環境のPostgreSQLにインポート

弊社ではGitLabのようなツール・ミドルウェアなどの導入設置・運用なども承っております。
今回のように、なかなか手間のかかるものなど、お気軽にお問い合わせください。