AWS上でGitLabを運用する際、マネージドサービスを利用することに関する考察

# 概要
パブリッククラウド上でGitLabを構築する際、PostgreSQLやRedis等をデフォルト設定のまま利用するか、マネージドサービスを利用するか検討し、マネージドサービスを使う場合どのように利用するべきか考える必要があります。当記事ではAWS上で複数のGitLab環境を構築・運用してきた経験から、マネージドサービスをどのように利用すべきかどうかの考察をします。


# 前提
GitLabにはOmunibus版やDocker版、k8s(helm)版と複数の構築方法があります。当記事ではk8s(helm)版をAWSのEKS上で構築・運用する前提とします。VM上にOmunibus版で構築する場合やECS上にDocker版で構築する場合は、当記事とは異なる考察結果になるかと思うのでご注意ください。

# 構成図
GitLabのアーキテクチャの構成図は以下になります。[^画像の引用元]
[^画像の引用元]: 画像の引用元：https://docs.gitlab.com/ee/development/architecture.html#simplified-component-overview

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697481/83a01e9b-61a7-8fe4-08ef-04c78d5e7686.png)

この中から、マネージドサービスの利用を検討すべきポイントは以下３点になります。
 - PostgreSQL 
 - Redis 
 - Object Storage　（※上記図には表現されていません）

# PostgreSQL

k8s(helm)版で構築するのであれば、ディスク拡張等の運用負荷が軽減できるのでRDSにするべきです。また、可用性を高めたい場合は、RDSをマルチAZ構成にすることで対応も可能です。

ポイントとなるのがサイジングになります。公式ドキュメントにはRDSがどの程度のインスタンスサイズにするべきか書いていません。結論からいうと"db.t3.small"(2vCpu, Memory2GB)のサイズで問題ないと考えています。以下1000人程度の利用者がいるGitLab環境でのリソース消費状況です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697481/0bea0a9d-2b04-7fd2-a850-95d145d4db29.png)

リソースに余裕があることが分かるかと思います。largeサイズ(2vCpu, Memory8GB)等で構築して、AWS利用料を過剰に支払うことはないようにしていただけるとよいかと思います。

### 余談
AWSではなくAzure上でGitLabを構築したとき、AzureのDBマネージドサービスであるAzure Database for PostgreSQL(単一サーバ版)が11までしておらず（2021年12月時点)、GitLab14系でサポートされてるPostreSQL 12が利用できませんでした。また、PostgreSQL12以降がサポートされているフレキシブルサーバ版はパブリックプレビューのため、本番環境利用には適してない状況でした。
パブリッククラウドにこのような制約がある場合は、マネージドサービスを使わずディスク上にPostgreSQLを構築せざるを得ないと思います。。

https://docs.microsoft.com/ja-jp/azure/postgresql/flexible-server/concepts-compare-single-server-flexible-server

# Redis
GitLabではRedisにCacheやジョブのキュー、セッションなどが格納されています。
https://docs.gitlab.com/ee/development/redis.html

Redisをマネージドサービスを使う場合、Elastic Cacheを利用することになります。ここでもポイントとなるのがサイジングです。GitLab公式ドキュメントでは"cache.t3.medium"(2vCpu, Memory3.09GB)が推奨されております。
https://docs.gitlab.com/ee/install/aws/manual_install_aws.html#create-the-redis-cluster

しかし、月あたり8,500円のAWS利用料がかかります。実はGitLabのRedisはあまりリソースを消費しません。
300人程度の利用者がいるGitLab環境(上述のPostgreSQLの例で出した環境とは別環境)でElastic Cacheを"t3.cache.small"(2vCpu, Memory1.37GB)にして運用したリソース消費は以下になります。（時刻表示がUTCなので+9時間だと考えてください)

![redis.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697481/b8b00866-79f2-ef9f-1f22-261d25650fb2.png)

あまりリソースを消費してないのが分かるかと思います。したがって、500人以上の大人数の利用またはお金に余裕がある場合は環境の場合は公式ドキュメント通り、"cache.t3.medium"で構築するべきですが、そうでない環境の場合はElastic Cacheを使わずRedis Podを使うか、Elastic Cacheを使う場合はsmall以下のサイズで構築したほうがコスト対効果が出てくると考えています。


# Object Storage

Object Storageにはジョブの実行結果であるArtifactsやマージリクエストの差分等が格納されます。

https://docs.gitlab.com/ee/administration/object_storage.html

マネージドサービス云々というより、Object Storageの方式は複数あります。方式評価は以下だと考えています。

| 方式 | 安定性 | 運用負荷 | AWS利用料 | 
| ---- | ---- | -- | -- | 
| S3 | △ |〇 | 〇 | 
| MinIO+EBS | 〇| △ | 〇 | 
| MinIO+EFS | 〇 | 〇 | △ |

### S3
k8s(helm)版では容量拡張性やコストを考え、当初はS3で運用していました。しかし運用期間が長くなるにつれ、パイプライン（ジョブ）でArtifactsのアップロードがタイムアウトによるエラーや、マージリクエストの差分がタイムアウトにより閲覧できないエラーが増えてきました。このエラーはGitLab本体側でも対応されてるのかよく分からない状況であり[^2]、S3の仕様上回避するのが難しい問題だと考えてます。そのため、現在ではエラーを回避するため後述するminIO+EFSの構成にしています。
[^2]: GitLab公式のIssueの例: https://gitlab.com/gitlab-org/gitlab-foss/-/issues/65730


### MinIO+EBS

VM上にOmunibus版で何も考えずに構築するとこの方式になります。パイプラインが多く実行される場合、パイプライン(ジョブ)の実行結果のデータが蓄積して、EBSのディスクをひっ迫しやすいです。ディスク拡張の運用が手間になるのであまり推奨しません。

### MinIO+EFS

パイプライン（ジョブ）でArtifactsのアップロードも安定し、かつディスク拡張も自動で行われ運用が楽になる方式になります。唯一の弱点はAWS利用料です。AWS利用料がかからないように、一定期間過去のArtifactsは自動削除する設定をするべきです。

MinIO+EFS方式ではEFSの性能劣化したことがあり、そのときはパイプラインが高頻度でEFSへのファイル入出力があったためでした。スループットモードを「バースト」から「プロビジョニング」に切り替えたことで対応してます。ただしAWS利用料が増えてしまうので、性能問題が出ない限りこの対応は不要かと考えています。

なお、GitLab公式ドキュメントではEFSの利用は推奨されてないので、EFS利用する場合は自己責任でお願いします。
https://docs.gitlab.com/ee/administration/nfs.html#avoid-using-cloud-based-file-systems


# まとめ
AWS上でGitLabを運用するする際、どのようにマネージドサービスを利用するべきかを考察しました。GitLab公式ドキュメントではマネージドサービス利用に関する情報は乏しく、実運用しないと分からない部分が多々あります。GitLabの最適なマネージドサービスの利用方法を今後も追及していきたいと思います。

# 参考URL