KubernetesクラスタをMicrok8sとUbuntu 20.04で作ってみる


## はじめに

Google Home や製造元アプリ、IFTTT に散らばっていた、スマート家電の制御をすべて、
HomeKit に寄せたくて [Homebridge](https://homebridge.io/) を構築したいと思い立った。

RaspberryPi 3 に構築しても良いとは思ったが、他の用途に使う予定があった。
Homebridge の Dockerイメージが存在したのでこの際 [Kubernetes](https://kubernetes.io/ja/) クラスタを構築しても良いと思ったので、逸般の誤家庭にあるVMware ESXi環境に `Ubuntu Server 20.04 LTS` を2ノード立てて、 [Microk8s](https://microk8s.io/) で Kubernetes クラスタを作成してみた。

初心者からステップアップしたい方向けにもわかるように説明してみる。


追記: MetalLB を構築する記事も書いたので合わせて読んで頂けると幸いだ｡

https://qiita.com/syamamura/items/57c529451b29cf532b38

## Ubuntu Server 20.04 LTS

要点のみ記載する。

### ネットワーク設定

インストール中にネットワーク設定を済ませておくと楽である
「インターフェイス名」->「Edit IPv4」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149815/945d87f9-4551-c956-460a-abb2b484b2ec.png)

我が家の環境の場合の例を示す。
クラスタを組む場合は、同じセグメントとするか、互いが疎通できる状態となるよう設定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149815/840fc895-6781-8a16-940d-638bd70ba1f3.png)


### LVMを有効にする(仮想環境のみ)

「仮想環境で実行している」かつ「よくわからない」場合は、以下の設定にチェックを入れると良い。

`[X] Set up this disk as an LVM group`

LVM(論理ボリュームマネージャ)を有効にしておくと後でボリュームサイズの変更が行いやすくなる。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149815/84fd90cb-b992-5254-91c5-b5eab5f3969e.png)


### OpenSSH server をインストールする

Ubuntu Server インストール後すぐに SSH ができるよう OpenSSH server をインスールする場合、
以下項目にチェックを入れる
`[X] Install OpenSSH server`

初めてみる機能だったが、 GitHub に登録している公開鍵をインポートできる便利すぎる機能があったので使ってみた。
`Import SSH identity:` を `from Github` に、`Github Username:` に自分の GitHub アカウントを設定してみた。

※GitHubに公開鍵を登録していない場合、手元に秘密鍵がない場合は有効に機能しないので、鍵の登録は事前に済ましておくこと。
よくわからない場合は、セキュリティレベルは下がるが、 `Allow password authentication over SSH` にチェックを入れておくと、パスワード認証が有効になる。

登録済みの公開鍵は以下のURLで確認できる
`https://github.com/<ユーザ名>.keys` 

私のアカウントの場合、以下のようになる
`https://github.com/gretchi.keys` 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149815/dcb2f69f-aada-7b3b-19d5-8a7f73ff9a9d.png)


### インストール画面では Microk8s を入れない

インストール画面でも Microk8s をインストールできるが、今回はsnapコマンドを使用してインストールするのでそのまま `[ Done ]` へ

余談だがこの画面で、 Microk8s をインストールする場合に Docker をインストールする必要があるか迷ったが不要であった。
もう一点、この画面でのインストールはインストール予約っぽくて、Ubuntu Server インストール直後に microk8s コマンドが見つからないと言われ、使えなかった。しばらく放置していると使えるようになった。(間違っていたらごめんなさい)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149815/f9ae00e3-acf2-ba83-2f17-62242e7a1ec1.png)

### インストール完了

インストールが完了するとオレンジ帯の部分が `Install complete!` となり、 `[ Reboot Now ]` ボタンが出現するのでそのまま reboot する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149815/5b9789ad-c735-92f3-aea3-4bef017e8ab1.png)



## Microk8s を入れる

`snap` コマンドを使用してインストールを行う

### 初期状態の確認

```bash
$ sudo snap list
Name        Version   Rev    Tracking       Publisher           Notes
core18      20201210  1944   latest/stable  canonical✓          base
lxd         4.0.5     19188  4.0/stable/…   canonical✓          -
snapd       2.48.2    10707  latest/stable  canonical✓          snapd
```

### 利用可能な channel バージョンの確認

`snap info microk8s` で Microk8s の詳細と利用可能な channel を確認する。

2021/03/24現在、安定版は v1.20.x が最新なようなので、 `1.20/stable` をインストールする。

