kubeadmによるKubernetesクラスタ構築 on AWS

Kubernetes公式のセットアップツール[kubeadm](https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/)を利用してのシングルマスター構成をAWS上に構築できるかのトライ。動作は確認、実働に耐えうるかについては未調査。

- Amazon Linux 2
- Nitro Systemベースのインスタンス

での動作の確認が目的

### kubeadm
公式のk8sクラスタ作成ツール。Kopsと違い一つノードの中からプロビジョニングしていくボトムアップなスタイルで、カスタマイズ性が高いのも特徴。

### Amazon Linux 2
K8Sが理想的に動作するのであれば、基本はベースOSはなんでもいいはずで、AWSで動作させるのであればメンテが便利なAmazon Linuxがベストのはず。EKS optimized AMIもAmazon Linux 2ベース。

### Nitro System
C5, M5, T3などのインスタンスの元のシステム。諸々すごいのだけれど、NW帯域幅が増大しているので積極的に利用したいインスタンス。
Kopsでは2018/10現在デフォルトで、ストレージアクセス速度を気にしてインスタンスストアを持つはM3インスタンスを利用しているのだけれど、もうM5dでいい気がする（mediumサイズはないけれど）

## 手順
- [Installing kubeadm](https://kubernetes.io/docs/setup/independent/install-kubeadm/)
- [Creating a single master cluster with kubeadm](https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/)
にそって実行していく。

### 下準備
- VPC
- Subnet
- Internet gateway
- RouteTable

については作成、設定しておく。めんどくさかったらDefaultVPCを利用すれば良い。
VPCについてはAction>Edit DNS Hostnameを「Yes」にしておく。こうすることでインスタンスのホストネーム(ip-xxx..)でプライベートIPを解決してくれるので、/etc/hostsを編集しなくてもノード間が通信できる。

### ベースAMIの作成
あらかじめ作成したサブネットに
- Amazon Linux 2
- t3.small (なるべく安く、かつ要求スペックがメモリ2GB以上のため)
を選択してEC2を起動する。ストレージは8GBあれば十分。T3 Unlimitedは時間さして変わらないと思うので外しておく。
セキュリティグループはまず22番SSHをMy IPにのみ開けたものを作成して付与したのち、このセキュリティ内からのAll traficを自己で許可するように設定。

sshでログインしたのち

```sh
# ともあれアップデート
sudo yum update -y
# docker インストール
sudo amazon-linux-extras install docker -y
# インスタンス起動時に自動でON
sudo systemctl enable docker && sudo systemctl start docker
# 公式ドキュメント通りだと2018/10現在キーの検証に失敗するので個別に入れる
sudo rpm --import https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
# リポジトリを登録
sudo bash -c "cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
EOF"
# kubelet, kubeadm, kubectlのインストール
sudo yum install -y kubelet kubeadm kubectl
# kubeletは自動起動するようにしておく
sudo systemctl enable kubelet && sudo systemctl start kubelet
# クラスタ構築・動作に必要なdocker imageについてあらかじめpullしておく
sudo kubeadm config images pull
```

ここまできたらインスタンスをstop, AMIを作成しておく。

### マスターノード
#### kubeadmでの初期化
先ほどstopしたインスタンスを再起動しマスターノードとする（AMIから改めて起こしても良い）
sshログインしkubeadmを実行。

```sh
# マスターとして起動、cidrはVPCのレンジに揃える
sudo kubeadm init --pod-network-cidr=10.0.0.0/16
```

うまくいけばしばらくすると
`kubeadm join a.b.c.d --token xxx... --discovery-token-ca-cert-hash sha256:yyy...`
のようなメッセージが出るので、これを控えておく（この後のノードの参加で利用する）

#### kubectlの設定
下記を打てと表示が出ているはずなので実行
```
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
```

これでkubectlコマンドが打てるようになる。

#### ネットワークの設定
[こちら](https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/#pod-network)にあるように、各Podが通信できるように仮想的なネットワークを敷く必要がある。と言ってもコマンド打つだけ。どれを選んだらいいのか分かりかねたのでKopsで使われてるWeaveを利用する。

```sh
# v1.2 は現在validation error が発生
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
```

### ワーカー
保存したAMIから起動して、マスターでinitした際に表示されたコマンドを打つ

```sh
sudo kubeadm join a.b.c.d --token xxx... --discovery-token-ca-cert-hash sha256:yyy...
```

うまくいけばマスターで`kubectl get node`を打てばワーカーが見えるようになっているはず。

---

- あらかじめネットワーク用のコンテナもpullしておけば制限があるNW上でも使えそう。
- Amazon VPC CNIも使えたら良かったのだけど、ECRからイメージ落とす必要あったり、結局 CoreDNSがうまく動かず一旦断念。