0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LonghornによるKubernetes環境での分散ストレージ構築

Last updated at Posted at 2025-10-27

はじめに

概要

私は、研究室にあるベアメタルサーバーを複数台用いてKubernetesクラスタを構築しています。
参考:

本クラスタはこれまで、各ノードのローカルディスクを個別に利用しており、ノード障害時に永続データが失われるリスクがありました。

そこで、今回は本クラスタに分散ストレージを導入するために、軽量な分散ブロックストレージシステムであるLonghorn をインストールし、動作確認を行いました。

なぜ分散ストレージが必要か

ノード障害によるデータ損失リスク

分散ストレージ導入前のクラスタには、PVCとして管理されるアプリケーションの永続データを保存するにあたり、以下2点の課題がありました。

1点目は、従来の構成では、各ノードがローカルディスク上にデータを保持していたため、ノードが停止するとそのデータにアクセスできなくなってしまうという点です。
2点目は、Podが別ノードに再スケジューリングされても、同じデータを引き継ぐことができず、永続性が保証されないという問題です。

これらの課題を解消するために、分散ストレージシステムの一つである、Longhornを導入しました。

Longhornについて

Longhorn は、Kubernetes 環境向けに設計された軽量で信頼性が高く、高性能な分散型ブロックストレージシステムです。

簡単に、アーキテクチャを確認します。

Kubernetesは CSI API により、LonghornのCSI Plugin と通信し PVC 作成や削除、アタッチ/デタッチなどの操作をLonghornに伝達します。

DaemonSetとして動作する Longhorn Manager は、Longhorn UIまたはLonghorn CSI PluginからのAPIリクエストを処理します。

Longhorn Manager にボリューム作成を指示すると、指定されたノード上に Longhorn Engine インスタンスが作成されます。

Longhorn Engine は、データの読み書きを行い、可用性を上げるため、複数の Replica に対してデータをレプリケーションします。

Longhorn UI は、Longhorn API を利用してクラスタ内の Volume 状態を可視化する Web インターフェースです。後に確認したいと思います。

