Amazon EKS で Kubernetes を使う

これは [Getting Started with Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html) の通りに作業した記録です。
世の中に沢山ある正式チュートリアルどおりにただなぞるだけの記事に存在意義はあるのか ??? と思っていたが自分でも書きます。書いてある通りに作業するのは難しい。四回くらい間違えました。そういう時意外と他人の記事で気付かされた点がありました。

この記録が英語版を参照しているのは、最初あまりにも上手く行かなくてに日本語版が間違っているのでは? と疑った名残です。多分日本語版でも大丈夫です。

## 作業の概要

* 準備:
  * IAM Role や EC2 key pair を作る
  * kubectl と heptio-authenticator-aws のインストール。aws コマンドの設定
* CloudFormation で VPC を作る。VPC の情報はクラスタとワーカーノードの作成に使う。
* `aws eks create-cluster` でクラスタを作る
  * ~/.kube/config-hoge を編集して kubectl がクラスタにアクセス出来るようにする。
* CloudFormation で ワーカーノードの作成
  * ConfigMap を作成して kubectl がノードにアクセス出来るようにする。
* あとは普通の kubernetes として使う。
  
## EKS 用 IAM Role を作る。

* IAM > Roles > Create role > EKS > Next: Permissions
* Next: Review
* Role name: hoge-role > Create role

作成したら Role ARN を控えておく。クラスタの作成に使います。

* Role ARN: arn:aws:iam::xxxxx:role/hoge-role

## EKS 用 VPC を作る。

以下作業リージョンは Oregon を選択しました

* CloudFormation > Create stack > Specify an Amazon S3 template URL: https://amazon-eks.s3-us-west-2.amazonaws.com/cloudformation/2018-08-30/amazon-eks-vpc-sample.yaml > Next
* Stack name: hoge-eks-vpc > Next
* Tags を適当に入れる > Next
* Create

作成されたら Output の内容を控えておく

* SecurityGroups:	sg-01612a9ab7bd7b236 # クラスタ作成とワーカーノード作成で使う
* VpcId:	vpc-0586bb50f37b84c72 # ワーカーノード作成に使う (クラスタ作成になぜか不要)
* SubnetIds:	subnet-04d20fe635763c36d,subnet-05a3c2235ce29c339,subnet-0a2cba5164ce5f198 # クラスタ作成とワーカーノード作成で使う

## kubectl と heptio-authenticator-aws のインストール

```
$ curl -o kubectl https://amazon-eks.s3-us-west-2.amazonaws.com/1.10.3/2018-07-26/bin/darwin/amd64/kubectl
$ curl -o heptio-authenticator-aws https://amazon-eks.s3-us-west-2.amazonaws.com/1.10.3/2018-07-26/bin/darwin/amd64/heptio-authenticator-aws
$ chmod 755 kubectl heptio-authenticator-aws
$ mkdir -p ~/aws/bin
$ mv kubectl heptio-authenticator-aws ~/aws/bin 
$ export PATH=~/aws/bin:$PATH
$ kubectl version --short --client
Client Version: v1.10.3
$ heptio-authenticator-aws help
A tool to authenticate to Kubernetes using AWS IAM credentials
...
```

# AWS CLI を設定しておく

profile=kube を使います。

```
$ aws configure --profile aws-kube
いろいろやる
$ export AWS_PROFILE=kube
```

# Amazon EKS クラスターを作る

```shell
$ aws eks create-cluster \
    --name hoge-eks-cluster \
    --role-arn arn:aws:iam::xxxxx:role/hoge-role \
    --resources-vpc-config subnetIds=subnet-04d20fe635763c36d,subnet-05a3c2235ce29c339,subnet-0a2cba5164ce5f198,securityGroupIds=sg-01612a9ab7bd7b236

{
    "cluster": {
        "status": "CREATING", 
        "name": "hoge-eks-cluster", 
        "certificateAuthority": {}, 
        "roleArn": "arn:aws:iam::xxxxx:role/hoge-role", 
        "resourcesVpcConfig": {
            "subnetIds": [
                "subnet-04d20fe635763c36d", 
                "subnet-05a3c2235ce29c339", 
                "subnet-0a2cba5164ce5f198"
            ], 
            "vpcId": "vpc-0586bb50f37b84c72", 
            "securityGroupIds": [
                "sg-01612a9ab7bd7b236"
            ]
        }, 
        "version": "1.10", 
        "arn": "arn:aws:eks:us-west-2:xxxxx:cluster/hoge-eks-cluster", 
        "platformVersion": "eks.2", 
        "createdAt": 1536198762.461
    }
}
```

結果に subnetIds, vpcId, securityGroupIds が含まれているか確認して下さい。私は securityGroupIds が抜けてて失敗しました。

10 分くらいかかるので状態表示

    aws eks describe-cluster --name hoge-eks-cluster --query cluster.status

## kubectl コマンドの設定

