お手軽Kubernetesクラスタ作成ツール "kind"の紹介

こんにちは、Necoプロジェクトのsatです。今回はKubernetesクラスタお手軽に作れるkindというツールを紹介します。kindはKubernetes In Dockerの略です。

本記事の要約

  • kindとはKubernetesクラスタを簡単に作れるツール
  • インストール、およびクラスタ作成がそれぞれたった1コマンドを実行するだけで完了
  • 他の類似ツールには存在しないマルチノードクラスタ作成機能がある
  • Kubernetesの公式プロジェクトかつ、Kubernetesそのもののテストにも用いられているため、実績や将来性は十分

修正履歴

  • 2019/7/04: 「クラスタの設定を変更する方法」節のapiVersion: kubeadm.k8s.io/v1beta1apiVersion: kubeadm.k8s.io/v1beta2に修正しました

kindとは

Kubernetesは複雑なソフトウェアなので、自分で一から構築するのは非常に大変であり*1。 このため、世の中にはローカル環境でとりあえずKubernetesを使ってみたいというような用途でminikubemicrok8sといった様々なツールが存在しており、kindもその一つです。 それぞれ構築できるKubernetesクラスタがサポートする機能が異なるために一長一短であり、どれを使うべきかは使いたい機能や好みによって変わります。 ただしkindにはマルチノードクラスタを作れるという他のツールには無い特長があります。

kindはKubernetesの公式ツールであり、v1.11以降ではKubernetesそのものをテストするために使われています。このためkindは実績と将来性が優れているといえます。

kindはKubernetesやその周辺ツールにまつわる問題についてそれぞれのコミュニティにissueを発行するときにも有用です。なぜならば独自ツール *2などの世間的には マイナーな方法で構築したクラスタ上で起きた問題は 「当該ソフトウェアの問題ではないか、まずは有名どころのツールを使って構築したクラスタで再現させてほしい」 と言われることがよくあるからです。Kubernetesの公式ツールであればそのような問題は起きにくいでしょう。

ではここからはkindの使い方、および動作のしくみについて説明します。

使い方

必要条件

kindのインストールをするためには次の条件を満たしておく必要があります。

インストール方法

次のコマンドを実行します。

$ GO111MODULE="on" go get sigs.k8s.io/kind@<kindのバージョン番号>

たとえば本書執筆時点における最新版であるv0.4.0を利用するには次のように実行します。

$ GO111MODULE="on" go get sigs.k8s.io/kind@v0.4.0

最も単純なクラスタを作る方法

次のコマンドを実行します。

$ kind create cluster [---name=<クラスタ名。無指定の場合はクラスタ名が"kind"になる>]

作ったクラスタにローカル環境からアクセスできるようにするためには以下のコマンドを実行します。

$ export KUBECONFIG="$(kind get kubeconfig-path [--name=<クラスタ名>])"

クラスタ名のデフォルトはkindです。

下記のように--loglevelオプションを付けると実行時に詳細なログを出力できます。

$ kind create cluster --loglevel debug

--waitオプションを指定すると、ノードがReady状態になるまで待つようになります(デフォルトでは待たない)。

$ kind create cluster --wait 100s

複数クラスタを作る方法

foo, barという二つのクラスタを立ち上げるには次のようにします。

$ kind create cluster --name=foo
Creating cluster "foo" ...
...
$ kind get clusters
foo
$ kind create cluster --name=bar
Creating cluster "bar" ...
...
$ kind get clusters
bar
foo
$ ls -1 .kube/kind-config-*
.kube/kind-config-bar
.kube/kind-config-foo
$ 

マルチノードクラスタを作る方法

kindの設定ファイルを作ればマルチノードクラスタを作れます。次に示すのはコントロールプレーンノード1つとワーカーノード3つのクラスタを作るための設定ファイルです。

kind: Cluster
apiVersion: kind.sigs.k8s.io/v1alpha3
# 1 control plane node and 3 workers
nodes:
# the control plane node config
- role: control-plane
# the three workers
- role: worker
- role: worker
- role: worker

nodes要素以下を変更すればノード数を自由に変えられます。

上記設定ファイルを使ってマルチノードk8sクラスタを作るには次のようにします。

