EKS for Fargate the Hard Way 〜 EKS for Fargateをeksctlに頼らず構築する

# TL:DR
`eksctl`に頼らず、EKS for Fargateクラスタを構築する際は以下を確認！

1. プライベートサブネットにアタッチするルートテーブルにはNAT GWへのルートを！
2. VPCのDNSホスト名を有効にしているか確認！
3. PodテンプレートのAnnotationに`eks.amazonaws.com/compute-type: fargate`をつけよう！

# EKS for Fargate the Hard Way
2019/12/5にAWS Re:InventにてGAとなった[EKS for Fargate](https://aws.amazon.com/jp/blogs/news/amazon-eks-on-aws-fargate-now-generally-available/)。皆様もう試してみたでしょうか？？ 私もただいまECS for Fargateと比較して、何ができて何ができないのか、絶賛検証中でございます！

さて、EKS for FargateのGAの記事を見ると、`eksctl`コマンドを使ってEKS for Fargateクラスタを構築する例が上がっております。しかし、私はブラックボックス化されたものの中身を理解したい性分なもので、EKS for Fargateを手動で構築してみることにいたしました。言ってみれば、「EKS for Fargate the Hard Way」です！ 本記事ではそんなハードな手順と共に、EKS for Fargateのハマりどころを紹介していきたいと思います:muscle:

# Hard Way手順
EKS for FargateクラスタでPodが実行されるためには以下の手順を実施しましょう！

1. VPC作成
まずはEKSクラスタが所属するVPCを作成します。このとき重要なことは`DNSホスト名`の値を`有効`に設定することです。
![無題 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151015/155ac444-6765-d154-066d-9ce6a98ab967.png)

1. パブリックサブネット、プライベートサブネットを切る
どちらもガチガチに可用性を固めたいなら3つずつ切ります。

1. EIPおよびNAT GWを切る
NAT GWは当然パブリックサブネットに切ります。こちらもガチガチに可用性を高めたいなら3つずつ切ります。

1. パブリックサブネット用のルートテーブルを切る
Internet GWへのルートを持つルートテーブルを切り、パブリックサブネットにアタッチします。

1. プライベートサブネット用のルートテーブルを切る
NAT GWへのルートを持つルートテーブルを切り、NAT GWの所属するAZにあるプライベートサブネットにアタッチします。もちろん、NAT GWを一つしか切らない場合は、作ったルートテーブルを全てのプライベートサブネットにアタッチします。

1. EKSクラスタ用デプロイ用IAMロールを切る
こちらはマネジメントコンソール上から作るのが簡単です。IAMのマネジメントコンソールから「ロールを作成」を選択し、AWSサービスとして`EKS`(`EKS - Nodegroup`ではない)を選択すれば必要な管理ポリシーが選択されます。

1. EKS Fargate Pod実行用IAMロールを切る
こちらもマネジメントコンソールから作れます。IAMのマネジメントコンソールから「ロールを作成」を選択し、AWSサービスとして`EC2`を選択します。表示された管理ポリシーの内、`AmazonEKSFargatePodExecutionRolePolicy`を選択しロールを作成します。その後、できたロールの信頼関係を以下のように修正します。

    ```
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Service": "eks-fargate-pods.amazonaws.com"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }
    ```

1. EKSクラスタを作る
今まで作ったリソースを使って、EKSクラスタを作ります。

1. Fargateプロファイル作る
最低限、`kube-system`名前空間に対するFargateプロファイルをEKSマネジメントコンソールから作ります。

1. CoreDNSのyamlファイルを編集する
ここまで作業すると、とうとう`kube-system`名前空間内でFargate上にPodを浮かべることができるようになります。そのためにはmanifestのPodテンプレートにおいて、Annotationに`eks.amazonaws.com/compute-type: fargate`を加えます。既存のCoreDNSのDeploymentには、`eks.amazonaws.com/compute-type: ec2`が指定されているので、こちらを書き換えます。

最終的にCoreDNSのPodが以下のように浮かび、Podの数だけWorkerノードを確認することができるはずです。

```
tatsunori@neptune-surface:~$ kubectl get pod -n kube-system
NAME                       READY   STATUS    RESTARTS   AGE
coredns-6d75bbbf58-77hks   1/1     Running   0          2m24s
coredns-6d75bbbf58-v5d7v   1/1     Running   0          2m24s
tatsunori@neptune-surface:~$ kubectl get node
NAME                                                        STATUS   ROLES    AGE     VERSION
fargate-ip-10-100-101-85.ap-northeast-1.compute.internal    Ready    <none>   3m38s   v1.14.8-eks
fargate-ip-10-100-103-157.ap-northeast-1.compute.internal   Ready    <none>   3m47s   v1.14.8-eks
```

# 最終的にできた構成
ガチガチに3AZで構成した場合は、以下のような構成でEKSクラスタが作成されます！
![ダウンロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151015/9c2df3f7-8f16-3fee-e2cc-b3c027ffe9ac.png)

# まとめ(注意点)
## NAT Gatewayの作成を忘れない
Fargateプロファイルで指定できるサブネットはプライベートサブネットのみです。つまり、Podはプライベートサブネットで起動します。このためプライベートサブネット上から`docker pull`によってコンテナイメージをインターネット上からダウンロードできる必要があります。

NAT Gatewayが作成され、それにルーティングされるルートテーブルがプライベートサブネットにアタッチされていないと`docker pull`できませんので注意が必要です。

## VPCのDNSホスト名を必ず有効化する
Fargate Podが起動するノードのノード名は`fargate-<VPC DNSホスト名>`となります。このため、VPCのDNSホスト名が有効化されていないとノード名は全て`fargate-null`となります。この場合登録ノード名が重複するため、最高1Podしかクラスタ上にPodが起動できない状態になってしまいます。。。

## Pod TemplateのAnnotationに`eks.amazonaws.com/compute-type: fargate`をつける
EKSクラスタを作成するとデフォルトでCoreDNSのDeploymentが作成されていますが、こちらのPod TemplateにはAnnotation `eks.amazonaws.com/compute-type: ec2`が指定されているため、いつまで経ってもFargate上にPodは起動してきません。`eks.amazonaws.com/compute-type: fargate`に変更するのを忘れないように。