仮想化通信

日本仮想化技術株式会社の公式エンジニアブログ

microk8sで分散型ブロックストレージの「Longhorn」を試す

Longhornは、Kubernetes用の分散型ブロックストレージシステムです。 Longhornの導入により、Kubernetesクラスターでコンテナーアプリケーションに対して永続ボリュームを提供できます。

LonghornはRancherのアプリカタログにあるため、Rancherを一度でも触ったことがあるならお馴染みのソフトウェアだと思います。実際、RancherでLonghornを展開するのは簡単で、アプリカタログからLonghornを選び、Longhornの設定をぽちぽち定義して展開するだけで利用可能になります。

f:id:virtualtech:20200618094325p:plain

展開後はRancherでコンテナーアプリケーションを展開する際に永続ストレージが必要なときにLonghornを呼び出すだけです。自分で作成したYAMLを使ってコンテナーアプリケーションをデプロイする際は、PersistentVolumeClaimの要求を含めることで永続ボリュームを提供できます。

f:id:virtualtech:20200618094715p:plain

さて、ではここからが本題です。 RancherやRancher Labs以外が提供するツールを用いて構築したKubernetes以外でLonghornが利用できるか確認してみます。 今回はKuberetesクラスターの構築にmicrok8sを使ってみます。

動作環境について

Longhornのデフォルト設定では、少なくとも3台のノードが必要です。そこで今回は次のような構成のマシンを4つ用意しました。

  • Ubuntu 18.04.4
  • vCPU 4
  • メモリ 4GB
  • ストレージ 40GB
  • 1 NIC

microk8sのインストール

1台目のマシンには、次のようにセットアップします。

$ sudo snap install microk8s --classic --stable
$ sudo usermod -a -G microk8s $USER
$ sudo chown -f -R $USER ~/.kube

$ microk8s status
$ sudo snap alias microk8s.kubectl kubectl

2台目以降のマシンには、次のようにセットアップします。

$ sudo snap install microk8s --classic --stable
$ sudo usermod -a -G microk8s $USER

microk8sノードを追加

以下のドキュメントを参考に、microk8sをクラスター化します。

次のようにマシンを用意しました。

$ microk8s kubectl get no
NAME         STATUS   ROLES    AGE   VERSION
microk8s-1   Ready    <none>   60m   v1.18.3-34+0c5dcc01175871
microk8s-2   Ready    <none>   58m   v1.18.3-34+0c5dcc01175871
microk8s-3   Ready    <none>   58m   v1.18.3-34+0c5dcc01175871
microk8s-4   Ready    <none>   28m   v1.18.3-34+0c5dcc01175871

1台目でmicrok8sを導入したあと、残りの3台をAdd Nodeしていきます。

アドオンの有効化

以下のアドオンを最低限導入します。

$ microk8s enable rbac dns

Longhornで特権コンテナが要求されるので許可

各ノードで実行しておきます。

$ sh -c 'echo "--allow-privileged=true" >> /var/snap/microk8s/current/args/kube-apiserver'
$ sudo systemctl restart snap.microk8s.daemon-apiserver.service

Longhornのデプロイ

そのあと以下の手順に従って、Longhornをデプロイします。

$ kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/master/deploy/longhorn.yaml
$ kubectl get pods --namespace longhorn-system --watch

※ 現時点ではmasterを指定しても問題ありませんでしたが、1.0.0をデプロイする場合は https://raw.githubusercontent.com/longhorn/longhorn/v1.0.0/deploy/longhorn.yaml を指定します。```

Longhornの動作確認

各種コマンドを実行して、デプロイがうまくいったことを確認します。

