LXCで学ぶコンテナ入門 -軽量仮想化環境を実現する技術

第21回 LXCの構築・活用 [7] ─ いろいろなストレージバックエンドの利用(3:LVM)

この記事を読むのに必要な時間:およそ 9 分

LVMを使ったコンテナの作成

まずはボリュームグループ上に直接論理ボリュームを作成するようにコンテナを作成してみましょう。

ここでは論理ボリューム上に2GBのext4ファイルシステムを作成する指定を行ってコンテナを作成してみます。

$ sudo lxc-create -n lvm01 -t download -B lvm --fstype ext4 --fssize 2G \
> -- -d ubuntu -r trusty -a amd64
     :(略)
  Logical volume "lvm01" created
     :(略)
You just created an Ubuntu container (release=trusty, arch=amd64, variant=default)
     :(略)
$ sudo lxc-ls -f
NAME   STATE    IPV4  IPV6  AUTOSTART  
-------------------------------------
lvm01  STOPPED  -     -     NO         

作成が成功しましたね。論理ボリュームの状態を確認してみましょう。

$ sudo lvs
  LV     VG        Attr      LSize    Pool Origin Data%  Move Log Copy%  Convert
  lvm01  lxc       -wi-a----    2.00g                                           

以上のようにコンテナ名で論理ボリュームが作成され,サイズは指定した通り2GBとなっています。

コンテナのディレクトリがどうなっているのか確認してみましょう。

$ sudo ls -F /var/lib/lxc/lvm01
config  rootfs/
$ sudo ls -F /var/lib/lxc/lvm01/rootfs
$ 

設定ファイルとrootfsディレクトリが存在しており,rootfs以下は空です。

設定ファイルを確認してみるとlxc.rootfsが論理ボリューム名になっています。それ以外は普通のコンテナと変わりありません。

$ sudo cat /var/lib/lxc/lvm01/config | grep -v "^#"

lxc.include = /usr/share/lxc/config/ubuntu.common.conf
lxc.arch = x86_64

lxc.rootfs = /dev/lxc/lvm01
lxc.utsname = lvm01

lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = lxcbr0
lxc.network.hwaddr = 00:16:3e:02:fb:36

ではコンテナを起動してみましょう。

$ sudo lxc-start -n lvm01 -d
$ sudo lxc-ls -f
NAME   STATE    IPV4        IPV6  AUTOSTART  
-------------------------------------------
lvm01  RUNNING  10.0.3.231  -     NO         

起動しましたのでlxc-attachコマンドを使ってコンテナ内でマウントの状況を確認するコマンドを実行してみます。

$ sudo lxc-attach -n lvm01 -- cat /proc/mounts | grep lvm01
/dev/lxc/lvm01 / ext4 rw,relatime,data=ordered 0 0
$ sudo lxc-attach -n lvm01 -- df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/lxc/lvm01  2.0G  383M  1.5G  21% /

/(ルート)として論理ボリューム/dev/lxc/lvm01がext4でマウントされており,サイズは指定した通りに2GBになっていますね。

このマウントはコンテナのマウント名前空間内で行われていますので,ホストOS上からは見えません。

$ sudo ls -F /var/lib/lxc/lvm01/rootfs (ホストOS上で実行)
$ grep lvm01 /proc/mounts (ホストのマウント名前空間からはマウントされていることは見えない)

LVMを使ったコンテナのクローン

それでは引き続いてLVMをストレージバックエンドに使っているコンテナのクローンを試しましょう。実は先に述べたLVMを使う場合の不具合はクローン機能の部分にあります。1.0.7ではバグがあり,LVMがストレージバックエンドの場合にコンテナのスナップショットを使ったクローンがエラーになってしまいます。

このバグは1.1.0では修正されています。またリポジトリでは1.0系列用ブランチであるstable-1.0ブランチでも修正は行われていますので,1.0.8がリリースされると修正がなされるはずです。

今回使っているstable-1.0ブランチのデイリービルドでも修正されていますので,コンテナは正常にクローンできます。

まずはlxc-clone-sオプションを指定せずにコンテナをクローンしてみましょう。

$ sudo time -p lxc-clone -o lvm01 -n lvm02
  Logical volume "lvm02" created
Created container lvm02 as copy of lvm01
real 13.48
user 2.23
sys 2.33

上記の例でも表示されているように,コピーによるスナップショットが行われていますので少し時間がかかります。この場合でもクローンされたコンテナのストレージバックエンドはLVMになります。

$ sudo lvs
  LV     VG        Attr      LSize    Pool Origin Data%  Move Log Copy%  Convert
  lvm01  lxc       -wi-a----    2.00g                                           
  lvm02  lxc       -wi-a----    2.00g                                           
