kind(Kubernetes in Docker)で学習を始めるまで

> 2019/11/1 kindのインストール方法を修正、MappingPortsの参考例を変更

Kubernetes in Dockerはご存知でしょうか？
[スライド](https://speakerdeck.com/masayaaoyama/cloudnativejp-09-kubernetes-in-docker-kind)を拝見して興味が湧いたので色々触ってみました。
上記スライドは全体像がわかりやすくまとまっていますので、ぜひご参照ください。

# はじめに

kindはdocker containerを利用してlocal環境にkubernetes clusterを構築します。
kubernetesの[conformance tests](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/conformance-tests.md)を最初の目的にデザインされており、テスト環境の構築やKubernetesのCI環境として利用される方法が[紹介](https://kind.sigs.k8s.io/docs/user/resources/)されています。
・Testing your K8s apps with KIND - Benjamin Elder & James Munnelly
・Deep Dive: Testing SIG - Benjamin Elder & James Munnelly
・Behind Your PR: How Kubernetes Uses Kubernetes to Run Kubernetes CI - Sen Lu & Benjamin Elder

kindは[kubernetes-sigs/kind](https://github.com/kubernetes-sigs/kind)で開発が進められています。詳細は[Documentation](https://kind.sigs.k8s.io/)を参照してください。

ただkindは下記の利点から「教育」といった点でも使えそうな気がしています。
・kubeadmよりも簡単にmulti-nodeでのkubernetes clusterを構築できる
・containerでnodeを用意できるのでclusterの数に対してリソースの使用効率が良い

ただ制限は多そうなので、初学者向けに社内の教育リソースといった形もいいんじゃないなと思いました。

# 始め方
### 仮想マシンの準備
今回はGCPのg1-smallを利用しています。

```sh
$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="18.04.3 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.3 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
```

### 事前準備

#### ~~go(1.11+)のインストール~~
~~[ドキュメント](https://golang.org/doc/install)を参考にインストールします。~~
~~1.13以上を推奨されていますので、用意しましょう。~~

~~`sudo rm -rf /usr/local/go`~~

~~`wget https://dl.google.com/go/go1.13.linux-amd64.tar.gz`~~

~~`sudo tar -C /usr/local/ -zxf go1.13.linux-amd64.tar.gz`~~

~~`export PATH=$PATH:/usr/local/go/bin`~~

~~`export GOPATH=$HOME/go`~~

~~`export PATH=$PATH:$GOPATH/bin`~~


#### ~~Goのコンパイラのインストール~~
~~`apt install gcc`~~

#### dockerのインストール
[ドキュメント](https://docs.docker.com/install/linux/docker-ce/ubuntu/)を参考にインストールします。
`sudo apt-get update`

`sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common`

`curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -`

`sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"`

`sudo apt-get update`

`sudo apt-get install docker-ce docker-ce-cli containerd.io`

#### kubectlのインストール
[ドキュメント](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/)を参考にインストールします。
本仮想マシンをkubernetesのnodeとして実行するわけではないので、kubeadmとkubeletは不要です。

`apt-get update && apt-get install -y apt-transport-https curl`

`curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -`

`cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF`

`apt-get update`

`apt-get install -y kubectl`

`apt-mark hold kubectl`

### kindのインストール
[kubernetes-sigs/kind](https://github.com/kubernetes-sigs/kind)を参考にインストールします。

~~`GO111MODULE="on" go get sigs.k8s.io/kind@v0.5.1`~~

`curl -Lo ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.5.1/kind-$(uname)-amd64`
`chmod +x ./kind`
`sudo mv ./kind /usr/bin/kind`

GOを利用したインストール方法も提示されていますが、binaryをダウンロードする方が簡単なので、そちらに修正しました。(2019/11/1)

### clusterの作成
clusterを作成します。
内容によりますがsingle node clusterはおおよそ30秒ほどで作成できます。（早い！簡単！素敵！）

#### rootで作成する場合
`kind create cluster`のコマンドにてsingle node clusterが作成できます。
作成できたら、アクセするための設定ファイルが`~/.kube/kind-config-CLUSTERNAME`で生成されます。
kubectlはデフォルトでは設定ファイルとして`~/.kube/config`を参照しているため、`export KUBECONFIG=`によってkindで生成された設定ファイルを参照するように変更します。

```sh
$ sudo su
# kind create cluster
Creating cluster "kind" ...
 ✓ Ensuring node image (kindest/node:v1.15.3) 🖼 
 ✓ Preparing nodes 📦 
 ✓ Creating kubeadm config 📜 
 ✓ Starting control-plane 🕹️ 
 ✓ Installing CNI 🔌 
 ✓ Installing StorageClass 💾 
Cluster creation complete. You can now use the cluster with:

export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"
kubectl cluster-info

# export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"
# kubectl cluster-info
Kubernetes master is running at https://127.0.0.1:40397
KubeDNS is running at https://127.0.0.1:40397/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
```
#### 一般ユーザーで作成する場合
```sh
$ sudo kind create cluster
Creating cluster "kind" ...
 ✓ Ensuring node image (kindest/node:v1.15.3) 🖼 
 ✓ Preparing nodes 📦 
 ✓ Creating kubeadm config 📜 
 ✓ Starting control-plane 🕹️ 
 ✓ Installing CNI 🔌 
 ✓ Installing StorageClass 💾 
Cluster creation complete. You can now use the cluster with:

export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"
kubectl cluster-info
```

[Issues #282](https://github.com/kubernetes-sigs/kind/issues/282)でも議論されていますが、一般ユーザーはsudoを付与しないとclusterを作成できません。これはkindが利用するdockerに[セキュリティの考え方](https://docs.docker.com/install/linux/linux-postinstall/)として以下があるためです。(間違ってたら指摘お願いします！)

>The Docker daemon binds to a Unix socket instead of a TCP port. By default that Unix socket is owned by the user root and other users can only access it using sudo. The Docker daemon always runs as the root user.
>If you don’t want to preface the docker command with sudo, create a Unix group called docker and add users to it. When the Docker daemon starts, it creates a Unix socket accessible by members of the docker group.

ただsudoありきで実行すると作成されるkubeconfigファイルがroot権限で作成されるため読み込めません。また、root userで実行しようとすると、`kind create cluster`を実行したのは一般ユーザーのためroot userのdirectoryには存在しないのでkubeconfigをコピーするなど多くの手間が必要です。

ちなみに、sudoなしだとこのように失敗します。

```sh
$ kind create cluster 
Error: could not list clusters: failed to list nodes: exit status 1
```

そこでセキュリティの問題を回避するために推奨はできませんが、自己責任を前提として案内されているdockerをsudoなしでも実行できるように変更することで一般ユーザーでもclusterを作成ができます。

`sudo groupadd docker`

`sudo gpasswd -a $USER docker`

`sudo systemctl restart docker`

`exit`

```sh
$ kind create cluster
Creating cluster "kind" ...
 ✓ Ensuring node image (kindest/node:v1.15.3) 🖼
 ✓ Preparing nodes 📦 
 ✓ Creating kubeadm config 📜 
 ✓ Starting control-plane 🕹️ 
 ✓ Installing CNI 🔌 
 ✓ Installing StorageClass 💾 
Cluster creation complete. You can now use the cluster with:

export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"
kubectl cluster-info

$ export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"
$ kubectl cluster-info
Kubernetes master is running at https://127.0.0.1:41785
KubeDNS is running at https://127.0.0.1:41785/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
```

# 基本的な操作方法
kindには下記のコマンドが用意されています。

```sh
$ kind -h | grep Ava -A 9
Available Commands:
  build       Build one of [base-image, node-image]
  completion  Output shell completion code for the specified shell (bash or zsh)
  create      Creates one of [cluster]
  delete      Deletes one of [cluster]
  export      exports one of [logs]
  get         Gets one of [clusters, nodes, kubeconfig, kubeconfig-path]
  help        Help about any command
  load        Loads images into nodes
  version     prints the kind CLI version
```
### kind create 
このコマンドはkindを利用してclusterを作成するために用います。
`--name`を使用して、clusterの名前を指定しますが、デフォルトでは`kind`が利用されます。
`--config`を使用して、YAMLで作成したkindの設定ファイルを読みこます。設定ファイルについては次の章で整理したいと思います。デフォルトではなければsingle nodeのclusterが作成されます。

`kind create cluster --name CLUSTERNAME --config CONFIGFILE`

### kind delete
このコマンドはkindで作成したclusterを削除するために用います。
`--name`を使用して、clusterの名前を指定しますが、デフォルトでは`kind`が利用されます。

`kind cluster delete --name CLUSTERNAME`

### kind export
このコマンドはkindで作成したcluster上のログを収集してexportしてくれます。
`--name`を使用して、clusterの名前を指定しますが、デフォルトでは`kind`が利用されます。

`kind export logs --name CLUSTERNAME`

以下を見ていいたらわかると思いますが、要は`/var/log/`を引っ張ってきてくれます。

```sh
$ kind export logs kind/1/
Exported logs to: kind/1/

$ tree kind/
kind/
└── 1
    ├── docker-info.txt
    └── kind-control-plane
        ├── containerd.log
        ├── containers
        │   ├── coredns-5c98db65d4-2mwxv_kube-system_coredns-17f53b5bffcfc02853a00e9e4cecc182d2f061ddf10ed2ba2b2f8f60f79358e8.log
        │   ├── coredns-5c98db65d4-ng8wh_kube-system_coredns-c3514496e2991685f8bf41da0bb545d5211ae3a22b0ea3e1469c0949b113be4f.log
        │   ├── etcd-kind-control-plane_kube-system_etcd-fedabc3f330bf5c3d17527716bd99f1b42b335f5cea53b265d858ec7481f36d1.log
        │   ├── kindnet-6544l_kube-system_kindnet-cni-44232004cd128fbd97c01103cb9ad0ac603092acba1000be7b0839828b97eef2.log
        │   ├── kindnet-6544l_kube-system_kindnet-cni-8df3d0ada87a2224c9e25d2081dc9d5c4d6c2fd35863b7a385d97c66c44122e5.log
        │   ├── kube-apiserver-kind-control-plane_kube-system_kube-apiserver-7965bca6f71a7af2961a544151fcaee43cf2b972edf3ee7962267e7d601e6965.log
        │   ├── kube-controller-manager-kind-control-plane_kube-system_kube-controller-manager-966e29b8434a7e3cdc5ffe840ea7ec83110bb1a719389c56acc142b1debf9fbe.log
        │   ├── kube-proxy-vrsmx_kube-system_kube-proxy-7294cbb0f6c3c7af81373a81b7cfc42225d4de08e7a23b21972c4d645651fa5c.log
        │   └── kube-scheduler-kind-control-plane_kube-system_kube-scheduler-b544767c02d1178023190f12b895fae85539d4cbdabbeab75b5cf82d3fab46a1.log
        ├── inspect.json
        ├── journal.log
        ├── kubelet.log
        ├── kubernetes-version.txt
        ├── pods
        │   ├── kube-system_coredns-5c98db65d4-2mwxv_2b415b37-094c-4d25-91f5-9257d8a29c17
        │   │   └── coredns
        │   │       └── 0.log
        │   ├── kube-system_coredns-5c98db65d4-ng8wh_8395d6c9-5cab-43da-800a-68be3aba6ca6
        │   │   └── coredns
        │   │       └── 0.log
        │   ├── kube-system_etcd-kind-control-plane_9cc88ff6505632640f7c61b0ed5a3af7
        │   │   └── etcd
        │   │       └── 0.log
        │   ├── kube-system_kindnet-6544l_758f183e-cd87-4fd3-afe1-10be7885d31a
        │   │   └── kindnet-cni
        │   │       ├── 0.log
        │   │       └── 1.log
        │   ├── kube-system_kube-apiserver-kind-control-plane_397622360c18dfe95f5589542d5d0eee
        │   │   └── kube-apiserver
        │   │       └── 0.log
        │   ├── kube-system_kube-controller-manager-kind-control-plane_c033e463e836024d2f4018a10e4dec76
        │   │   └── kube-controller-manager
        │   │       └── 0.log
        │   ├── kube-system_kube-proxy-vrsmx_27844f5e-021f-4bd5-99bf-11a02027609e
        │   │   └── kube-proxy
        │   │       └── 0.log
        │   └── kube-system_kube-scheduler-kind-control-plane_7d5d3c0a6786e517a8973fa06754cb75
        │       └── kube-scheduler
        │           └── 0.log
        └── serial.log

20 directories, 25 files
```

### kind get
このコマンドはkindで管理している下記の情報を確認できます。作成したcluster上のログを収集してexportしてくれます。
`--name`を使用して、clusterの名前を指定しますが、デフォルトでは`kind`が利用されます。

`kind get clusters`により、作成しているcluster一覧を確認できます。
`kind get nodes`により、kindで作成しているnode一覧を確認できます。
`kind get kubeconfig-path`により、kindで作成したclusterのkubeconfig file名が参照できます。
`kind get kubeconfig`により、kindで作成したkubeconfigの中身が参照できます。

```sh
$ kind get clusters
kind

$ kind get nodes
kind-control-plane

$ kind get kubeconfig-path
/home/sour/.kube/kind-config-kind

$ kind get kubeconfig
apiVersion: v1
clusters:
---snip---
```
### kind version
このコマンドはkindのversionを確認できます。

```sh
$ kind version
v0.5.1
```

### kind load
このコマンドはkindで管理しているclusterのnodeに、ホストにあるdocker imageを配置することができます。
ただdocker imageはregistryに置くかと思うので使うケースは多くはないのかな？と勝手に思っています。（実際にビジネスで利用している皆さんからすると有用なんですかね？教えてください！）

`kind load docker-image IMAGENAME:TAG --name CLUSTERNAME --nodes NODENAME`

### kind build
このコマンドはkindによって作成するclusterで利用するimageのbuildを行います。
imageには以下の２種類が用意されています。

- base image

簡単にはkubernetes clusterを構築するためのnode imageを作成するために利用するimageです。[ドキュメント](https://kind.sigs.k8s.io/docs/design/base-image/)にも記載がありますが、kubernetesを構築するための周辺の機能の下準備です。
kindest/baseで管理されており[DockerHub](https://hub.docker.com/r/kindest/base) / [GitHub](https://github.com/kubernetes-sigs/kind/tree/master/images/base)で確認できます。
ちなみにUbuntu:18.04を利用していると記載がありますが、すでにUbuntu:19.04に変更されているようです。

- node image

簡単にはkubernetes clusterを構築するためのimageです。base-imageを元にkubernetes sourceを利用して任意のbuild imageを作成可能です。
~~ちょうどKubernetes v1.16がリリースされたので、下記のように作れます。~~

> errorでうまく進まず、、成功の参考があればぜひ教えてください。テストしてうまくいった内容に修正したいと思っています。

```sh
$ wget https://dl.k8s.io/v1.16.0/kubernetes-src.tar.gz
$ mkdir ./kubernetes
$ sudo tar -zxf kubernetes-src.tar.gz -C ~/kubernetes
$ kind build node-image --kube-root ./kubernetes --image k8s:1.16
---snip---
ERRO[10:55:21] Failed to build Kubernetes: failed to build binaries: exit status 1 
Error: error building node image: failed to build kubernetes: failed to build binaries: exit status 1
```

`kind build node-image`には下記のオプションを利用することができます。
`--kind-root`オプションでkubernetes sourceのdirectoryを指定することができます。
`--image`オプションでbuildして作成したimageのtagを指定することができます。

# 色々なCluster作成
kindはconfigファイルを利用して作成するclusterを設計できます。

### simple cluster(Master Node *1, Worker Node *2)
下記の設定ファイルで作成できます。勉強環境として構築する機会の多い構成かと思います。

```sh
$ cat simple-k8s.yaml 
kind: Cluster
apiVersion: kind.sigs.k8s.io/v1alpha3
nodes:
- role: control-plane
- role: worker
- role: worker
- 
$ kind create cluster --config simple-k8s.yaml --name simple-k8s
Creating cluster "simple-k8s" ...
 ✓ Ensuring node image (kindest/node:v1.15.3) 🖼 
 ✓ Preparing nodes 📦📦📦 
 ✓ Creating kubeadm config 📜 
 ✓ Starting control-plane 🕹️ 
 ✓ Installing CNI 🔌 
 ✓ Installing StorageClass 💾 
 ✓ Joining worker nodes 🚜 
Cluster creation complete. You can now use the cluster with:

export KUBECONFIG="$(kind get kubeconfig-path --name="simple-k8s")"
kubectl cluster-info
```

作成できると、`docker ps`にてcontainerとして起動していることが確認できます。

``` sh
$ docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                                  NAMES
619975e16299        kindest/node:v1.15.3   "/usr/local/bin/entr…"   52 minutes ago      Up 50 minutes                                              simple-k8s-worker
84fa2c237f90        kindest/node:v1.15.3   "/usr/local/bin/entr…"   52 minutes ago      Up 50 minutes       34839/tcp, 127.0.0.1:34839->6443/tcp   simple-k8s-control-plane
63ff3d8cdadd        kindest/node:v1.15.3   "/usr/local/bin/entr…"   52 minutes ago      Up 50 minutes                                              simple-k8s-worker2
```

### HA cluster(Master Node *3, Worker Node *3)
下記の設定ファイルで作成できます。

```sh
$ cat ha-k8s.yaml 
kind: Cluster
apiVersion: kind.sigs.k8s.io/v1alpha3
nodes:
- role: control-plane
- role: control-plane
- role: control-plane
- role: worker
- role: worker
- role: worker
```

### Option: Mapping Ports
下記の設定ファイルにある`extraPortMappings`を利用することで、HostとContainerで開けるportを追加できます。

(2019/11/01 port80開けてもnodePortと合わず、現実的ではないので下記の例を変えました。)
例えばkindで作成したkubernetes cluster内でNode Portなどでtcp:30001を利用している場合に、host側でportがcontainerと接続されていないためアクセスできません。
そういった外部から指定したportでアクセスするテストをする場合には、このオプションで開ける必要があります。

```sh
kind: Cluster
apiVersion: kind.sigs.k8s.io/v1alpha3
nodes:
- role: control-plane
- role: worker
  extraPortMappings:
  - containerPort: 30001
    hostPort: 30001
```

例えば以下のように比較するとわかりやすいですが、空いているportが増えています。
ただ注意点は、Dockerと同じでhost portは重複できないので調整することは必要です。

```sh
$ docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                                  NAMES
d4f7d91fc32b        kindest/node:v1.15.3   "/usr/local/bin/entr…"   11 minutes ago      Up 11 minutes       61745/tcp, 127.0.0.1:61745->6443/tcp   simple-control-plane
c010aea876d5        kindest/node:v1.15.3   "/usr/local/bin/entr…"   11 minutes ago      Up 11 minutes       0.0.0.0:30001->30001/tcp               simple-worker
````

以下のようにアクセスが確認できました。

```
$ kubectl get pod,svc
NAME        READY   STATUS    RESTARTS   AGE
pod/nginx   1/1     Running   0          6m40s

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
service/kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        11m
service/nginx        NodePort    10.108.0.28   <none>        80:30001/TCP   5m39s

$ curl 127.0.0.1:30001
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
```

ちなみにcontrol-planeにportが空いていますが、これはhostからMaster Nodeのkube-apiserverにアクセスするためのport番号です。

```sh
$ kind get kubeconfig --name simple | grep server
    server: https://127.0.0.1:61745
```

# clusterの確認

### 正常性確認
問題なく動いていそうです。

```sh
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.0", GitCommit:"2bd9643cee5b3b3a5ecbd3af49d09018f0773c77", GitTreeState:"clean", BuildDate:"2019-09-18T14:36:53Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.3", GitCommit:"2d3c76f9091b6bec110a5e63777c332469e0cba2", GitTreeState:"clean", BuildDate:"2019-08-20T18:57:36Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"linux/amd64"}

$ kubectl cluster-info
Kubernetes master is running at https://127.0.0.1:34839
KubeDNS is running at https://127.0.0.1:34839/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

$ kubectl get node
NAME                       STATUS   ROLES    AGE   VERSION
simple-k8s-control-plane   Ready    master   37m   v1.15.3
simple-k8s-worker          Ready    <none>   36m   v1.15.3
simple-k8s-worker2         Ready    <none>   36m   v1.15.3

$ kubectl get pod --all-namespaces
NAMESPACE     NAME                                               READY   STATUS    RESTARTS   AGE
kube-system   coredns-5c98db65d4-2f6lt                           1/1     Running   0          37m
kube-system   coredns-5c98db65d4-mtqtg                           1/1     Running   0          37m
kube-system   etcd-simple-k8s-control-plane                      1/1     Running   1          36m
kube-system   kindnet-4nwgv                                      1/1     Running   1          37m
kube-system   kindnet-kx656                                      1/1     Running   1          37m
kube-system   kindnet-m96kc                                      1/1     Running   1          37m
kube-system   kube-apiserver-simple-k8s-control-plane            1/1     Running   0          36m
kube-system   kube-controller-manager-simple-k8s-control-plane   1/1     Running   7          36m
kube-system   kube-proxy-7jck9                                   1/1     Running   0          37m
kube-system   kube-proxy-h2lmd                                   1/1     Running   0          37m
kube-system   kube-proxy-x9mcn                                   1/1     Running   0          37m
kube-system   kube-scheduler-simple-k8s-control-plane            1/1     Running   4          36m
```

### PodのDeploy
問題なさそうですね。

```sh
$ kubectl run bb --image=busybox:1.28 --replicas=2 --command -- sleep 4800 
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/bb created

$ kubectl get deploy,rs,pod
NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/bb   2/2     2            2           14s

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.extensions/bb-6576d769b8   2         2         2       14s

NAME                      READY   STATUS    RESTARTS   AGE
pod/bb-6576d769b8-9n65d   1/1     Running   0          14s
pod/bb-6576d769b8-mswjk   1/1     Running   0          14s
```

### リソースの使用率
control-planeはやはりメモリの使用率が高いですね。RAM 1GB程度あればMaster node *1, Worker node *2の構成をケチケチ使うなら耐えられそうです。

```sh
$ docker container stats
CONTAINER ID        NAME                 CPU %               MEM USAGE / LIMIT    MEM %               NET I/O             BLOCK I/O           PIDS
1b6785dcd7b6        kind-worker2         1.43%               74.55MiB / 1.65GiB   4.41%               97.5kB / 56.7kB     10.4MB / 57.3kB     28
ac5bf48abfe4        kind-worker          1.47%               73.89MiB / 1.65GiB   4.37%               104kB / 60.2kB      14.7MB / 98.3kB     28
ee4fbad67374        kind-control-plane   7.00%               821.7MiB / 1.65GiB   48.63%              119kB / 196kB       88.4MB / 52MB       213
```

### Nodeにアクセス
kubectlだけではなく、該当nodeに直接アクセスしたい場合があると思います。その時はdockerを利用していた時と同じで、`docker exec -it CONTAINERID bash`で操作が可能です。

```sh
$ docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                                  NAMES
619975e16299        kindest/node:v1.15.3   "/usr/local/bin/entr…"   47 minutes ago      Up 46 minutes                                              simple-k8s-worker
84fa2c237f90        kindest/node:v1.15.3   "/usr/local/bin/entr…"   47 minutes ago      Up 46 minutes       34839/tcp, 127.0.0.1:34839->6443/tcp   simple-k8s-control-plane
63ff3d8cdadd        kindest/node:v1.15.3   "/usr/local/bin/entr…"   47 minutes ago      Up 46 minutes                                              simple-k8s-worker2

$ docker exec -it 84 bash
root@simple-k8s-control-plane:/# 
```
### Directoryの確認
kindの内部でkubeadmを利用してノードの構成や証明書を処理しています。これは[ドキュメント](https://kind.sigs.k8s.io/docs/design/principles/)にも書かれていますが可能な限り車輪の再発明を避けるためです。そのため、Master nodeにおけるdirectory構造は同じです。

>Where possible we should not reinvent the wheel.
Examples include:
・kubeadm is used to handle node configuration, certificates, etc.
・kustomize is used to handle merging user provided config patches with our generated kubeadm configs
・k8s.io/apimachinery is used to build our own configuration functionality
・In general we re-use k8s.io utility libraries and generators

>Re-implementing some amount of functionality is expected, particularly between languages and for internal / insufficiently-generic components, but in general we should collaborate where possible.

```sh
root@simple-k8s-control-plane:/# ls /etc/kubernetes/
admin.conf  controller-manager.conf  kubelet.conf  manifests  pki  scheduler.conf
```

### kind directoryの構造
kindのclusterコマンドがclusterを構成する際に利用するファイル群が`/kind`に保存されています。これは、Master NodeやWorker Node関係なく保存されています。

```sh
root@simple-k8s-control-plane:/# ls /kind/
bin  kubeadm.conf  manifests  product_name  systemd  version
```

[ドキュメント](https://kind.sigs.k8s.io/docs/design/node-image/)も参照ください。

>Other than the requirement that this image inherits from the “base” image, which provides most of the tools statically needed for a kubernetes deployment (eg systemd), variants of this image have the following properties:
・/kind/images/ contains various *.tar files which are Docker image archives, these images will be loaded by the cluster tooling prior to running kubeadm
・kubeadm, kubectl, kubelet are in the path
・A systemd service is enabled for kubelet, and is configured to not fail on swap being enabled. (we must do the latter because swap is inherited from the host and we don’t want to force users to disable swap before using kind)
・/kind/version is a regular text file containing the gitVersion of the installed Kubernetes build
These properties are used by the cluster tooling to boot each “node” container with kubeadm.

# まとめ
長々となりましたが、kindは触れば触るほど使い道の可能性を感じますね。
社内にkindを利用した「kubernetesを触ってみよう」環境を作るのに良さそうなので、作ったらQiitaにまとめたいと思います。

node-imageのbuild失敗に関しては継続的に原因を調べて解決したら更新したいと思います。

読んでいただきありがとうございました。