遅ればせながらMicroK8sをためす

こんにちは、オールアバウトのSRE numa_numaと申します。

当社では、GKE (Google Kubernetes Engine) をアプリケーション稼働のメインに使用しています。
今回もKubernetes (K8S) まわりのネタで、MicroK8sというツールを検証したのでそちらをご紹介します。

# MinikubeとMicroK8sの違い

オールアバウトでは、手元でK8Sを試したい時のツールとしてMinikubeを使ってきました。

ただ、先般よりCNCFの認定ディストリビューションとしてMicroK8sというのが出ていて、かねてより気になっていたものの、触る機会がなかったのでこの機にためしてみました。

それなりに情報が出ているので、二番煎じ三番煎じになってしまうかもしれませんが、当社としては私がこのツールのパイオニアです(笑)

## Minikubeの特徴

MinikubeはローカルのPCにインストールする想定のツールのため、以下のような特徴があります。

- PCにインストールして気軽に使える
- Minikube・kubectl・	VirtualBoxなどを別々にインストール
- 動作は重くなりがち

## MicroK8sの特徴

対してMicroK8sはUbuntuが開発しているディストリビューションであり、以下のような特徴があります。

- Ubuntu (Debian) 系のOSでsnapでパッケージ管理する必要がある
- 1ホストで完結し、軽量/軽快に動く
- microk8sという単一のコマンドで行えるオペレーションの単純性

# どうためすか？

とはいえ、できればPCで手軽に利用したいということで、私のMacBookに入れられないか調べてみました。
https://microk8s.io/docs/install-alternatives#macos

公式には上記のように出ていて、multipassで仮想化した上にMicroK8sを積み込むというイレギュラーであり、PCリソースの無駄なやり方しかなさそうです。。。
泣く泣くこの方法は断念することにします。

## 試行する環境

当社のメインクラウドはGCPですので、GCE (Google Compute Engine)を使用し以下の要件でサクッとMicroK8sを構築していきます。

- GCE（n1-standard-2）
    - 2vCPU
    - 7.5GB Mem
    - 50GB HDD
    - asia-northeast (東京)
    - Debian GNU/Linux 10 (buster)

# MicroK8sをインストール！

立てたGCEインスタンスにSSHログインします。

rootにスイッチして、snapdをインストールします。

```
# apt-get install snapd
# dpkg -l | grep snap
ii  snapd                                 2.37.4-1+b1                  amd64        Daemon and tooling that enable snap packages
```

snapを使ってMicroK8sをインストールします。
(公式にしたがって、2019年12月現在のstableで。)

```
# snap install microk8s --classic --channel=1.16/stable
2019-12-18T07:09:59Z INFO Waiting for restart...
microk8s (1.16/stable) v1.16.3 from Canonical✓ installed
```

インストール完了。とても簡単です:bangbang:

これも公式にしたがって、自分のユーザでmicrok8sが利用できるようにしておきます。

```
# usermod -a -G microk8s numa_numa
```

# MicroK8sをオペレーション

自分のユーザに戻って状況を確認します。

```
$ snap info microk8s
name:      microk8s
summary:   Kubernetes for workstations and appliances
publisher: Canonical✓
contact:   https://github.com/ubuntu/microk8s
license:   unset
description: |
  MicroK8s is a small, fast, secure, single node Kubernetes that installs on just about any Linux
  box. Use it for offline development, prototyping, testing, or use it on a VM as a small, cheap,
  reliable k8s for CI/CD. It's also a great k8s for appliances - develop your IoT apps for k8s and
  deploy them to MicroK8s on your boxes.
commands:
  - microk8s.add-node
  - microk8s.cilium
  - microk8s.config
  - microk8s.ctr
  - microk8s.disable
  - microk8s.enable
  - microk8s.helm
  - microk8s.inspect
  - microk8s.istioctl
  - microk8s.join
  - microk8s.kubectl
  - microk8s.leave
  - microk8s.linkerd
  - microk8s.remove-node
  - microk8s.reset
  - microk8s.start
  - microk8s.status
  - microk8s.stop
【〜以下省略〜】
```

あと `.bashrc` に以下を追記して、コマンド実行がフルパスでなくてもいいようにしておきましょう。
これを有効にするためには、一度サーバから抜けて再ログイン。

```
export PATH=$PATH:/snap/bin
```

microk8sコマンドで状態確認。

```
$ microk8s.status
microk8s is running
addons:
cilium: disabled
dashboard: disabled
dns: disabled
fluentd: disabled
gpu: disabled
helm: disabled
ingress: disabled
istio: disabled
jaeger: disabled
knative: disabled
linkerd: disabled
metrics-server: disabled
prometheus: disabled
rbac: disabled
registry: disabled
storage: disabled
```