Screenshot 2025-10-27 at 6.02.18 PM.png
(図は https://longhorn.io/docs/1.10.0/concepts/ より引用)

Longhornの構築

Longhorn導入前にあたり必要な設定

ツールのインストール

以下ページを参考に、open-iscsiの導入、専用ディスクの作成とマウントなど、Longhornを動かすための前提を整理します。

open-iscsi と NFSクライアント、デバイスマッパーのインストール

apt-get install -y open-iscsi nfs-common dmsetup

専用ディスクの作成とマウント設定

Longhornはデフォルトで各ノードの /var/lib/longhorn/ をディスクパスとして利用します。
ここではシステムディスクと分離するため、新しいディスク /dev/sdb/var/lib/longhorn-data にマウントし、UI上でこのパスをLonghornのディスクとして登録しました。

今回は、VirtualBoxを利用しVMを作成しKubernetes Nodeとしているため、以下のように10GBの新しい仮想ハードディスクファイルを接続します。

# worker-1 
VBoxManage createhd --filename worker1-longhorn.vdi --size 10240
VBoxManage storageattach "k8s-worker-1" --storagectl "SATA Controller" --port 2 --device 0 --type hdd --medium worker1-longhorn.vdi

# worker-2 
VBoxManage createhd --filename worker2-longhorn.vdi --size 10240
VBoxManage storageattach "k8s-worker-2" --storagectl "SATA Controller" --port 2 --device 0 --type hdd --medium worker2-longhorn.vdi

# worker-3 
VBoxManage createhd --filename worker3-longhorn.vdi --size 10240
VBoxManage storageattach "k8s-worker-3" --storagectl "SATA Controller" --port 2 --device 0 --type hdd --medium worker3-longhorn.vdi

OSは、元々あったディスクを /dev/sda (サイズ約30GB) として認識しており、それに加えて、/dev/sdb という名前で、サイズが 10GB の新しいディスクを認識しています。

k8s-worker-1,2,3
$ lsblk
NAME                      MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
sda                         8:0    0 29.3G  0 disk 
├─sda1                      8:1    0    1M  0 part 
├─sda2                      8:2    0    2G  0 part /boot
└─sda3                      8:3    0 27.3G  0 part 
  └─ubuntu--vg-ubuntu--lv 253:0    0 13.6G  0 lvm  /
sdb                         8:16   0   10G  0 disk 

新しいディスク(/dev/sdb)を ext4 でフォーマットし、/var/lib/longhorn-data をLonghornがデフォルトでデータを保存する領域として使用するディレクトリとして作成します。そして、フォーマットした /dev/sdb をマウントします。

最後に、OSを再起動してもこのマウント設定が保持されるよう、/etc/fstab に設定を追記します。

k8s-worker-1,2,3
sudo mkfs.ext4 /dev/sdb

sudo mkdir -p /var/lib/longhorn-data
sudo mount /dev/sdb /var/lib/longhorn-data

UUID=$(sudo blkid -s UUID -o value /dev/sdb)
echo "UUID=$UUID /var/lib/longhorn-data ext4 defaults,nofail 0 0" | sudo tee -a /etc/fstab

10GBのディスク(/dev/sdb)が /var/lib/longhorn-data に正しくマウントされ、Longhornがデータ保存に使える状態になっていることを確認します。

k8s-worker-1,2,3
$ df -h
Filesystem                         Size  Used Avail Use% Mounted on
tmpfs                              297M  1.4M  296M   1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv   14G  8.6G  4.2G  68% /
/dev/sdb                           9.8G   24K  9.3G   1% /var/lib/longhorn-data

ディスク容量の拡張

後述のLonghornデプロイ時に、Node上のディスク容量が不足し、複数のPodがEvictedとなる事態が発生しました。
/var/lib/longhorn はルートファイルシステム上にマウントされており、その使用率が 83% に達していることが根本的な原因でした。

$ df -h /var/lib/longhorn
Filesystem                         Size  Used Avail Use% Mounted on
/dev/mapper/ubuntu--vg-ubuntu--lv   14G   11G  2.2G  83% /

次に、ディスクとLVMの構成を確認しました。
物理ディスク sda のパーティションである sda3 の27.3Gから ubuntu--vg-ubuntu--lv の13.6Gを引いた13.7Gは、ボリュームグループ(VG)内の未割り当て領域です。

$ lsblk -o NAME,SIZE,FSTYPE,TYPE,MOUNTPOINTS
NAME                       SIZE FSTYPE      TYPE MOUNTPOINTS
sda                       29.3G             disk 
├─sda1                       1M             part 
├─sda2                       2G ext4        part /boot
└─sda3                    27.3G LVM2_member part 
  └─ubuntu--vg-ubuntu--lv 13.6G ext4        lvm  /
sdb                         10G ext4        disk /var/lib/longhorn-data

$ sudo pvs; sudo vgs; sudo lvs
  PV         VG        Fmt  Attr PSize  PFree  
  /dev/sda3  ubuntu-vg lvm2 a--  27.29g <13.65g
  VG        #PV #LV #SN Attr   VSize  VFree  
  ubuntu-vg   1   1   0 wz--n- 27.29g <13.65g
  LV        VG        Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  ubuntu-lv ubuntu-vg -wi-ao---- 13.64g

このVG内の未割り当て領域(約13.6G)をすべて既存のLV ubuntu-lv に割り当て、ディスク容量を拡張します。

$ sudo lvextend -r -l +100%FREE /dev/ubuntu-vg/ubuntu-lv
  Size of logical volume ubuntu-vg/ubuntu-lv changed from 13.64 GiB (3493 extents) to 27.29 GiB (6987 extents).
  Logical volume ubuntu-vg/ubuntu-lv successfully resized.
resize2fs 1.46.5 (30-Dec-2021)
Filesystem at /dev/mapper/ubuntu--vg-ubuntu--lv is mounted on /; on-line resizing required
old_desc_blocks = 2, new_desc_blocks = 4
The filesystem on /dev/mapper/ubuntu--vg-ubuntu--lv is now 7154688 (4k) blocks long.

実行後、ルートファイルシステムで利用可能なディスクサイズが13G増えたことを確認しました。

$ df -h /
Filesystem                         Size  Used Avail Use% Mounted on
/dev/mapper/ubuntu--vg-ubuntu--lv   27G  7.7G   18G  30% /

Longhornのインストール

様々なインストール方法があります。

今回はkubectlでインストールしました。

kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.10.0/deploy/longhorn.yaml

ディスクの容量を十分に確保した状態で、Longhornのコンポーネントが正常にRunningになるまで待ちます。

ryu@k8s-master:~$ k get pods -n longhorn-system 
NAME                                                READY   STATUS    RESTARTS        AGE
csi-attacher-699d7b6777-2slns                       1/1     Running   1 (3m33s ago)   5m6s
csi-attacher-699d7b6777-b2f4q                       1/1     Running   3 (2m23s ago)   5m6s
csi-attacher-699d7b6777-fdfjn                       1/1     Running   2 (79s ago)     5m6s
csi-provisioner-84bbd9588b-d8gh6                    1/1     Running   2 (2m57s ago)   5m6s
csi-provisioner-84bbd9588b-lzf5g                    1/1     Running   2 (58s ago)     5m6s
csi-provisioner-84bbd9588b-pr88z                    1/1     Running   1 (3m24s ago)   5m6s
csi-resizer-7878697556-4rth9                        1/1     Running   0               5m5s
csi-resizer-7878697556-9rgvn                        1/1     Running   2 (2m49s ago)   5m5s
csi-resizer-7878697556-mz5kl                        1/1     Running   2 (37s ago)     5m5s
csi-snapshotter-765dc584c4-f6vkq                    1/1     Running   0               5m4s
csi-snapshotter-765dc584c4-sp9p5                    1/1     Running   1 (54s ago)     5m4s
csi-snapshotter-765dc584c4-znvlc                    1/1     Running   2 (2m38s ago)   5m5s
engine-image-ei-26bab25d-2sp7z                      1/1     Running   0               6m41s
engine-image-ei-26bab25d-j5972                      1/1     Running   0               6m40s
engine-image-ei-26bab25d-qgtnv                      1/1     Running   0               6m40s
instance-manager-3d5f1d60a1df63e5736aabfd9def5d1e   1/1     Running   0               6m12s
instance-manager-88ea077425c744e8b67e7496b0a07087   1/1     Running   0               6m1s
instance-manager-968cb0acf46106ca167c39a2633ce055   1/1     Running   0               5m4s
longhorn-csi-plugin-54kqj                           3/3     Running   0               5m3s
longhorn-csi-plugin-czc6f                           3/3     Running   0               5m4s
longhorn-csi-plugin-zgpc9                           3/3     Running   0               5m3s
longhorn-driver-deployer-57b6ff7bf7-88dfx           1/1     Running   0               14m
longhorn-manager-f6zxp                              2/2     Running   0               8m23s
longhorn-manager-pkt7h                              2/2     Running   0               7m13s
longhorn-manager-r827v                              2/2     Running   0               8m23s
longhorn-ui-6797874dbf-g6wqx                        1/1     Running   0               14m
longhorn-ui-6797874dbf-xlsjf                        1/1     Running   0               14m

Longhorn UIの確認

ポートフォワードしてLonghorn UIを開きます。

kubectl port-forward --namespace longhorn-system service/longhorn-frontend 8080:80

UIのトップページ

image.png

各ノードのディスクパスを先ほど作成した/var/lib/longhorn-data に修正します。

image.png

動作確認

PVCとPodの作成

1GiのPVCを作成し、それをマウントしたPodでデータを書き込む例を示します。

なお、Longhornをデプロイすると、自動的に longhorn という StorageClass が作成されます。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: longhorn
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: driver.longhorn.io
allowVolumeExpansion: true
reclaimPolicy: Delete
volumeBindingMode: Immediate
parameters:
  numberOfReplicas: "3"
  dataEngine: "v1"
  fsType: "ext4"
  dataLocality: "disabled"
  disableRevisionCounter: "true"

そのため、PVCの storageClassNamelonghorn を指定することで、Longhorn経由のボリュームが自動的にプロビジョニングされます。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: longhorn-test-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: longhorn
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-pod
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-pod
  template:
    metadata:
      labels:
        app: test-pod
    spec:
      initContainers:
        - name: init-once-write
          image: busybox:latest
          command: ["/bin/sh","-c"]
          args:
            - |
              if [ ! -f /data/test.txt ]; then
                echo "$(date) - This is a one-time write test" > /data/test.txt;
              fi
          volumeMounts:
            - name: storage
              mountPath: /data
      containers:
        - name: busybox
          image: busybox:latest
          command: ["/bin/sh","-c"]
          args: ["sleep infinity"]
          volumeMounts:
            - name: storage
              mountPath: /data
      volumes:
        - name: storage
          persistentVolumeClaim:
            claimName: longhorn-test-pvc

Podは、k8s-worker-3にスケジューリングされています。

$ k get po -o wide
NAME                       READY   STATUS    RESTARTS   AGE     IP            NODE           NOMINATED NODE   READINESS GATES
test-pod-dfc4fdc7c-s6dmg   1/1     Running   0          2m23s   10.244.3.45   k8s-worker-3   <none>           <none>

ボリュームにデータが書き込まれたことも確認できます。

$ k exec test-pod-dfc4fdc7c-s6dmg -- cat /data/test.txt
Defaulted container "busybox" out of: busybox, init-once-write (init)
Mon Oct 27 06:12:26 UTC 2025 - This is a one-time write test

データの複製確認

/var/lib/longhorn-data/ にレプリカが作成されています。

k8s-worker-3
$ sudo ls -l /var/lib/longhorn/replicas/
total 0

$ sudo ls -l /var/lib/longhorn-data/replicas/
total 4
drwx------ 2 root root 4096 Oct 27 06:12 pvc-40b9b143-d67d-44a1-a066-c1d81b1a0fd4-1a64cc5d

k8s-worker-3だけでなく、k8s-worker-2, k8s-worker-1にも、同様のデータが格納されています。これにより、分散ストレージとしてレプリケーションが機能していることが確認できます。

k8s-worker-2
$ sudo ls -l /var/lib/longhorn-data/replicas/
total 4
drwx------ 2 root root 4096 Oct 27 06:12 pvc-40b943-d67d-44a1-a066-c1d81b1a0fd4-4844e8f5
k8s-worker-1
$ sudo ls -l /var/lib/longhorn-data/replicas
total 4
drwx------ 2 root root 4096 Oct 27 06:12 pvc-40b943-d67d-44a1-a066-c1d81b1a0fd4-a72a9ce0

各ノードの /var/lib/longhorn-data/replicas にレプリカが生成されていることは、UIからも確認できます。

image.png

image.png

ノード障害時のデータ維持

ここで、k8s-worker-3のVMをシャットダウンする形でノードを意図的に停止します。この時、Podが他ノードで再スケジューリングされてもデータが失われずに保持されます。

Longhorn CSIがPVCを自動的にデタッチ/再アタッチすることで、同じボリュームが新しいノードから継続してアクセス可能になるためです。

image.png

k8s-worker-3が利用できなくなり、Podはk8s-worker-1にスケジューリングされるようになりました。

$ k get po -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP            NODE           NOMINATED NODE   READINESS GATES
test-pod-dfc4fdc7c-5pnjg   1/1     Running   0          10m   10.244.1.80   k8s-worker-1   <none>           <none>

Nodeを落とし再スケジューリングが行われても、データが失われていないことを確認します。

$ kubectl exec test-pod-dfc4fdc7c-5pnjg -- cat /data/test.txt
Defaulted container "busybox" out of: busybox, init-once-write (init)
Mon Oct 27 06:12:26 UTC 2025 - This is a one-time write test

ノード復旧後の自動リビルド

VMを再起動し、k8s-worker-3が再度k8sクラスタに参加すると、Longhornはそれを検知し、レプリカの再同期(リビルド)を行っていることが、UIから確認できます。

image.png

これにより、再び設定通りのレプリカ数が確保され、ボリュームの冗長性が回復します。

まとめ

今回は、KubernetesクラスタにLonghornを用いて分散ストレージの仕組みを導入し、基本的な挙動について確認を行いました。

導入自体は非常にシンプルで、GUIもとても整っており良い体験でした。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?