```bash
$ sudo snap info microk8s
name:      microk8s
summary:   Lightweight Kubernetes for workstations and appliances
publisher: Canonical✓
store-url: https://snapcraft.io/microk8s
contact:   https://github.com/ubuntu/microk8s
license:   Apache-2.0
description: |
  MicroK8s is the smallest, simplest, pure production Kubernetes for clusters, laptops, IoT and
  Edge, on Intel and ARM. One command installs a single-node K8s cluster with carefully selected
  add-ons on Linux, Windows and macOS.  MicroK8s requires no configuration, supports automatic
  updates and GPU acceleration. Use it for offline development, prototyping, testing, to build your
  CI/CD pipeline or your IoT apps.
snap-id: EaXqgt1lyCaxKaQCU349mlodBkDCXRcg
channels:
  1.20/stable:      v1.20.4         2021-03-16 (2074) 218MB classic
  1.20/candidate:   v1.20.4         2021-03-10 (2074) 218MB classic
  1.20/beta:        v1.20.4         2021-03-10 (2074) 218MB classic
  1.20/edge:        v1.20.5         2021-03-22 (2094) 218MB classic
  latest/stable:    v1.20.4         2021-03-17 (2074) 218MB classic
  latest/candidate: v1.20.4         2021-03-09 (2081) 190MB classic
  latest/beta:      v1.20.4         2021-03-09 (2081) 190MB classic
  latest/edge:      v1.20.5         2021-03-22 (2093) 189MB classic
  dqlite/stable:    –
  dqlite/candidate: –
  dqlite/beta:      –
  dqlite/edge:      v1.16.2         2019-11-07 (1038) 189MB classic
  1.21/stable:      –
  1.21/candidate:   –
  1.21/beta:        v1.21.0-beta.1  2021-03-12 (2085) 191MB classic
  1.21/edge:        v1.21.0-alpha.3 2021-03-08 (2080) 190MB classic
  1.19/stable:      v1.19.8         2021-03-16 (2060) 216MB classic
  1.19/candidate:   v1.19.8         2021-03-10 (2060) 216MB classic
  1.19/beta:        v1.19.8         2021-03-10 (2060) 216MB classic
  1.19/edge:        v1.19.9         2021-03-22 (2095) 216MB classic
  1.18/stable:      v1.18.16        2021-03-16 (2055) 198MB classic
  1.18/candidate:   v1.18.16        2021-03-09 (2055) 198MB classic
  1.18/beta:        v1.18.16        2021-03-09 (2055) 198MB classic
  1.18/edge:        v1.18.16        2021-02-17 (2055) 198MB classic
  1.17/stable:      v1.17.17        2021-01-15 (1916) 177MB classic
  1.17/candidate:   v1.17.17        2021-01-14 (1916) 177MB classic
  1.17/beta:        v1.17.17        2021-01-14 (1916) 177MB classic
  1.17/edge:        v1.17.17        2021-01-13 (1916) 177MB classic
  1.16/stable:      v1.16.15        2020-09-12 (1671) 179MB classic
  1.16/candidate:   v1.16.15        2020-09-04 (1671) 179MB classic
  1.16/beta:        v1.16.15        2020-09-04 (1671) 179MB classic
  1.16/edge:        v1.16.15        2020-09-02 (1671) 179MB classic
  1.15/stable:      v1.15.11        2020-03-27 (1301) 171MB classic
  1.15/candidate:   v1.15.11        2020-03-27 (1301) 171MB classic
  1.15/beta:        v1.15.11        2020-03-27 (1301) 171MB classic
  1.15/edge:        v1.15.11        2020-03-26 (1301) 171MB classic
  1.14/stable:      v1.14.10        2020-01-06 (1120) 217MB classic
  1.14/candidate:   ↑
  1.14/beta:        ↑
  1.14/edge:        v1.14.10        2020-03-26 (1303) 217MB classic
  1.13/stable:      v1.13.6         2019-06-06  (581) 237MB classic
  1.13/candidate:   ↑
  1.13/beta:        ↑
  1.13/edge:        ↑
  1.12/stable:      v1.12.9         2019-06-06  (612) 259MB classic
  1.12/candidate:   ↑
  1.12/beta:        ↑
  1.12/edge:        ↑
  1.11/stable:      v1.11.10        2019-05-10  (557) 258MB classic
  1.11/candidate:   ↑
  1.11/beta:        ↑
  1.11/edge:        ↑
  1.10/stable:      v1.10.13        2019-04-22  (546) 222MB classic
  1.10/candidate:   ↑
  1.10/beta:        ↑
  1.10/edge:        ↑
```

