AWS Kubernetes(EKS)の環境を作成し、マイクロサービスのサンプル（Sock Shop）を立ち上げる

今はとにかくKubernetes とMicroserviceが　熱いですが、  
実環境が欲しいという場合に、ワンコインで環境を構築したくなります。そして使い終わったら削除します。これは、自動構築用のスクリプトを使用して実施し、費用を抑えます。   

ここでAWS上にアカウントを持っていることを前提に、簡単に作成できるAWS EKSの環境作成方法を記述します。
    

以下Kubernetes はk8sと表記します。

# 使うもの

* [Amazon EKS QuickStart](https://aws.amazon.com/quickstart/architecture/amazon-eks/) 

AWS上でK8s環境を作成するのに使います。
３つのAZに、ワーカーノードを設置して使います。
それなりの費用がかかりますので、検証を素早く終わらせて費用がかさむ前に環境ごとCloudFormation で削除してしまうというのがポイントです。。
構築に30分程度かかります。  

* [MicroService Demo(Sock Shop)](https://microservices-demo.github.io/)

靴下のオンラインストアをマイクロサービスで実装したデモです。これはWeaveWorksが主体となって作成されています。

# 費用の目安   


| コンポーネント | 時間単価  （Oregonベース） | 数量 | 時間単価 |  
|:-----------------|------------------:|-------------------:|----:|
| EKS Control Plane |              0.20 |        1        |  0.20 |
| T3.medium |            0.03~0.05 |       3       | 0.15 |
| Bastion       |             0.01 |        1       | 0.01 |
| ELB       |             0.03 |        1       | 0.03 |
| NAT Gateway       |             0.01 |        3       | 0.03 |
| 合計 |   |   | 0.41 |

二時間使用して　$3 超えないぐらい…だと思いますが皆さん自己責任で！！

# EKSの構築

まずはBastion（踏み台）へのアクセスに必要なEC2のキーペアをターゲットとなるリージョンに作成しておきます。私はKPR-EKS といった命名規約で作成し、リージョンはインスタンスの時間単価が安くて比較的低レイテンシなOregonにしています。    

Quickstart の　How To Deploy の [Deploy into a new VPC](https://us-east-2.console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/create/template?stackName=Amazon-EKS&templateURL=https://s3.amazonaws.com/aws-quickstart/quickstart-amazon-eks/templates/amazon-eks-master.template.yaml)  
を選んでいきます。するとCloudFormationで自動構築する画面が上がって来ます。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192988/21028232-6d23-4ef4-4bbf-cc1f3e41e9be.png)

Availability Zones は３つ選ぶ必要があります。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192988/8057fd01-578b-da11-ad5f-2a62c018f167.png)

外からアクセスするIPアドレスは自分の環境のグローバルIPに絞り、  
キーペアはEC2で作成したキーペアを入れます。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192988/7fdb0846-bca0-887d-ae30-63ce0c930492.png)

K8sのクラスタを構成するインスタンスのタイプはまあまあ安そうな物を選びましょう。  
ここで選択を誤ると費用が大変な事になります。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192988/201c65af-c282-debd-0b82-522aacfdb0f6.png)

AutoScaler は、このQuickStartが用意してくれている仕組みです。  
リソースが足りなくなると、K8sのワーカーノードを追加してくれます。  
EFS Storage Class はEFS(マネージドストレージのnfs)がK8sのコンテナのストレージとして使えるようになるという事です。

どちらも初期費用はかかりませんが、有効にするかどうかはあなた次第です。  

S３バケットはデフォルトにしておけば、問題なく動作します。  

# もっと安く！スポットインスタンスに！！

ここで、このQuickStartが起動するインスタンスはオンデマンドインスタンスで起動します。  
真のケチケチ野郎ならば、スポットインスタンスにしたいところです。  
これは、元々の[QuickStartのテンプレート](https://github.com/aws-quickstart/quickstart-amazon-eks)をいじらないとできません。  

実際のところ、ネストしたテンプレートの  
amazon-eks-nodegroup.template.yaml の NodeLaunchConfig というリソース（LaunchConfiguration）のプロパティに、`SpotPrice: 0.03` というものを追加すると、ワーカノードのスポットインスタンス化が実現できます。
これは、スポットインスタンス用のスポット価格設定です。私の場合は t3.mediumをターゲットにしてそのオンデマンド価格をスポット上限価格に設定しています。    

抜粋  

```
      BlockDeviceMappings:
        - DeviceName: !If [ SuseOS, /dev/sda1, /dev/xvda ]
          Ebs:
            VolumeSize: !Ref NodeVolumeSize
            VolumeType: gp2
            DeleteOnTermination: true
      SpotPrice: 0.03
      UserData: !If
```

このようにテンプレートに改編を行う場合は、関連する全てのテンプレートをS3にアップロードし、 Submodulesとして使用している、quickstart-aws-vpc、/quickstart-linux-bastionのテンプレートも用意する必要があります。

また、実行する際のパラメータの内、自分が用意したS３のバケット名称等を下記のパラメータで指定する必要があります。   

| パラメータ | 設定内容 |
|:--|:--|:--|
| QSS3BucketName | テンプレートを置いたS３のバケット名称 |
| QSS3KeyPrefix | バケット内のフォルダ（tempatesフォルダの親フォルダ名：なければ省略） |

# EKSの踏み台へのアクセス  

こうして作成されたK8sクラスタのBastion（踏み台）のIPが、CloudFormationのOutputとして出力されますので、作成時に指定したEC2のキーペアを使用してアクセスします。  


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192988/a9e8831b-cf7d-4aa4-c489-644a8765bcda.png)

