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

第23回 LXCの構築・活用[9]─ lxc-start-ephemeralとフック(1)

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

前回までで,LXC 1.0でサポートされているストレージバックエンドの紹介が一通り終わりました。今回はこれまで紹介していなかったlxc-start-ephemeralコマンドを紹介しましょう。

lxc-start-ephemeralコマンドは,コンテナ起動前の準備や終了後の後始末で,LXCが持つフック機能を使っています。以前にLXCの設定について紹介した第11回第12回ではこの機能について紹介していませんでしたので,lxc-start-ephemeralコマンドを実例にしてあわせて簡単に紹介したいと思います。

今回の例はUbuntu 14.04.2 LTS上で,パッケージでインストールしたlxc 1.0.7を使って実行しています。

lxc-start-ephemeralコマンドの概要

lxc-start-ephemeralコマンドは,存在しているコンテナの一時的なコピーとなるコンテナを作成し,起動するコマンドです。

既存のコンテナをベースにいろいろな作業を行うには,これまでに紹介したlxc-cloneコマンドによるクローンが便利です。

一方,⁠ちょっと試したいことがある」という場合で,試した結果が保存されている必要がない場合にはlxc-start-ephemeralコマンドが便利な場面もあるでしょう。⁠一時的な(ephemeral)コピー」というくらいですので,デフォルトでは起動後に行った変更はすべて消えてなくなりますので注意してください。

また,lxc-start-ephemeralコマンドはoverlayfsもしくはaufsを使用しますので,このどちらかが使えない場合は動作しません。注意してください。

まずは使ってみましょう

まずは簡単にlxc-start-ephemeralコマンドの動きを見てみましょう。

lxc-start-ephemeralコマンドを一番シンプルに使用するには,一時的なコンテナのコピー元となるコンテナ名だけを指定します。

$ sudo lxc-ls
ct01  
$ sudo lxc-start-ephemeral -o ct01

以上のように実行するとフォアグラウンドでの起動になりますので,起動したコンソール上にログインプロンプトが表示されます。テンプレートによっては,コンテナを作成した直後はログインできるユーザが存在しない場合がありますので注意しましょう。

あらかじめ-oで指定したコピー元のコンテナにアクセスできるユーザが設定されていればそのまま使えますが,そうでなければ別の端末からlxc-stopで終了させるか,lxc-attachコマンドで必要な設定や操作を行いましょう。

なおlxc-startコマンドで起動したコンテナがデフォルトでバックグラウンド起動になるLXC 1.1をインストールした環境であっても,lxc-ephemeralコマンドは特に指定しなければフォアグラウンドでの起動になります。

lxc-startと同様に,lxc-start-ephemeralでも-dオプションを使ってバックグラウンドで起動できます。ここから後はバックグラウンドで起動していろいろな機能を紹介していきます。

それではバックグラウンドでコンテナを起動してみましょう。

$ sudo lxc-start-ephemeral -o ct01 -d
The ephemeral container is now started.

You can enter it from the command line with: lxc-console -n ct01-zvsn8pmn
The following IP addresses have be found in the container:
 - 10.0.3.130

バックグラウンドで起動すると,以上のようにコンテナ名とIPアドレスが表示されます。起動するコンテナ名はコピー元のコンテナ名をベースにランダムな文字列が付与された名前になります。

もし,コンテナへ直接アクセスしてコマンドを実行する必要があるのであれば,以下のような方法でコンテナにアクセスして必要な処理を行います。

  • lxc-consoleコマンドを使ってログインする
  • ssh経由でログインする
  • lxc-attachコマンドでコンテナ上でコマンドを実行する

一時的とは言え,通常のコンテナを起動している場合と何も変わりませんのでlxc-lsで確認できます。

$ sudo lxc-ls -f
NAME           STATE    IPV4        IPV6  AUTOSTART  
---------------------------------------------------
ct01           STOPPED  -           -     NO         
ct01-zvsn8pmn  RUNNING  10.0.3.130  -     NO         

起動を確認したあとコンテナを停止させてみます。

$ sudo lxc-stop -n ct01-zvsn8pmn
$ sudo lxc-ls 
ct01  

以上のように停止後はコンテナは消えています。

lxc-start-ephemeralコマンドのオプション

lxc-start-ephemeralコマンドを詳しく見ていく前に,指定できるオプションを見ておきましょう。

オプション オプションの説明
-o,--orig コピー元のコンテナ名
-n,--name 一時的に起動するコンテナの名前
-d,--daemon コンテナをバックグラウンドで実行
-b,--bdir コンテナ内にバインドマウントするディレクトリ
-u,--user コンテナに接続するためのユーザ
-S,--key コンテナ内にコピーする SSH 公開鍵
-U,--union-type 使用する union filesystem
-k,--keep-data コマンド終了後にコンテナイメージを残す
-s,--storage-type 使用するストレージバックエンド

以上のオプションのうち,指定が必須のオプションは-oのみです。--storage-typeは現時点でマニュアルに記載がありません。筆者がパッチを送ってありますので,そのうちマニュアルにも記載されるはずです。

lxc-start-ephemeralコマンドの仕組みとフック

lxc-start-ephemeralコマンドがどのように一時的なコンテナを実現しているのかを少し詳しく見ていきましょう。あらためてバックグラウンドでコンテナを起動してみます。

$ sudo lxc-start-ephemeral -o ct01 -d
The ephemeral container is now started.

You can enter it from the command line with: lxc-console -n ct01-7iv1faqo
The following IP addresses have be found in the container:
 - 10.0.3.240

まずはコンテナ用のディレクトリを見てみましょう。