### インストール

`snap install` コマンドでインストールする。
最新安定板を使用する場合は、`--channel=<channel>` を除外するか、`--channel="latest/stable"` と明示的に指定する

```bash
$ sudo snap install microk8s --classic --channel="1.20/stable"
Run configure hook of "microk8s" snap if present
microk8s (1.20/stable) v1.20.4 from Canonical✓ installed
```

### 確認

snap install 後、自動的に立ち上がってくる(と思う)ので、 `microk8s.status` または `microk8s status` コマンドで状態を確認する
正常に立ち上がっている場合、1行目に `microk8s is running` と表示される


```bash
$ sudo microk8s.status
microk8s is running
high-availability: no
  datastore master nodes: 127.0.0.1:19001
  datastore standby nodes: none
...
```

#### トラブルシューティング

snap インストールに失敗していると思われるので、手順を確認して欲しい

> microk8s.status: command not found


立ち上がってないか、クラスタリングの設定(後述)に失敗した可能性がある
`microk8s.start` または `microk8s start` で改善するか確認

> microk8s is not running. Use microk8s inspect for a deeper inspection.


クラスタリングの設定(後述)に失敗した直後に起こりがち
`microk8s reset && snap remove microk8s` で再インストールしないと再び上がってくることはなかった
設定のリストア方法をご存知であればコメントいただけると助かります。

> The connection to the server 127.0.0.1:16443 was refused - did you specify the right host or port?


## クラスタリング設定

2ノードで運用する予定だが、説明のしやすい3ノードで説明する
 
### 初期状態

インストール直後は各ノード独立した状態である
![microk8s-Page-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149815/26d4d7f5-0d1e-1789-9477-b9c1e6018d5c.png)



### 1番目のノードでノードを追加するためのコマンドを確認 (microk8s.add-node)

`kube-01` で `microk8s.add-node` または `microk8s add-node` コマンドを実行し「**ノードを追加するためのコマンドを確認**」する

```bash
$ sudo microk8s.add-node
From the node you wish to join to this cluster, run the following:
microk8s join 10.227.5.101:25000/c36731ea4adcc0e6ad723f3b37dcc148

If the node you are adding is not reachable through the default interface you can use one of the following:
 microk8s join 10.227.5.101:25000/c36731ea4adcc0e6ad723f3b37dcc148
 microk8s join 10.1.126.64:25000/c36731ea4adcc0e6ad723f3b37dcc148
```

設定したネットワークインターフェイスのIPアドレスが記載されたコマンドを抽出する

> microk8s join 10.227.5.101:25000/c36731ea4adcc0e6ad723f3b37dcc148

補足: ノード追加の実施は `microk8s join` で行われる。 `microk8s add-mode` はクラスタに参加するための microk8s join コマンドを取得するコマンドである

### 2番目以降のノードでクラスタに参加する (microk8s join)

先ほど取得した `microk8s join` コマンドを**2番目以降**のノードで実行する

```bash
$ sudo microk8s join 10.227.5.101:25000/1510b873d87bd55d6a7202c837925be2
Contacting cluster at 10.227.5.101
Waiting for this node to finish joining the cluster. ..
```