$ kind create cluster --name multi --config multinode.yaml
Creating cluster "multi" ...
...
Cluster creation complete. You can now use the cluster with:

export KUBECONFIG="$(kind get kubeconfig-path --name="multi")"
kubectl cluster-info
$ export KUBECONFIG="$(kind get kubeconfig-path --name="multi")"
$ kubectl get node
NAME                  STATUS   ROLES    AGE     VERSION
multi-control-plane   Ready    master   10m     v1.15.0
multi-worker          Ready    <none>   9m44s   v1.15.0
multi-worker2         Ready    <none>   9m44s   v1.15.0
multi-worker3         Ready    <none>   9m44s   v1.15.0
$ 

Kubernetesのバージョンを指定する方法

kindがインストールするKubernetesのバージョンはkindのバージョンごとにデフォルト値が決まっています(kind v0.4.0ではKubernetes v1.15.0, kind v0.3.0ではkubernetes v1.14.2、など)。 次のようにクラスタ設定ファイルのkubeadmConfigPatchesにバージョンを指定することで、任意のバージョンのKubernetesを使えます。

kind: Cluster
apiVersion: kind.sigs.k8s.io/v1alpha3
kubeadmConfigPatches:
- |
  apiVersion: kubeadm.k8s.io/v1beta2
  kind: ClusterConfiguration
  metadata:
    name: config
  kubernetesVersion: v1.14.3
  networking:
    serviceSubnet: 10.0.0.0/16

kindが作るクラスタを構成する個々のノードはDockerコンテナとして表現されます(詳細は後述)。これらコンテナのイメージを変更するには次のようにクラスタ作成時にイメージを指定します。

$ kind create cluster --image kindest/node:v1.14.3

指定できるイメージの一覧はこちらをごらんください。

ノードコンテナにアクセスする方法

以下のようにdocker execでコントロールプレーンノードに入れます。

$ docker exec -it kind-control-plane bash

コントロールプレーンノード 内では、kubeadm, ctr, crictlなどのコマンドを利用できます。

ログを見る方法

kubectl logsによってkube-apiserverやkube-schedulerのログを確認できます。

kubectl logs -n kube-system kube-scheduler-kind-control-plane

次のコマンドを実行すると各コンポーネントのログを収集してローカルマシンの/tmp以下に書き出してくれます。

$ kind export logs
Exported logs to: /tmp/486658715  

kube-schedulerがpodとして立ち上がっていない場合は、この方法でログを見ることができます。

クラスタの設定を変更する方法

kindは内部でkustomizeを使っており、設定ファイル内にkubeadmConfigPatches、およびkubeadmConfigPatchesJson6902というものを定義できます。 内容はそれぞれkustomizeのpatchesStrategicMergepatchesJson6902に相当します。 これによってkindが内部で利用しているkubeadmの設定ファイルにパッチを当てられます。

例えばkube-schedulerのconfigオプションを指定したい場合は、下記のように記述できます。

kind: Cluster
apiVersion: kind.sigs.k8s.io/v1alpha3
# patch the generated kubeadm config with some extra settings
kubeadmConfigPatches:
- |
  apiVersion: kubeadm.k8s.io/v1beta2
  kind: ClusterConfiguration
  metadata:
    name: config
  scheduler:
    extraVolumes:
      - name: "config"
        hostPath: /mnt/host/scheduler
        mountPath: /var/lib/scheduler
        readOnly: true
    extraArgs:
      config: /var/lib/scheduler/scheduler-config.yaml

ローカルマシン上のファイルをコントロールプレーンで利用したい場合は、extraMounts を使えます。

kind: Cluster
apiVersion: kind.sigs.k8s.io/v1alpha3
nodes:
- role: control-plane
  extraMounts:
    - containerPath: /mnt/host
      hostPath: /tmp/path/to

kindとkubeadmの設定ファイルについての詳細はそれぞれのgodocを参照してください。

動作のしくみ

実行時にはコントロールプレーンノードとワーカーノードに対応するDockerコンテナがそれぞれ起動されています。それぞれdocker psで確認できます。

