前々回、前回でAufs、Overlayfs、Btrfsと言ったファイルシステムをストレージバックエンドに使った場合のLXCの使い方を紹介してきました。
今回も引き続きLXCがサポートするストレージバックエンドの紹介をします。今回はLVMをストレージバックエンドとして使った場合のLXCの使い方を紹介します。
前回同様、LVMについてはここでは説明しません。
実は執筆時点でのLXCのstableリリースの最新である1.0.7ではストレージバックエンドとしてLVMを使う場合の不具合があるため、今回の実行例はUbuntu 14.04.2 LTSに以下のようにUbuntu LXCチームが作成しているstable-1.0 ブランチのデイリービルド用PPAのパッケージをインストールした環境で試しています。
1.0.8がリリースされたあとは、標準のLXCパッケージで今回の実行例がそのまま実行できるようになるはずです。
不具合については後で紹介します。
LXCでLVMをストレージバックエンドとして指定する場合、コンテナイメージを置くための論理ボリュームには以下の2通りのパターンがあります。
- ボリュームグループ上に直接論理ボリュームを作成
- Thin Provisioning用のプール上に論理ボリュームを作成
Thin Provisioning機能はLinux 3.2で導入された機能でLVMから使える機能です。
以下ではまずはThin Provisioning機能を使わない方法を紹介したあと、Thin Provisioning機能を使った方法を紹介します。
LVMをストレージバックエンドとして使う場合の準備
LVMをLXCのストレージバックエンドとして使う場合の特別な準備はありません。普通にLVMを操作するコマンド群があれば使えます。ここでは以降の実行例で使う環境で行った準備を紹介しておきます。
LVMを操作するコマンドはUbuntuでは"lvm2"というパッケージですので、これとLVMでサポートされているThin Provisioning機能を使う場合のツールをインストールしました。
まずはLVM用に設定したパーティションが必要ですね。ここの例では/dev/vdb1
をLVM用に作成しています。
/dev/vdb1
を物理ボリュームとして設定します。
LXCではデフォルトではlxc
という名前のボリュームグループを使います。このボリュームグループ名はlxc-create
コマンド実行時のオプション、もしくはLXCのシステム設定ファイル(Ubuntuの場合/etc/lxc/lxc.conf
)で設定できます。
ここではデフォルトで使われる名前を設定しました。
これで準備ができました。
LVMを使ったコンテナ用のシステム設定と作成時のオプション
LXCのシステム設定でストレージバックエンドとしてLVMを使う際の設定を行えます。これはコンテナ作成時のデフォルト値として使われます。この設定項目が設定されていない場合は表1に示したデフォルト値が使われます。
表1 LVM関係のシステム設定項目
設定項目 |
設定項目の説明 |
デフォルト値 |
lxc.bdev.lvm.vg |
デフォルトのLVMボリュームグループ名 |
lxc |
lxc.bdev.lvm.thin_pool |
デフォルトのThin Provisioning用プール名 |
lxc |
デフォルトではLXCのLVMストレージバックエンドは、lxc.bdev.lvm.thin_pool
で設定した値の名前を持つThin Provisioning用のプールが存在する場合には自動的にそのプールに論理ボリュームを作成します。Thin Provisioning用のプールがない場合はlxc.bdev.lvm.vg
で設定した値の名前を持つボリュームグループに論理ボリュームを作成します。
表1の設定項目を含め、コンテナ作成時にlxc-create
コマンドに-B lvm
を指定してLVMをストレージバックエンドとして使う場合に指定できるオプションがありますので紹介しておきましょう。指定しなければデフォルト値が使われます。
表2 ストレージバックエンドがLVMの場合に使えるオプション
オプション |
オプションの説明 |
デフォルト値 |
--lvname |
コンテナ用に使う論理ボリューム名 |
コンテナ名 |
--vgname |
コンテナ用に使うボリュームグループ名 |
lxc.bdev.lvm.vgの値 |
--thinpool |
Thin Provisioning用のプール名の指定 |
lxc.bdev.lvm.thin_poolの値 |
--fstype |
論理ボリューム上に作成するファイルシステム名 |
ext3 |
--fssize |
作成するファイルシステムのサイズ |
1G |
デフォルト値以外の名前を持つThin Provisioning用プールを使いたい場合は--thinpool
オプションでプール名を指定します。
デフォルト値以外のボリュームグループを使いたい場合は、--vgname
オプションでボリュームグループ名を指定します。Thin Provisioning機能を使う場合でも使用するボリュームグループ名はlxc-create
コマンドが使う値(つまりlxc.bdev.lvm.vg
の値もしくは--vgname
の設定値)と一致している必要があります。
特に指定しなければ論理ボリューム名はコンテナ名となります。コンテナ名以外の論理ボリュームを使いたい場合は--lvname
で指定します。
あらかじめOS上で作成しておくファイルシステムと違って、LVMの場合はコンテナを作成したりクローンしたりする際に論理ボリュームを作成しますので、その上に作成するファイルシステムの種類やサイズを指定します。
コンテナ作成の際にいろいろなファイルシステムを指定できますので、各種ファイルシステムの特長を活かせるかもしれませんね。
LVMを使ったコンテナの作成
まずはボリュームグループ上に直接論理ボリュームを作成するようにコンテナを作成してみましょう。
ここでは論理ボリューム上に2GBのext4ファイルシステムを作成する指定を行ってコンテナを作成してみます。
作成が成功しましたね。論理ボリュームの状態を確認してみましょう。
以上のようにコンテナ名で論理ボリュームが作成され、サイズは指定した通り2GBとなっています。
コンテナのディレクトリがどうなっているのか確認してみましょう。
設定ファイルとrootfs
ディレクトリが存在しており、rootfs
以下は空です。
設定ファイルを確認してみるとlxc.rootfs
が論理ボリューム名になっています。それ以外は普通のコンテナと変わりありません。
ではコンテナを起動してみましょう。
起動しましたのでlxc-attach
コマンドを使ってコンテナ内でマウントの状況を確認するコマンドを実行してみます。
/
(ルート)として論理ボリューム/dev/lxc/lvm01
がext4でマウントされており、サイズは指定した通りに2GBになっていますね。
このマウントはコンテナのマウント名前空間内で行われていますので、ホストOS上からは見えません。
LVMを使ったコンテナのクローン
それでは引き続いてLVMをストレージバックエンドに使っているコンテナのクローンを試しましょう。実は先に述べたLVMを使う場合の不具合はクローン機能の部分にあります。1.0.7ではバグがあり、LVMがストレージバックエンドの場合にコンテナのスナップショットを使ったクローンがエラーになってしまいます。
このバグは1.1.0では修正されています。またリポジトリでは1.0系列用ブランチであるstable-1.0ブランチでも修正は行われていますので、1.0.8がリリースされると修正がなされるはずです。
今回使っているstable-1.0ブランチのデイリービルドでも修正されていますので、コンテナは正常にクローンできます。
まずはlxc-clone
で-s
オプションを指定せずにコンテナをクローンしてみましょう。
上記の例でも表示されているように、コピーによるスナップショットが行われていますので少し時間がかかります。この場合でもクローンされたコンテナのストレージバックエンドはLVMになります。
それでは-s
オプションを指定してスナップショットによるクローンを実行してみましょう。
スナップショットなのでlxc-clone
コマンドはすぐに終了しています。ここでクローン元のコンテナを起動して、終了させてみました。
lvs
コマンドで論理ボリュームの状態を確認してみましょう。
lvs
コマンドで確認するとスナップショットによるクローンでできたlvm03
コンテナはLVMのスナップショット機能を使ったlvm01
のスナップショットになっていることがわかります。
また、クローン後に元のコンテナを起動しましたので、ログ出力などが行われて、スナップショット時点からは少し変化しました。そのためスナップショット領域であるlvm03
は少し容量が増えていますね。
もちろんlvm03
コンテナも起動できます。
なお、LVMのスナップショットの仕組み上、スナップショットのスナップショットは作れませんので、スナップショットによるクローンで作成したコンテナをスナップショットを使ってクローンできません。
現時点では、前述の1.0系列のクローン以外にも、LVMをストレージバックエンドに使った場合の処理には少し不具合が残っています。
LVMのスナップショット機能を使ったクローンで作成したコンテナが存在する場合でも、以下のようにクローン元のコンテナが削除できてしまいます。この時、クローン元の論理ボリュームと共にスナップショットの論理ボリュームも同時に削除されてしまいます。しかしクローンにより作成したコンテナの設定ファイルとディレクトリは残ったままになります。しかし、当然コンテナイメージの実体である論理ボリュームは削除されてしまっていますので起動はしません。現時点では注意が必要です。
この例でlvm01
を削除すると、同時にlvm03
用の論理ボリュームであるlvm03
が削除されますので、コンテナは起動できません。
この記事を書いている最中に筆者がこの不具合を修正するパッチを送付したところパッチがAckされました。まだマージはされていませんが、将来的にはこの問題はなくなるはずです。
Thin Provisioning機能を使っていない場合で、LVMのスナップショット機能を使ったクローンを行った場合、第19回で説明したaufsやoverlayfsを使ったクローンの際に使われていたコンテナの依存関係を表す仕組みと同じ仕組みを使い、クローン元のコンテナが削除できなくなる予定です。(※1)
Thin Provisioning 機能の利用
Linux kernel 3.2でDevice MapperにThin Provisioning機能が入りました。この機能をLVMから使用することで、実際のディスク容量以上の論理ボリュームを作成したり、スナップショット機能を使って既存の論理ボリュームのコピーを作成できます。
DockerをRHELやCentOS上で使う際には、このThin Provisioningの機能を使っていますのでご存じの方も多いのではないでしょうか。
LXCのLVMストレージバックエンドもこの機能をサポートしています。また、lxc-clone
を使ってクローンできます。
ここでは簡単にThin Provisioning機能を使ったコンテナの操作を紹介しておきます。Thin Provisioning機能そのものの詳細や、細かな操作についてはここでは述べません。
Thin Provisioning 機能を使う場合の準備
ボリュームグループは先の例で使ったlxc
をそのまま使います。
Thin Provisioning用のプールをlxc
という名前で作成します。データを保存する領域の他にメタデータを保存する領域が必要です。このためボリュームグループlxc
の全部をプールとして確保するわけにはいきませんので、とりあえず90%程度を確保します。
Thin Provisioning 機能を使ったコンテナの作成
ではコンテナを作成してみましょう。ここでは--thinpool lxc
と指定して明示的にThin Provisioning用のプールを指定しています。
LXCはデフォルトではlxc.bdev.lvm.thin_pool
で設定した名前のThin Provisioning用のプールがある場合は、自動的にそのプールを使ってコンテナ用の論理ボリュームを作成しますので、ここの例では--thinpool lxc
は指定しなくても同じ結果となります。
逆にlxc.bdev.lvm.thin_pool
で指定したプールがない場合に--thinpool
でプール名を指定せずに実行すると、Thin Provisioning機能は使わずに直接論理ボリュームを作成しようとします。少しややこしいですが、実際に使う場合はThin Provisioning機能を使ったり使わなかったりという状況は考えにくいので、あまり問題にならないかも知れませんね。
作成できました。論理ボリュームの状態を見てみましょう。
7.2GBの領域に8GBのコンテナ用の論理ボリュームが作成されています。物理的に存在している容量以上のコンテナを作ったところでも、さらにコンテナを作れます。
7.2GBの領域に8GBのコンテナが2つ存在しています。これは極端な例ですが、常にコンテナに割り当てた容量を使わない場合もあるでしょうから、ある程度の領域を準備しておいて足りなくなりそうな場合に追加するという運用ができるようになりますね。
Thin Provisioning 機能を使ったコンテナのクローン
lxc-clone
に-s
オプションを指定しないコピーによるクローンの場合は、コンテナを新たに作成する場合と変わりませんのでここでは述べません。では-s
を指定してクローンしてみましょう。
以上のようにthin02
コンテナのスナップショットを使ったクローンとしてthin03
コンテナが作成されました。
コンテナを2つ起動して、apt-get update
を実行してみました。
それぞれのコンテナで使用量が増えていますね。
先に紹介したThin Provisioning機能を使わないLVMでは、スナップショットのスナップショットが作成できませんでしたので、スナップショットを使ったクローンにより作成したコンテナをさらにスナップショットを使ってクローンできませんでした。
それに対してThin Provisioning機能を使うと、スナップショットのスナップショットが作成できます。試してみましょう。
コンテナの削除を試してみましょう。クローン元のコンテナから削除してみます。
Thin Provisioning機能を使った場合、スナップショットを使っても、それぞれの論理ボリュームは独立したコピーとなります。従って、クローン元を削除しても、クローン先のスナップショットが削除されることはありませんので、先に紹介したような不具合は起こりません。
まとめ
今回はストレージバックエンドとしてLVMを使った場合のコンテナの作成、クローンを紹介しました。
Thin Provisioning機能を使わない場合に不具合がある点を除いても、Thin Provisioning機能を使った方がスナップショットを使ったクローンを含めて便利な気がします。
ストレージバックエンドとしてLVMを使う場合は、カーネルがThin Provisioning機能に対応している場合はThin Provisioning機能の使用を前提にしても良いのかな、と記事を書きながら思いました。
次回もストレージバックエンドを便利に使う方法や、その他のまだ紹介していないLXCの機能を紹介する予定です。