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

第9回LXCの基本操作[2]

前回でコンテナの基本的な操作は一通りできるようになったと思いますので、今回と次回でその他の周辺コマンドを紹介していきます。

コンテナの削除 ~ lxc-destroy

前回コンテナを作成するコマンドとしてlxc-createを紹介しました。その逆でコンテナを削除するコマンドがlxc-destroyです。

lxc-destroyの実行は削除したいコンテナ名を指定するだけです。

# lxc-destroy -n ct02

ただし、コンテナが実行中の場合は削除は失敗します。

# lxc-destroy -n ct02
ct02 is running

実行中でも強制的に削除したい場合は-fを指定すると、コンテナを停止してから削除を行います。

# lxc-destroy -n ct02 -f

cgroup設定の確認、変更 ~ lxc-cgroup

コンテナに設定されているcgroupの制限値を確認したり、コンテナの稼働中に値を設定したりする場合にはlxc-cgroupを使用します。

設定されている値を確認するにはコンテナ名と共に、cgroupfsのサブシステムのファイル名を指定します。

例えばメモリの制限値を設定したり確認したりする場合、memoryサブシステムのmemory.limit_in_bytesというファイルを使いました。lxc-cgroupでもこの名前をそのまま指定します。

# lxc-cgroup -n ct01 memory.limit_in_bytes 
268435456

コンテナct01には256MBの制限が設定されているようです。これを128MBに変更してみましょう。確認と同様にファイル名を指定したあと、変更したい値を指定します。

# lxc-cgroup -n ct01 memory.limit_in_bytes 128M
# lxc-cgroup -n ct01 memory.limit_in_bytes 
134217728

変更されましたね。設定と確認に使うファイルが同じ場合は以上のように同じファイル名を指定しますが、設定と確認に異なるファイルを使うサブシステムもありましたので注意が必要です。

例えばdevicesサブシステムの場合、確認はdevices.listで、設定はdevices.allowもしくはdevices.denyファイルで行いました。

# lxc-cgroup -n ct01 devices.list
c *:* m
b *:* m
c 1:3 rwm
c 1:5 rwm
c 5:0 rwm
  : (略)
# lxc-cgroup -n ct01 devices.deny "c 1:3 rwm"
# lxc-cgroup -n ct01 devices.list
c *:* m
b *:* m
c 1:5 rwm
c 5:0 rwm
c 5:1 rwm

第7回「LXCの気になる点」として紹介したように、cgroupfsの各サブシステムにあるファイルについての知識が必要になるので少し不便ですね。

cgroupで値を設定したり確認したりする場合、第4回第5回で説明したように直接cgroupfsのファイルを操作できますので、わざわざlxc-cgroupを使う必要はないと思われるかもしれません。

しかし、Ubuntu 14.04 LTSではcgroupをcgmanagerというプログラムが管理しています。このため、以前紹介したように直接cgroupfsを操作する方法は使えません。/sys/fs/cgroup以下を探しても、各種サブシステムがマウントされたディレクトリ自体見つけることができません。

このためUbuntu 14.04 LTSでcgroupの確認、設定を確認するにはlxc-cgroupを使う必要があります。cgmanagerについては次回説明する予定です。

直接cgroupfsをマウントしている環境では直接cgroupfsのファイルを操作してコンテナに対するcgroupの制限値の確認や変更ができます。例えばUbuntuでも12.04 LTSでは直接cgroupfsを操作できます。

コンテナのクローン ~ lxc-clone

lxc-cloneは文字通り存在するコンテナのクローンを作るコマンドです。コンテナに限らず仮想マシンでもクローンが使えるととても便利ですね。LXCではバックエンドストレージの特性に応じたクローンが使えるようになっていますので便利です。

まずはlxc-cloneのオプションを紹介しましょう。

表1 lxc-cloneのオプション
オプションオプションの意味
-sクローンをスナップショットで取得。btrfsとlvmとzfsの時のみ指定可能
-pオリジナルのコンテナの『コンテナの保存場所』
-Pクローン先のコンテナの『コンテナの保存場所』
-B元のコンテナと違うバックエンドストレージを使う場合にバックエンドストーレジ形式を指定
-oクローン元のコンテナ名
-nクローン先のコンテナ名

ここでいう『コンテナの保存場所』は、前回の表1で紹介したものと同じで、コンテナの設定ファイルやコンテナイメージが保存される場所です。Ubuntuのデフォルト値は/var/lib/lxcですが、ここと違う場所を使用する場合は指定します。

指定する場合にはコンテナ名のディレクトリを含みません。クローン先でもコンテナ名を含みませんので、指定したディレクトリ直下にコンテナ名のディレクトリを作成して、そこにクローンを行います。

lxc-cloneはコピーもしくはスナップショットによってクローンを作成します。ただし、スナップショットはバックエンドストレージがサポートしている場合のみ選択でき、btrfs、lvm、zfsの時に選択できます。

lxc-cloneにはこの他にも多数のオプションがありますので、詳しくはman lxc-cloneで確認してください。

それではコンテナのクローンを作成してみましょう。基本的にクローン元のコンテナ名とクローンで作成したいコンテナ名を指定するだけです。クローン元のコンテナが起動中はエラーになりますので停止してから実行してください。

# lxc-clone -o ct01 -n ct02 
lxc_container: error: Original container (ct01) is running
clone failed       (コンテナct01が実行中なので失敗した)
# lxc-stop -n ct01 (コンテナct01を停止)
# lxc-clone -o ct01 -n ct02
Created container ct02 as copy of ct01

-sでスナップショットを指定しないと、rsyncコマンドでコンテナイメージをコピーします。デフォルトでは特にオプションを与えなくてもクローン元のコンテナのストレージバックエンドと同じ形式でクローンを作成します。

クローンで作成されたct02の設定ファイルを見てみましょう。

lxc.utsname = ct02
lxc.rootfs = /var/lib/lxc/ct02/rootfs

以上はコンテナ名に依存する設定のみを抜き出しました。きちんとlxc-cloneで指定したコンテナ名に書き換わっています。これだけでなく、コンテナイメージ中の/etc/hostname(以上の例だとホストから見た場合/var/lib/lxc/ct02/rootfs/etc/hostnameの中身も書き換えてくれます。ただし、ディストリビューションによっては別のファイルにホスト名が書かれていたりしますので、必ずしもコンテナイメージ中のホスト名が書き換わるわけではありません。また/etc/hostsなど、他のファイルは書き換わりませんので、自分で修正が必要です。

バックエンドストレージがスナップショット機能をサポートしている場合は-sを指定すると、バックエンドストレージ側のスナップショット機能を使ってクローンを作成します。

色々なバックエンドストレージを使ったLXCの活用については、この連載の後の回で紹介する予定です。

コンテナのスナップショットの取得 ~ lxc-snapshot

lxc-snapshotはコンテナのある時点のイメージをスナップショットとして保存します。あとでコンテナイメージをスナップショット時点のイメージに戻したり、スナップショットから新しいコンテナを作成したりできます。

それではlxc-snapshotのオプションを見てみましょう。

表2 lxc-snapshotのオプション
オプションオプションの意味
-c / --comment指定したファイルに書かれたコメントをスナップショットのコメントとして設定する
-d / --destroy指定した名前のスナップショットを削除する
-L / --listスナップショットをリスト表示する
-C / --showcommentsリスト表示の際にコメントを表示する
-r / --restore指定したスナップショットを使ってリストアを行う

-d / --destroyオプションはバージョン1.0.5のmanには出てきませんがきちんと機能します

※)
1.0.6でmanに-dオプションの説明が追加されました。

それではスナップショットを取得してみましょう。コンテナが起動している状態ではエラーになりますので停止してから実行してください。

$ sudo lxc-snapshot -n ct01 
lxc_container: Snapshot of directory-backed container requested.
lxc_container: Making a copy-clone.  If you do want snapshots, then
lxc_container: please create an aufs or overlayfs clone first, snapshot that
lxc_container: and keep the original container pristine.

警告が出ていますね。これはバックエンドストレージがdir形式のコンテナのスナップショットを取得しているからです。dirバックエンドストレージでオプションを指定しないでスナップショットを取得すると、スナップショットは単にこの時点のコンテナイメージのコピーとなります。

-Lオプションを使ってスナップショットを確認してみましょう。

$ sudo lxc-snapshot -n ct01 -L
snap0 (/var/lib/lxcsnaps/ct01) 2014:09:02 17:42:33

snap0という名前でスナップショットが作成されています。このあと同様にスナップショットを作成するとsnap1snap2と通し番号が増加していきます。

$ sudo lxc-snapshot -n ct01 
  : (略)
$ sudo lxc-snapshot -n ct01 -L
snap1 (/var/lib/lxcsnaps/ct01) 2014:09:02 17:58:18
snap0 (/var/lib/lxcsnaps/ct01) 2014:09:02 17:42:33

リスト表示で表示されているようにスナップショットは/var/lib/lxcsnapsディレクトリにコンテナ名のディレクトリを作成し、その下のスナップショット名のディレクトリに保存されます。

スナップショットディレクトリの下を少しのぞいてみましょう。

$ ls -F /var/lib/lxcsnaps/ct01/snap0/
config  rootfs/  ts

通常のコンテナディレクトリと同様のconfigファイルとrootfsディレクトリ以外にtsというファイルがあります。

$ cat /var/lib/lxcsnaps/ct01/snap0/ts 
2014:09:02 17:42:33

tsファイルの中を見てみると、リスト表示で表示されていたスナップショット作成のタイムスタンプが保存されています。

それでは-rオプションを使ってスナップショットからリストアを実行してみましょう。同時に、きちんとスナップショットから戻っているかも簡単に確認してみたいと思います。

$ echo "0" | sudo tee /var/lib/lxc/ct01/rootfs/testfile (中身が"0"のテストファイル作成)
0
$ sudo lxc-snapshot -n ct01 (スナップショット作成)
  : (略)
$ echo "1" | sudo tee /var/lib/lxc/ct01/rootfs/testfile (テストファイルの中身を書き換え)
1
$ sudo cat /var/lib/lxc/ct01/rootfs/testfile
1
$ sudo lxc-snapshot -n ct01 -r snap0 ("snap0"へのリストア)
$ sudo cat /var/lib/lxc/ct01/rootfs/testfile (スナップショット作成時点の状態に戻っている)
0

コンテナを起動せずにホストOSからコンテナイメージを触って試しているのでちょっと手抜きですが、コンテナを起動して同様に実行しても結果は同じになります。

以上のリストアの例はスナップショット取得元のコンテナに上書きでリストアしています。スナップショット元のコンテナはそのまま置いておきたいという場合、コンテナ名を指定すれば別のコンテナを新たに作成できます。

$ sudo lxc-snapshot -n ct01 -L
snap0 (/var/lib/lxcsnaps/ct01) 2014:09:02 18:36:59
$ sudo lxc-snapshot -n ct01 -r snap0 ct02
$ sudo lxc-ls --fancy
NAME  STATE    IPV4  IPV6  AUTOSTART  
------------------------------------
ct01  STOPPED  -     -     NO         
ct02  STOPPED  -     -     NO         

ct01コンテナのスナップショットsnap0を元にct02コンテナが作成されました。

最後にスナップショットを削除しましょう。-dオプションでスナップショット名を指定します。

$ sudo lxc-snapshot -n ct01 -d snap0
$ sudo lxc-snapshot -n ct01 -L
No snapshots

ここでの例ではdirストレージバックエンドを使っているため、スナップショットと言っても単なるコピーが行われているだけでした。一方、btrfsのようなスナップショット機能を持ったストレージバックエンドを使ったり、aufsやoverlayfsなどの重ね合わせができるストレージバックエンドを使うと、それぞれのストレージバックエンドが持つ特長を生かしてスナップショットを作成できます。色々なストレージバックエンドを使ったスナップショットの例は、この連載の後の回で紹介する予定です。

なお、LXC 1.1からはスナップショットはコンテナのディレクトリ(Ubuntuの場合/var/lib/lxc/(コンテナ名)以下に保存されるようになります/var/lib/lxcsnapsが存在すれば互換性維持のためにそちらを使います⁠⁠。つまりct01snap0/var/lib/lxc/ct01/snap0に保存されます。

また、執筆時点では LVM がストレージバックエンドの場合、スナップショットがうまく動いていないようです。このため修正されるまではLVMがストレージバックエンドのコンテナはスナップショットが取れないようにバージョン1.0.6で変更されるようです。

まとめ

今回はコンテナを便利に使うコマンドをいくつか紹介しました。lxc-clonelxc-snapshotはこの連載の後の回でも取り上げて、より便利に使う方法を紹介する予定です。

次回は前回と今回で紹介できなかったコマンドと、Ubuntu 14.04 LTSでcgroupを管理するために採用されたcgmanagerについて紹介する予定です。

おすすめ記事

記事・ニュース一覧