AWS EC2にkubeadmでkubernetesクラスタ構築

kubernetesが公式に提供しているクラスタ構築ツール「kubeadm」で
AWS EC2上にk8sクラスタを構築したメモ。

k8s ver. v1.12.2

kubeadmは現在β版で、2018年中にGAになる予定。

###参考）その他のクラスタ構築ツール

kubernetesクラスタ構築ツールはほかにもいろいろある。

・Kubespray（Ansibleベース）
　:https://github.com/kubernetes-incubator/kubespray

・kube-aws（Cloud Formationベース）
　:https://github.com/kubernetes-incubator/kube-aws

・kops
　: https://github.com/kubernetes/kops

・Rancher（2.0～）
　：https://rancher.com/

ちょっとした検証用にシングルクラスターを立てたい場合はこれ
・minikube
　:https://kubernetes.io/docs/setup/minikube/

#インスタンスと環境

・CentOS 7　※Marketplaceから
・t3.small

※最低限以下のスペックが必要なので、t2.microなどはNG
2 GB or more of RAM per machine
2 CPUs or more

###SG関連

Master/Workerでは、最低限以下を許可する必要あり

![k8sport.png](https://qiita-image-store.s3.amazonaws.com/0/112537/caf17b4d-73ee-1b28-6d93-7e8396dc65d8.png)


#事前環境設定

コンテナランタイムにはcri-oやcontainerdなども利用できるが、ここではdockerの例。
yum updateと、dockerのinstallのみ。

```
sudo su
yum update -y
yum install -y docker
systemctl start docker
systemctl enable docker.service
```

#kubeadmセットアップ
参考）
https://kubernetes.io/docs/setup/independent/install-kubeadm/

###①リポジトリの追加
```
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
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kube*
EOF
```

###②SE Linuxの無効化
```
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
```

###③kubeadm/kubelete/kubectlをインストール
```
yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
systemctl enable kubelet && systemctl start kubelet
```

###④非root権限ユーザ向けのconfig設定
非rootユーザでkubectlを実行するための設定
※対象ユーザで実行

```
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
```


#クラスタ構築
参考）
https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/

###①master

master用インスタンスでroot権限で`kubeadm init`を実行。
各種オプションがある。
例えば、k8sバージョンを指定したい場合は`--kubernetes-version` で指定可能。無指定で実行したところ、最新の1.12.2がインストールされた。
https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-init/

試しにバージョン指定でv1.8.0を試したが、kubeadmのバージョンで、対象のk8sバージョンも制約がある。
v1.12.2のkubeadmの場合、k8sはv1.11.0以上しか指定できない。

```
this version of kubeadm only supports deploying clusters with the control plane version >= 1.11.0.
```

HA(高可用性)構成のk8sクラスタにするには、SPoFとなるMasterノードやetcdの冗長化などの対応が考えられるが、ここでは両者シングル構成で。

Pod間通信のためには、オーバーレイネットワーク(Container Network Interface (CNI))構築用のオプションをつける。
CNIには各種選択肢があるが、ここではflannelを例に。

```
kubeadm init --pod-network-cidr=10.244.0.0/16
```
成功すると、以下のようなコマンドが表示される

```
kubeadm join 172.16.XXX.XXX:6443 --token XXXXXX.XXXXXX --discovery-token-ca-cert-hash sha256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

何かしらのエラーでやり直したい場合は

```
kubeadm reset
```

initが成功したらflannelを設定（k8s上にインストール）

```
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
```

必要なコンポーネントが正しく設定されているか確認。

```
kubectl get pods --all-namespaces
NAMESPACE     NAME                                                                       READY   STATUS    RESTARTS   AGE
kube-system   coredns-576cbf47c7-j6k87                                                   1/1     Running   0          9m5s
kube-system   coredns-576cbf47c7-zvmpk                                                   1/1     Running   0          9m5s
kube-system   etcd-ip-172-16-30-117.ap-northeast-1.compute.internal                      1/1     Running   0          8m13s
kube-system   kube-apiserver-ip-172-16-30-117.ap-northeast-1.compute.internal            1/1     Running   0          8m27s
kube-system   kube-controller-manager-ip-172-16-30-117.ap-northeast-1.compute.internal   1/1     Running   0          8m17s
kube-system   kube-flannel-ds-amd64-795pv                                                1/1     Running   0          3m
kube-system   kube-flannel-ds-amd64-dglpv                                                1/1     Running   0          3m
kube-system   kube-proxy-6x9s8                                                           1/1     Running   0          6m51s
kube-system   kube-proxy-m9fgg                                                           1/1     Running   0          9m5s
kube-system   kube-scheduler-ip-172-16-XXX-XXX.ap-northeast-1.compute.internal            1/1     Running   0          8m22s
```

全て Running になってればOK

###②worker

kubeadmのセットアップまでが完了した後で、masterのkubeadm init実行時に発行されたkubeadm joinのコマンドを実行

```
kubeadm join 172.16.XXX.XXX:6443 --token XXXXXX.XXXXXX --discovery-token-ca-cert-hash sha256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

すると、masterノードにて、該当のworkerが追加されていることがわかる

```
kubectl get nodes
NAME                                               STATUS   ROLES    AGE   VERSION
ip-172-16-30-117.ap-northeast-1.compute.internal   Ready    master   15m   v1.12.2
ip-172-16-59-104.ap-northeast-1.compute.internal   Ready    <none>   13m   v1.12.2
```

workerを追加したければ、同じ動作を繰り返す。

#サンプルPod実行

構築したk8sクラスタで、Deploymentでnginxを立ててみる。

master nodeでpodをスケジューリングしたい場合は、以下のコマンドを実行しておく。

```
kubectl taint nodes --all node-role.kubernetes.io/master-
```

参考）
https://kubernetes.io/docs/tasks/run-application/run-stateless-application-deployment/

nginx.yaml）

```
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
```

Deployment作成

```
kubectl create -f nginx.yaml
```

無事に作成できたことを確認

```
kubectl get deployment
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   2         2         2            2           4m4s
```

```
kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-5c689d88bb-6h64j   1/1     Running   0          2m4s
nginx-deployment-5c689d88bb-kwlwp   1/1     Running   0          2m4s
```

#Worker NodeがNotReady

Worker NodeがNotReadyの場合、kubeletが原因ならば、Workerで下記実行で復旧。

```
for SERVICES in kubelet docker ; do
    systemctl restart $SERVICES
    systemctl enable $SERVICES
    systemctl status $SERVICES
done
```