【AWS】 EKS on Fargate のクラスタを構築してみる

# はじめに
[UL Systems Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ulsystems) の9日目です。

先日のAWS re:invent で Fargate for EKS が発表されました（[AWSブログの記事](https://aws.amazon.com/jp/blogs/news/amazon-eks-on-aws-fargate-now-generally-available/)）。
そしてなんと東京リージョンで利用できます。
もうEC2を管理しなくていいんです！！

これまでは EC2 の管理を避けるため（泣く泣く） ECS + Fargate を使っていた方もいらっしゃったのではないでしょうか。
この記事はそのような方を含めて、はじめて EKS をさわる方のためのチュートリアルです。
Fargate の EKS クラスタを構築するという基本的な操作を通して、実際の動きを確認してみます。

それでは、はじめてみましょう。

## 準備
### 作業用の EC2 インスタンスを構築
本記事では作業用の EC2 インスタンスから EKS を操作します（以降「作業端末」と呼びます）。既にお持ちの場合は不要です。（[【10分間チュートリアル】Linux 仮想マシンの起動 ](https://aws.amazon.com/jp/getting-started/tutorials/launch-a-virtual-machine/?trk=gs_card&e=gs&p=gsrc)を参考にご準備ください）

### EKS 用のツールをインストール

- 作業端末に kubectl をインストールします（2019.12.08 時点では「Client Version: v1.14.7-eks-1861c5」でした）。

```
$ sudo curl --silent --location -o /usr/local/bin/kubectl https://amazon-eks.s3-us-west-2.amazonaws.com/1.14.6/2019-08-22/bin/linux/amd64/kubectl
$ sudo chmod +x /usr/local/bin/kubectl
$ kubectl version --short --client
```

- jq, envsubst (from GNU gettext utilities), bash-completion, git をインストールします。

```
$ sudo yum -y install jq gettext bash-completion git
```

- kubectl bash_completionを有効にします。

```
$ kubectl completion bash >>  ~/.bash_completion
$ . /etc/profile.d/bash_completion.sh
$ . ~/.bash_completion
```


### 作業端末用の IAM ロールを作成

1. [このリンク](https://console.aws.amazon.com/iam/home#/roles$new?step=review&commonUseCase=EC2%2BEC2&selectedUseCase=EC2&policies=arn:aws:iam::aws:policy%2FAdministratorAccess)をクリックし、管理者権限の IAM ロールを作成します。
2. 「信頼されたエンティティの種類を選択」で「AWSサービス」が選択されていること、「このロールを使用するサービスを選択」で「EC2」が選択されていることを確認して「次のステップ：アクセス権限」ボタンをクリックします。
3. 「Attach アクセス権限ポリシー」で「AdministratorAccess」が選択されていることを確認して「次のステップ：タグ」ボタンをクリックします。
4. デフォルト（タグを追加しない）のまま「次のステップ：確認」ボタンをクリックします。
5. 「ロール名」に「eks-admin」と入力して「ロールの作成」ボタンをクリックします。

![iamrole_for_ec2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/7f639fd4-5110-34d7-7de0-684c54c20664.png)


### 作業端末に IAM ロールをアタッチ

1. [マネジメントコンソールでEC2サービスを開き](https://ap-northeast-1.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-1#Instances:)、作業端末を選択します。
2. 「アクション」→「インスタンスの設定」→「IAM ロールの割り当て/置換」をクリックします。
3. 「IAM ロール」のドロップダウンで「eks-admin」を選択し「適用」ボタンをクリックします。

![attach_iamrole_to_ec2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/14a3b61f-df12-2c39-4bc8-c3615a78699d.png)


### AWS CLI の更新と設定

- 作業端末に ssh で接続します。
- AWS CLI を更新します（EC2 インスタンス構築直後のバージョンでは古いため、kubectl が失敗します）。

```
$ sudo yum install python3 -y
$ sudo pip3 install awscli --upgrade
```
（インストール先は、/usr/local/bin になります）

- バージョンを確認します。古い AWS CLI （/usr/bin/aws）のままの場合、ログインしなおしてください。

```
$ aws --version
aws-cli/1.16.298 Python/3.7.4 Linux/4.14.152-127.182.amzn2.x86_64 botocore/1.13.34
```


- aws configure します。

```
$ aws configure
AWS Access Key ID [None]: （未入力でEnter）
AWS Secret Access Key [None]: （未入力でEnter）
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

- ここまでの作業が正しく行われていることを確認します。コマンド実行結果にロール名とインスタンスIDが含まれていることを確認します。

```
$ aws sts get-caller-identity --output text --query Arn
arn:aws:sts::123456789012:assumed-role/eks-admin/i-0af444c1234567890
```

- 環境変数を設定します。

```
$ export ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account)
$ export AWS_REGION=ap-northeast-1
$ echo "export ACCOUNT_ID=${ACCOUNT_ID}" | tee -a ~/.bash_profile
$ echo "export AWS_REGION=${AWS_REGION}" | tee -a ~/.bash_profile
```

### eksctl をインストール
eksctlは、EKS専用のコマンドラインツールです。
VPCやセキュリティグループの作成も行われるため、クラスターの作成作業を簡単に行うことができます。

- ダウンロードして /usr/local/bin に配置します。

```
$ curl --silent --location "https://github.com/weaveworks/eksctl/releases/download/latest_release/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp

$ sudo mv -v /tmp/eksctl /usr/local/bin
```

- バージョンを確認します（2019.12.08 時点では「0.11.1」でした）。

```
$ eksctl version
[?]  version.Info{BuiltAt:"", GitCommit:"", GitTag:"0.11.1"}
```

- eksctl bash-completion を有効にする

```
$ eksctl completion bash >> ~/.bash_completion
$ . /etc/profile.d/bash_completion.sh
$ . ~/.bash_completion
```

## EKS クラスター作成
### Fargate の EKS クラスター作成

- eksctl コマンドの引数に「--fargate」を指定して EKS クラスターを作成します。15分～20分程度かかります。

```
$ eksctl create cluster --name ekstest-cluster --fargate
[?]  eksctl version 0.11.1
[?]  using region ap-northeast-1
[?]  setting availability zones to [ap-northeast-1d ap-northeast-1c ap-northeast-1a]
[?]  subnets for ap-northeast-1d - public:192.168.0.0/19 private:192.168.96.0/19
[?]  subnets for ap-northeast-1c - public:192.168.32.0/19 private:192.168.128.0/19
[?]  subnets for ap-northeast-1a - public:192.168.64.0/19 private:192.168.160.0/19
[?]  using Kubernetes version 1.14
[?]  creating EKS cluster "ekstest-cluster" in "ap-northeast-1" region with Fargate profile
[?]  if you encounter any issues, check CloudFormation console or try 'eksctl utils describe-stacks --region=ap-northeast-1 --cluster=ekstest-cluster'
[?]  CloudWatch logging will not be enabled for cluster "ekstest-cluster" in "ap-northeast-1"
[?]  you can enable it with 'eksctl utils update-cluster-logging --region=ap-northeast-1 --cluster=ekstest-cluster'
[?]  Kubernetes API endpoint access will use default of {publicAccess=true, privateAccess=false} for cluster "ekstest-cluster" in "ap-northeast-1"
[?]  1 task: { create cluster control plane "ekstest-cluster" }
[?]  building cluster stack "eksctl-ekstest-cluster-cluster"
[?]  deploying stack "eksctl-ekstest-cluster-cluster"
[?]  all EKS cluster resources for "ekstest-cluster" have been created
[?]  saved kubeconfig as "/home/ec2-user/.kube/config"
[?]  creating Fargate profile "fp-default" on EKS cluster "ekstest-cluster"
[?]  created Fargate profile "fp-default" on EKS cluster "ekstest-cluster"
[?]  "coredns" is now schedulable onto Fargate
[?]  "coredns" is now scheduled onto Fargate
[?]  "coredns" pods are now scheduled onto Fargate
[?]  kubectl command should work with "/home/ec2-user/.kube/config", try 'kubectl get nodes'
[?]  EKS cluster "ekstest-cluster" in "ap-northeast-1" region is ready
```

- Fargate プロファイルを確認します。Pod 実行 IAM ロール、ネームスペース、サブネットが自動で作成されています。

```
$ eksctl get fargateprofile --cluster ekstest-cluster -o yaml
- name: fp-default
  podExecutionRoleARN: arn:aws:iam::123456789012:role/eksctl-ekstest-cluster-clu-FargatePodExecutionRole-YLXXXXXXXXXX
  selectors:
  - namespace: default
  - namespace: kube-system
  subnets:
  - subnet-0aa6a123456789012
  - subnet-0731d123456789012
  - subnet-080a4123456789012
```

- ノードを確認します。おおお、2 つ起動しています。Hello Fargate！

```
$ kubectl get nodes
NAME                                                         STATUS   ROLES    AGE     VERSION
fargate-ip-192-168-130-96.ap-northeast-1.compute.internal    Ready    <none>   2m51s   v1.14.8-eks
fargate-ip-192-168-154-188.ap-northeast-1.compute.internal   Ready    <none>   4m21s   v1.14.8-eks
```

eksctl の詳細は[公式ページ](https://eksctl.io/usage/fargate/)をご覧ください。

### Pod 起動

- nginx を起動するだけの Deployment を作成します。

```
$ kubectl create deployment demo-app --image=nginx
deployment.apps/demo-app created
```

- Pod の状態を確認します（READY になるまで 1 分程度かかりました）。

```
$ kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
demo-app-6dbfc49497-b8b79          1/1     Running   0          2m19s
```

- node の状態を確認します。ひとつ増えていますね。Hello Fargate！！

```
$ kubectl get nodes
NAME                                                         STATUS   ROLES    AGE   VERSION
fargate-ip-192-168-130-96.ap-northeast-1.compute.internal    Ready    <none>   65m   v1.14.8-eks
fargate-ip-192-168-154-188.ap-northeast-1.compute.internal   Ready    <none>   66m   v1.14.8-eks
fargate-ip-192-168-167-220.ap-northeast-1.compute.internal   Ready    <none>   11m   v1.14.8-eks
```

## 削除

### Pod 終了

- デプロイメントを削除します。

```
$ kubectl delete deployment demo-app
deployment.extensions "demo-app" deleted
$ kubectl get pods
No resources found in default namespace.
```

- node の状態を確認します。

```
$ kubectl get nodes
NAME                                                         STATUS   ROLES    AGE   VERSION
fargate-ip-192-168-130-96.ap-northeast-1.compute.internal    Ready    <none>   74m   v1.14.8-eks
fargate-ip-192-168-154-188.ap-northeast-1.compute.internal   Ready    <none>   75m   v1.14.8-eks
```

### クラスター削除

- eksctl コマンドでクラスターを削除します。

```
$ eksctl delete  cluster --name ekstest-cluster
[?]  eksctl version 0.11.1
[?]  using region ap-northeast-1
[?]  deleting EKS cluster "ekstest-cluster"
[?]  deleting Fargate profile "fp-default"
[?]  deleted Fargate profile "fp-default"
[?]  deleted 1 Fargate profile(s)
[?]  kubeconfig has been updated
[?]  cleaning up LoadBalancer services
[?]  1 task: { delete cluster control plane "ekstest-cluster" [async] }
[?]  will delete stack "eksctl-ekstest-cluster-cluster"
[?]  all cluster resources were deleted
```

## おわりに

非常に簡単な操作だけでしたが、Fargate のクラスタ上で EKS が動作することを確認しました。
コンテナ系の技術は必要な知識エリアが広く、書籍や記事を読んだだけではわかりにくい技術のため、実際に手を動かして「やってみる」ことが大切だと感じています。

本記事が、皆さまのコンテナ技術の理解のお役に立てたら幸いです。