弊社ではかなり前から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点ありました。
PostgreSQLへ移行しなければならないパターンが発生
PostgreSQLへの移行ツールの問題
GitLab公式に記載された移行方法が実行できない
PostgreSQL 10で起動に失敗する件
GitLab 10.0でのDBマイグレーションで発生する問題
DBマイグレーション実行後のGitLab起動失敗
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のようなツール・ミドルウェアなどの導入設置・運用なども承っております。 今回のように、なかなか手間のかかるものなど、お気軽にお問い合わせください。