インターネットからアクセスできないリポジトリをAWS上に作成したい

# はじめに
この記事はDevOps on AWS大全 実践編の一部です。
DevOps on AWS大全 実践編の一覧は[こちら](https://qiita.com/tech4anyone/items/c27e74f9ae569ced259f)。

この記事ではプライベートGitリポジトリのアーキテクチャを決める流れを解説しています。

具体的には以下流れで説明します。

- 解決したい課題の整理
- 今回使うAWSサービスの整理
- アーキテクチャの策定
- 策定したアーキテクチャで達成できたこと

AWSの区分でいう「Level 400 : 複数のサービス、アーキテクチャによる実装でテクノロジーがどのように機能するかを解説するレベル」の内容です。

# この記事を読んでほしい人
- DevOpsエンジニアがアーキテクチャを決めるときにどのような思考フローを踏んでいるか知りたい人
- セキュアなGitリポジトリのアーキテクチャを知りたい人
- AWS Certified DevOps Engineer Professionalを目指している人

# 前回までの流れ
[こちら](https://zenn.dev/tech4anyone/articles/b6c4ef50597448)の記事で以下のアーキテクチャを策定しました。

![](https://storage.googleapis.com/zenn-user-upload/c88478fd0384-20231227.png)

# 解決したい課題の整理
現在、解決したいと思っている課題は以下になります。
- プロジェクトのポリシー上、インターネット上のサイトにソースコードを配置できないがGitリポジトリが欲しい
- Gitリポジトリのインフラストラクチャ部分は可能な限り管理したくない
- GitリポジトリでCICDパイプラインをトリガーできるようにしたい

ということで、これをどうやって解決するか考えていきましょう。

# 今回使うAWSサービスの整理
今回使う代表的なAWSサービスの概要とベストプラクティスを以下にまとめました。

## AWS Fargate
AWS Fargateとは、コンテナ化されたアプリケーションをサーバーレスに実行できるサービスです。
AWS Fargateは、Amazon ECSやAmazon EKSと統合されており、コンテナのプロビジョニングや管理を自動化してくれます。
AWS Fargateを使うと、コンテナの数や種類に応じて必要なリソースを自動的に割り当ててくれるため、サーバーやクラスターの管理に手間がかかりません。

## Amazon ECS
Amazon ECSとは、AWS上でコンテナ化されたアプリケーションを簡単に管理できるサービスです。
Amazon ECSは、DockerやKubernetesなどの標準的なコンテナオーケストレーションツールと互換性があります。
Amazon ECSを使うと、コンテナのスケーリングやロードバランシング、ヘルスチェックなどの機能を利用できます。
また、Amazon ECSは、AWSの他のサービスとも連携できるため、セキュリティやモニタリングなどの面でも強力なサポートを受けられます。

## Amazon EFS
Amazon EFSとは、AWS上でファイルシステムを提供するサービスです。
Amazon EFSは、NFSv4プロトコルに基づいており、複数のEC2インスタンスやコンテナから同時にアクセスできます。
Amazon EFSは、高い耐久性と可用性を持ち、パフォーマンスモードやスループットモードなどのオプションを選択できます。
また、Amazon EFSは、ライフサイクル管理やバックアップなどの機能も備えています。

## AWS Transit Gateway
AWS Transit Gatewayとは、AWS上で仮想的なネットワークハブを作成できるサービスです。
AWS Transit Gatewayを使うと、VPCやVPNなどの異なるネットワークリソースを一つの中央ポイントに接続できます。
これにより、ネットワークの複雑さや管理コストを削減できます。
また、AWS Transit Gatewayは、ルーティングテーブルやセキュリティグループなどの機能を利用して、ネットワークのトラフィックやアクセス制御を柔軟に設定できます。

## ベストプラクティス

| トピック | ベストプラクティス |
| --- | --- |
| AWS Fargate | - タスク定義にCPUやメモリなどのリソース要件を明記する<br>- タスクロールやタスク実行ロールを適切に設定する<br>- タスク間の通信にはサービスディスカバリやロードバランサーを利用する |
| Amazon ECS | - クラスター内のインスタンスやタスクの状態を定期的に監視する<br>- サービス定義にデプロイメント設定やヘルスチェック設定を行う<br>- コンテナイメージのバージョニングやレジストリ管理を行う |
| Amazon EFS | - ファイルシステムのパフォーマンスモードやスループットモードを用途に応じて選択する<br>- ファイルシステムへのアクセス制御をセキュリティグループやNFSクライアント設定で行う<br>- ファイルシステムのライフサイクル管理やバックアップを有効にする |
| AWS Transit Gateway | - ルーティングテーブルやルートプロパゲーションを利用してネットワークのトポロジーを設計する<br>- セキュリティグループやネットワークACLを利用してネットワークのアクセス制御を行う<br>- ネットワークのパフォーマンスやコストを最適化するために、トランジットゲートウェイピアリングやインターリージョンピアリングを利用する |

# アーキテクチャの策定
ここからはやりたいことを順番に考えながらアーキテクチャを策定していきます。

## プライベートなネットワーク内にGitリポジトリが欲しい
まず、一番大きな問題であるインターネット上はNGだがGitリポジトリが欲しいという課題を解決していきます。
GitリポジトリというとGitHubやBitBucketなどSaaS型、つまりインターネット上にリポジトリを置くことが通常です。

しかし、プロジェクトによってはセキュリティ要件を満たせないという理由でインターネット上にリポジトリを置くことができません。
そういった場合には、ローカルインストールでGitリポジトリを構築できるGitLabを採用します。
なお、AWS CodeCommitはIssueの管理などがしずらいので実プロジェクトでの運用に耐えられず不採用としています。

さて、GitLabのリポジトリをAWS内に構築するのは良いですがどのように構築すればよいでしょうか。
ここは、AWSのベストプラクティスに沿ってFaaS、CaaS、IaaSの順で検討していきましょう。

まずFaaS、つまりLambdaですがこれは常設されるアプリケーション向きではないので不採用です。
続いて、CaaSつまりコンテナ系ですがコンテナ系の中ではECS on Fargate、EKS on Fargate、ECS on EC2、EKS on EC2の順で検討していきます。
これはFaaSからIaaSの順で検討するとの同じで運用工数がより少ないもの、つまりクラウドネイティブに近いものから検討していくという考え方です。

今回の場合には、ECS on Fargateで満たせない要件は特にないので素直にECS on Fargateを採用します。
CICDをやるとChatOpsをしたくなるのでGitLabと親和性の高いチャットツールであるMattermostも一緒にインストールすると以下のようなアーキテクチャ図になります。

![](https://storage.googleapis.com/zenn-user-upload/2fc3ce412e95-20231227.png)

## プライベートサブネットにあるFargateからDockerイメージをプルしたい
ECS on FargateにGitLabリポジトリを構築するのは決まりましたが、コンテナを構築するためにはイメージを管理するリポジトリが必要です。
そのため、ECRを採用しますが、今回は外部からのアクセスを防ぐためにECS on Fargateをプライベートサブネット内に構築しています。

ということは、ECRにはインターフェース型エンドポイント経由でアクセスする必要があります。

これらをまとめると以下のようなアーキテクチャになります。

![](https://storage.googleapis.com/zenn-user-upload/4037763b471c-20231227.png)

## GitLabリポジトリとして使うために永続ボリュームが欲しい
ECS on FargateにGitLabリポジトリを構築しましたが、ECS on Fargateはコンテナなのでコンテナが落ちるとボリュームが揮発します。
しかし、GitLabリポジトリとして使うのであればボリュームが揮発するとソースコードが消えてしまい大事故です。

そこで、EFSをECS on Fargateにマウントしてここを永続ボリュームとして使います。
なお、ECR同様、プライベートサブネットからアクセスするためにインターフェース型エンドポイントが必要です。

これらをまとめると以下のようなアーキテクチャになります。

![](https://storage.googleapis.com/zenn-user-upload/9da99ce088f1-20231227.png)

なお、本当であればコストの観点からS3をマウントしたいところですが今のところFargateにS3マウントはできないためEFSを採用しています。
逆に、S3をマウントするために on EC2タイプを採用する可能性も考えられますが、運用工数の増加分に対してボリュームコストの減少分が小さすぎるので今回はECS on FargateにEFSをマウントします。

## 作成したGitLabリポジトリにAmazon WorkSpacesからつなげるようにしたい
ここまで、GitLabリポジトリを作るためのECS on Fargateと関連サービスを組み合わせてきましたが、[前回](https://zenn.dev/tech4anyone/articles/b6c4ef50597448)作ったAmazon WorkSpacesと別のVPCにたてているため、このままではAmazon WorkSpacesからつなげません。

ちなみに、同じVPC内に作るというアーキテクチャも考えられますが、セキュリティや誤操作防止の観点からVPCは用途ごとに切ることをおすすめします。

本題に戻るとAmazon WorkSpacesがあるVPCとGitLabリポジトリがあるVPC間で通信ができるようにするためにVPC PeeringあるいはTransit GatewayでVPC間をつなぎます。

普通だと、コストの観点からVPC Peeringを採用するのですが、今回はVPCが増えていく可能性を考慮して拡張性を重視します。
この辺はプロジェクト計画をたてるときに、どこまで続くプロジェクトなのかを考えつつ拡張性とコストの天秤を考える必要があります。
ただ、私個人の経験だと拡張性を持たせたアーキテクチャのほうが結局、将来の改修が容易になりやすくなるという感覚です。

これらをまとめると以下のようなアーキテクチャになります。

![](https://storage.googleapis.com/zenn-user-upload/e28bd0369d9d-20231227.png)


## CodePipelineでパイプラインを組むためにCodeCommitとGitLabを連携したい
ここまででAmazon WorkSpacesからプライベートなGitLabにつなげられるようになりましたがここで一つ大きな問題があります。

CodePipelineでソースとしてサポートされているGitLabはSaaS版のみなのです。
ということは、GitLabをどうにかしてCodeCommitに連携してあげないとGitLab起点でCodePipelineを動かすことができません。

そこで、やむを得ずですがGitLabリポジトリをCodeCommitリポジトリにミラーリングすることにします。
二重でリポジトリを持つような形になるため本当は美しくないですがセキュリティとメンテナンス容易性を考えるとこれが一番です。
なお、GitLab RunnerをAWS内に構築するという手もありますがやはりAWSのCode三兄弟を使ったほうが管理工数が少なく楽になるのでGitLab Runnerなどの採用は見送ります。

これらをまとめると以下のようなアーキテクチャになります。

![](https://storage.googleapis.com/zenn-user-upload/2035eb2b5d05-20231227.png)

# まとめ
本記事ではインターネットからアクセスできないリポジトリをAWS上に作成し、Amazon WorkSpacesからつなぐ方法をまとめました。

今回策定したアーキテクチャで実現できたのは以下の項目です。
- AWS内のプライベートサブネットにGitLabリポジトリを構築する
- GitLabリポジトリはFargate上に構築し、運用管理工数を極小化する
- Amazon WorkSpacesからプライベートサブネットのGitLabリポジトリに接続する
- GitLab起点でCodePipelineを動かせるようにする

次回はCICDパイプラインの作成を考えてみたいと思います。