Longhornは、Kubernetes用の分散型ブロックストレージシステムです。 Longhornの導入により、Kubernetesクラスターでコンテナーアプリケーションに対して永続ボリュームを提供できます。
LonghornはRancherのアプリカタログにあるため、Rancherを一度でも触ったことがあるならお馴染みのソフトウェアだと思います。実際、RancherでLonghornを展開するのは簡単で、アプリカタログからLonghornを選び、Longhornの設定をぽちぽち定義して展開するだけで利用可能になります。
展開後はRancherでコンテナーアプリケーションを展開する際に永続ストレージが必要なときにLonghornを呼び出すだけです。自分で作成したYAMLを使ってコンテナーアプリケーションをデプロイする際は、PersistentVolumeClaimの要求を含めることで永続ボリュームを提供できます。
さて、ではここからが本題です。 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を使っていきたいと思います。