【AWS】EKS on Fargateでゲームをデプロイしてみたので解説してみる（with Ingress Controller, 2048）vol.1

# はじめに
[AWS re:Invent 2019](http://reinvent.awseventsjapan.com)にて`EKS on Fargate`が発表されました。
もう3ヶ月くらい前ですが。。

その`EKS on Fargate`を使ってみましたので、使い方とその解説をしてみようと思います。（タイトル通り）

また、操作画面のスクショを貼っているのですが、
記事が非常に長くなってしまうため、一部折りたたんでいます。

想像以上に作成に時間がかかってしまい、2部作で展開します。
完全に私の力不足です。。

# EKSとは
<details><summary>[AWS公式](https://aws.amazon.com/jp/eks/features/)より</summary><div>

> Amazon Elastic Kubernetes Service

> AWSでKubernetesを簡単に実行できるマネージド型のKubernetesサービスです。
</div></details>

`Kubernetes`をよしなに管理してくれるサービスです。（雑）
`ECS`(Elastic Container Service)というDockerコンテナを管理するサービスがあるのですが、
そのKubernetes版と考えています。（私感）

# Fargateとは
<details><summary>[AWS公式](https://aws.amazon.com/jp/fargate/)より</summary><div>

> コンテナ向けサーバーレスコンピューティングエンジンです。

> サーバーのプロビジョニングと管理が不要になります。

> インスタンスの選択やクラスター容量のスケーリングなしに、適切なコンピューティング容量が割り当てられます。
</div></details>

コンテナを稼働させるサーバーをよしなに管理してくれるサービスです。

`ECS` or `EKS`を使用する際に、サーバーを`EC2` or `Fargate`から選択することができます。
選択されたサーバー(`EC2` or `Fargate`)の上で、サービス(`ECS` or `EKS`)で管理するコンテナが稼働することになります。

`EC2`を選択した場合、この`EC2`の起動・停止やスケーリングは、ユーザーが設定・管理しなければなりません。
一方`Fargate`を選択した場合、サーバーの管理等が必要なくなります。

少しまとめると、コンテナサービス利用の選択肢としてはこの4択になります。

1. ECS + EC2
2. ECS + Fargate
3. EKS + EC2
4. EKS + Fargate

デプロイするアプリやサービスの特性によってこの4択から最適なものを選ぶ必要がありますね。

長くなってしまいましたが、`4. EKS + Fargate`を当記事では扱います。


# 当記事でのゴール
EKS on Fargateを使って、
2048ゲームをデプロイして遊べるようにしたいと思います。

2048とはこのようなゲームです。
きっと皆さん見たこと、遊んだことのあるゲームだと思います。

![2048_play.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/420b02ce-aae0-d4dc-ad72-6a4f2841a531.gif)


# 前提条件
- AWSのアカウントを所持している
- macOS
- `eksctl`コマンドではなく、マネジメントコンソールを使用して構築する
    - サービスの理解を深めるため

実際には`eksctl`コマンドで一発でクラスターを作成できたりします。

```
$ eksctl create cluster
```

それでは何もわからないまま終わってしまうので、
一つ一つ解説を入れながらマネジメントコンソールで作っていきたいと思います。

# 全体の流れ
1. クラスターの作成
2. Fargateプロファイルの作成
3. `kubectl`コマンドでサービスをデプロイ


# 1. クラスターの作成
まず初めにクラスターを作成します。
クラスターとは以下の2つの要素で構成されています。

- EKSコントロールプレーン
    - Kubernetesソフトウェアを実行してくれるやつ
    - EKSエンドポイントを持っています（後で利用します）

- EKSワーカーノード
    - コンテナを立ち上げるサーバー
    - これをFargateであれこれよしなにやってもらいます

では実際に作成してみましょう。

## 1.1. （一般設定） クラスター名とIAMロールの設定

[AWSマネジメントコンソール](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=2ahUKEwjsy9jZ2dXnAhWPyosBHeR5AP4QFjAAegQIBxAC&url=https%3A%2F%2Faws.amazon.com%2Fjp%2Fconsole%2F&usg=AOvVaw1yVeaToVi2rj68q1N4C5sx)からEKSのサービスを選択します。
そして左のメニューから、「EKSクラスター」 > 「クラスターを作成」を選択していきます。

<img width="360" alt="スクリーンショット 2020-02-16 18.01.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/41cd1897-7905-17bc-0692-2a8856e5f52d.png"> >>> <img width="360" alt="スクリーンショット 2020-02-16 18.03.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/ad36b27a-79ba-1f0b-d003-b5b9b420b9a1.png">

まずは一般設定として、以下の項目を設定します。

- クラスター名
- Kubernetesバージョン（デフォルトのままでOK）
- IAMロール

該当するIAMロールが存在しない場合、新規に作成する必要があります。

**（2020 3/30追記）**
ここでのIAMロールは、EKSとKubernetesコントロールプレーンに与える権限を設定します。
主な権限は、EC2とELB（ロードバランサー）の操作権限です。

<img width="360" alt="スクリーンショット 2020-03-08 13.41.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/c8253334-2602-ad82-9bba-928c94ff57bc.png">


## 1.2. IAMロール作成（未作成の場合）
<details><summary><font color="Red">**以下、IAMロールが未作成の場合に実施してください**</font></summary><div>

---

一般設定の「ロール名」を選択することで、別タブにIAMロール作成画面が表示されるので、**「ロールの作成」**を選択します。

<img width="360" alt="スクリーンショット 2020-03-08 13.42.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/2b392471-b38f-2961-4ce4-b3b4e87ca982.png">

次にロール作成画面にて、
**「AWSサービス」 > 「EKS」 > 「EKS」 > 「次のステップ：アクセス権限」> 「次のステップ：タグ」**
と選択していきます。

<img width="360" alt="スクリーンショット 2020-02-16 18.37.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/b90eca28-e856-5047-bc08-40b2391c492d.png"> >>> <img width="360" alt="スクリーンショット 2020-02-16 18.39.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/07943f20-744a-2568-0296-202dbde42ccd.png">

タグにロールの名前を設定して、「次のステップ：権限」を選択します。
次のページでロール名を入力してから「ロールの作成」を選択することで、EKSクラスター用のIAMロールが作成されます。

<img width="360" alt="スクリーンショット 2020-02-16 18.47.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/9021b02c-33c7-3bd5-8f1d-d8def9333450.png"> >>> <img width="360" alt="スクリーンショット 2020-02-16 18.49.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/180e6668-a35a-766a-0361-20f61a690baf.png">

---

</div></details>

## 1.3. プライベートサブネット作成（未作成の場合）
次のチャプターでクラスターのネットワーク設定を行うのですが、
Fargateに設定するためのプライベートサブネットが最低1つ必要になります。

作成したことがない場合、以前の記事で解説していますのでそちらを参照ください。
[【AWS】プライベートサブネット3分クッキング（ハンズオン）](https://qiita.com/hesma2/items/db0913dff8b041dc89d1)

またパブリックサブネットとプライベートサブネットの違いについても、以前の記事で解説しています。
[【AWS】パブリックサブネットとプライベートサブネットの違いとは](https://qiita.com/hesma2/items/29db7ccb8678a84d267a)


#### **（2020 3/30追記）**

今回はIngress Controllerを使用します。
Ingress ControllerによってALB（ロードバランサー）が作成されるのですが、このALBは **最低2AZ（アベイラビリティゾーン）** にまたがる必要があります。
そのため、ここでは最低2つ、AZの異なるプライベートサブネットを用意ください。
NATゲートウェイは共用で構いません。



## 1.4. ネットワーク設定
EKSクラスターのネットワーク設定では、以下を設定する必要があります。

- VPC（1つのみ)
- サブネット（最低2つのAZ）
- セキュリティグループ

AWSアカウントにはデフォルトのVPCと、
それに付随するパブリックサブネットが3つとセキュリティグループが1つ、
既に作成されていると思います。（私はありました）

また、Fargateに設定するためのプライベートサブネットが最低1つ必要になります。
今回私は以下を設定しています。

- デフォルトのVPC
- デフォルトのパブリックサブネット2つ(複数AZ)、プライベートサブネット ~~1つ~~ **2つ(複数AZ)**
- ~~デフォルトのセキュリティーグループ~~

<img width="360" alt="スクリーンショット 2020-03-08 13.45.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/7bee5317-3312-94b3-2e6c-ec78a3886648.png">


EKSクラスターに設定すべきセキュリティグループについては、
[Amazon EKS セキュリティグループの考慮事項](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/sec-group-reqs.html)
に記載されています。
<img width="480" alt="スクリーンショット 2020-02-16 22.44.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/0e67f91b-8207-e3be-7ce7-b4d36bc1a280.png">
これはVPCのデフォルトセキュリティグループと同等の設定なので、問題ありません。

また、APIサーバーエンドポイントのプライベート/パブリック設定ですが、
自分のPCから`kubectl`コマンドを使って操作する必要があるため、パブリック設定をONにしています。

セキュリティを考えるのであれば、同じVPC内にEC2を立ててそこから操作するべきなのかもしれません。

#### **（2020 3/30追記)**
2点修正点があります。

1. プライベートサブネットは2つ(複数AZ)を設定する
2. セキュリティグループの設定は必要ない

1点目は上記でも記載していますが、ALBを使用する際に必要になるためです。
2点目に関しては、ここでのセキュリティグループは追加で必要な時に設定するようです。
クラスターのセキュリティグループは自動で設定されます。

## 1.5. ロギング、タグ設定
Loggingは全て無効化のままで良いです。
必要なものを有効化することで、CloudWatchにログが送られるので、興味があったら設定してみてください。

Tagsにはクラスターの名前を設定します。
「Add tag」を選択すれば入力欄が出てきます。

EKSクラスターの設定は以上になるので、「作成」を実行してください。
クラスターの作成には数分かかります。

<img width="360" alt="スクリーンショット 2020-02-16 22.51.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/8083e120-318b-67c6-5b37-73f7030b3c3f.png">


# 2. Fargateプロファイルの作成
EKSクラスターを作成したら、次にFargateプロファイルを作成します。
Fargateプロファイルでは、Fargate上で起動するPodを指定することができます。

#### Podとは

> 1つ以上のアプリケーションコンテナのグループ

基本的にはPod=コンテナのイメージで良いと思います。
ただ、1つのPodには複数のコンテナを共存させることもできることを、覚えておいてください。

#### Nodeとは

> Podは常にノード上で動作します。
> ノードはワーカーマシンであり、仮想・物理マシンのどちらであってもかまいません。

Node=サーバーです。
FargateおよびEC2を指します。

#### まとめると
Node上でPodは動作する ≒ Fargate上でコンテナは動作する
（厳密には違うかもしれません）

では実際にFargateプロファイルを作成していきましょう。
作成したクラスターの画面から、「Fargateプロファイルを追加」を選択します。
<img width="960" alt="スクリーンショット 2020-02-16 23.20.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/d43ffed2-bd3d-9dde-8624-3c291b8a614c.png">


## 2.1. プロファイル設定・タグ設定
ここでは以下の4項目を設定します。

- プロファイルに設定する名前
- ポッド実行ロール
- サブネット
- タグ

サブネットには、プライベートサブネットを設定する必要があります。
全て設定したら、「Next」を選択します。

<img width="360" alt="スクリーンショット 2020-03-08 14.56.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/9d02f9c9-ac4f-0b9b-eb78-ad86a2153ba8.png">


ポッド実行ロールとは、Fargate(Node)上でコンテナ(Pod)を作成する際に使用するIAMロールです。
Fargate(Node)上にはコンテナイメージがないため、クラスターからそのイメージを取得する必要があります。
未作成であれば、新規に作成が必要です。次の章でその手順を説明します。

サブネットはクラスターに設定されたサブネットの中から選択する必要があります。
Fargateは選択されたサブネットの中のいずれかに起動されます。（冗長化する場合は、別のサブネットに起動することが可能）
サブネットを1つのみにすれば、Fargateを起動するサブネットを固定することが可能です。

#### **（2020 3/30追記)**

ALB Ingress Controllerに対応するため、プライベートサブネットは最低2つ（複数AZ）を指定してください。


## 2.2. ポッド実行ロールの作成（未作成の場合）
<details><summary><font color="Red">**以下、IAMロールが未作成の場合に実施してください**</font></summary><div>

---

手順`1.2`と同様の手順で、IAMロールを作成していきます。
Fargateプロファイル設定画面の「ロール名」を選択することで、別タブにIAMロール作成画面が表示されるので、**「ロールの作成」**を選択します。

<img width="360" alt="スクリーンショット 2020-03-08 15.04.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/2bbb2057-70f3-8e62-4603-fc2e1695a330.png">

次にロール作成画面にて、
**「EKS」 > 「EKS - Fargate pod」 > 「次のステップ：アクセス権限」> 「次のステップ：タグ」**
と選択していきます。
<img width="360" alt="スクリーンショット 2020-02-16 23.37.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/f5478a49-750e-4bcb-a6c4-7c72ea740ba9.png"> >>> <img width="360" alt="スクリーンショット 2020-02-16 23.41.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/416f34e4-571a-ef14-d01c-e2ae77a32dd8.png">

次にNameタグを設定し、ロール名にも同様の設定をしたら、「ロールの作成」を実行します。
<img width="360" alt="スクリーンショット 2020-02-16 23.43.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/baf4d0cf-0fc4-5a62-cf0c-f8f69f530284.png"> >>> <img width="360" alt="スクリーンショット 2020-02-16 23.44.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/cf60d192-6fc6-fcad-3718-d42f6734ef76.png">

これでFargateプロファイルに必要な、ポッド実行ロールが作成できました。
手順`2.1`に戻り、Fargateプロファイルの設定を続けてください。

---

</div></details>


## 2.3. ポッドセレクタの設定
次に、ポッドセレクタを設定します。
Fargate上に起動するPodの条件を指定することができます。
ここでは、以下の名前空間(`namespace`)を持つPodをFargateで起動する設定をしています。

- handson（今回デプロイするアプリ用）
- kube-system（Kubernetesで使用されるnamespace）
- default

その名前空間の中でも更に条件をつけることが可能です。
「ラベルを一致させる」を選択することで設定できますが、今回は行いません。

<img width="360" alt="スクリーンショット 2020-03-08 22.45.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533841/ec76f6a5-c048-5a0e-7423-981a03a2ab74.png">



「次へ」を選択したら、確認画面が表示されるので「作成」を実行しましょう。
これでFargateプロファイルが作成されます。

# 3. `kubectl`コマンドでサービスをデプロイ

以降はvol.2の記事で解説していけたらと思います。。
~~記事は近日中（来週目標）に作成して公開します！！~~

**（2020 3/31追記）**
vol.2の記事を作成しました！
[【AWS】EKS on Fargateでゲームをデプロイしてみたので解説してみる（with Ingress Controller, 2048）vol.2](https://qiita.com/hesma2/items/9e1cbbc0b44c40b62981)


# まとめ
想像以上に時間がかかってしまいました。
Ingress Controllerの設定周りでだいぶ苦戦してしまっています。。

KubernetesやEKSを初見で触った時には、
[数時間で完全理解！わりとゴツいKubernetesハンズオン！！](https://qiita.com/Kta-M/items/ce475c0063d3d3f36d5d)
の記事に本当にお世話になりました。

図解付きで説明されていて、非常にわかりやすいと感じました。
こちらもぜひ、参考にしてみてください。

#### **（2020 3/30追記）**

今回命名にスネークチェーン（aaaa_bbb）を使用していますが、
AWSでは基本的に-（ハイフン）を使用することが望ましいかもしれません。
CloudFormationでは_（アンダーバー）が使えないことや、自動で作成されるリソースに-（ハイフン）が使われているためです。

とりあえずこの記事の範囲であれば問題はなさそうですが。

# 参考
AWS公式

- [AWS re:Invent 2019](http://reinvent.awseventsjapan.com)
- [Amazon EKS の機能](https://aws.amazon.com/jp/eks/features/)
- [AWS Fargate](https://aws.amazon.com/jp/fargate/)
- [Amazon EKS セキュリティグループの考慮事項](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/sec-group-reqs.html)
- [AWS Fargate プロファイル](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/fargate-profile.html)
- [ポッド実行ロール](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/pod-execution-role.html)

その他記事

- [【AWS】パブリックサブネットとプライベートサブネットの違いとは](https://qiita.com/hesma2/items/29db7ccb8678a84d267a)
- [数時間で完全理解！わりとゴツいKubernetesハンズオン！！](https://qiita.com/Kta-M/items/ce475c0063d3d3f36d5d)