kubeconfig ファイルの生成

    aws eks update-kubeconfig --kubeconfig ~/.kube/config-hoge --name hoge-eks-cluster

設定と動作確認

```
$ export KUBECONFIG=~/.kube/config-hoge
$ kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.100.0.1   <none>        443/TCP   14m
```

## Amazon EC2 SSH キーペア

無くても良いらしいが一応作っておく

    aws ec2 create-key-pair --key-name hoge-eks-keypair --query 'KeyMaterial' --output text > hoge.pem

## ワーカーノードの作成

ここは間違いやすいので注意！！！ClusterName には aws eks create-cluster で作成したクラスタの名前を書く。間違ってもエラーが出ないので凶悪。私はうっかり VPC の Stack Name を書いてしまって一日を無駄にした。

* CloudFormation > Create stack > Specify an Amazon S3 template URL: https://amazon-eks.s3-us-west-2.amazonaws.com/cloudformation/2018-08-30/amazon-eks-nodegroup.yaml > Next
* Specify Details
  * Stack name: hoge-eks-worker-nodes
  * ClusterName: hoge-eks-cluster # aws eks create-cluster で作成したクラスタの名前を書く。
  * ClusterControlPlaneSecurityGroup: sg-01612a9ab7bd7b236 # 上で作成した VPC の SecurityGroups
  * NodeGroupName: hoge-eks-node-group # なんでもいいい。
  * NodeImageId: ami-08cab282f9979fc7a # リージョンごとに違う
  * KeyName: hoge-eks-keypair # 上で作成したキーペアの名前
  * VpcId: vpc-0586bb50f37b84c72 # 上で作成した VPC の VpcId
  * Subnets: subnet-04d20fe635763c36d,subnet-05a3c2235ce29c339,subnet-0a2cba5164ce5f198 # 上で作成した VPC の subnet
* 必要に応じて Tags を入れる > Next
* I acknowledge that AWS CloudFormation might create IAM resources. をチェック > Create

Outputs > NodeInstanceRole を控えておく

* NodeInstanceRole: arn:aws:iam::xxxxx:role/hoge-eks-worker-nodes-NodeInstanceRole-8662QRNALFAN

## ワーカーノードをクラスターの結合

aws-auth-cm.yaml を作成し rolearn に NodeInstanceRole を記述

```
apiVersion: v1
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system
data:
  mapRoles: |
    - rolearn: arn:aws:iam::xxxxx:role/hoge-eks-worker-nodes-NodeInstanceRole-8662QRNALFAN
      username: system:node:{{EC2PrivateDNSName}}
      groups:
        - system:bootstrappers
        - system:nodes
```

適用

```
$ kubectl apply -f aws-auth-cm.yaml
configmap "aws-auth" created
```

動作確認

```
$ kubectl get nodes
NAME                                            STATUS    ROLES     AGE       VERSION
ip-192-168-122-23.us-west-2.compute.internal    Ready     <none>    1m        v1.10.3
ip-192-168-133-252.us-west-2.compute.internal   Ready     <none>    1m        v1.10.3
ip-192-168-209-79.us-west-2.compute.internal    Ready     <none>    1m        v1.10.3
```

## Guest Book のサンプルを動かす

```
kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/v1.10.3/examples/guestbook-go/redis-master-controller.json
kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/v1.10.3/examples/guestbook-go/redis-master-service.json
kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/v1.10.3/examples/guestbook-go/redis-slave-controller.json
kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/v1.10.3/examples/guestbook-go/redis-slave-service.json
kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/v1.10.3/examples/guestbook-go/guestbook-controller.json
kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/v1.10.3/examples/guestbook-go/guestbook-service.json
kubectl get services -o wide
```

http://a33ef341ab17d11e8809d0a672eabb93-2075656303.us-west-2.elb.amazonaws.com:3000

## 削除

```
kubectl delete rc/redis-master rc/redis-slave rc/guestbook svc/redis-master svc/redis-slave svc/guestbook
aws cloudformation delete-stack --stack-name hoge-eks-worker-nodes
aws cloudformation delete-stack --stack-name hoge-eks-vpc
aws ec2 delete-key-pair --key-name hoge-eks-keypair
aws iam detach-role-policy --role-name hoge-role --policy-arn arn:aws:iam::aws:policy/AmazonEKSClusterPolicy
aws iam detach-role-policy --role-name hoge-role --policy-arn arn:aws:iam::aws:policy/AmazonEKSServicePolicy
aws iam delete-role --role-name hoge-role
```

何故か subnet がいつも消えないで残る。

## 参考

* [【まずは触って体験】リリース直後のAmazon EKSでサンプルアプリケーションを動かしてみた](https://dev.classmethod.jp/cloud/aws/eks-getting-started/)
* [Getting Started with Amazon EKSが長いので自動化してみた](https://qiita.com/os1ma/items/2bc38867c5cd9a6ae020)
* [フォーラム](https://forums.aws.amazon.com/forum.jspa?forumID=303)