lxc(7) | lxc(7) |
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(7), 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 <daniel.lezcano@free.fr>
Christian Brauner <christian.brauner@ubuntu.com>
Serge Hallyn <serge@hallyn.com>
Stéphane Graber <stgraber@ubuntu.com>
2023-11-30 | Version 5.0.2 |