lxc - Linux コンテナ
コンテナ技術は、メインストリームの
Linux Kernel
で活発に開発が進んでいる技術です。コンテナ技術は、cgroup
によりリソースを管理する機能を提供し、名前空間によりリソースを隔離する機能を提供します。
lxc
は、アプリケーションまたはシステムのために完全なリソースの隔離やコントロールを提供する、ユーザースペースのコンテナオブジェクトを提供するためのこれらの新しい機能を使う事を目指しています。
lxc
は、シンプルなコマンドラインでコンテナを簡単に管理できるほど軽量で、他の用途に使うのにも十分に機能がそろっています。
カーネルのバージョンが
3.10
以上のディストリビューションであれば、
lxc
が動作するでしょう。このバージョンは機能は少ないですが、それでも十分楽しめるでしょう。
lxc
はカーネルが提供する様々な機能に依存します。
lxc-checkconfig
がカーネルの設定や、必要な機能、足りない機能についての情報を提供してくれるでしょう。
コンテナは、ホストのリソースのいくつかを隔離して、内部でアプリケーションやシステムを実行します。
アプリケーションやシステムは、あらかじめ作成した設定や、コマンドへのパラメータで与えた設定で、コンテナ内で実行されます。
コンテナ内でアプリケーションを実行する方法
アプリケーションを実行する前に、隔離したいリソースについて知っておくべきです。デフォルトの設定では、PID、sysv
IPC、マウントポイントが隔離されます。コンテナ内でシンプルなシェルを実行したい場合で、特に
rootfs
を共有したい場合、基本的な設定が必要です。
もし、
sshd
のようなアプリケーションを実行したい場合、新しいネットワークスタックと、新しいホスト名を準備しなくてはなりません。もし、同じファイル
(
/var/run/httpd.pid 等)
の衝突を避けたい場合、空の
/var/run/
を再度マウントしなければなりません。
どんな場合でも衝突を避けたい場合、コンテナ専用の
rootfs
を指定することができます。rootfs
はディレクトリツリーとする事も可能で、前もって元の
rootfs を bind マウントし、
/etc や
/homeだけは自身のディレクトリを使って、自身のディストリビューションを使えます。
ここで、
sshd
のためのディレクトリツリーのサンプルを示しましょう。
[root@lxc sshd]$ tree -d rootfs
rootfs
|-- bin
|-- dev
| |-- pts
| `-- shm
| `-- network
|-- etc
| `-- ssh
|-- lib
|-- proc
|-- root
|-- sbin
|-- sys
|-- usr
`-- var
|-- empty
| `-- sshd
|-- lib
| `-- empty
| `-- sshd
`-- run
`-- sshd
そして、それに対応するマウントポイントのファイルは以下のようになります。
[root@lxc sshd]$ cat fstab
/lib /home/root/sshd/rootfs/lib none ro,bind 0 0
/bin /home/root/sshd/rootfs/bin none ro,bind 0 0
/usr /home/root/sshd/rootfs/usr none ro,bind 0 0
/sbin /home/root/sshd/rootfs/sbin none ro,bind 0 0
コンテナ内でシステムを実行する方法
コンテナ内でシステムを実行するのは、逆説的ではありますが、アプリケーションを実行するよりも簡単です。
それは、隔離するリソースについて考える必要がないからで、全てを隔離する必要があるからです。
他のリソースは、コンテナが設定を行うので、設定なしで隔離されるように指定されます。
例えば、IPv4
アドレスはコンテナの
init
スクリプトでシステムによってセットアップされるでしょう。
以下に、(システムを実行するときの)
マウントポイントファイルを示します。
[root@lxc debian]$ cat fstab
/dev /home/root/debian/rootfs/dev none bind 0 0
/dev/pts /home/root/debian/rootfs/dev/pts none bind 0 0
コンテナが作成されるとき、コンテナは設定情報を含みます。プロセスが生成されるとき、コンテナは開始し、実行されるでしょう。コンテナ内で実行されている最後のプロセスが終了したとき、コンテナは停止します。
コンテナの初期化時の失敗の場合は、(以下の図の)
中断の状態を通ります。
---------
| STOPPED |<---------------
--------- |
| |
start |
| |
V |
---------- |
| STARTING |--error- |
---------- | |
| | |
V V |
--------- ---------- |
| RUNNING | | ABORTING | |
--------- ---------- |
| | |
no process | |
| | |
V | |
---------- | |
| STOPPING |<------- |
---------- |
| |
---------------------
コンテナは設定ファイル経由で設定します。設定の書式は
lxc.conf(5)
で説明しています。
持続性のコンテナオブジェクトは
lxc-create
コマンドで作成できます。コマンドにはコンテナ名をパラメータとして与え、オプションで設定ファイルとテンプレートを指定します。ここで指定する名前は、他のコマンドからこのコンテナを参照する際に使います。
lxc-destroy
コマンドはコンテナオブジェクトを削除します。
lxc-create -n foo
lxc-destroy -n foo
コンテナを開始する前にコンテナオブジェクトを作成する必要はありません。パラメータとして設定ファイルを指定して、コンテナを直接起動できます。
コンテナが作成されると、アプリケーションもしくはシステムを実行できます。このために使用するのが
lxc-execute と
lxc-start
コマンドです。
アプリケーションを開始する前にコンテナを作成しなかった場合、コンテナはコマンドにパラメータとして渡した設定ファイルを使用します。もし、このようなパラメータもない場合は、デフォルトで指定されている通りに隔離されます。
アプリケーションが終了した場合、コンテナも停止します。
lxc-stop
コマンドを使って、実行中のアプリケーションを停止することもできます。
コンテナ内でアプリケーションを実行することは、正確にはシステムとして実行するのとは異なります。このため、コンテナ内でアプリケーションを実行するためのコマンドには、2
種類の違ったものがあります。
lxc-execute -n foo [-f config] /bin/bash
lxc-start -n foo [-f config] [/bin/bash]
lxc-execute
コマンドは、間に
lxc-init
プロセスを介して、コンテナ内で指定したコマンドを実行します。
lxc-init
はコマンドを実行した後、(コンテナ内でのデーモンの実行をサポートするために)
実行したコマンドと生成された全てのプロセスが終了するのを待ちます。
言いかえると、コンテナ内では
lxc-init は PID 1
を持ち、アプリケーションの最初のプロセスは
PID 2 をもちます。
lxc-start
コマンドは、コンテナ内の特定のコマンドを直接実行します。最初のプロセスの
PID が 1 となります。
もし、実行するコマンドが指定されていない場合は、
lxc-start は lxc.init.cmd
で設定されたコマンドを実行します。もし
lxc.init.cmd
が設定されていない場合は
/sbin/init を実行します。
まとめると、
lxc-execute
はアプリケーションを実行するためのコマンドであり、
lxc-start
はシステムを実行するのにより適したコマンドです。
もしアプリケーションの反応がなくなった場合や、アクセスできなくなった場合、自分で終了できない場合は、荒っぽいですが、
lxc-stop
コマンドがコンテナ内の全てのプロセスを容赦なく停止させてくれるでしょう。
lxc-stop -n foo -k
コンテナが tty
を持つように設定されているならば、tty
を通してコンテナにアクセスすることができます。
アクセスできるかどうかは、以下のコマンドが使う
tty
がコンテナで利用できるように設定されているか次第です。
tty
が失われたとき、再度のログインなしでその
tty
に再接続することが可能です。
lxc-console -n foo -t 3
ジョブスケジューリングなどで、コンテナに属する全てのプロセスを停止する事が役に立つときがあります。
コマンド
lxc-freeze -n foo
は、全てのプロセスを中断不可能な状態に置きます。そして、
lxc-unfreeze -n foo
その全てのプロセスを再開します。
この機能は、カーネルで
cgroup v1 の freezer
コントローラが有効になっている場合に使用できます。
多数のコンテナが存在する場合、それらが実行されたり削除されたりすること、何が実行されていて、特定のコンテナ内で実行されている
PID
が何であるかをフォローするのは大変です。このような時には、以下のようなコマンドが役に立つかもしれません。
lxc-ls -f
lxc-info -n foo
lxc-ls
はコンテナをリスト表示します。
lxc-info
は、指定したコンテナに関する情報を表示します。
ここで、以上のコマンドを組み合わせて、どのようにしたら全てのコンテナのリストと、それぞれの状態が得られるかの例を示します。
for i in $(lxc-ls -1); do
lxc-info -n $i
done
時々、コンテナの状態を追跡することが出来ると便利な事があります。例えば、状態をモニタリングしたり、スクリプト内で特定の状態を待ったりするような場合です。
lxc-monitor
コマンドは、一つもしくは複数のコンテナをモニタリングします。このコマンドのパラメータは、正規表現を受け付けます。例えば
lxc-monitor -n "foo|bar"
は 'foo' と 'bar'
という名前のコンテナの状態をモニタリングします。そして、
lxc-monitor -n ".*"
は全てのコンテナの状態をモニタリングします。
コンテナ 'foo'
が開始され、いくつか処理を行い、終了した場合、出力は以下のようになります。
'foo' changed state to [STARTING]
'foo' changed state to [RUNNING]
'foo' changed state to [STOPPING]
'foo' changed state to [STOPPED]
lxc-wait
コマンドは指定した状態を待って終了します。これは、コンテナの開始や終了に同期したいスクリプトで役に立ちます。パラメータは、異なった状態の論理和
(OR) を指定します。
以下の例は、バックグラウンドで実行されたコンテナをどのようにして待つかを示します。
# launch lxc-wait in background
lxc-wait -n foo -s STOPPED &
LXC_WAIT_PID=$!
# this command goes in background
lxc-execute -n foo mydaemon &
# block until the lxc-wait exits
# and lxc-wait exits when the container
# is STOPPED
wait $LXC_WAIT_PID
echo "'foo' is finished"
コンテナは control group
と結合しています。コンテナを開始すると
cgroup
が生成され、結びつけられます。
cgroup
のプロパティは、lxc-cgroup
コマンドを使って、コンテナが実行中に読み取ったり変更したりできます。
lxc-cgroup
コマンドは、コンテナと結びつけられている
control group
サブシステムを設定したり、取得したりするのに使います。サブシステム名の指定はユーザが行ない、このコマンドはサブシステム名の文法チェックは一切行ないません。もし、指定したサブシステム名が存在しない場合は、コマンドの実行は失敗します。
lxc-cgroup -n foo cpuset.cpus
は、このサブシステムの内容を表示します。
lxc-cgroup -n foo cpu.shares 512
は、このサブシステムに指定した値を設定します。
,
lxc-create(1),
lxc-copy(1),
lxc-destroy(1),
lxc-start(1),
lxc-stop(1),
lxc-execute(1),
lxc-console(1),
lxc-monitor(1),
lxc-wait(1),
lxc-cgroup(1),
lxc-ls(1),
lxc-info(1),
lxc-freeze(1),
lxc-unfreeze(1),
lxc-attach(1),
lxc.conf(5)
Daniel Lezcano <
[email protected]>
Christian Brauner <
[email protected]>
Serge Hallyn <
[email protected]>
Stéphane Graber <
[email protected]>