私はローカル環境の Kubernetes にDocker Desktop for Windows を用いています。
Minikube や kubeadm、k3s、kind、microk8s など各種クラスタ構成がある中で、WSL2にローカルのクラスタ環境を他で組んだ場合の違いを改めてみておくことにしました。
今回は ローカル Kubernetes クラスタの構成にMinikubeを用いて構築してみて、最終的にどれがいいかの所感です。
目次
- 目次
- TL;DR
- はじめに
- Kubernetes のローカルクラスター構成
- Minikube on WSL2 のインストール
- minikube の動作確認
- kind on WSL2 はどうなのか
- おまけ: WSL環境の選定
- おまけ: Kubernetes のインストール先の検討
TL;DR
Windows/WSL で共通のコードベースを Windows にファイルを置きつつ、Windows と WSL でファイルマウントして、docker-compose も使って、Kubernetesも使いたい、という環境だとDocker Desktop (Hyper-V) + WSL1 が現時点ではおすすめ。 Docker Desktop での Kubernetes Cluster は、展開も極めて容易で local docker registry も共用され、Windows/WSLの両方からアクセスが容易なのでとてもいいです。Minikubeやkindと比べても何気に構成も奇をてらっていないのもいいです。今後のdockershimsに対する同行が気になります。
- Docker Desktop (Hyper-V) + WSL1 がストレスなく快適。WSL1 Ubuntu での docker volume マウントだけ注意
- Docker Desktop (WSL2) + WSL2 は、Kubernetes は快適だが docker-compose でファイルマウント、dockerアプリのWebレスポンスが絶望なので無理筋
- Minikube を docker-driver でWSL2 に建てる場合、Windows からのアクセスは
minikube tunnel
で Load Balancerをトンネルする以外は手がない、悲しい - Docker Desktop (Hyper-V) + WSL2 は ホスト docker イメージの共有ができず、大変に厳しいものがある
半年余り WSL2 で組んでいましたが、Minikube の結果も受けたうえで、Hyper-V + WSL1 に戻ることにしました。 2020年は WSL2 で喜び、WSL2 に泣いた。 2021年がどうなるのか... WSL2 の 9P が劇的改善、vmmem/COM Surrogate の CPUあげあげも解消したら最高ですね、WSL2に戻ります。
なお、Linux 上でファイル操作が完結するなら WSL2 が圧倒的におすすめです。WSL と違って妙な制約一切ないので WSL2 最高。Windows と Linux でファイル操作をまたぐ頻度、ファイル量がほぼないなら WSL2 でいいでしょう。
はじめに
この記事の視点は利用用途に強く依存しています。 私と同じ使い方をしたい方でないとまったく違う検討結果になると予想されます。
環境と利用方法が合致するときにだけ参考になるかもしれませんし、あるいは参考にもならないかもしれません。
環境
- Windows 10 Pro 20H2
- Docker for Windows 3.0.0
- Ubuntu 20.04 on WSL2
期待する利用方法
- Windows から WSL にたてたKubernetes の Ingress/LoadBalancer へのアクセスを行う
- Kubernetes より簡便に動作確認を行う環境として docker-compose も同様の構成で動かす
NOTE: WSL内部からの Kubernetes アクセスのしやすさは評価対象ではない。
Kubernetes のローカルクラスター構成
ローカルのKubernetes Cluster構成には選択肢がいくつかあります。 この記事ではMinikube on WSL2 で見ていきますがちらっと見ておきましょう。
NOTE: おおむね今のローカルKubernetesクラスタの選択肢はなんとなくここをみていただくとして。
- kind
- microk8s
- k3s
- k3d
それぞれ WSL2 と組み合わせて動作させる方法があるので興味ある人はみるといいでしょう。
NOTE: kind は LoadBalancer に対応していないので、こういう用途では使いにくいのを付記しておきます。インストールは本当に簡単なのですが。
WSL2 ではなく、ホストOS に Kubernetes クラスターを組むのも十分に有用な方法です。 Windows/macOS で最も簡便、かつ構成の組みなおしも用意なのは Docker Desktop の Kubernetes クラスターでしょう。
VMに建てるという意味では、Minikube を Hyper-V/Virtual Box で入れるという手もあります。(よくやられているやつ) Minikube に限らず、WSL2 で建てるのとVMで建てるのはおおむね概念は同じなので、どれもそういった方法を提供しています。
Minikube on WSL2 のインストール
WSL2 で起動した Ubuntu 20.04 に Minikube を入れて、Minikubeの自動起動をsystemd にさせることろまで構築します。 おおむね Kubernetesブログ に沿ってみていきましょう。
記事では Docker Desktop の WSL2 Integration を有効にしていますが、docker のファイルマウントの遅さを排除するため Hyper-V のまま動作させます。
Hyper-Vバックエンドの場合、WSL2 Ubuntu には docker /docker-compose / kubectl は入らないので、Ubuntuには自分で入れましょう。
systemd の構成
Minikube は --vm-driver=none
の場合 systemd が必要ですが、docker の場合不要です。
--vm-driver=docker
でも、WSL2ログインごとに minikube 起動をやっていられない + SysV Init を用意するのもつらいという場合、WSL2でSystemdを動かして minikube.service を作って調整してもいいでしょう。
NOTE: もちろん、.bashrc で適当に開始させてもいいでしょう。
systemd を WSL2 に入れる方法は、Kubernetes のminikube ブログやいい記事が紹介しています。
これで systemd の起動が確認できます。
systemd で自動起動するためのminikube.service は適当にこんな感じで。
[Unit] Description=Runs minikube on startup After=docker.service [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/local/bin/minikube start --vm-driver=docker --addons ingress --kubernetes-version v1.18.0 ExecStop=/usr/local/bin/minikube stop User={{ ansible_user_id }} Group={{ ansible_user_id }} [Install] WantedBy=multi-user.target
systemd を構成する場合、genie ではなく enter-systemd-namespace スクリプトの方がカスタマイズしやすいのでおすすめです。
例えば、systemd にすると Windows からの WSL2 ログイン時に bash loginをするため /mnt/Windowsパス
が維持されず ~/
になってしまいますが、enter-systemd-namespace で bash login 前に今のパスを保持しておいて、ログイン後に自動的に cd するなどの対処が取れます。
minikube の動作確認
minikube を docker driver で起動させてみます。
minikube start --vm-driver=docker
minikube の起動が確認できます。
$ minikube status minikube type: Control Plane host: Running kubelet: Running apiserver: Running kubeconfig: Configured timeToStop: Nonexistent
$ kubectl get node NAME STATUS ROLES AGE VERSION minikube Ready master 21h v1.18.0 $ k get pod -A NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-66bff467f8-tmqw6 1/1 Running 1 21h kube-system etcd-minikube 1/1 Running 1 21h kube-system ingress-nginx-admission-create-49j8v 0/1 Completed 0 21h kube-system ingress-nginx-admission-patch-cwrkz 0/1 Completed 0 21h kube-system ingress-nginx-controller-6f5f4f5cfc-9hw8f 1/1 Running 1 21h kube-system kube-apiserver-minikube 1/1 Running 1 21h kube-system kube-controller-manager-minikube 1/1 Running 1 21h kube-system kube-proxy-72482 1/1 Running 1 21h kube-system kube-scheduler-minikube 1/1 Running 1 21h kube-system storage-provisioner 1/1 Running 3 21h
minikube on WSL2 の面倒な点
minikube を --vm-driver=docker-driver
で起動した場合に面倒なのは2点です。
- minikube の docker registry に push しないといけない
- ingress に Windows ホストからアクセスできない
minikube を docker driver で起動した場合、minikube の docker registry は Ubuntu とは別に構成されます。
そのため、bashログイン時に eval $(minikube docker-env)
をする必要があるので注意です。
minikube を docker driver で起動した場合、ingress のAddress は docker ドライバーで起動した minikube ip
のアドレスになります。
localhost ではないため、Windows から WSL2 への直接のアクセスはできません。
この場合、Service: LoadBalancer にしておくと minikube tunnel
でlocalhost にトンネルされるので Windows からアクセス可能になります。
余談: なぜローカル Kubernetes 環境を必要とするのか
開発環境、開発ブランチ環境に対応するKubernetes があるとき、なぜローカルのKubernetes は必要なのかという話があります。
私はKubernetesの管理者であり、Devでもあるので、ローカル開発は何にもまして最速でプロダクトに期待する動作を確認する必須の場といえます。 ローカル開発は PoC であり、実際の運用環境とくらべて構成要素はミニマムだったりクラウド依存のなさなど差異もあるでしょう。 しかし、想定するアプリ動作を満たす場としては最適であり、常にメンテされていくべきと考えています。 また、自分のみに閉じているという意味でもローカル開発環境は整備する価値があります。 Kubernetes に各種 Operator/Controller を入れて動作させる場合は、ローカルKubernetes がない状況で、Devなどに展開するのは開発効率の面からみて避けたいものです。
ただしこれらの前提として、実際に動作する環境とかけ離れた構成になることは望ましくありません。 例えば、ローカルKubernetesではIngress に何かしらの制約がありLoad Balancer にする、といった状況は絶対的に避けたいものです。 運用環境とかけ離れ、期待する動作環境をローカルに作れず、メンテもできない場合、そのローカルKubernetes 環境はむしろ害悪になるので避けたいものがあります。
別の視点としてKubernetesの管理者という前提がない場合、ローカルKubernetes が必要である必然性が消えます。 例えば、通常のアプリコードを書いて動かすだけにおいては、Kubernetes だろうとどこででもいいからコードがデプロイされて動作すればいいです。 というか Kubernetes とか知りたくないし、ぐらいでもいいでしょう。
Kubernetes の管理をしつつDevもする身としては、ローカルKubernetes 環境はほしいものですが、メンテできるか、その構成は常に今のスタンダードからみてかけ離れていないかは常に気にする必要があります。Minikube はそういう意味ではスタンダードですが、悩ましい側面も多いですね。
kind on WSL2 はどうなのか
インストールはスムーズです。minikube より楽。 ただし、kind は Load Balancer に対応していないので使いにくさは否めません。
おまけ: WSL環境の選定
WSL には、WSL1 と WSL2 があり、この2つはホストOS のWindows との相互利用で結構な違いがあります。 Kubernetes を WSL に建てる場合、これは大きな違いになります。
WSL2 なのか WSL1 なのか
選択肢はおおむね2択であることが多いかと思います。
- WSL2のみで利用し純粋にLinuxとほぼ同様に扱いたい、WSL2とWindows は速度面などで気にならない場合、WSL2 + Docker on WSL2 がいいでしょう
- Windows と WSL2 のファイルマウント1 の9Pに由来する遅さ、Docker on WSL2のパフォーマンス制約、ホストOSのCPU/メモリ負荷が気になり許容できない場合、WSL1 がいいでしょう
別の構成として、Docker のみ Hyper-V で動かし、WSL2 でUbuntu を動かすことも考えられます。 この場合、docker 利用時のファイルマウントの遅さは生じず、WSL2 の Ubuntu はLinux 同様に扱えますが ホストWindows の Docker は共有できません。(tls:localhost:2375 がだめなんですよね)
WSL2 でないといけないのか WSL1 ではだめなのか
Windows/WSLの相互利用時のパフォーマンス、docker volume のマウントの取捨選択になります。 私の利用ケースはWindowsとWSLの相互利用がメインなので、WSL2 よりもWSL1 のほうが望ましいとなります。
ファイルマウント、ホストCPU負荷の両面でWSL1 は優れています。 一方で、純粋なLinux として使うには細かな差異とdocker 動作の制約が大きなハンデになります。(エラーもでないので罠に感じやすい)
WSL2
ほとんどのケースで問題ないことが多いでしょうが、パフォーマンス制約は軽く見るのは避けるほうがいいでしょう。
NOTE: Zen3 5900X + PCIE 4.0 NVMe でCPU負荷は無視できます。しかしWindowsホストファイルのマウントはどうしようもなく遅く回避策が現状ありません。
回避不可能な Windows ホストとのファイルボリュームマウント制約、そしてCPU負荷 (vmmem / COM Surrogate) があることに注意です。
NOTE: .wslconfing でメモリ、CPUの上昇をある程度止められますが十分に負荷が大きいので厄介です。
ただ、WSL2 Ubuntu と Docker WSL2 で Docker registry も共有され、docker/kubectl も入ってくるので非常に使いやすいです。
WSL1
WSLでdocker volume マウントができない制約があります。また、単純なWSL内部のファイルアクセスもWSL2 に比べて格段に遅いので注意がいります。
NOTE: docker実行はWindows でdocker run している限りは起こらないので回避策はあります。
WSL2 と違って、Windows ホストに対するパフォーマンスペナルティがなく、WSL での動作制約があるだけなのはバランスがいい選択になります。
WSL Ubuntu から docker を使うには、Docker Desktop で tls:localhost:2375 を開放して、WSLのDOCKER_HOST にする必要があります。 これで Windows の docker registry が WSL Ubuntu でも共有されるので、使い勝手の面で非常に楽になります。
おまけ: Kubernetes のインストール先の検討
ホストOSのWindowsでKubernetes クラスターを組んだ場合、Windows/WSLの両方からアクセスしても問題ありません。 WSL2 でKubernetes を組んだ場合、Windows からのアクセスには WSL2 の localhost でアクセスができる必要があります。
こういう意味では、Windows ホストにサクッとクラスターを組んで、いつでも爆破できる状況を作るのが最も使いやすいでしょう。
Docker Desktop for Windows なら、Settings 画面から Kubernetes Cluster のファクトリーリセット、再構成も用意なのでいいでしょう。
- それに伴うネットワーク速度の遅さも発生する↩