Ubuntu Weekly Recipe

第571回LXD 3.0のストレージ設定

第521回ではLXD 3.0の基本的な使い方を、第535回ではネットワークの設定方法を紹介しました。今回はLXD 2.0から3.0にかけて非常に便利になったストレージ関連の設定について紹介しましょう。

LXDにおけるコンテナストレージ

LXDはシステムコンテナである以上、コンテナのベースイメージや、インスタンスであるルートファイルシステムをどこかに保存しなくてはなりません。LXDにおいてこれは「ストレージプール」と呼ばれています。また、ストレージプールを管理するシステムは「ストレージバックエンド」です。

LXD 2.0ではストレージプール・ストレージバックエンドはシステム上に1つしか設定できませんでした。実際には初期設定時にバックエンドを選択してそれで完了だったのです。

この状況はLXD 2.9で大きく変わることになります。1つのシステム上で複数のストレージプールを設定できるようになったのです。ストレージプールごとに異なるストレージバックエンドを選択可能です。さらにlxd storageコマンドが実装され、ストレージに関する様々な設定を操作できるようになりました。

これにより、たとえばワークロードの大きなインスタンスはSSD上に構築したストレージプールを利用し、サイズが重要なインスタンスはHDD上に構築したストレージプールを利用するといった使い分けが可能になります。

さらにはストレージプールを利用して、コンテナに対して追加のストレージボリュームをかんたんに追加・削除できるようになりました。これはDockerで言うところのVolumeコンテナをイメージすれば良いでしょう。

さて、LXDのインストール直後はストレージプールは何も作られていません。最初のストレージプールはlxd initコマンドで作成します。第521回にも出ている実行例から抜粋すると、次の部分です。

$ sudo lxd init
Do you want to configure a new storage pool? (yes/no) [default=yes]:
  => ストレージプール(コンテナの保存先)を作成するかどうか
Name of the new storage pool [default=default]:
  => 作成するストレージプールの名前
Name of the storage backend to use (btrfs, dir, lvm) [default=btrfs]:
  => ストレージバックエンドの選択
     速度・利便性の両方においてbtrfsを選ぶのが無難です
     ホストのファイルシステムがbtrfsである必要はありません
Create a new BTRFS pool? (yes/no) [default=yes]:
  => btrfsのプールを作成するかどうか
Would you like to use an existing block device? (yes/no) [default=no]:
  => 既存のブロックデバイスを利用するかどうか
     利用しない場合はbtrfsでフォーマットしたイメージファイルを作成します
Size in GB of the new loop device (1GB minimum) [default=15GB]: 5
  => ストレージプールのサイズ

設定を変更しなければ「default」という名前のストレージプールが「btrfsバックエンド」を利用して作成されます。

LXD 3.0でサポートしているバックエンドは次の5つです。

  • Dir
  • Btrfs
  • LVM
  • ZFS
  • CEPH

Dirはディレクトリツリーをそのままコンテナとして見せる方式です。古式ゆかしいchrootをLXD再現しているようなものです。どんなシステムでも確実に動くという強みはあるものの、性能的にも容量的にも非常に効率が悪い上に、LXDのコンテナ操作に関するさまざまな便利機能をサポートしていません。よっぽどのことがない限りは、これを選ぶことはないでしょう。

BtrfsとLVM、ZFSはいずれも十分なパフォーマンスを発揮しますので、どれを選んでも良いでしょう。これらのバックエンドを使用するためには、それぞれbtrfs-progs、lvm2、zfsutils-linuxパッケージがインストールされていなくてはなりません。Ubuntuのクラウドイメージだとzfsutils-linuxは初期インストールされていないため、上記のlxd initではZFSでは表示されていないのです。

Btrfsを選んでおくと、LXDの中でLXDを使う場合に便利です。どれにするか迷ったのなら、UbuntuであればBtrfsを選んでおけば良いでしょう。

分散型計算機向けのオブジェクトストレージシステムであるCephはLXD 2.16からサポートされるようになりました。LXDそのものをクラスタ化する際には、Cephは十分な選択肢となってくるでしょう。

その他、バックエンドごとの機能比較やストレージプールの容量増加方法、注意点などは公式のドキュメントを参照してください。

ちなみに今回の記事も、Ubuntu 18.04 LTS/LXD 3.0を前提としています。

ストレージプールの基本

さて実際にストレージプールを使ってみましょう。まずはlxd initで生成されたdefaultプールを確認してみます。

$ lxc storage list
To start your first container, try: lxc launch ubuntu:18.04

+---------+-------------+--------+--------------------------------+---------+
|  NAME   | DESCRIPTION | DRIVER |             SOURCE             | USED BY |
+---------+-------------+--------+--------------------------------+---------+
| default |             | btrfs  | /var/lib/lxd/disks/default.img | 1       |
+---------+-------------+--------+--------------------------------+---------+

defaultプールが作られていることがわかります。btfsバックエンドでは、ブロックデバイスを指定しない場合、ファイルイメージ上にbtrfsを構築します。