$ docker ps
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS              PORTS                                  NAMES
df7d631bb6a8        kindest/node:v1.14.1      "/usr/local/bin/entr…"   2 hours ago         Up 2 hours                                                 kind-worker3
4da3bf000b00        kindest/node:v1.14.1      "/usr/local/bin/entr…"   2 hours ago         Up 2 hours                                                 kind-worker2
772938eaed30        kindest/node:v1.14.1      "/usr/local/bin/entr…"   2 hours ago         Up 2 hours          37735/tcp, 127.0.0.1:37735->6443/tcp   kind-control-plane
957d78a62abd        kindest/node:v1.14.1      "/usr/local/bin/entr…"   2 hours ago         Up 2 hours                                                 kind-worker

kindはこれらのコンテナの中でsystemdサービスとしてkubeletを実行しています。

$ docker exec -it kind-control-plane systemctl status kubelet.service
● kubelet.service - kubelet: The Kubernetes Node Agent
   Loaded: loaded (/kind/systemd/kubelet.service; enabled; vendor preset: enabled)
  Drop-In: /etc/systemd/system/kubelet.service.d
           └─10-kubeadm.conf
   Active: active (running) since Fri 2019-06-28 02:38:32 UTC; 1h 52m in ago

etcd, kube-apiserver, kube-scheduler, kube-controller-managerは、 Static PodとしてKubernetes上にセルフホストされています。 kube-proxy, weave, corednsは、DeploymentやDaemonSetとしてKubernetes上にデプロイされています。

$ kubectl get all -A
NAMESPACE     NAME                                             READY   STATUS    RESTARTS   AGE
kube-system   pod/coredns-fb8b8dccf-4gwkb                      1/1     Running   0          113m
kube-system   pod/coredns-fb8b8dccf-xgm69                      1/1     Running   0          113m
kube-system   pod/etcd-kind-control-plane                      1/1     Running   0          112m
kube-system   pod/kube-apiserver-kind-control-plane            1/1     Running   0          112m
kube-system   pod/kube-controller-manager-kind-control-plane   1/1     Running   0          112m
kube-system   pod/kube-proxy-cqh6s                             1/1     Running   0          113m
kube-system   pod/kube-proxy-frxz6                             1/1     Running   0          113m
kube-system   pod/kube-proxy-j9q2r                             1/1     Running   0          113m
kube-system   pod/kube-proxy-kn7xd                             1/1     Running   0          113m
kube-system   pod/kube-scheduler-kind-control-plane            1/1     Running   0          112m
kube-system   pod/weave-net-69crj                              2/2     Running   0          113m
kube-system   pod/weave-net-f8fqv                              2/2     Running   0          113m
kube-system   pod/weave-net-lc7tz                              2/2     Running   0          113m
kube-system   pod/weave-net-q6k67                              2/2     Running   0          113m

NAMESPACE     NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
default       service/kubernetes   ClusterIP   10.0.0.1     <none>        443/TCP                  113m
kube-system   service/kube-dns     ClusterIP   10.0.0.10    <none>        53/UDP,53/TCP,9153/TCP   113m

NAMESPACE     NAME                        DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
kube-system   daemonset.apps/kube-proxy   4         4         4       4            4           <none>          113m
kube-system   daemonset.apps/weave-net    4         4         4       4            4           <none>          113m

NAMESPACE     NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
kube-system   deployment.apps/coredns   2/2     2            2           113m

NAMESPACE     NAME                                DESIRED   CURRENT   READY   AGE
kube-system   replicaset.apps/coredns-fb8b8dccf   2         2         2       113m

おわりに

今回はKubernetesの入門、テスト、およびKubernetesなどのOSSへのissue発行において便利なkindというツールを紹介しました。 Necoにおいても自社製ツールに依存しないテストをするためにはこれまでmicrok8sを使っていたのですが、 現在はマルチクラスタ作成機能に注目してkindに移行中です。いまのところ大変便利に使えています。 本記事を読むことによってKubernetesのユーザ、およびkindによってKubernetesを使ったシステムの開発が楽になる人が増えれば幸いです。

*1:これはこれですごく勉強になりますが、それはまた別の話

*2:NecoでもCKEというクラスタ作成/管理ツールを作っています