AWS FargateのIPアドレスを固定化してみる

#はじめに
機械学習APIを公開するため、AWS Fargateを利用しようと考えています。
なぜFargateを使うかというと、サーバーやクラスターの管理をAWSに任せることができるので、デプロイとその後の運用が非常に楽だからです。
しかし、FargateでAPIを運用する時、１点大きな問題にぶつかりました。
Fargateタスクに対して直接Elastic IPを割り当てることができないのです。
このままでは、IPアドレスが動的に変化してしまうので、機械学習APIにうまくアクセスできなくなる可能性があります。
そこで今回は、FargateとNetwork Load Balancer（NLB）を組み合わせることで、IPアドレスを固定化し、この問題を解決します。

#目次
1.アーキテクチャ
2.VPCの設計
3.Network Load Balancerの作成
4.Fargateサービスの作成
5.確認

#1.アーキテクチャ
いきなりですが、まずは今回のアーキテクチャをお見せします。

![図1.png](https://qiita-image-store.s3.amazonaws.com/0/247957/eeda6d0d-04c1-2192-e7d4-eb0e4e074793.png)

「FargateのIPアドレスを固定したい」という要望が特になければ、Fargateタスク横のElastic Network Interface（ENI）にPublic IPを割り当てて、システムを構築することも可能です。
しかし、「FargateのIPアドレスを固定したい」場合、現状のFargateはElastic IPを付与できない仕様になっているので、一工夫が必要になります。
そこで今回は、Fargateタスクと同じサブネット内にNetwork Load Balancerを追加し、そこにElastic IPを割り当てることで、問題を解決することができました！
それでは、上記アーキテクチャの構築手順についてご説明します。

#2.VPCの設計
まずはVPCを設計します。
[サービス]→[VPC]→左列の[VPC]→上部の[VPCの作成]を選択します。
「sample-vpc」という名前でVPCを作成します。

<img width="626" alt="スクリーンショット 2018-07-16 14.11.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/247957/a93e5a0d-763d-ad37-9540-7e7b594b6adf.png">

続いて、左列の[サブネット]→上部の[サブネットの作成]を選択します。

![図1.png](https://qiita-image-store.s3.amazonaws.com/0/247957/0e5184cc-3033-be9b-b998-015efb927083.png)

次に、インターネットゲートウェイを用意します。
左列の[インターネットゲートウェイ]→上部の[インターネットゲートウェイの作成]を選択します。
名前は「sample-gateway」としておきます。

<img width="505" alt="スクリーンショット 2018-07-16 14.33.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/247957/a8c5324e-4cc7-a4c2-3b3a-7ce48c966310.png">

ゲートウェイを作成するだけでは、デタッチ状態です。
これをVPCにアタッチするため、「sample-gateway」を選択し、上部の[アクション]から[VPCにアタッチ]を選択します。
ここで「sample-vpc」→[アタッチ]を選択します。

続いて、左列の[ルートテーブル]を選択すると、「sample-vpc」のルートテーブルがあります。
このチェックボックスを押した状態で、下部の[ルート]→[編集]→[別のルートを追加]で送信先とターゲットにインターネットゲートウェイの情報を追加します。

![図1.png](https://qiita-image-store.s3.amazonaws.com/0/247957/7cd99af8-f91d-b63a-5b25-ba04d4367b4e.png)

[サブネットの関連付け]に移動し、[編集]→「sample-subnet」の[関連付け]にチェック→[保存]を選択します。
以上でVPCの設計は完了です。

#3.Network Load Balancerの作成
[サービス]→[EC2]→左列の[ロードバランサー]→上部の[ロードバランサーの作成]→中央のNetwork Load Balancerの[作成]を選択します。
まずステップ１では、名前を「sample-NLB」とし、スキームは「インターネット向け」とします。

<img width="574" alt="スクリーンショット 2018-07-16 14.49.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/247957/e43cda5e-da3b-a44e-3fe1-96021d7a6a4a.png">

アベイラビリティ−ゾーンでは、「sample-vpc」を選択し、予め作成しておいたElastic IPを割り当てます。

![図1.png](https://qiita-image-store.s3.amazonaws.com/0/247957/e8ae15a9-9dc4-2731-10e6-b2812036852d.png)

ステップ２では、ルーティングの設定を行います。
「sample-targetGP」という名称で新しいターゲットグループを作成します。
また今回は、サーバーレスアーキテクチャとなるので、ターゲットの種類を「ip」としておきます。

<img width="739" alt="スクリーンショット 2018-07-16 14.59.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/247957/d53a1312-d2b3-681f-7fa0-994022667d09.png">

ステップ３のターゲットの登録は、飛ばします。
まだFargateサービスを作成する前なので、機械学習APIのIPアドレスも決まっていないからです。
最後にステップ4の確認で[完了]を選択すると、Network Load Balancerの作成が完了します。

#4.Fargateサービスの作成
最後に、Fargateサービスを作成します。
AWS Elastic Container Serviceから、
①リポジトリの作成
②タスク定義の作成（タスク名：「sample-task」）
③クラスターの作成
を行います。
なお、①②の詳細な手順は、下記URLに記載されているので、こちらをご確認下さい。
https://qiita.com/oyngtmhr/items/45a0d3158e6dccb0882d

今回は、③の手順について説明します。
まず、左列の[クラスター]→上部の[クラスターの作成]を選択します。
クラスターテンプレートは「ネットワーキングのみ」とします。

<img width="734" alt="スクリーンショット 2018-07-16 15.19.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/247957/9377a746-a729-35d8-9d80-eeb0455d356b.png">

名前は「sample-cluster」とし、クラスターを作成します。
作成後の画面から、[サービス]→[作成]を選択し、ステップ1のサービスの設定を行います。

<img width="795" alt="スクリーンショット 2018-07-16 15.26.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/247957/a9c90c29-f41b-239b-b268-21b338022d09.png">

ステップ2では、ネットワーク構成を決めます。
クラスターVPCには「sample-vpc」、サブネットには「sample-subnet」を設定します。
また、セキュリティーグループの設定では、[インバウンドのルール]の[ソース]にVPCのCIDRブロック「10.0.0.0/16」を記載します。
この設定により、FargateはNLBからのトラフィックのみを許可することができます。
続いて、Elastic Load Balancing（オプション）で、「Network Load Balancer」を選択し、ELBには「sample-ELB」とします。
負荷分散用のリスナーポートを設定しておきます。

ステップ3のAuto Scalingは適宜仕様に合わせて設定しますが、今回は「サービスの必要数を直接調整しない」を選択します。
最後に[サービスの作成]を選択して、Fargateサービスの作成が完了します。

#5.確認
[サービス]→[EC2]→左列の[ターゲットグループ]を選択します。
「sample-targetGP」のボックスにチェックを入れ、下部の[ターゲット]を選択すると、登録済みターゲットが記載されています。

![図1.png](https://qiita-image-store.s3.amazonaws.com/0/247957/ed3e2350-4c68-2a66-a0a8-301c557822a5.png)

登録済みターゲットのIPアドレスが、FargateタスクのIPアドレスと一致しており、ステータスが「healthy」となっていればOKです。
FargateタスクのENIに付与されているPrivate IPを、ターゲットとして手動で登録することも可能です。
NLBに付与したElastic IPに入力データをPOSTすると、Fargate上の機械学習APIが起動し、推論結果が返ってきます。

#おわりに
Fargateタスクに直接EIPを付与できない問題に直面しましたが、NLBを活用することで解決できました！
色んなAWSサービスを使いまくって、定期的にTipsを発信できれば良い感じですね！
こちらの記事が参考になった方は、
是非「いいね」を頂ければ幸いです！