一応vctl kindが利用できるというので試してみましたが、せっかくVMware Workstation Proを実行しているので複数VMを作成してkubesprayで本物のk8sクラスターを構築する方がテスト環境としては汎用性が高いと思います。
CustomControllerの作成やDeployment, StatefulSetの学習にしてもrook.ioなどでStorageClassが準備できる環境をお勧めします。
はじめに
VMware Workstation 16 Pro/Playerは、kubernetesクラスターを構築できると宣伝されています。
Fusion 12も同様の機能を持っています。むしろFusion 12の目玉機能としてニュースサイトに掲載されている記事もあるので、Workstaiton版でも動くとはすぐには気がつきませんでした。
VMwareの公式マニュアルは、何をしたら良いか分からない初心者には十分でないと感じたので、メモを残すことにしました。
環境
- VMware Workstation 16.1 Pro
- ThinkPad T480 (i7-8550u, 32GB, 2TB NVMe SSD)
参考資料
- vmware公式ガイド - KIND を有効にして vctl コンテナをノードとして使用した Kubernetes クラスタの実行
- VMware Fusion v12 – Kubernetes / Kind integration
実際の作業
まず公式ガイドでは、VMWareホストのPowerShell等端末上でvctlを利用して次のコマンドを実行するように記述があります。
- vctl system start
- vctl kind
PS C:\Users\yasu> vctl system start
Preparing storage...
Container storage has been prepared successfully under C:\Users\yasu\.vctl\storage
Preparing container network...
Container network has been prepared successfully using vmnet: vmnet8
Launching container runtime...
Container runtime has been started.
PS C:\Users\yasu> vctl kind
ここまで実行すると別ウィンドウが開きますが、ここから先に何をすれば良いのか公式ガイドでは十分ではありません。
この状態で、kubectlコマンドを実行してもサーバーが起動していないことが分かります。
PS C:\Users\yasu> kubectl get node
Unable to connect to the server: dial tcp [::1]:8080: connectex: No connection could be made because the target machine actively refused it.
次に参考にしたドキュメントから、クラスターを作成していますが、これは通常のkindの利用方法のようです。kind関連の文書では困ったらlogを参照するようにと書かれていますが、この環境では利用できないようです。
vctl は kind build および kind export logs kind サブコマンドをサポートしていません。
ただ、実際にexport logsを実行してみるとログが出力されています。
PS C:\Users\yasu> kind export logs
Exported logs for cluster "kind" to:
C:\Users\yasu\AppData\Local\Temp\103590923
PS C:\Users\yasu> cd C:\Users\yasu\AppData\Local\Temp\103590923
PS C:\Users\yasu\AppData\Local\Temp\103590923\kind-control-plane> ls
ディレクトリ: C:\Users\yasu\AppData\Local\Temp\103590923\kind-control-plane
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2020/11/23 19:55 containers
d----- 2020/11/23 19:55 pods
-a---- 2020/11/23 19:55 375 alternatives.log
-a---- 2020/11/23 19:55 30624 containerd.log
-a---- 2020/11/23 19:55 12420 inspect.json
-a---- 2020/11/23 19:55 165190 journal.log
-a---- 2020/11/23 19:55 126832 kubelet.log
-a---- 2020/11/23 19:55 7 kubernetes-version.txt
-a---- 2020/11/23 19:55 0 serial.log
これが期待と違う挙動なのか不明ですが、後からログが出力できることに気がついたので、今回はこのログは参考にしませんでした。
kindでクラスターを作成する前に、正常稼動していない場合もあるので、必ず事前にクラスターの有無を確認しています。
PS C:\Users\yasu> kind get clusters
kind
PS C:\Users\yasu> kind delete cluster
Deleting cluster "kind" ...
kind get clusters
で定義されているクラスターがなくなってから、クラスターを作成します。
PS C:\Users\yasu> kind get clusters
No kind clusters found.
PS C:\Users\yasu> kind create cluster
Creating cluster "kind" ...
[32m✓[0m Ensuring node image (kindest/node:v1.19.1) 🖼
[32m✓[0m Preparing nodes 📦
[32m✓[0m Writing configuration 📜
[32m✓[0m Starting control-plane 🕹️
[32m✓[0m Installing CNI 🔌
[32m✓[0m 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! 😊
ここまで来たらkubectlコマンドを実行します。
PS C:\Users\yasu> kubectl cluster-info --context kind-kind
Kubernetes master is running at https://127.0.0.1:62402
KubeDNS is running at https://127.0.0.1:62402/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
とりあえずkubeletが普通に実行できるようになりました。
PS C:\Users\yasu> kubectl get all --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system pod/coredns-f9fd979d6-8wdwg 1/1 Running 0 4m11s
kube-system pod/coredns-f9fd979d6-w8ct6 1/1 Running 0 4m11s
kube-system pod/etcd-kind-control-plane 1/1 Running 0 4m13s
kube-system pod/kindnet-hmgtk 1/1 Running 0 4m10s
kube-system pod/kube-apiserver-kind-control-plane 1/1 Running 0 4m13s
kube-system pod/kube-controller-manager-kind-control-plane 1/1 Running 0 4m13s
kube-system pod/kube-proxy-tbcvt 1/1 Running 0 4m11s
kube-system pod/kube-scheduler-kind-control-plane 1/1 Running 0 4m13s
local-path-storage pod/local-path-provisioner-78776bfc44-ll456 1/1 Running 0 4m4s
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4m28s
kube-system service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 4m21s
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
kube-system daemonset.apps/kindnet 1 1 1 1 1 <none> 4m11s
kube-system daemonset.apps/kube-proxy 1 1 1 1 1 kubernetes.io/os=linux 4m20s
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
kube-system deployment.apps/coredns 2/2 2 2 4m21s
local-path-storage deployment.apps/local-path-provisioner 1/1 1 1 4m4s
NAMESPACE NAME DESIRED CURRENT READY AGE
kube-system replicaset.apps/coredns-f9fd979d6 2 2 2 4m11s
local-path-storage replicaset.apps/local-path-provisioner-78776bfc44 1 1 1 4m4s
k8s公式ガイドのYAMLを利用して挙動を確認します。
PS C:\Users\yasu> kubectl apply -f https://k8s.io/examples/service/load-balancer-example.yaml
deployment.apps/hello-world created
PS C:\Users\yasu> kubectl get pod
NAME READY STATUS RESTARTS AGE
hello-world-6df5659cb7-9m9kx 0/1 ContainerCreating 0 48s
hello-world-6df5659cb7-cr7k9 0/1 ContainerCreating 0 48s
hello-world-6df5659cb7-pdgxg 0/1 ContainerCreating 0 48s
hello-world-6df5659cb7-r8wsv 0/1 ContainerCreating 0 48s
hello-world-6df5659cb7-wn5hd 0/1 ContainerCreating 0 48s
PS C:\Users\yasu> kubectl expose deployment hello-world --type=LoadBalancer --name=my-service
service/my-service exposed
PS C:\Users\yasu> kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 95m
my-service LoadBalancer 10.102.48.208 <pending> 8080:32715/TCP 14s
調子よく進んできましたが、LoadBalancerは配置されていないので永久にExternal-IPはpending状態のままとなります。
ポートフォワードによって特定のPodを指定して、127.0.0.1の特定ポートにフォワードさせることが可能です。
PS C:\Users\yasu> kubectl expose deployment hello-world --type=NodePort --name=my-service2
service/my-service2 exposed
PS C:\Users\yasu> kubectl port-forward svc/my-service2 9090:8080
Forwarding from 127.0.0.1:9090 -> 8080
Forwarding from [::1]:9090 -> 8080
Handling connection for 9090
とりあえず動きましたが、本来であればkind本家のガイドを読んで、ingress controllerを配置するべきなのだと思います。
ただ、kindを利用して本格的な環境を構築するのであれば、VMware上に3VMぐらいを起動して、kubesprayでfull-specなk8sクラスターを構築して、MetalLBでLoadBalancerを構築します。
VMware Workstation Proのネットワーク設定は強力で、自分用に閉じた10.1.1.0/24のようなネットワークを作ったりすることは簡単にできます。VMware上のkindはNATネットワークに接続するのがデフォルト設定なので、公式ガイドにあるように設定を変更すれば、同様に別のVMNetに接続できるのだと思いますが、いまのところは個人的には積極的に利用するつもりはありません。
これは得意分野が何にあるのかに依るのかとは思いますが、kindの経験が本番環境でも活かせるかというと、本番との差分を吸収するノウハウばかりが蓄積されるような印象が強いです。この観点ではkindのようなソリューションの利用は個人的にはあまりお勧めしません。
とはいえkubesprayを推しても、これはこれで問題があります。ただ本番環境とテスト環境をできるだけ同じにしたいという小規模環境であれば、現時点ではベストな選択と思っています。
遭遇したエラーについて
最初に試した時には、kindでクラスターが実行されているはずなのに、kubectlコマンドではエラーになってしまいました。
PS C:\Users\yasu> kubectl cluster-info --context kind-kind
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
Unable to connect to the server: net/http: TLS handshake timeout
Docker Desktopを導入しているので、~/.kube/configファイルにはKindの分が加わって2つのcontextが定義されています。
別のWindowsマシン上で、VMware Workstation 16 Playerを利用した限りでは、この状態で問題なく動いています。
最終的には再起動し、VMware Workstation 16 Proは起動せずにPowerShellの端末を開き、vctl system startから再度実行し無事に起動しました。
遭遇したエラーについて ver.2
前述のエラーでいろいろ試している段階で、また別のエラーに遭遇してクラスターが作成できなくなりました。
PS C:\Users\yasu> kind create cluster
Creating cluster "kind" ...
[32m✓[0m Ensuring node image (kindest/node:v1.19.1) 🖼
[31m✗[0m Preparing nodes 📦
[31mERROR[0m: failed to create cluster: docker run error: command "docker run --hostname kind-control-plane --name kind-control-plane --label io.x-k8s.kind.role=control-plane --privileged --security-opt seccomp=unconfined --security-opt apparmor=unconfined --tmpfs /tmp --tmpfs /run --volume /var --volume /lib/modules:/lib/modules:ro --detach --tty --label io.x-k8s.kind.cluster=kind --net kind --restart=on-failure:1 --publish=127.0.0.1:63985:6443/TCP kindest/node:v1.19.1@sha256:98cf5288864662e37115e362b23e4369c8c4a408f99cbc06e58ac30ddc721600" failed with error: exit status 2
[31mCommand Output[0m: panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x30 pc=0x10d59d2]
goroutine 1 [running]:
gitlab.eng.vmware.com/core-build/vctl/pkg/container.StartExistingContainer(0x159a860, 0xc00003e330, 0x0, 0x0, 0xc0002c4370, 0x1, 0x1, 0xc000046101, 0x1, 0xc00033b33d, ...)
d:/build/ob/bora-17139912/kubernetesdesktop/build/release/win64_vc140/kubernetesdesktop/build/src/vctl/pkg/containerと/start.go:144 +0xd2
gitlab.eng.vmware.com/core-build/vctl/pkg/container.RunContainer(0x159a860, 0xc00003e330, 0xc0000363a0, 0x12, 0xc000046180, 0x5c, 0xc0002c4370, 0x1, 0x1, 0xc0001f2e40, ...)
d:/build/ob/bora-17139912/kubernetesdesktop/build/release/win64_vc140/kubernetesdesktop/build/src/vctl/pkg/container/run.go:47 +0x375
gitlab.eng.vmware.com/core-build/vctl/cmd.glob..func28(0x1ebc3c0, 0xc00022a1c0, 0x1, 0x1c, 0x0, 0x0)
d:/build/ob/bora-17139912/kubernetesdesktop/build/release/win64_vc140/kubernetesdesktop/build/src/vctl/cmd/run.go:59 +0x1b5
github.com/spf13/cobra.(*Command).execute(0x1ebc3c0, 0xc00022a000, 0x1c, 0x1c, 0x1ebc3c0, 0xc00022a000)
d:/build/ob/bora-17139912/kubernetesdesktop/build/release/win64_vc140/kubernetesdesktop/build/pkg/mod/gitlab.eng.vmware.com/core-build/mirrors_github_spf13_cobra@v0.0.0-20200421035935-b81270fac540/command.go:827 +0x467
github.com/spf13/cobra.(*Command).ExecuteC(0x1ebfac0, 0x13adfa2, 0x10, 0x0)
d:/build/ob/bora-17139912/kubernetesdesktop/build/release/win64_vc140/kubernetesdesktop/build/pkg/mod/gitlab.eng.vmware.com/core-build/mirrors_github_spf13_cobra@v0.0.0-20200421035935-b81270fac540/command.go:915 +0x30b
github.com/spf13/cobra.(*Command).Execute(...)
d:/build/ob/bora-17139912/kubernetesdesktop/build/release/win64_vc140/kubernetesdesktop/build/pkg/mod/gitlab.eng.vmware.com/core-build/mirrors_github_spf13_cobra@v0.0.0-20200421035935-b81270fac540/command.go:865
gitlab.eng.vmware.com/core-build/vctl/cmd.Execute()
d:/build/ob/bora-17139912/kubernetesdesktop/build/release/win64_vc140/kubernetesdesktop/build/src/vctl/cmd/root.go:55 +0x5d
main.main()
d:/build/ob/bora-17139912/kubernetesdesktop/build/release/win64_vc140/kubernetesdesktop/build/src/vctl/main.go:13 +0x5e
コンテナのイメージを確認します。
PS C:\Users\yasu> vctl images
──── ───────────── ────
NAME CREATION TIME SIZE
──── ───────────── ────
nginx:latest 2020-11-23T11:44:30+09:00 51.1 MiB
kindest/node@sha256:98cf5288864662e37115e362b23e4369c8c4a408f99cbc06e58ac30ddc721600 2020-11-21T23:22:49+09:00 481.5 MiB
kindest/nodeを削除してみます。
PS C:\Users\yasu> vctl rmi kindest/node@sha256:98cf5288864662e37115e362b23e4369c8c4a408f99cbc06e58ac30ddc721600
──── ────── ──────
NAME RESULT REASON
──── ────── ──────
kindest/node@sha256:98cf5288864662e37115e362b23e4369c8c4a408f99cbc06e58ac30ddc721600 REMOVED
この状態で2つ目のpowershellを終了し、再び vctl system stop; vctl system start; vctl kindを実行します。
PS C:\Users\yasu> vctl system stop
Stop virtual machine kind-control-plane ...
Virtual machine kind-control-plane is stopped
Terminating container runtime...
成功: PID 20444 のプロセスは強制終了されました。
Container runtime has been stopped.
PS C:\Users\yasu> vctl system start
Preparing storage...
Container storage has been prepared successfully under C:\Users\yasu\.vctl\storage
Preparing container network...
Container network has been prepared successfully using vmnet: vmnet8
Launching container runtime...
Container runtime has been started.
PS C:\Users\yasu> vctl kind
再び新たに開いたPowerShellのコマンドラインでkindコマンドを実行していきます。
PS C:\Users\yasu> kind get clusters
No kind clusters found.
PS C:\Users\yasu> kind create cluster
Creating cluster "kind" ...
[32m✓[0m Ensuring node image (kindest/node:v1.19.1) 🖼
[32m✓[0m Preparing nodes 📦
[32m✓[0m Writing configuration 📜
[32m✓[0m Starting control-plane 🕹️
[32m✓[0m Installing CNI 🔌
[32m✓[0m 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! 😊
この状態からも結局はうまく動きませんでしたが、再起動したところ問題なく稼動しました。
さいごに
kindはk8s環境にふれる目的ではお手軽かもしれませんが、VMwareのPro版を使えば複数のVMを別のサブネットワークに接続させることができるので、kubesprayなどで本番と同等の環境を構築した方が便利だと思います。