`microk8s.kubectl` または `microk8s kubectl` コマンドで Kubernetes のコマンドラインツールである [kubectl](https://kubernetes.io/ja/docs/reference/kubectl/overview/) でクラスタ内のノード一覧を確認する

`kube-01`, `kube-02` でそれぞれ実行し、お互いのノードが一覧表示されればOK


```bash
$ sudo microk8s.kubectl get nodes
NAME         STATUS   ROLES    AGE     VERSION
gn-kube-01   Ready    <none>   12h     v1.20.4-34+1ae8c29bbb48f7
gn-kube-02   Ready    <none>   4h38m   v1.20.4-34+1ae8c29bbb48f7
```

Ubuntu 22.04 LTS + microk8s v1.24.3 でクラスタを生成しようとしたところ以下のエラーが出たが､ `/etc/hosts` に各ホスト情報を記載することで解決した

```bash
$ sudo microk8s join 10.227.5.101:25000/1510b873d87bd55d6a7202c837925be2
Contacting cluster at 10.227.5.101
Connection failed. The hostname (kube-02) of the joining node does not resolve to the IP "10.227.5.102". Refusing join (400).
```

```plaintext:/etc/hosts
10.227.5.101 kube-01
10.227.5.102 kube-02
10.227.5.103 kube-03
```


2ノードのクラスタ構築の手順としては以上で終了である

![microk8s-Page-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149815/7114ed38-89ee-6e90-6bad-7c4858a9aa0f.png)

### 3番目のノードも追加してみる

3ノード目以降の挙動も確認していく

`kube-03` で `kube-01` で発行した `microk8s join` コマンドを実行すると以下イラストの状態となる

![microk8s-Page-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149815/8ae682b3-292f-5e5c-b4d2-69c5e06bbdd8.png)

`kube-03` のクラスタ参加が他のノード(kube-02)にも通知され、3ノード構成のクラスタリングが完了する

![microk8s-Page-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149815/eb114f6f-ca5d-c5fc-8d03-42ccee5b90c6.png)

`kubectl get nodes` で状態を確認すると、3ノード存在することが確認できる

```bash
$ sudo microk8s.kubectl get nodes
NAME         STATUS   ROLES    AGE     VERSION
gn-kube-01   Ready    <none>   12h     v1.20.4-34+1ae8c29bbb48f7
gn-kube-02   Ready    <none>   4h52m   v1.20.4-34+1ae8c29bbb48f7
gn-kube-03   Ready    <none>   37s     v1.20.4-34+1ae8c29bbb48f7
```

## 嵌ったポイント

`microk8s join` は、 kube-01, kube-02 双方で行う必要があるのかと思ってほぼ同時(ブロードキャスト)に join した結果デットロック状態となり、うんともすんとも言わなくなった。
結局 `snap remove` で microk8s をアンインストールして、再度インストールする手順を踏んだが、2～3回同じことをやった

## おまけ

### ダッシュボード(WebUI)を使う

ダッシュボードは add-on の形で提供されている

https://microk8s.io/docs/addon-dashboard

#### dashboard の有効化

いずれかのノードで dashboard を有効にする
add-on を有効にするコマンドは `microk8s.enable` または `microk8s enable` である

```bash
$ sudo microk8s.enable dashboard

Enabling Kubernetes Dashboard
Addon metrics-server is already enabled.
Applying manifest
serviceaccount/kubernetes-dashboard created
service/kubernetes-dashboard created
secret/kubernetes-dashboard-certs created
secret/kubernetes-dashboard-csrf created
secret/kubernetes-dashboard-key-holder created
configmap/kubernetes-dashboard-settings created
role.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
deployment.apps/kubernetes-dashboard created
service/dashboard-metrics-scraper created
deployment.apps/dashboard-metrics-scraper created

If RBAC is not enabled access the dashboard using the default token retrieved with:

token=$(microk8s kubectl -n kube-system get secret | grep default-token | cut -d " " -f1)
microk8s kubectl -n kube-system describe secret $token

In an RBAC enabled setup (microk8s enable RBAC) you need to create a user with restricted
permissions as shown in:
https://github.com/kubernetes/dashboard/blob/master/docs/user/access-control/creating-sample-user.md
```

有効にすると dashboard の pod が立ち上がることが確認できる

```bash
$ sudo microk8s.kubectl get pods -n kube-system
NAME                                         READY   STATUS    RESTARTS   AGE
kubernetes-dashboard-7ffd448895-rtzb4        1/1     Running   0          15m
...
```

#### 外部アクセスできる状態にする

ポートフォワードしクライアントからの通信を pod へ転送する

```bash
$ sudo microk8s kubectl port-forward -n kube-system service/kubernetes-dashboard 10443:443
```

`https://<host>:10443/` へアクセスし画面が表示されることを確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149815/fede1c64-ec4c-2ffa-11e0-e1082fcf70c1.png)

#### ログイントークンの取得

以下コマンドでトークンを取得し、サインインに使用する

```bash
sudo microk8s kubectl -n kube-system describe secret $(sudo microk8s kubectl -n kube-system get secret | grep default-token | cut -d " " -f1)
```

## 最後に

LBやストレージクラスまで構築していかないと実用上は落第点だが、クラウドサービスを利用していて感じる複雑な Kubernetes のイメージからは想像できないほどあっさり構築することができた。

Homebridge の構築に Kubernetes はオーバースペックだが､飼い鳥のケージ温度の管理にダッシュボードを作ったりすることを考えて今回 Microk8s で Kubernetes 環境を構築してみた。

最後まで読んでいただきありがとうございました。

![image.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149815/0a9389de-b3df-0adc-cc55-7e2e1e53a285.jpeg)