$ sudo grep lxc.rootfs /var/lib/lxc/lvm02/config
lxc.rootfs = /dev/lxc/lvm02

それでは-sオプションを指定してスナップショットによるクローンを実行してみましょう。

$ sudo time -p lxc-clone -o lvm01 -n lvm03 -s -B lvm
  Logical volume "lvm03" created
Created container lvm03 as snapshot of lvm01
real 1.56
user 0.00
sys 0.05
$ sudo lxc-start -n lvm01 -d
$ sudo lxc-ls -f | grep lvm03
lvm01    RUNNING  10.0.3.135  -     -       NO         
$ sudo lxc-stop -n lvm01

スナップショットなのでlxc-cloneコマンドはすぐに終了しています。ここでクローン元のコンテナを起動して,終了させてみました。

lvsコマンドで論理ボリュームの状態を確認してみましょう。

$ sudo lvs
  LV     VG        Attr      LSize    Pool Origin Data%  Move Log Copy%  Convert
  lvm01  lxc       owi-a-s--    2.00g                                           
  lvm02  lxc       -wi-a----    2.00g                                           
  lvm03  lxc       swi-a-s--    2.00g      lvm01    0.02

lvsコマンドで確認するとスナップショットによるクローンでできたlvm03コンテナはLVMのスナップショット機能を使ったlvm01のスナップショットになっていることがわかります。

また,クローン後に元のコンテナを起動しましたので,ログ出力などが行われて,スナップショット時点からは少し変化しました。そのためスナップショット領域であるlvm03は少し容量が増えていますね。

もちろんlvm03コンテナも起動できます。

$ sudo lxc-start -n lvm03 -d
$ sudo lxc-ls -f
NAME     STATE    IPV4       IPV6  GROUPS  AUTOSTART  
----------------------------------------------------
    :(略)
lvm03    RUNNING  10.0.3.68  -     -       NO         

なお,LVMのスナップショットの仕組み上,スナップショットのスナップショットは作れませんので,スナップショットによるクローンで作成したコンテナをスナップショットを使ってクローンできません。

現時点では,前述の1.0系列のクローン以外にも,LVMをストレージバックエンドに使った場合の処理には少し不具合が残っています。

LVMのスナップショット機能を使ったクローンで作成したコンテナが存在する場合でも,以下のようにクローン元のコンテナが削除できてしまいます。この時,クローン元の論理ボリュームと共にスナップショットの論理ボリュームも同時に削除されてしまいます。しかしクローンにより作成したコンテナの設定ファイルとディレクトリは残ったままになります。しかし,当然コンテナイメージの実体である論理ボリュームは削除されてしまっていますので起動はしません。現時点では注意が必要です。

$ sudo lxc-ls
lvm01  lvm02  lvm03
$ sudo lxc-destroy -n lvm01  (スナップショット元のコンテナを削除)
     :(略)
  Logical volume "lvm03" successfully removed  (スナップショットのボリュームが削除された)
  Logical volume "lvm01" successfully removed

$ sudo lxc-ls
lvm02  lvm03  ("lvm03"ボリュームは削除されたがコンテナは表示される)

この例でlvm01を削除すると,同時にlvm03用の論理ボリュームであるlvm03が削除されますので,コンテナは起動できません。

この記事を書いている最中に筆者がこの不具合を修正するパッチを送付したところパッチがAckされました。まだマージはされていませんが,将来的にはこの問題はなくなるはずです。

Thin Provisioning機能を使っていない場合で,LVMのスナップショット機能を使ったクローンを行った場合,第19回で説明したaufsやoverlayfsを使ったクローンの際に使われていたコンテナの依存関係を表す仕組みと同じ仕組みを使い,クローン元のコンテナが削除できなくなる予定です。※1

※1)
この記事の公開直後にパッチがmasterブランチにマージされました。次のリリースである1.1.1ではここに書いたようにスナップショットを使ったクローン元のコンテナは削除できなくなります。おそらくstableリリースの1.0.8にも反映されると思います。

著者プロフィール

加藤泰文(かとうやすふみ)

2009年頃にLinuxカーネルのcgroup機能に興味を持って以来,Linuxのコンテナ関連の最新情報を追っかけたり,コンテナの勉強会を開いたりして勉強しています。英語力のない自分用にLXCのmanページを日本語訳していたところ,あっさり本家にマージされてしまい,それ以来日本語訳のパッチを送り続けています。

Plamo Linuxメンテナ

Twitter:@ten_forward
技術系のブログ:http://tenforward.hatenablog.com/