ローカル環境でKubernetesクラスタを構築するkindをさくらのクラウドで動かす

ローカル環境でKubernetesクラスタを構築するkindをさくらのクラウドで動かしてみます。
https://kind.sigs.k8s.io

kindはDocker上にKubernetesクラスタを構築します。1つのサーバ上で試験的にクラスタを構築したい場合には最適です。

ローカルKubernetesクラスタの構築ツールとしてminikubeもありますが、
kindはマルチノードクラスタに対応しているため要件によってはkindが良いと思います。

今回はmaster node 1つ、worker node 2つの構成で構築をします。

## 事前準備
kindが動く条件として、Dockerがインストールされていることが必要になります。
さくらのクラウドにはDockerを自動でインストールするスタートアップスクリプトがあるのでそれを使いました。

サーバのスペックは余裕を持って4Core / 4GB / SSD 20GBを選択しました。
場合によっては適切なスペックに変更しても良いかもしれません。
スタートアップスクリプト `Docker Engine CE for CentOS 7` を選択してサーバを作成します。

## kubectlのインストール、bash補完有効化
```bash
yum install bash-completion -y
curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
chmod +x ./kubectl
mv ./kubectl /usr/local/bin/kubectl
echo 'source <(kubectl completion bash)' >>~/.bashrc
kubectl completion bash >/etc/bash_completion.d/kubectl
```

## kindインストール
```bash
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.8.1/kind-$(uname)-amd64
chmod +x ./kind
mv ./kind /usr/local/bin/
```

## 設定ファイル作成
```yaml:kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "ingress-ready=true"
        authorization-mode: "AlwaysAllow"
  extraPortMappings:
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP
- role: worker
- role: worker
```
## クラスタの作成
```bash
kind create cluster --config kind-config.yaml
Creating cluster "kind" ...
 ✓ Ensuring node image (kindest/node:v1.17.0) 🖼
 ✓ Preparing nodes 📦 📦 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
 ✓ Joining worker nodes 🚜
Set kubectl context to "kind-kind"
You can now use your cluster with:

kubectl cluster-info --context kind-kind

Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂
```

```bash
kubectl get nodes
NAME                 STATUS   ROLES    AGE   VERSION
kind-control-plane   Ready    master   98m   v1.17.0
kind-worker          Ready    <none>   98m   v1.17.0
kind-worker2         Ready    <none>   98m   v1.17.0
```

## helmの有効化
```bash
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
helm repo add stable https://kubernetes-charts.storage.googleapis.com/
```

## ingress有効化
```bash
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml
kubectl patch deployments -n ingress-nginx nginx-ingress-controller -p '{"spec":{"template":{"spec":{"containers":[{"name":"nginx-ingress-controller","ports":[{"containerPort":80,"hostPort":80},{"containerPort":443,"hostPort":443}]}],"nodeSelector":{"ingress-ready":"true"},"tolerations":[{"key":"node-role.kubernetes.io/master","operator":"Equal","effect":"NoSchedule"}]}}}}'
```

## ingressの動作確認
ingressではホスト名にIPアドレスを設定することができないため、ワイルドカードDNSサービスnip.ioを利用します。
サーバのグローバルIPアドレス.nip.io とすることでサーバのグローバルIPアドレスが返ってきます。

```
$ dig +short 1.2.3.4.nip.io
1.2.3.4
```

```bash
kubectl apply -f https://kind.sigs.k8s.io/examples/ingress/usage.yaml
kubectl patch ingresses example-ingress --type='json' -p='[{"op": "replace", "path": "/spec/rules/0/host", "value":"サーバのグローバルIPアドレス.nip.io"}]'
curl サーバのグローバルIPアドレス.nip.io/foo
foo
```

## firewall
Webサーバを外部に公開する場合はfirewallの設定をします。

```bash
firewall-cmd --zone=public --add-service=http --permanent
firewall-cmd --reload
```

最低限Kubernetesクラスタで必要なものが動くことが確認できました。
すぐにクラスタが立ち上がってくるのでE2Eテストなどにちょうどいいですね。