kindは、Docker コンテナのノード上で動作するKubeneteクラスタである。Kubernetesのセルフテストのために開発されたものだが、ローカル環境での開発に利用できるかもしれない。仮想マシンを利用するKubernetesクラスタに比べると、軽量で起動も早い。しかし、非常にクセが強いので、開発環境に使えるかは判断が必要だ。
kindのインストール
Macの例であるが、インストールは極めて簡単だ。
$ brew install kind
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 4 taps (homebrew/core, homebrew/cask, minio/stable and argoproj/tap).
<以下省略>
とりあえず起動
動作確認も兼ねて、とりあえず、構成ファイルを指定しないで、起動して見る。
$ kind create cluster
Creating cluster "kind" ...
✓ Ensuring node image (kindest/node:v1.18.2) 🖼
✓ Preparing nodes 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
Set kubectl context to "kind-kind"
You can now use your cluster with:
kubectl cluster-info --context kind-kind
Thanks for using kind! 😊
起動の確認として、APIサーバーの情報を表示してみる。
$ kubectl cluster-info --context kind-kind
Kubernetes master is running at https://127.0.0.1:49320
KubeDNS is running at https://127.0.0.1:49320/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
kind-control-plane Ready master 113s v1.18.2
今回のクラスタは削除して、次へすすむ。
$ kind delete cluster
Deleting cluster "kind" ...
マルチノードクラスタ
Kindでマルチノードクラスタを起動するには、以下の構成ファイルを作成する。nodes以下にノードの役割を記述するだけだ。
# three node (two workers) cluster config
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
構成ファイルを指定してクラスタを起動する。
$ kind create cluster --config config-multi-node.yaml
Creating cluster "kind" ...
✓ Ensuring node image (kindest/node:v1.18.2) 🖼
✓ Preparing nodes 📦 📦 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
✓ Joining worker nodes 🚜
Set kubectl context to "kind-kind"
<以下省略>
起動の確認としてノードをリストする。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready master 74s v1.18.2
kind-worker Ready <none> 39s v1.18.2
kind-worker2 Ready <none> 39s v1.18.2
起動しているポッドを全数表示する。
CoreDNS、etc、kube-apiserver, kube-controller-manager, kube-porxy, kube-scheduklerが動作しているのがわかる。
それから CNI のネットワークプラグインは、kindnet-* というポッドが使われているのがわかる。
$ kubectl get pod --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-66bff467f8-sx4c6 1/1 Running 0 2m18s
kube-system coredns-66bff467f8-tbnc4 1/1 Running 0 2m18s
kube-system etcd-kind-control-plane 1/1 Running 0 2m34s
kube-system kindnet-9hv4d 1/1 Running 1 2m3s
kube-system kindnet-plvx9 1/1 Running 0 2m17s
kube-system kindnet-sbrjh 1/1 Running 0 2m3s
kube-system kube-apiserver-kind-control-plane 1/1 Running 0 2m34s
kube-system kube-controller-manager-kind-control-plane 1/1 Running 0 2m34s
kube-system kube-proxy-ds9b9 1/1 Running 0 2m3s
kube-system kube-proxy-lmlk8 1/1 Running 0 2m17s
kube-system kube-proxy-n8bz8 1/1 Running 0 2m3s
kube-system kube-scheduler-kind-control-plane 1/1 Running 0 2m34s
local-path-storage local-path-provisioner-bd4bb6b75-r5t5d 1/1 Running 0 2m18s
Docker Desktop 上で動作しているので、docker ps で動作中のコンテナをリストして見る。ノードの分だけコンテナが動作しているのが判る。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9d393ea2af42 kindest/node:v1.18.2 "/usr/local/bin/entr…" 3 minutes ago Up 3 minutes kind-worker2
abe63ea3a5d1 kindest/node:v1.18.2 "/usr/local/bin/entr…" 3 minutes ago Up 3 minutes kind-worker
8278c8c43a52 kindest/node:v1.18.2 "/usr/local/bin/entr…" 3 minutes ago Up 3 minutes 127.0.0.1:49513->6443/tcp kind-control-plane
ストレージクラスを表示して確認する。プロビジョナーには local-pathが使われることが読み取れる。
$ kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
standard (default) rancher.io/local-path Delete WaitForFirstConsumer false 4m21s
マルチマスター
もう一つ、マルチノードのクラスタを構成してみる。
# a cluster with 3 control-plane nodes and 3 workers
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: control-plane
- role: control-plane
- role: worker
- role: worker
- role: worker
構成ファイルを指定して、クラスタを起動する。
$ kind create cluster --config config-multi-master.yaml
ノードをリストする。 EXTERNAL-IPが付与されない点に注目。
$ kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
kind-control-plane Ready master 4m43s v1.18.2 172.21.0.6 <none> Ubuntu 19.10 4.19.76-linuxkit containerd://1.3.3-14-g449e9269
kind-control-plane2 Ready master 4m13s v1.18.2 172.21.0.5 <none> Ubuntu 19.10 4.19.76-linuxkit containerd://1.3.3-14-g449e9269
kind-control-plane3 Ready master 3m26s v1.18.2 172.21.0.7 <none> Ubuntu 19.10 4.19.76-linuxkit containerd://1.3.3-14-g449e9269
kind-worker Ready <none> 3m11s v1.18.2 172.21.0.4 <none> Ubuntu 19.10 4.19.76-linuxkit containerd://1.3.3-14-g449e9269
kind-worker2 Ready <none> 3m11s v1.18.2 172.21.0.8 <none> Ubuntu 19.10 4.19.76-linuxkit containerd://1.3.3-14-g449e9269
kind-worker3 Ready <none> 3m10s v1.18.2 172.21.0.3 <none> Ubuntu 19.10 4.19.76-linuxkit containerd://1.3.3-14-g449e9269
全てのネームスペースのポッドを表して見る。マスターノード 3台のポッドは、それぞれ起動していることが判る。
maho:kind maho$ kubectl get pod --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-66bff467f8-64n5z 1/1 Running 0 6m4s
kube-system coredns-66bff467f8-vmcc8 1/1 Running 0 6m4s
kube-system etcd-kind-control-plane 1/1 Running 0 6m15s
kube-system etcd-kind-control-plane2 1/1 Running 0 5m37s
kube-system etcd-kind-control-plane3 1/1 Running 0 3m46s
kube-system kindnet-946cg 1/1 Running 0 6m3s
kube-system kindnet-c94gg 1/1 Running 0 4m45s
kube-system kindnet-gdpn8 1/1 Running 0 5m47s
kube-system kindnet-tzh4d 1/1 Running 0 4m44s
kube-system kindnet-x79zx 1/1 Running 2 5m
kube-system kindnet-zchc6 1/1 Running 2 4m45s
kube-system kube-apiserver-kind-control-plane 1/1 Running 0 6m15s
kube-system kube-apiserver-kind-control-plane2 1/1 Running 0 4m30s
kube-system kube-apiserver-kind-control-plane3 1/1 Running 1 3m53s
kube-system kube-controller-manager-kind-control-plane 1/1 Running 1 6m15s
kube-system kube-controller-manager-kind-control-plane2 1/1 Running 0 4m42s
kube-system kube-controller-manager-kind-control-plane3 1/1 Running 0 3m57s
kube-system kube-proxy-7ffq2 1/1 Running 0 4m45s
kube-system kube-proxy-8hdbb 1/1 Running 0 6m3s
kube-system kube-proxy-fpds6 1/1 Running 0 5m
kube-system kube-proxy-kbwss 1/1 Running 0 4m45s
kube-system kube-proxy-lvkrc 1/1 Running 0 4m44s
kube-system kube-proxy-wd5rm 1/1 Running 0 5m47s
kube-system kube-scheduler-kind-control-plane 1/1 Running 1 6m15s
kube-system kube-scheduler-kind-control-plane2 1/1 Running 0 4m36s
kube-system kube-scheduler-kind-control-plane3 1/1 Running 0 4m
local-path-storage local-path-provisioner-bd4bb6b75-wqp5k 1/1 Running 1 6m4s
コンテナからノードに入って、プロセスの状況を確認してみる。contianerd と kubelet が起動していることが読み取れる。
$ docker exec -it 16a5392ba6c6 bash
root@kind-control-plane:/# ps -ax
PID TTY STAT TIME COMMAND
1 ? Ss 0:00 /sbin/init
114 ? S<s 0:00 /lib/systemd/systemd-journald
125 ? Ssl 0:07 /usr/local/bin/containerd
421 ? Sl 0:00 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 87e541960ab1c3ba36c7faac8c46016e5968da2092a0e0ce71d2b5d3a435c48e -address /run/containerd/containerd.sock
422 ? Sl 0:00 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id b596cdfc5bfcdd7eedcbe4f89fb6b807a1bcbdd5d6595b1dca7a6f1befb9bb00 -address /run/containerd/containerd.sock
423 ? Sl 0:00 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id b6d6ca329468c2d41c3b7266233e0e0c14a85622759537fbe52579ed1a20ce2b -address /run/containerd/containerd.sock
427 ? Sl 0:00 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 73b3ecd02605d64730e6d32972d543f1f1eb2e95538a758ea0f7b3c34d954986 -address /run/containerd/containerd.sock
503 ? Ss 0:00 /pause
504 ? Ss 0:00 /pause
505 ? Ss 0:00 /pause
523 ? Ss 0:00 /pause
645 ? Ssl 0:37 kube-apiserver --advertise-address=172.21.0.6 --allow-privileged=true --authorization-mode=Node,RBAC --client-ca-file=/etc/kubernetes/pki/ca.crt --enable-admission-plugins=NodeRestriction --enable-bootstrap-token
725 ? Ssl 0:29 etcd --advertise-client-urls=https://172.21.0.6:2379 --cert-file=/etc/kubernetes/pki/etcd/server.crt --client-cert-auth=true --data-dir=/var/lib/etcd --initial-advertise-peer-urls=https://172.21.0.6:2380 --initia
795 ? Ssl 0:15 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --container-runtime=remote --container-runtime-endpoi
1018 ? Sl 0:00 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id d8f2ca0244e580d253bbb0018d5f0bf3ef3fd402fb735958e747064a9136f7fe -address /run/containerd/containerd.sock
1027 ? Sl 0:00 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 6bc58fe6b05a92eeb523ac130ce031a27080798dc4ea485c7dd4d58beaf11dfe -address /run/containerd/containerd.sock
1063 ? Ss 0:00 /pause
1070 ? Ss 0:00 /pause
1126 ? Ssl 0:00 /bin/kindnetd
1136 ? Ssl 0:00 /usr/local/bin/kube-proxy --config=/var/lib/kube-proxy/config.conf --hostname-override=kind-control-plane
1345 ? Sl 0:00 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 5c9559c4d48d44ed92e10f3897b95bed1f3b93f3b213c47df2b6022c6c4d0412 -address /run/containerd/containerd.sock
1351 ? Sl 0:00 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 52b9e5bb4ecf79408851683a4415313629061feaaa69337ac35658f9b9dfa086 -address /run/containerd/containerd.sock
1378 ? Sl 0:00 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id e53dc2378582ba57ecc88c6ad87c015c7087c7d2297242c855aa7f4bde357f05 -address /run/containerd/containerd.sock
1418 ? Ss 0:00 /pause
1420 ? Ss 0:00 /pause
1432 ? Ss 0:00 /pause
1514 ? Ssl 0:01 /coredns -conf /etc/coredns/Corefile
1526 ? Ssl 0:01 /coredns -conf /etc/coredns/Corefile
1790 ? Ssl 0:03 kube-scheduler --authentication-kubeconfig=/etc/kubernetes/scheduler.conf --authorization-kubeconfig=/etc/kubernetes/scheduler.conf --bind-address=127.0.0.1 --kubeconfig=/etc/kubernetes/scheduler.conf --leader-el
1797 ? Ssl 0:00 local-path-provisioner --debug start --helper-image k8s.gcr.io/debian-base:v2.0.0 --config /etc/config/config.json
1862 ? Ssl 0:02 kube-controller-manager --allocate-node-cidrs=true --authentication-kubeconfig=/etc/kubernetes/controller-manager.conf --authorization-kubeconfig=/etc/kubernetes/controller-manager.conf --bind-address=127.0.0.1 -
2877 pts/1 Ss 0:00 bash
2884 pts/1 R+ 0:00 ps -ax
アプリケーションの動作確認
簡単なアプリケーションとして、NGINXを起動する。
$ kubectl apply -f https://raw.githubusercontent.com/takara9/codes_for_lessons/master/step09/deploy.yml
deployment.apps/web-deploy created
$ kubectl apply -f https://raw.githubusercontent.com/takara9/codes_for_lessons/master/step09/svc-lb.yml
service/web-service-lb created
アプリをデプロイして起動した結果である。 LoadBalancer は連携先が無いので、pendingとなる。そこで NodePort にアクセスを試みたが、残念ながらアクセスできなかった。設定が足りないうようだ。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mypod 1/1 Running 0 39m
web-deploy-756987f8f4-j6fpz 1/1 Running 0 56m
web-deploy-756987f8f4-jnt4s 1/1 Running 0 56m
web-deploy-756987f8f4-wh9m5 1/1 Running 0 56m
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 68m
web-service-lb LoadBalancer 10.104.142.6 <pending> 80:30504/TCP 56m
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
web-deploy 3/3 3 3 57m
アクセステスト用のポッドを起動して、curlでNGINXをアクセスと、いつもの結果が返ってきた。
$ kubectl run -it mypod --image=maho/my-ubuntu:0.1 -- bash
If you don't see a command prompt, try pressing enter.
root@mypod:/# curl http://web-service-lb/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
まとめ
Kubernetesのノードを丸ごとコンテナで動かして、クラスタを構成する発想は素晴らしい。ノードはサーバーという固定概念に縛られてはいけないことを思い知った。
参考資料
- Kind https://kind.sigs.k8s.io/
- GitHun Kind https://github.com/kubernetes-sigs/kind