$ sudo ls -F /var/lib/lxc/ct01-7iv1faqo/
config  configured  delta0/  post-stop*  pre-mount*  rootfs/

見慣れたファイルの他にいくつか初めて見るファイルが存在しますね。

まずは設定ファイルであるconfigを見てみましょう。lxc-createコマンドを使ってコンテナを作成した時にも設定される項目は除いて,lxc-start-ephemeral特徴的な設定だけ挙げてみます。

$ sudo cat /var/lib/lxc/ct01-7iv1faqo/config
   :(略)
lxc.utsname = ct01-7iv1faqo
   :(略)
lxc.hook.pre-mount = /var/lib/lxc/ct01-7iv1faqo/pre-mount
lxc.hook.post-stop = /var/lib/lxc/ct01-7iv1faqo/post-stop
lxc.rootfs = /var/lib/lxc/ct01-7iv1faqo/rootfs

lxc.utsnamelxc.rootfslxc-start-ephemeralコマンドがランダムで付与したコンテナ名で設定されています。この2つの設定以外が初めて目にする設定ではないでしょうか。

LXCはコンテナを起動させようとした時からコンテナが停止するまでのいろいろな場面と,クローン時に必要な処理が行えるようにフックとしてプログラムやスクリプトを指定できるようになっています。lxc-start-ephemeralコマンドはこのフックを使って必要な処理を行っています。

第11回第12回でLXCの設定を紹介した時にはフックについては触れませんでした。

まずはこの2つのフックについて説明しましょう。

lxc-start-ephemeralコマンドのコンテナ起動前の処理

lxc-start-ephemeralコマンドは起動するコンテナのルートファイルシステムをunion filesystemを使って準備します。この準備をフックを使って行っています。

lxc.hook.pre-mountは,コンテナのルートファイルシステムが設定される前に実行されます。ルートファイルシステムが設定される前ですので,ルートファイルシステムに対する処理をここで行えます。この処理はコンテナのマウント名前空間で行われ,コンテナが停止する前にクリーンアップされますのでホストには影響を与えません。

lxc.hook.pre-mountで指定されているpre-mountスクリプトは,実行権限が付いたシェルスクリプトで以下のような内容です。

 1: #!/bin/sh
 2: LXC_DIR="/var/lib/lxc/ct01-7iv1faqo"
 3: LXC_BASE="ct01"
 4: LXC_NAME="ct01-7iv1faqo"
 5: mkdir -p /var/lib/lxc/ct01-7iv1faqo/delta0 /var/lib/lxc/ct01-7iv1faqo/rootfs/
 6: mount -n -t tmpfs -o mode=0755 none /var/lib/lxc/ct01-7iv1faqo/delta0
 7: mount -n -t overlayfs -oupperdir=/var/lib/lxc/ct01-7iv1faqo/delta0,lowerdir=/var/lib/lxc/ct01/rootfs none /var/lib/lxc/ct01-7iv1faqo/rootfs/
 8:
 9: [ -e $LXC_DIR/configured ] && exit 0
10: for file in $LXC_DIR/rootfs/etc/hostname \
11:             $LXC_DIR/rootfs/etc/hosts \
12:             $LXC_DIR/rootfs/etc/sysconfig/network \
13:             $LXC_DIR/rootfs/etc/sysconfig/network-scripts/ifcfg-eth0; do
14:         [ -f "$file" ] && sed -i -e "s/$LXC_BASE/$LXC_NAME/" $file
15: done
16: touch $LXC_DIR/configured

順に見ていきましょう。

  • 2~4行目:変数の定義です。
  • 5行目:delta0ディレクトリとrootfsディレクトリを作成します。
  • 6行目:rootfsをtmpfsとしてマウントします。
  • 7行目:上層側ディレクトリとしてdelta0を,下層側ディレクトリとしてコピー元であるコンテナのイメージを指定してrootfsをoverlayfsとしてマウントします。
  • 9行目:既にconfiguredファイルが存在する場合は10行目以下の処理を行いません。
  • 10行目~15行目:コンテナのルートファイルシステム以下に存在しているファイルに記載されているホスト名を,これから起動するコンテナ名で書き換えます。
  • 16行目:configuredファイルを作成する。

という処理を行っています。

つまりoverlayfsが変化を記録するために使う上層側ディレクトリとしてtmpfsを使い,これから起動するコンテナのルートファイルシステムをoverlayfsで準備します。上層側ディレクトリがtmpfsですから,コンテナの名前空間が消滅するコンテナ終了時に中身は消えてしまいます。そのため,起動後に行ったコンテナイメージに対する変更が消えてしまうわけです。

overlayfsを使っているので,元となるコンテナイメージを全てコピーする必要はありません。このようにして素早くコンテナのイメージを準備しています。

lxc-start-ephemeralコマンドのコンテナ終了後の処理

lxc-start-ephmeralコマンドを使って作成されたコンテナでは,もう一つフックが使われていましたのでそちらも見ておきましょう。

コンテナ終了後に後始末をするため,lxc.hook.post-stopという設定がされていました。これはコンテナがシャットダウンされた後にホストの名前空間上で実行されるフックです。

lxc.hook.post-stop = /var/lib/lxc/ct01-7iv1faqo/post-stop

ここで指定されているファイルの中を見てみましょう。

#!/bin/sh
[ -d "/var/lib/lxc/ct01-7iv1faqo" ] && rm -Rf "/var/lib/lxc/ct01-7iv1faqo"

一時的なコンテナ用に作成されたディレクトリを消去しています。このようにlxc.hook.post-stopを使って,コンテナ終了後の後処理が行えますね。

著者プロフィール

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

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

Plamo Linuxメンテナ。ファーストサーバ株式会社所属。

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

コメント

コメントの記入