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

第22回LXCの構築・活用 [8] ─ いろいろなストレージバックエンドの利用(4:loop)

前回までで、LXCでいろいろなストレージバックエンドを使ったコンテナの操作を紹介しました。今回も引き続きLXCがサポートするストレージバックエンドの紹介をします。今回は"loop"ストレージバックエンドです。

LVMを使ったコンテナに対するlxc-snapshotコマンドの実行

loopを紹介する前に、前回説明していなかったLVMストレージバックエンドを使ったコンテナに対するlxc-snapshotコマンドの実行について補足しておきます。

lxc-snapshot第9回で説明したように、コンテナのある時点のコンテナイメージを保存しておく機能です。

実は、LVMストレージバックエンドを使っている場合は、現時点ではバージョン1.0系列、1.1系列両方でlxc-snapshotコマンドは実行できません。実行すると以下のようにエラーとなります。

$ sudo lxc-create -n lvm01 -t download -B lvm --fstype ext4 -- -d ubuntu -a amd64 -r trusty
(LVMを使ったコンテナの作成)
   :(略)
You just created an Ubuntu container (release=trusty, arch=amd64, variant=default)
   :(略)
$ sudo lxc-snapshot -n lvm01 (
lxc_container: lxccontainer.c: lxcapi_snapshot: 2888 lvm01's backing store cannot be backed up.
lxc_container: lxccontainer.c: lxcapi_snapshot: 2889 Your container must use another backing store type.
lxc_container: lxc_snapshot.c: do_snapshot: 55 Error creating a snapshot

これは、LVMをストレージバックエンドに使ったコンテナではlxc-snapshotの実行が無効化されているのが理由です。以前、LVMを使っているとlxc-snapshotコマンドが正常に動作しない問題が発見されたためです。修正が行われた後に再度有効にされる予定ですが、今の所修正が進んでいる様子はなさそうです。lxc-snapshotコマンドを活用してコンテナを運用する場合は注意しましょう。

LVMをストレージバックエンドとして使って、コンテナのある時点のイメージを保存したい場合はlxc-cloneを使うなど、別の運用を考えましょう。

loopストレージバックエンドを使ったコンテナの作成

さて、それではloopストレージバックエンドの紹介に移ります。

loopは文字通りループバックデバイスのことで、イメージファイルをコンテナイメージとして使うためにループバックデバイスを使います。loopストレージバックエンドを使うには特に準備は必要ありませんので、さっそくコンテナを作成してみましょう。

現時点ではloopを使う場合も、前回紹介したクローン時の不具合と同じ原因でクローンが失敗します。そこで今回も前回と同じstable-1.0ブランチのデイリービルドパッケージをインストールした環境で実行しました。

$ dpkg-query -s lxc | grep Version
Version: 1.0.7+stable~20150225-0206-0ubuntu1~trusty

loopを使った場合にクローンが失敗する問題は、LVMのクローン時の不具合と同じものですので1.1.0では既に修正済みです。1.0-stableブランチでも修正済みですので1.0.8のリリースで修正されるはずです。

まずはloopストレージバックエンドで使えるオプションを見てみましょう。

表1 ストレージバックエンドがloopの場合にlxc-createで使えるオプション
オプション オプションの説明 デフォルト値
--fstype ファイル内に作成するファイルシステム名 ext3
--fssize 作成するファイルのサイズ 1G

実は1.0.7までと1.1.0のマニュアルにはストレージバックエンドとしてloopを指定した場合、どういうオプションが使えるのか、デフォルトのサイズ、ファイルシステムの種類についての記載がありません。

筆者が送ったパッチがマージされたので1.1.1では説明が入っており、1.0.8でも説明が入るはずです。

それではlxc-createコマンドで-B loopを指定してコンテナを作成してみましょう。

$ sudo lxc-create -n loop1 -B loop -t download -- -d ubuntu -r trusty -a amd64
   :(略)
You just created an Ubuntu container (release=trusty, arch=amd64, variant=default)
   :(略)
$ sudo lxc-ls
loop1

作成できました。まずは設定ファイルを見ておきましょう。

$ sudo cat /var/lib/lxc/loop1/config | grep -v '^#'

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

lxc.rootfs = loop:/var/lib/lxc/loop1/rootdev
lxc.utsname = loop1

lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = lxcbr0
lxc.network.hwaddr = 00:16:3e:8d:1c:3c

loopを使う場合は、設定ファイルでlxc.rootfsに"loop:"に続けてファイルのフルパスを記述します。上記の例でもlxc.rootfsloop:/var/lib/lxc/loop1/rootdevとなっていますね。それ以外は普通のコンテナと変わりありません。

$ sudo ls -l /var/lib/lxc/loop1/rootdev
-rw------- 1 root root 1073741825 Mar 10 17:53 /var/lib/lxc/loop1/rootdev

/var/lib/lxc/loop1/rootdevを見ると、デフォルト値の1GBのファイルになっています。このファイルをマウントしてみましょう。

$ sudo mount -o loop /var/lib/lxc/loop1/rootdev /mnt (ループバックデバイスとしてマウント)
$ cat /proc/mounts | grep /mnt  (マウント情報をチェック)
/dev/loop0 /mnt ext3 rw,relatime,data=ordered 0 0
$ ls /mnt
bin   dev  home  lib64       media  opt   root  sbin  sys  usr
boot  etc  lib   lost+found  mnt    proc  run   srv   tmp  var

ファイル内部はext3になっていますね。マウントしたディレクトリを見てみると、コンテナの/(ルート)のようですね。

アンマウントしてからコンテナを起動します。

$ sudo umount /mnt
$ sudo lxc-start -n loop1 -d
$ sudo lxc-ls -f
NAME   STATE    IPV4       IPV6  AUTOSTART
------------------------------------------
loop1  RUNNING  10.0.3.87  -     NO

起動しました。さっそくコンテナ内でマウントの様子を見てみましょう。

$ sudo lxc-attach -n loop1 -- cat /proc/mounts
   :(略)
/dev/loop7 / ext3 rw,relatime,data=ordered 0 0
   :(略)
$ sudo lxc-attach -n loop1 -- df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop7      976M  384M  541M  42% /
   :(略)

/dev/loop7が/(ルート)としてマウントされており、ループバックデバイスを使ってマウントされていることがわかります。

次にオプションを指定してコンテナを作成してみましょう。ファイルシステムはbtrfs、サイズは2GBを指定してみます。

$ sudo lxc-create -n loop2 -t download -B loop --fstype=btrfs --fssize=2G \
> -- -d ubuntu -r trusty -a amd64  (オプションを指定してコンテナの作成)
   :(略)
You just created an Ubuntu container (release=trusty, arch=amd64, variant=default)
   :(略)
$ sudo ls -l /var/lib/lxc/loop2/rootdev  (ファイルサイズの確認)
-rw------- 1 root root 2147483649 Mar 10 18:13 /var/lib/lxc/loop2/rootdev
$ sudo lxc-start -n loop2 -d  (コンテナの起動)
$ sudo lxc-ls -f  (コンテナの起動を確認)
NAME   STATE    IPV4        IPV6  AUTOSTART  
-------------------------------------------
loop1  STOPPED  -           -     NO         
loop2  RUNNING  10.0.3.139  -     NO         
$ sudo lxc-attach -n loop2 -- cat /proc/mounts | grep loop
(コンテナ内のマウントの確認)
/dev/loop7 / btrfs rw,relatime,space_cache 0 0
$ sudo lxc-attach -n loop2 -- df -h | grep loop
(コンテナ内のマウントとサイズの確認)
/dev/loop7      2.0G  385M  1.5G  21% /

2GBでファイルが作られ、起動後にコンテナ内で見てみると確かにファイルシステムはBtrfsとなっており、ファイルシステムのサイズも2GBになっていることが確認できました。

なお、ソースコードを見る限り、-B loopを指定してlxc-createでコンテナを作成した場合に作成されるファイルの名前はrootdevで固定のようです。

loopストレージバックエンドを使ったコンテナのクローンとスナップショット

loopストレージバックエンドを使った場合、コンテナイメージは単なるファイルですので、スナップショットのような特別な機能はありません。コンテナのクローンはコピーによるクローンになります。

$ sudo lxc-clone -o loop1 -n loop2
Created container loop2 as copy of loop1

ファイルをコピーしますので少し時間がかかります。

$ sudo ls -lF /var/lib/lxc/loop2
total 445452
-rw-r--r-- 1 root root       1475 Mar 16 16:35 config
-rw------- 1 root root 1073741825 Mar 16 16:35 rootdev
drwxr-xr-x 2 root root       4096 Mar 16 16:34 rootfs/

以上のようにコンテナイメージ用のファイルがコピーされ、空のrootfsディレクトリ、新しいコンテナ用の設定ファイルが作成されます。

クローンしたコンテナの設定ファイルはincludeを使わない形で作成されます。設定内容はlxc.rootfsが新しいコンテナ用に変わっているだけです。

$ sudo grep rootfs /var/lib/lxc/loop2/config
lxc.rootfs = loop:/var/lib/lxc/loop2/rootdev

lxc-snapshotを使ったコンテナのバックアップについてもクローンと同様にコピーを使います。実行するたびにコンテナイメージ用のファイルがコピーされ、イメージファイルの分だけ容量を消費していきます。あまり現実的ではないかもしれませんね。

$ sudo lxc-snapshot -n loop2  (スナップショットを取得)
$ sudo lxc-snapshot -n loop2 -L  (スナップショットの一覧を表示)
snap0 (/var/lib/lxcsnaps/loop2) 2015:03:17 17:32:36  (取得できている)
$ sudo ls -lF /var/lib/lxcsnaps/loop2/snap0/  (スナップショットのディレクトリの表示)
total 445448
-rw-r--r-- 1 root root       1486 Mar 17 17:32 config
-rw------- 1 root root 1073741825 Mar 17 17:32 rootdev
drwxr-xr-x 2 root root       4096 Mar 17 17:32 rootfs/
-rw-r--r-- 1 root root         19 Mar 17 17:32 ts

まとめ

今回はストレージバックエンドとしてloopを使った場合のコンテナの作成、クローン、スナップショットを紹介しました。

紹介した通り非常にシンプルなストレージバックエンドです。lxc-createでloopを指定してコンテナを作成するより、既存のイメージファイルを使ってコンテナを起動する場合に便利なストレージバックエンドかも知れません。

LXC 1.1.1

今回の記事を執筆中にLXC 1.1.1がリリースされました。

バグフィックスが中心で、リリースアナウンス(日本語訳)にもあるように変更点はそれほど多くはありません。

ここしばらく、LXDの開発が非常に活発でリリースも頻繁なため、LXCのリリース作業に手が回らないのか、長期サポート版の次のバージョンである1.0.8がなかなかリリースされません。前回と今回の実行例を手軽に楽しめる環境がなかなか手に入りませんね。

おすすめ記事

記事・ニュース一覧