$ sudo file /var/lib/lxd/disks/default.img
/var/lib/lxd/disks/default.img: BTRFS Filesystem label "default", sectorsize 4096,
  nodesize 16384, leafsize 16384, UUID=32b2fda6-a184-436d-8a86-49e9c37aa250,
  262144/4999999488 bytes used, 1 devices

さらにストレージプールごとの詳細情報を表示してみましょう。

$ lxc storage info default
info:
  description: ""
  driver: btrfs
  name: default
  space used: 17.24MB
  total space: 5.00GB
used by:
  profiles:
  - default

サイズの「5GB」lxd init時に設定した値です。used_byはこのストレージプールを利用しているコンポーネントのリストです。LXDでは、コンテナ用の設定テンプレートとしてプロファイルが用意されています。このプロファイルもまた、ストレージプールに保存されるのです。

lxd initで作成されるdefaultプロファイルの内容を確認してみましょう。

$ lxc profile show default
config: {}
description: Default LXD profile
devices:
  eth0:
    name: eth0
    nictype: bridged
    parent: lxdbr0
    type: nic
  root:
    path: /
    pool: default
    type: disk
name: default
used_by: []

defaultプロファイルを指定してコンテナを作ったとき、rootディレクトリはdefaultストレージプールを利用することがわかります。

実際にコンテナを作成・立ち上げてみましょう。

$ lxc launch ubuntu:18.04 mihono
Creating mihono
Starting mihono

コンテナが作られた状態で、defaultプールの状態を確認してみます。

$ lxc storage info default
info:
  description: ""
  driver: btrfs
  name: default
  space used: 808.94MB
  total space: 5.00GB
used by:
  containers:
  - mihono
  images:
  - c4681ac755d9f8e858bb278741a4a0f0a91580ff046caa6b434d8804cdfb51af
  profiles:
  - default

コンテナ本体だけでなく、ダウンロードしたコンテナイメージもまたdefaultプールを使っていることがわかりますね。

新規にストレージプールを作成する

今度は新規にストレージプールを作ってみましょう。

$ lxc storage create kofuki btrfs
Storage pool kofuki created

コマンドのフォーマットはlxc storage create ストレージプール名 バックエンド名 設定です。設定を省いた場合は、既定の値が使われます。たとえばbtrfsの場合、ソースファイルはイメージファイルとなります。

$ lxc storage list
+---------+-------------+--------+--------------------------------+---------+
|  NAME   | DESCRIPTION | DRIVER |             SOURCE             | USED BY |
+---------+-------------+--------+--------------------------------+---------+
| default |             | btrfs  | /var/lib/lxd/disks/default.img | 3       |
+---------+-------------+--------+--------------------------------+---------+
| kofuki  |             | btrfs  | /var/lib/lxd/disks/kofuki.img  | 0       |
+---------+-------------+--------+--------------------------------+---------+

defaultプールと異なり、追加で作られたばかりのストレージプールは誰からも使われていません。

$ lxc storage info kofuki
info:
  description: ""
  driver: btrfs
  name: kofuki
  space used: 17.43MB
  total space: 15.00GB
used by: {}

ちなみにイメージファイルの場合、シンプロビジョニングになりますので、イメージファイルが存在するデバイスの実サイズ以上のサイズを指定することも可能です。もちろんその場合は、ストレージプールの使用量が100%に達するより前に、ディスクフルになってしまいます。

もうひとつ既定の値以外の設定を使って、ストレージプールを作成してみましょう。設定は「キー=値」の形で指定できます。指定可能なキーは公式ドキュメントのStorage pool configurationを参照してください。

たとえばsourceを指定しなかった場合は、上記のようにイメージファイルを使用します。イメージファイルの代わりにブロックデバイスを使いたい場合は、次のように設定します。

$ lxc storage create chie btrfs source=/dev/sdb1
Storage pool chie created

$ lxc storage info chie
info:
  description: ""
  driver: btrfs
  name: chie
  space used: 17.43MB
  total space: 21.47GB
used by: {}

$ lsblk /dev/sdb1
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sdb1   8:17   0  20G  0 part /var/lib/lxd/storage-pools/chie

新しく作成したストレージプールが/dev/sdb1を専有していることがわかりますね。ストレージプールごとの設定はlxc storage set プール名 キー 値でも変更できます。

作成したストレージプールを指定してコンテナを起動する

新しく作成したストレージプールを指定してコンテナを作成してみましょう。ストレージプールを明示的に指定するにはlxc initlxc launch--storageオプション(短縮形は-s⁠)を利用します。

$ lxc launch ubuntu:18.04 kiyoka --storage kofuki
Creating kiyoka
Starting kiyoka

新しいコンテナをdefaultプールではなくkofukiプールに作成した結果、kofukiプールのほうにのみ新しいコンテナが現れていることがわかります。

$ lxc storage info kofuki
info:
  description: ""
  driver: btrfs
  name: kofuki
  space used: 810.18MB
  total space: 15.00GB
used by:
  containers:
  - kiyoka
  images:
  - c4681ac755d9f8e858bb278741a4a0f0a91580ff046caa6b434d8804cdfb51af

