kind (Kubernetes IN Docker) を Docker Desktop for Mac で使う

kind は Kubernetes クラスターを Docker 上で動かすツールです。

github.com

コンテナオーケストレーションツールである Kubernetes 自体をコンテナ上で動かす・・ちょっとイメージしづらいですが、コンテナをノード *1 として利用することで、Minikube のようなシングルノードではない真のマルチノードが構成できて、コンテナ仮想化の恩恵により構築も速い。要らなくなったらサクッと消せる Immutable なクラスター環境が手に入ります。

Docker Desktop for Mac 環境に kind をインストールします。Docker Desktop の Kubernetes は無効化しておきます。kubectl も最新版をインストールしておきました。

kubernetes.io

kind コマンドを実行するユーザが sudo なしで docker コマンドを実行できるようにする必要がありますが、Docker Desktop の場合はすでにそうなっています。

Quick Start の通り、Go の最新版を導入。自分の場合 Go は brew ではなく公式のインストーラで入れてました。

golang.org

go と gopath に PATH を通します。

export PATH=$PATH:/usr/local/go/bin
export PATH=$PATH:$(go env GOPATH)/bin

go get で kind をインストールします。$GOPATH 配下にインストールされます。

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

とりあえず、クラスターを作成してみます。

$ kind create cluster

f:id:kondoumh:20190708001126p:plain

数分で作成されました。kubectl の環境変数を整えます(クラスター名はデフォルトで kind になっています)。

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

nginx をデプロイして、ポートフォワードして確認してみます。

$ kubectl create deployment nginx --image=nginx
$ kubectl create service nodeport nginx --tcp=8080:80
$ kubectl port-forward --address localhost svc/nginx 8080:8080 

f:id:kondoumh:20190708234532p:plain

OK です。

Kubernetes のパッケージマネージャ Helm を導入してみます。

helm.sh

$ brew install kubernetes-helm

$ helm init --history-max 200
    :
$HELM_HOME has been configured at /Users/masa/.helm.

Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.

$ helm version
Client: &version.Version{SemVer:"v2.14.2", GitCommit:"a8b13cc5ab6a7dbef0a58f5061bcc7c0c61598e7", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.14.2", GitCommit:"a8b13cc5ab6a7dbef0a58f5061bcc7c0c61598e7", GitTreeState:"clean"}

インストールはできました。

$ kubectl get pod -n kube-system
NAMESPACE     NAME                                         READY   STATUS    RESTARTS   AGE
  :
kube-system   tiller-deploy-6bfc8fcbf4-v825k               1/1     Running   0          30s

Helm のクラスター内サービスの Tiller も上がっています。しかしパッケージをインストールしようとすると、Error: no available release name found と言われてしまうので serviceacount の設定をします。

github.com

$ kubectl create serviceaccount --namespace kube-system tiller
serviceaccount/tiller created
$ kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
clusterrolebinding.rbac.authorization.k8s.io/tiller-cluster-rule created
$ kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
deployment.extensions/tiller-deploy patched

MySQL を Helm Charts でインストールしてみます。

$ helm install stable/mysql

NAME:   zinc-hog
LAST DEPLOYED: Wed Jul 31 23:29:40 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/ConfigMap
NAME                 DATA  AGE
zinc-hog-mysql-test  1     0s

    :
To connect to your database directly from outside the K8s cluster:
    MYSQL_HOST=127.0.0.1
    MYSQL_PORT=3306

    # Execute the following command to route the connection:
    kubectl port-forward svc/zinc-hog-mysql 3306

    mysql -h ${MYSQL_HOST} -P${MYSQL_PORT} -u root -p${MYSQL_ROOT_PASSWORD}


$ kubectl get pod

NAMESPACE     NAME                                         READY   STATUS    RESTARTS   AGE
default       zinc-hog-mysql-67cd9bcc85-qjr7b              1/1     Running   0          30m

インストールできたようです。ポートフォワードして クラスターの外から繋げるようにしておきます。

$ kubectl port-forward svc/zinc-hog-mysql 3306
Forwarding from 127.0.0.1:3306 -> 3306
Forwarding from [::1]:3306 -> 3306

mysql client で接続してみます。

$ MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default zinc-hog-mysql -o jsonpath="{.data.mysql-root-password}" 
$ MYSQL_HOST=127.0.0.1
$ MYSQL_PORT=3306
$ mysql -h ${MYSQL_HOST} -P${MYSQL_PORT} -u root -p${MYSQL_ROOT_PASSWORD}
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 469
Server version: 5.7.14 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

接続できました。

普通の Kubernetes クラスターとして使えてますね。

マルチノードクラスターを作るのも、kind 用の config を書いて create すれば数分でできてしまいます。

# a cluster with 1 control-plane nodes and 3 workers
kind: Cluster
apiVersion: kind.sigs.k8s.io/v1alpha3
nodes:
- role: control-plane
- role: worker
- role: worker
- role: worker

内部的には kubeadm が使われていて、config で色々な追加設定が可能です。CI で色々な環境を擬似的に作成するのにも向いていそうです*2。Canonical が開発している MicroK8s も導入が簡単で Immutable な クラスター環境が構築できますが、構成のカスタマイズはさほど柔軟ではありません。

microk8s.io

kind はリリース前の WSL2 もサポートしていたりして、開発での利用を重視していることが伺えます。

https://kind.sigs.k8s.io/docs/user/using-wsl2/

こんなイケてる kind ですが、ググラビリティが低いのがちょっと残念です。

ちなみに社内ネットワークの proxy 配下の環境では現時点の最新版(v0.4.0) では deployment 作成時イメージ取得ができませんでした。v0.3.0 以降コンテナランタイムが containerd にスイッチされていて関連する issue が上がっていました。

github.com

コンテナランタイムに Docker を採用している v0.2.1 は proxy 配下でも動作してました。

*1:Kubernetes クラスタを構成するワーカーマシン

*2:もともと kind は Kubernetes 自身のテストのために設計されたそうです。