$ kubectl get pods --namespace longhorn-system
NAME                                       READY   STATUS    RESTARTS   AGE
csi-attacher-9656c557d-b84cd               1/1     Running   0          7m38s
csi-attacher-9656c557d-qsdct               1/1     Running   0          7m38s
csi-attacher-9656c557d-st7pd               1/1     Running   0          7m38s
csi-provisioner-6cb5bdd789-mvw6s           1/1     Running   0          7m37s
csi-provisioner-6cb5bdd789-pxz68           1/1     Running   0          7m37s
csi-provisioner-6cb5bdd789-wzzl4           1/1     Running   0          7m37s
csi-resizer-6c4674db7c-qlb76               1/1     Running   0          7m37s
csi-resizer-6c4674db7c-vw2z6               1/1     Running   0          7m37s
csi-resizer-6c4674db7c-zpx7f               1/1     Running   0          7m37s
engine-image-ei-eee5f438-27fnh             1/1     Running   0          8m14s
engine-image-ei-eee5f438-2kml5             1/1     Running   0          8m14s
engine-image-ei-eee5f438-9fjx5             1/1     Running   0          8m14s
engine-image-ei-eee5f438-xffp7             1/1     Running   0          8m14s
instance-manager-e-3766fe8e                1/1     Running   0          8m8s
instance-manager-e-64bb0030                1/1     Running   0          7m9s
instance-manager-e-8ec18770                1/1     Running   0          7m51s
instance-manager-e-94b08b11                1/1     Running   0          7m32s
instance-manager-r-0d5ae924                1/1     Running   0          7m50s
instance-manager-r-27c175cd                1/1     Running   0          7m32s
instance-manager-r-61cfc52c                1/1     Running   0          7m9s
instance-manager-r-de8bda14                1/1     Running   0          8m7s
longhorn-csi-plugin-m42p4                  2/2     Running   0          7m37s
longhorn-csi-plugin-m4qbm                  2/2     Running   0          7m37s
longhorn-csi-plugin-n8lh4                  2/2     Running   0          7m37s
longhorn-csi-plugin-xtm75                  2/2     Running   0          7m37s
longhorn-driver-deployer-cd74cb75b-656b4   1/1     Running   0          8m34s
longhorn-manager-878gt                     1/1     Running   0          8m34s
longhorn-manager-9rkhj                     1/1     Running   0          8m34s
longhorn-manager-fz6xc                     1/1     Running   0          8m34s
longhorn-manager-rngt2                     1/1     Running   0          8m34s
longhorn-ui-8486987944-bh5mt               1/1     Running   0          8m34s

$ kubectl get sc
NAME       PROVISIONER          RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
longhorn   driver.longhorn.io   Delete          Immediate           true                   3m20s

$ kubectl get svc -nlonghorn-system
NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)     AGE
csi-attacher        ClusterIP   10.152.183.37    <none>        12345/TCP   109s
csi-provisioner     ClusterIP   10.152.183.51    <none>        12345/TCP   109s
csi-resizer         ClusterIP   10.152.183.165   <none>        12345/TCP   109s
longhorn-backend    ClusterIP   10.152.183.132   <none>        9500/TCP    3m53s
longhorn-frontend   ClusterIP   10.152.183.50    <none>        80/TCP      3m53s

使ってみる

以下のようにYAMLを用意して、ストレージ割り当てしたPodを作成してみます。ポイントはストレージクラスとしてlonghornを指定することです。そのほかは特に今までの使い方と変わりありません。

$ cat testpod.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
  labels:
    app: myclaim
spec:
  storageClassName: longhorn
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginxapp1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginxapp1
  template:
    metadata:
      labels:
        app: nginxapp1
    spec:
      containers:
      - name: nginxapp1
        image: nginx:alpine
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: "/usr/share/nginx/html/"
          name: nginxapp1
      volumes:
      - name: nginxapp1
        persistentVolumeClaim:
          claimName: myclaim
---
apiVersion: v1
kind: Service
metadata:
  name: nginxapp1-nodeport
  labels:
    app: nginxapp1
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
  selector:
    app: nginxapp1
    
    
$ kubectl apply -f testpod.yaml
$ kubectl get -f testpod.yaml 
NAME                            STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/myclaim   Bound    pvc-ded7c3e9-3ab0-453b-a182-3a3e797f1197   1Gi        RWO            longhorn       7m1s

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginxapp1   1/1     1            1           7m1s

NAME                         TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/nginxapp1-nodeport   NodePort   10.152.183.180   <none>        80:30080/TCP   7m1s

問題なく利用できました。

microk8sではstorageというアドオンを有効にすることで永続ストレージを提供できますが、ローカルパスを利用したストレージであったため、マルチノードでの利用は制約があり使いにくい場合がありました。

Longhornを利用すれば、コンテナークラスターに分散型のブロックストレージ機能を手軽に提供できます。使い勝手が良く安定して利用できたので、これからもLonghornを使っていきたいと思います。