# MicroK8sへサービスデプロイ

ここまでできたら、さっそく簡単なサービスをデプロイしてみましょう。

サービスを公開するにあたってIngressを使用するので、まずこのaddonを有効化します。

```
$ microk8s.enable ingress

Enabling Ingress
namespace/ingress created
serviceaccount/nginx-ingress-microk8s-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-microk8s-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-microk8s-role created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-microk8s created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-microk8s created
configmap/nginx-load-balancer-microk8s-conf created
daemonset.apps/nginx-ingress-microk8s-controller created
Ingress is enabled
```

ドキュメントを見ると、先月くらいにMetal LBが使用可能になっておりとても気になったのですが、まず一般的なプラクティスでセオリー通り使ってみます。

マニュフェストファイルを用意していきます。
Deploymentから。見えるようにするアプリケーションのイメージは適当にnginxのものにしておきます。
各マニュフェストファイルは、ホームディレクトリなどに作成して置いておきます。

```test-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-test
spec:
  replicas: 2
  revisionHistoryLimit: 5
  selector:
    matchLabels:
      name: web-test
  template:
    metadata:
      labels:
        name: web-test
    spec:
      containers:
      - name: web-test-container
        image: nginx:mainline-alpine
        ports:
        - containerPort: 8080
```

Deploymentをデプロイします。

```
$ microk8s.kubectl apply -f test-deployment.yaml
deployment.apps/web-test created
```

次にService。MicroK8sインスタンスの外部IPで公開するので、ターゲットはポート80にしておきます。

```test-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: web-test-service
spec:
  type: NodePort
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 80
  selector:
    name: web-test
```

Serviceをデプロイします。

```
$ $ microk8s.kubectl apply -f test-service.yaml
service/web-test-service created
```

最後にIngressです。これもテストなので最低限の記述にしておきます。

```test-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: web-test-ingress
spec:
    backend:
      serviceName: web-test-service
      servicePort: 8080
```

Ingressをデプロイします。

```
$ microk8s.kubectl apply -f test-ingress.yaml
ingress.extensions/web-test-ingress created
```

kubectlで各リソースの状態を確認します。

```
$ microk8s.kubectl get pod,svc,ingress
NAME                           READY   STATUS    RESTARTS   AGE
pod/web-test-c7b4cc54f-d2jx4   1/1     Running   0          5m
pod/web-test-c7b4cc54f-nr7n9   1/1     Running   0          5m

NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/kubernetes         ClusterIP   10.152.183.1     <none>        443/TCP          23h
service/web-test-service   NodePort    10.152.183.102   <none>        8080:31911/TCP   3m39s

NAME                                  HOSTS   ADDRESS     PORTS   AGE
ingress.extensions/web-test-ingress   *       127.0.0.1   80      2m22s
```

インスタンスの外部IPを直接指定し、WEBを見てみます。

<img width="1044" alt="test_microk8s.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147015/055838c2-e213-57c1-e4bb-b84df7e2969d.png">

nginxのテストページが確認できました！

以下のコマンドで、構築した環境をクリーンアップすることができます。

```
$ microk8s.reset

Calling clean_cluster
namespace "ingress" deleted
Cleaning resources in namespace default
No resources found
No resources found
deployment.apps "web-test" deleted
endpoints "kubernetes" deleted
endpoints "web-test-service" deleted
event "gce-test-numa-numa-microk8s.15e11812b61d432a" deleted
event "web-test-c7b4cc54f-pgf4v.15e1186518d6cf70" deleted
event "web-test-c7b4cc54f-xbrh8.15e11865172d0ca2" deleted
event "web-test-c7b4cc54f-xbrh8.15e11bfc367091f6" deleted
【〜以下省略〜】
```

リセットするとインスタンスのTCPポート自体がlistenしなくなります。

<img width="1044" alt="reset_microk8s.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147015/18d751a1-0536-04db-0223-9e36b1966a73.png">

# まとめと所感

MicroK8sの構築はsnapですぐにできますし、何よりmicrok8sコマンドを使用したオペレーションが非常に分かりやすく感じました。

ただ今回試したやり方ですと、サービスページがGCEインスタンスの外部IPに依存するために、複数人で使用することができません。
共用の開発環境として使用を検討するためには、GCE側の権限を強化するか Google Cloud Load Balancer の併用などを検討する必要があるでしょう。

addonについては、helm・Istioなどを併用してやると、効率的な開発/サービス管理に役立つかもしれないと感じました。
有用なaddonが依存性の解決なしにコマンド1つで有効化できるのは、Minikubeにない魅力だと思います。

https://metallb.universe.tf/
Metal LBは使ってみたいですね…:smiley: