AWS Fargateについて深掘りしてみた

# 

## イントロダクション
皆さんはコンテナを使用していますか。
AWSでコンテナをホストするサービスとしてはECS、EKSが挙げられると思います。
その両方のサービスでノードの選択肢として利用できる選択肢としてAWS Fargateがあります。
この記事ではそのAWS fargateに焦点を当て、AWS fargateの基盤技術まで深掘っていこうと思います。
低レイヤーによった話かつ、開発者には必要のない事も含まれかもしれませんが物好きな方は付き合っていただけると幸いです。

## AWS Fargateの概要
AWS Fargateはそれ単体で動作するサービスではなく、ECSやEKSのデータプレーンとして利用できる選択肢の一つです。
その他の選択肢となるEC2と大きく異なる点は、AWS FargateはAWSマネージドな基盤である事です。
そのためアプリケーションの開発・運用においてサーバを意識する機会が少ない、所謂サーバレスな基盤です。

スケールアウトが必要な時に自動的に作成され、スケールインのタイミングで自動的に削除するようなことが可能で、
基盤のOSまでのレイヤーはAWSの責務となっているため、セキュリティパッチの適用などの運用作業が不要となります。
さらにリソースの利用料金はノードのスペックに起動時間を乗じた従量課金のため、料金が実際の利用状況に最適化されるというメリットもあります。

このようにメリットが多いAWS fargateですが、ECSやEKSのデータプレーンとして常に正解な選択肢というわけではなく、
同一スペックのEC2と比較したコストが高価である点や、サーバレス特有の仕様（起動時に毎度コンテナイメージ取得が必要やノードへの接続が手間、他にも複数）もあります。
実際にAWS fargateを採用するかはアプリケーションの運用体制や特性に応じて選定する必要がありますがこの記事では特に触れません。




## AWS Fargateのアーキテクチャ
ここからは、コントロールプレーンがECSの時にデータプレーンとしてAWS Fargateがどのように利用されるのか深掘りしてみます。
### RunTaskAPIとCreateServiceAPI
AWS Fargateの説明に入る前にECSを構成するAPIについてざっくり調べてみました。
以下の記事を参考にしています。

https://aws.amazon.com/jp/blogs/news/the-role-of-aws-fargate-in-the-container-world/


ECSは図のように「RunTaskAPI」と「CreateServiceAPI」の2つのAPIで構成されています。
RunTaskAPIは、クラスターの仮想マシン上で1つ以上のコンテナを持つタスクというリソースを定義・実行するために使用される一方で、CreateServiceAPIはECS内でアプリケーションの可用性とスケーラビリティを保証するために、指定された数のタスクを継続的に実行し、維持するために使用されます。
RunTaskAPIは低レイヤーなインフラ層を抽象化しているのに対して、CreateServiceAPIはより高レベルなアプリケーションの抽象化を行なっているAPIとして表現されていました。
<img width="90%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031771/ce5cb1f9-8c28-a618-2b4b-90b8f16f4fd4.png">


AWS Fargateが利用されるのは、この「RunTaskAPI」を```-launch-type:FARGATE```フラグとともに使用した時です。
これは利用者が直接「RunTaskAPI」を実行する以外にも、「CreateService」APIを使用してECSサービスを作成した際にも実行されます。
上記の図のように「RunTaskAPI」が実行された際にクラスターを構成するEC2でのコンテナ実行の代替として、コンテナを実行する巨大なリソースプールとして利用できるサービスがAWS Fargateとなります。




### RunTask APIのフロー
次にRunTaskAPIが実行された後のフローを調べてみます。
参考としてre:Invent2019のセッションを見てみます。

https://www.youtube.com/watch?v=Hr-zOaBGyEA

RunTaskAPIがAWSのエンドポイントにリクエストされると、ECSのコントロールプレーンではリクエストの内容を基に以下のフローに沿って自動的にAWS fargateの起動や削除が行われるようです。

1. RunTaskAPIのエントリーポイントで認証認可やリミット制限をチェック
1. 必要な仮想マシンのキャパシティ確認を行う
1. Fargate AgentのActivateを行い、Fargateを起動する
1. タスク定義の内容を基に初期化が開始される

<img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031771/9f15468a-275b-aacd-8b95-7baaf82eb136.png">

### Fargate Data Plane
上記のフロー図で記載したようにRunTaskAPIがリクエストされると、タスク実行に必要な仮想マシンがAWS fargateとして利用者のVPCで利用できるようになります。
この時、AWS fargateの仮想マシンは利用者のVPCに直接配置されるのではなく、専用のVPCに作成されたEC2インスタンスの上で実行されており、そこから利用者のVPCにENI(ネットワークインタフェース)を伸ばす形でアクセスしているようです。
この時、AWS fargateのコンテナランタイムまでの層はAWSが責任を持つため利用者が意識する必要はありません。利用者はAWS fargateの上で実行するコンテナイメージのみに気を配れば良いのです。
<img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031771/298c622f-7b7c-2cd7-e4b9-00b6d5bfc95d.png">






## AWS fargateの実行基盤
前段の記事でAWS FargateがAWSが管理するEC2の上で実行されていることが分かりました。
ではどのように大量のコンテナをEC2に割り当て、互いに隔離しセキュリティを担保した状態で高速に起動しているのでしょうか。
AWS Fargateの基盤ではfirecrackerというAWSが開発した軽量の仮想マシン（micoroVM）が使用されているようです。
（firecrakerはAWS Lambdaの実行基盤としても利用されています）

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031771/fbca4531-e28e-599c-c3f9-4e462c0ced89.png">

https://github.com/firecracker-microvm/firecracker

firecrakerはコンテナの実行に特化した軽量な仮想マシンです。
起動速度にフォーカスして開発されているようで、125ミリ秒以下で仮想マシンのゲストOSのLinuxコードを起動し、1ホストあたり150個のmicroVMを1秒以下で起動できるとのことです。

AWS fargateはこのfirecrakerのmicroVMの上でECSタスクコンテナを起動して処理を行っているようです。
AWS fargateを利用する場合、同一EC2インスタンスの上で複数のAWS fargateが起動されるため、異なるテナントのコンテナが同一EC2インスタンスに共存することになります。
図のようにEC2の上で直接タスクコンテナを実行するのではなく、microVMの層を持たせることでその上のゲストOS、カーネルが互いに隔離され、マルテテナントで実行される環境のセキュリティ向上が行なわれているようです。

<img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031771/50be21e7-08ac-5f5d-ed99-fd46a5f2c142.png">








## さいごに
今回はAWS fargateについて深掘りしてみました。
私は普段ECS+fargateを利用したサービスの開発を行っているため、本記事を書くにあたってAWS fargateの裏側の技術について入門できてfargateへの愛着が強くなりました。
記事の中で触れたfirecrakerについては、OSSとして公開されているので個人のラップトップPCやRaspberryPiなどで動作させることが可能です。
次の記事ではfirecrakerの動作検証をしてみたいと考えています。