すでにBastionにkubectl導入済みですので、下記のコマンドでワーカーノードを確認してみましょう。  

```bash

[ec2-user@ip-10-0-153-131 ~]$ kubectl get nodes
NAME                                       STATUS    ROLES     AGE       VERSION
ip-10-0-21-83.us-west-2.compute.internal   Ready     <none>    17m       v1.13.7-eks-c57ff8
ip-10-0-60-10.us-west-2.compute.internal   Ready     <none>    17m       v1.13.7-eks-c57ff8
ip-10-0-89-6.us-west-2.compute.internal    Ready     <none>    17m       v1.13.7-eks-c57ff8
[ec2-user@ip-10-0-153-131 ~]$ 
```

# Sock Shopの導入
 
Sock Shop はGitのリポジトリ上に用意されていますので、Cloneでコピーします。Cloneする為にはgitコマンドが必要ですので、yum コマンドで導入し、その後[Sock Shop](https://github.com/microservices-demo/microservices-demo)をCloneしましょう。  

```
[ec2-user@ip-10-0-153-131 ~]$ sudo yum install -y git
~~（省略）~~

[ec2-user@ip-10-0-153-131 ~]$ git clone https://github.com/microservices-demo/microservices-demo
Cloning into 'microservices-demo'...
remote: Enumerating objects: 9638, done.
remote: Total 9638 (delta 0), reused 0 (delta 0), pack-reused 9638
Receiving objects: 100% (9638/9638), 52.85 MiB | 31.21 MiB/s, done.
Resolving deltas: 100% (5789/5789), done.
[ec2-user@ip-10-0-153-131 ~]$
```

Sock Shop は、様々な環境で動くようにデプロイ用コマンドが環境毎に用意されています。  
今回は通常のK8s用のマニフェスト、`deploy/kubernetes/complete-demo.yaml`を使用してインストールします。

このマニフェストは`sock-shop`というNameSpaceを使用しますのであらかじめ作ってから実行しましょう。  

また、このSock Shop　へのブラウザアクセスには、NodePort という、ローカルでしか使用できないリソースが使用されています。  
これをLoadBalancer に変更し、内部アクセス用にALBが自動で起動するようにしてから実行しましょう。  

```
[ec2-user@ip-10-0-153-131 ~]$ cd microservices-demo/deploy/kubernetes/
[ec2-user@ip-10-0-153-131 kubernetes]$ sed -i 's/NodePort/LoadBalancer/g' complete-demo.yaml
[ec2-user@ip-10-0-153-131 kubernetes]$ grep LoadBalancer complete-demo.yaml
  type: LoadBalancer
[ec2-user@ip-10-0-153-131 kubernetes]$ kubectl create namespace sock-shop
namespace/sock-shop created
[ec2-user@ip-10-0-153-131 kubernetes]$ kubectl apply -f complete-demo.yaml 
deployment.extensions/carts-db created
service/carts-db created
deployment.extensions/carts created
service/carts created
deployment.extensions/catalogue-db created
service/catalogue-db created
deployment.extensions/catalogue created
service/catalogue created
deployment.extensions/front-end created
service/front-end created
deployment.extensions/orders-db created
service/orders-db created
deployment.extensions/orders created
service/orders created
deployment.extensions/payment created
service/payment created
deployment.extensions/queue-master created
service/queue-master created
deployment.extensions/rabbitmq created
service/rabbitmq created
deployment.extensions/shipping created
service/shipping created
deployment.extensions/user-db created
service/user-db created
deployment.extensions/user created
service/user created
[ec2-user@ip-10-0-153-131 kubernetes]$ 
```

しばらくすると、ELBが上がって来ます。このDNS名称をコピーします。    

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192988/e1c168e5-eec1-6c06-82e0-69f079b40601.png)

このアクセスポイントにアクセスして、靴下屋が表示されたら成功です！！  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192988/f0379a13-30db-c20c-6229-6a616a807a93.png)

このサンプルには、監視用のManifest等も同梱されていますのでそのあたりも実行してみましょう。 

気が済んだら、CloudFormation を削除して終了しましょう。
※K8s内の LoadBalancerリソースで作成したELBは、CloudFormationのテンプレートを削除する事によって、削除されます。    
※稀にVPCが削除されませんが、VPCを手動で削除してから再度テンプレートを削除すると正常に削除されます。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192988/0ffaf8a5-aec6-533d-c443-3138e9ffd24d.png)