社内GitLabの大型マイグレーションをした話

# はじめに

この記事は[富士通クラウドテクノロジーズ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/fjct) の 15 日目の記事です。

こんにちは。富士通クラウドテクノロジーズ株式会社 (FJCT) でエンジニアをしている @aokuma です。
昨日の記事は :mouse: エンドエンジニアの [@seumo](https://zenn.dev/seumo) 氏による [SmithyでAPIリファレンス作成してみよう](https://zenn.dev/seumo/articles/d33581c111a6d7) でした。
Smithy、現在は主に AWS SDK の実装として使われているみたいですが、多言語 SDK が求められるサービスプロバイダーにとって、このような仕組みがオープンになるのはとても嬉しいですね。利用できる言語が更に拡張されるのを期待しています！

さて、今日は弊社の開発基盤の中心である **社内 GitLab** の大型マイグレーションを実施したお話をしようと思います。


# 背景

現在、弊社の開発基盤の中でコード管理...にとどまらず、プロジェクト管理や DevOps 基盤として、セルフホスト版 [GitLab](https://about.gitlab.com/) を使用しています。
このあたりの変遷については過去のスライド・記事が参考になるので、気になる方はぜひ見てみてください。

1. [モダンな開発・運用環境を導入するために奮闘した\(している\)話 2nd \- FJCT Tech blog](https://tech.fjct.fujitsu.com/entry/2017/12/24/chatops-progress-report) by @ysaotome
1. [GitLab から GitLab に移行したときの思い出](https://www.slideshare.net/Fujitsu_CloudTechnologies/gitlab-gitlab-108050041) by @YOMOGItaro 
1. [全社員が利用するプロジェクト管理ツールとして GitLab Enterprise Edition Premium を導入した話 \- FJCT Tech blog](https://tech.fjct.fujitsu.com/entry/Story-of-introducing-GitLab-Enterprise-Edition-Premium) by @ysaotome 

2021/12/15 現在では下記のような規模の GitLab となっており、導入時と比べるとかなり利用が増えてきています。(**Just 6000 Projects!!**)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72278/3694608a-7ba5-e9b2-1476-e73e8b1a05bd.png)

ちなみにデータ総量は 8TB ほどだったかと思います。 (コンテナレジストリのデータが約 5TB ほど占めていました…。)

さて、そんな弊社の GitLab (上記のスライドでいう天下統一した GitLab) ですが、運用開始から約 5 年ほど経過した段階で下記のような問題を抱えていました。

- 手動管理なインフラ
    - `docker-compose.yml` は Git 管理されていましたが、それだけ…。
- インフラの老朽化
    - EOL な OS を使い続けている
- シングル VM 構成
    - 障害発生時にアクセスできなくなってしまう
    - ユーザー増加による負荷に耐えきれない
        - 一部ユーザーが大量にリクエストをしてきた際に高負荷となり、レスポンス全体が著しく遅くなるなどの事象が発生した経緯あり

当初はスモールスタート想定で上記のような課題については目を逸していたのだと思うのですが、利用者の増加・開発の中心となるツールへと格上げされる中で、上記のような課題を抱えたまま運用を続けるのは大変リスキーな状態でした。

そんなタイミングで GitLab Premium を導入することができ、 GitLab Inc. の手厚いサポートを受けることもできるようになったことから、総データサイズ 8TB のシングル構成 GitLab を HA構成へマイグレーションするプロジェクトが立ち上がりました。

# 計画

上記課題の中から、シングル VM 構成による可用性と処理能力の問題を解決するために下記のような移行計画を立てました。

1. まずは 1 リージョンで HA 構成を構築し、データをすべてマイグレーションする (今回はここの話です)
1. HA 構成が安定したら複数リージョンを使った [GitLab Geo](https://about.gitlab.com/solutions/geo/) による DR 構成を導入する

なお、すべてのコンポーネントはニフクラのパーツを使いながらニフクラ上に稼働させます。

インフラ構成を含めた移行計画の詳細は GitLab Inc. との定例にて連携をとり、適宜レビューを受けながら進めていきました。
計画当初はすべて VM 上に構築する構成を検討していましたが、計画をすすめる中で [Cloud Native Hybrid Architecture](https://docs.gitlab.com/ee/administration/reference_architectures/3k_users.html#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) の存在を教えていただきました。これはステートレスな Web フロントエンドコンポーネントを Kubernetes 上に稼働させ、それ以外の DB などのステートフルなコンポーネントを VM や PaaS 上に稼働させる構成です。
弊社も 2021 年 3 月に Kubernetes Service Hatoba を正式リリースしたということもあり、この構成でチャレンジしてみることにしました。

ちなみに検討の中ですべてのコンポーネントを Kubernetes 上に乗っける案も出ましたが、Praefect, Gitaly を Kubernetes 上で本番稼働させるにはまだ時期尚早のようで今回はやめておきました。

最終的には下記のような構成としました。

![gitlab_infrastructure.dio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72278/b9e3921b-63d9-4206-541d-723563a40180.png)

※各コンポーネントの役割

* Kubernetes: ステートレスなコンポーネントを稼働させる (webservice, registry, etc...)
* PostgreSQL: GitLab のメイン DB
* KVS: Redis, Consul Server
* Gitaly: Git リポジトリデータ管理 (Gitaly, Praefect, Praefect DB)
* External Load Balancer: 外部からのリクエストの負荷分散用 LB
* Internal Load Balancer: 内部通信負荷分散用 LB
* Bastion: 踏み台

# 構築・テスト

課題の 1 つであった「手動管理なインフラ」脱却のため、インフラリソースの管理は Terraform と Ansible、Helm を活用しています。

ニフクラのリソースは [terraform-provider-nifcloud](https://github.com/nifcloud/terraform-provider-nifcloud) を使いながらすべて Terraform で管理し、 VM の中身のプロビジョニングは Ansible で自前の role を作成して管理することとしました。
また、Kubernetes 上のコンポーネントについては、[GitLab が公開している Helm Chart](https://docs.gitlab.com/charts/) を利用しつつ、 複数の Helm Chart を宣言的に管理できる [Helmfile](https://github.com/roboll/helmfile) で各 Chart を管理するようにしています。

構築後のベンチマークとして、 GitLab が公式で公開している [GPT](https://gitlab.com/gitlab-org/quality/performance) を実施しました。具体的には 5000 人想定の負荷テストが All Green になるように、インフラのチューニングを実施しました。

# マイグレーション

## 事前準備

GitLab を HA 構成にするためには、 Gitaly が管理する Git リポジトリのデータ以外のアップロードされたファイル、コンテナレジストリのデータ等はオブジェクトストレージにアップロードしておく必要があります。 (詳細は [Object storage \| GitLab](https://docs.gitlab.com/ee/administration/object_storage.html))
移行前の構成はデータをすべてローカルのディスク上に保存していたため、これらのデータの移行の必要がありました。設定変更時に GitLab の再起動が必要ですが、移行処理自体はバックグラウンドで無停止で実行可能なため、マイグレーション前日までに移行を実施しておきました。

移行手順は公式のドキュメントに詳しく記載されています。

- https://docs.gitlab.com/ee/administration/raketasks/uploads/migrate.html
- https://docs.gitlab.com/charts/installation/migration/package_to_helm.html#migration-steps

また、Kubernetes クラスターや VM 等のインフラリソースも事前に実施しておいたほうが当日の手順が減るため、こちらも先に作成しておきました。

## 実施当日

当日 (某月の土曜日) は 0:00 から 18:00 まで GitLab を停止させる想定で告知を出し、 0 時から GitLab をメンテナンスモードに設定し、裏で `gitlab-backup create` コマンドによるバックアップを取得しました。

バックアップ取得完了後、 Kubernetes クラスターで稼働している task-runner Pod を使い、バックアップファイルからリストアを実施します。
Helm 版 GitLab ではバックアップ、リストアの実行が `backup-utility` というコマンドで実施することになるため、注意が必要です。 (https://docs.gitlab.com/charts/architecture/backup-restore.html#backup-utility)

我々の場合はここのリストア実施で問題が発生。 DB のリストア時にタイムアウトエラーが発生し、リストア処理を継続できなくなってしまいました。このときはだいぶヒヤヒヤしましたが、 Premium 以上のライセンスを契約していると受けることができる Emergency Support の話を事前に GitLab Inc. の担当の方から聞いていたため、当日はこのサポートを受けて対処を実施しました。 (https://about.gitlab.com/support/)

具体的には DB サーバーが稼働している VM の `/etc/gitlab/gitlab.rb` に下記の設定を追加し、 `gitlab-ctl reconfigure` してから再度リストアを実施することで、問題は解消しました。

```/etc/gitlab/gitlab.rb
postgresql["statement_timeout"] = "600000"
```

DB のサイズが 10 ~ 15GB 程度あったので、ある程度大きな環境の GitLab には必要だったチューニングなのかもしれません。

# 移行後

移行後はかなりドキドキしていましたが、ニフクラのインフラ構成に起因する一部の問題が発生しただけで、 GitLab としては今の所安定して稼働してくれています。

本番稼働後に一度、ニフクラの自動フェイルオーバー機能によって VM が再起動されたことがありましたが、特にエラーもなく GitLab は稼働してくれていました。

# まとめ

さて、今回は 500 人規模, データ総量 8TB のシングル構成 GitLab を HA 構成へマイグレーションする手順や構成、裏話について書いてみました。スモールスタートでシングル構成の GitLab を構築し、後々 HA 構成にしたくなったときに参考になればと思います。

最初にあげた課題に関しての振り返りは下記です。

- 手動管理なインフラ
    - → Terraform, Ansible, Helm によるインフラのコード管理化を達成
- インフラの老朽化
    - → ここはまだ戦い続ける必要があるが、 IaC 化によって対処しやすくなったはず
- シングル VM 構成
    - → HA 構成化による可用性・性能の向上を達成

今後については GitLab Geo を使った DR 構成について検討を進め、さらなる可用性の向上を目指していこうと思っています。

また、今回のマイグレーションにあたっては GitLab Inc. の皆様には移行計画段階から当日の Emergency Support まで多大なるサポートをしていただきました。非常に感謝しております。

こんなところで今回の記事は終わりにしておこうかなと思います。明日は @digfield さんが記事を書いてくれるみたいです。お楽しみに！