安物のWindowsPC上にtype:LoadBalancerが使えるおうちKubernetesを構築する

所用で[メモリ16GBを積んだWindows11ノートPC](https://www.amazon.co.jp/gp/product/B0CMTX962R)を18800円で購入した。
せっかくメモリが16GBあるので軽量KubernetesディストリビューションであるMicroK8sを立ち上げて、ついでに`type: LoadBalancer`が使えるようにするところまでやってみる。
## MicroK8sとは
MicroK8sのインストールの前に、簡単にMicroK8sとは何かを書いておく。
軽量KubernetesディストリビューションはMinikube、K3s等色々あるが、[MicroK8s](https://microk8s.io/)もその1つであり、UbuntuでおなじみのCannonicalが主体となって開発しているディストリビューションである。GitHubのリポジトリは[こちら](https://github.com/canonical/microk8s)。
他の軽量ディストリビューションとの比較はMicroK8sの[こちらのページ](https://microk8s.io/compare)にあるが、お遊び程度であればそれほど差を気にする必要はなさそうだ。
軽量とだけあって、メモリ8GBくらいの環境でもクラスタを立ち上げることは可能なので、余ってるPCなどでKubernetesに触りたい人には使ってみることをお勧めする。

## MicroK8sのインストール
ここではWindowsで進める。
[Install MicroK8s](https://microk8s.io/#install-microk8s)のページのWindowsのタブを選択し、インストーラをダウンロードする。
ダウンロード後にインストーラを実行し、設定値はデフォルトのまま進める。
最後まで進めるとMultipass（仮想化環境の管理ツール）がインストールされる。
インストール後、以下のような再起動を促す画面が出てくるので再起動する。
![7be6f875bb1be8a697f7107fc1f0a498452e96f54b75fdbe061ff6c5a2b6265b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/3c2306dd-ed6f-b266-3ef8-d1eb19537818.png)

再起動後、Windowsキー＋Rで「ファイル名を指定して実行」を表示し、`cmd`を実行してコマンドプロンプトを表示する。
![b73aa44b351a177fc8731d629de47f0fff5dd2e5edc0ab4ed054773113e865da.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/18dc9853-eecc-2ea9-3d20-b595498d36a9.png)

コマンドプロンプトが立ち上がったら、以下のコマンドを実行してMicroK8sをインストールする。
```
microk8s install
```
インストールが終わると自動的にMircoK8sが起動する。
`microk8s status`でMicroK8sの状態を確認できる。
```sh
>microk8s status --wait-ready
microk8s is running
high-availability: no
  datastore master nodes: 127.0.0.1:19001
  datastore standby nodes: none
  ：（省略）
```
クラスタを管理するための`kubectl`コマンドは`microk8s`コマンドを挟んで`microk8s kubectl`で実行することでkubeconfigの用意なしで実行することが出来る。
以下が実行した結果だが、最低限のPodが起動していることが確認できる。
```sh
>microk8s kubectl get pod -A
NAMESPACE     NAME                                     READY   STATUS    RESTARTS   AGE
kube-system   calico-node-x49l5                        1/1     Running   0          8m41s
kube-system   coredns-864597b5fd-r7zl5                 1/1     Running   0          8m41s
kube-system   calico-kube-controllers-77bd7c5b-gdc9l   1/1     Running   0          8m41s
```

これでMicroK8sが使えるようになったが、より便利に使えるようにするため、以下を行う。

- 起動停止をデスクトップ上から出来るようにバッチファイルを用意する
- kubectlコマンドでクラスタ操作できるようにバッチファイルを用意する


起動停止のバッチファイルは以下の手順で作成する。
まずデスクトップ上で右クリックから`新規作成`->`テキストドキュメント`で`新規テキストドキュメント.txt`を作成し、ファイルをテキストエディタで開いて以下を記載する。
```sh:microk8s_start.bat
microk8s start
timeout 10
```
`timeout`は起動に失敗した場合に失敗メッセージを確認する前にウィンドウが閉じるのを避けるために10秒待つよう入れている。
保存後、microk8s_start.batにリネームする。
同じように以下のファイルを作成してmicrok8s_stop.batで保存する。
```sh:microk8s_stop.bat
microk8s stop
timeout 10
```
以降はそれぞれのbatファイルを実行するだけでデスクトップ上から簡単に起動停止が出来るようになる。
なお、microk8s_start.batを実行しても`microk8s kubectl`が上手く動かない場合は最後に載せているトラブルシュートを参考にするとうまく行くかもしれない。

kubectlコマンドについては、パスが通っている箇所（例：C:\Users\<ユーザ名>\AppData\Local\Microsoft\WindowsApps）にmicrok8s_start.batを作成した時と同じ手順で以下の内容のkubectl.batを作成する。
```sh:kubectl.bat
@echo off
microk8s kubectl %*
```
保存すればkubectlが利用できるようになる。
```sh
>kubectl get node
NAME          STATUS   ROLES    AGE   VERSION
microk8s-vm   Ready    <none>   74m   v1.28.3
```
## MicroK8sのアドオンをインストールしてtype: LoadBalancerを利用する
MicroK8sでは`microk8s enable xxx`でPrometheus、ArgoCD、Istio、MinIOやcert-managerといったKubernetesのエコシステムでよく使うOSSを簡単に追加することが出来る。非常に便利。
ここではUIでクラスタの状態を可視化できるKubernetes dashboardと、仮想LBによってIPをクラスタ内のサービスに自動で提供する　（＝`type: LoadBalancer`が利用できるようになる）MetalLBをアドオンにてインストールする。
なお、利用可能な一覧は[ここ](https://microk8s.io/docs/addons)を参照。
まずMetalLBを追加する。MetalLBが払い出すIPのレンジは以下のようにコロンの後にハイフンかカンマで区切って指定するか、
```sh
microk8s enable metallb:10.64.140.43-10.64.140.49,192.168.0.105-192.168.0.111
```
以下のようにサブネットを指定して渡す。
```sh
microk8s enable metallb:192.168.1.240/24
```
ここでは`multipass info --all`のIPから近いところを適当に以下のように渡した。
```sh
microk8s enable metallb:172.20.221.240-172.20.221.249
```
コマンドが完了すると、以下のようにMetalLBのコントローラが配置される。
```sh
>kubectl get pod -n metallb-system
NAME                          READY   STATUS    RESTARTS   AGE
speaker-hnnsb                 1/1     Running   0          49s
controller-5f7bb57799-4lrc6   1/1     Running   0          49s
```
次にkubernetes dashboardを有効化する。
```
microk8s enable dashboard
```
こちらもコマンドが完了してしばらく待つと、dashboardのPodが起動してRunningとなる。
```sh
>kubectl get pod -l k8s-app=kubernetes-dashboard -A
NAMESPACE     NAME                                   READY   STATUS    RESTARTS   AGE
kube-system   kubernetes-dashboard-54b48fbf9-nw8cb   1/1     Running   0          56s
```
以上でkubernetes dashboardが利用できる。
ただ、dashboardのServiceはデフォルトでは`type: ClusterIP`でデプロイされるため、 `type: LoadBalancer`に変更する。
対象リソースを`kubectl edit`で編集する。
```sh
kubectl edit svc kubernetes-dashboard -n kube-system
```
実行するとデフォルトでメモ帳が起動するので、
`type: ClusterIP`となっている箇所を`type: LoadBalancer`に変更して保存してメモ帳を閉じる。
すると設定が反映され、dashboardにアクセスするためのIPが`External-IP`の箇所に表示される。
```
>kubectl get svc -A
NAMESPACE        NAME                        TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)                  AGE
default          kubernetes                  ClusterIP      10.152.183.1     <none>           443/TCP                  126m
kube-system      kube-dns                    ClusterIP      10.152.183.10    <none>           53/UDP,53/TCP,9153/TCP   126m
metallb-system   webhook-service             ClusterIP      10.152.183.82    <none>           443/TCP                  4m56s
kube-system      metrics-server              ClusterIP      10.152.183.33    <none>           443/TCP                  3m18s
kube-system      dashboard-metrics-scraper   ClusterIP      10.152.183.224   <none>           8000/TCP                 3m15s
kube-system      kubernetes-dashboard        LoadBalancer   10.152.183.83    172.20.221.240   443:32148/TCP            3m15s
```
上記の`172.20.221.240`のようにMetalLBで指定したIPが割り当てられていればOK。`Pending`になっている場合は上手くいっていないので、MetalLBのデプロイが正常か、そのIPを別の誰かが使っていないか、などを確認する。
ブラウザでhttps\://<割り当てたIP>にアクセスするとKubernetes dashboardの画面が表示される。
![5f258b4112cc64f7ace53bac948c2f50c57f6a8c5d3d27a06b7a2e7c3d1fd0de.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/7001b5c8-3455-f9a0-34fd-7472c50a4e57.png)
トークンかkubeconfigのパスを要求されるが、トークンはMicrok8sではデフォルトで`kube-system`のNamespace内に用意されているのでこれを使う。
以下のコマンドを1行ずつ実行する。
```
kubectl get secret -n kube-system microk8s-dashboard-token -o jsonpath={.data.token} > b64.txt
certutil -decode b64.txt b64_decode.txt
type 
```
上記のコマンドは、kubectlを使ってbase64でエンコードされているトークンの値を一度ファイルに吐き出し、それをcertutilコマンドで変換してtypeコマンドで画面表示している。
ブラウザのdashboardに戻って表示された文字列を入力してサインインを押すと、無事クラスタ内のリソースが可視化される。
上部の `default`と書かれているプルダウンはNamespaceを選択するためのプルダウンなので、`すべてのネームスペース`を選択し、左サイドバーの`ポッド`をクリックすると、以下のような画面が表示されるはずだ。
![a3a44505a99c2dc74a0d539374d4c82060dd5f19669dd0af4159074ebffcadad.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/5e651617-fb1b-39e2-833d-94fe6840b69d.png)

以上で安物のノートPCにおうちKubernetesが構築できることが確認できた。
おうちというか、ノートPCなのでどこでもKubernetesとも言える。
電車の中やカフェでもKubernetesを勉強したい人にはうってつけだ。

## 感想
MicroK8sが思った以上に優秀だった。
特にアドオンでのインストールが簡単すぎて、かなり好きになった。
いいですよ、MicroK8s。
ただ、今回誰にでも使えるようにコマンドラインベースで書いたけど、kubectlの結果をgrepしたり加工したりすることを考えるとWSLとか使ってLinuxベースでやった方が絶対いい。


## おまけ：トラブルシューティング
### `microk8s kubectl`が受け付けなくなる
具体的には以下のようなエラーが出る。
```sh
>microk8s kubectl get node
Unable to connect to the server: dial tcp 172.18.83.215:16443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
```
`microk8s kubectl`が参照しているクラスタのIPと、Multipassが管理しているIPが異なる場合はこのようなエラーが出る。
問題の確認方法は以下の通り。
1. クラスタのIPを確認する
```sh
microk8s kubectl config view --raw
```
clusters.cluster.serverのIPを控える。
2. Multipassが管理するIPを確認する
```sh
multipass info --all
```
IPv4のところに表示されるIPを控える。

1と2のIPが異なっていた場合、以下の方法でIPを修正する。
```
microk8s kubectl config set-cluster microk8s-cluster --server="https://<MultipassのIP>:16443"
```
### helmが動かない
helmはkubeconfigを使って動こうとするので、一般的に配布されているhelmコマンドを使おうとしてもそのままでは動かない。
一番楽なのは、`microk8s`のサブコマンドのhelmを使うとよい。
`microk8s helm install xxx`のような感じで使う。
面倒なら、kubectlと同じように以下のファイルをパスが通るところに設置する。
```sh:helm.bat
@echo off
microk8s helm %*
```