もう一つ注意すべきポイントは、コンテナイメージもkofukiプールに表示されていることです。しかもフィンガープリントはdefaultプールにあるそれと同じです。

LXDではリモートからコンテナイメージを取得した上で、インスタンスを立ち上げます。よって初回のコンテナの立ち上げは、インターネット経由でのイメージの取得の時間が必要になるためどうしても時間がかかってしまうのです。その代わり、同じコンテナイメージを使う限り、2回目以降はすぐに立ち上がります。

しかしながら、今回のように同じコンテナイメージを使うインスタンスであっても、別のストレージプールに作る場合は再度コンテナイメージの取得が必要です。LXDはローカルのイメージを優先的に使用するため、defaultコンテナからkofukiコンテナへのイメージのコピーが発生します。このため、インターネット経由の取得ほどではないにしろ、それなりに時間がかかります。ただし一度kofukiプールにコピーさえしてしまえば、以降は再利用されます。

新規にストレージボリュームを作成する

新しいLXDのストレージ関連のもう一つの新機能が、コンテナにアタッチできる「カスタムストレージボリューム」です[1]⁠。これは要するにDockerのボリュームコンテナみたいなものです。

ストレージプール上に任意の数のボリュームを作成し、そのボリュームを好きなコンテナにアタッチできます。同時に複数のコンテナにもアタッチできるため、コンテナ間の共有ディレクトリのような使い方も可能です。

まずはストレージボリュームを作成してみましょう。

$ lxc storage volume create chie miruya
Storage volume miruya created

$ lxc storage volume list chie
+--------+--------+-------------+---------+
|  TYPE  |  NAME  | DESCRIPTION | USED BY |
+--------+--------+-------------+---------+
| custom | miruya |             | 0       |
+--------+--------+-------------+---------+

$ lxc storage volume show chie miruya
config: {}
description: ""
name: miruya
type: custom
used_by: []
location: none

ボリュームの最大容量はプールの容量に依存します。ただしlxc storage volume set ボリューム名 size 値で明示的に制限をかけることも可能です。

特定のコンテナにボリュームをアタッチするにはlxc storage volume attach プール名 ボリューム名 コンテナ名 コンテナ上のパスを指定します。少し長いですね。

$ lxc storage volume attach chie miruya kiyoka /opt/data/akabane
$ lxc exec kiyoka mount | grep akabane
/dev/sdb1 on /opt/data/akabane type btrfs (rw,relatime,space_cache,user_subvol_rm_allowed,subvolid=261,subvol=/custom/miruya)

chieプールはブロックタイプ(/dev/sdb1)のストレージプールなので、そのボリュームであるmiruyaは、そのままbtrfsのサブボリュームがマウントされていることがわかります。アタッチ時は、コンテナ内の必要なパスが適切に作成されます。

ストレージボリュームの利点は、複数のコンテナにマウントできることです。そこで同じmiruyaボリュームをmihonoコンテナにもマウントしましょう。

$ lxc storage volume attach chie miruya mihono /opt/data/akabane

この時点でボリュームには何もないため、kiyokaコンテナから適当なファイルを表示しようとしても、何も表示されません。

$ lxc exec kiyoka ls /opt/data/akabane
$ lxc exec kiyoka cat /opt/data/akabane/pudding
cat: /opt/data/akabane/pudding: No such file or directory

ここで別のmihonoコンテナからファイルを書いてみましょう。

$ lxc exec mihono -- sh -c 'echo "tabeta" > /opt/data/akabane/pudding'
$ lxc exec kiyoka cat /opt/data/akabane/pudding
tabeta

上記のように即座にkiyokコンテナにもその結果が反映されましたね。

ちなみにmihonoコンテナはdefaultプールに、kiyokaンテナはkofukiプールに、miruyaボリュームはchieプールに所属しているものの、これらの違いは特に気にすることなくアタッチ可能なのも便利なポイントのひとつです。

また、不要になれば次のようにデタッチできます。

$ lxc storage volume detach chie miruya mihono

ボリュームのコピーや移動

ボリュームはプール間のコピーや移動が可能です。

$ lxc storage volume copy chie/miruya kofuki/miruya
Storage volume copied successfully!

$ lxc storage volume list kofuki
+-----------+------------------------------------------------------------------+-------------+---------+
|   TYPE    |                               NAME                               | DESCRIPTION | USED BY |
+-----------+------------------------------------------------------------------+-------------+---------+
| container | kiyoka                                                           |             | 1       |
+-----------+------------------------------------------------------------------+-------------+---------+
| custom    | miruya                                                           |             | 2       |
+-----------+------------------------------------------------------------------+-------------+---------+
| image     | c4681ac755d9f8e858bb278741a4a0f0a91580ff046caa6b434d8804cdfb51af |             | 1       |
+-----------+------------------------------------------------------------------+-------------+---------+

もちろん別名にも変更できますし、複製の伴わない移動も可能です。

$ lxc storage volume move chie/miruya default/2m
Error: Volume is still in use by running containers

上記のように、アタッチ中のボリュームは当然のことながら移動できませんので、適宜デタッチしてください。

おすすめ記事

記事・ニュース一覧