今回は前回紹介できなかったコマンドの紹介を続けます。その後、
アプリケーションコンテナ
lxc-startを使ったアプリケーションコンテナの起動
第8回でlxc-startコマンドの使い方を紹介しました。その際に紹介したのはシステムコンテナを起動する方法でした。lxc-startは特に指定しなければコンテナイメージ内の/sbin/を実行します。
ここでコマンドを指定するとlxc-startはアプリケーションコンテナとして指定したコマンドを実行します。
$ sudo lxc-start -n ct01 -- /bin/bash bash: cannot set terminal process group (-1): Inappropriate ioctl for device bash: no job control in this shell root@ct01:/# hostname ct01
/bin/を指定すると警告は出るものの、ct01として/bin/が実行されています。
lxc-startでアプリケーションコンテナを実行するときには注意が必要です。指定したコマンドがすぐに終了して制御が戻ってきてしまうような場合、lxc-startはコンテナのinitに相当するコンテナ内のPIDが1のプロセスがすぐに終了したとみなしてコンテナが起動しません。
以下の例を見てください。これはCentOSコンテナにApacheをインストールして、
# lxc-start -n apache01 -o log -l DEBUG -- /usr/sbin/httpd # lxc-ls --fancy NAME STATE IPV4 IPV6 AUTOSTART ---------------------------------------- apache01 STOPPED - - NO
lxc-startの実行はエラー出力もなく成功しているようです。しかし、
# cat log
: (略)
lxc-start 1409655419.090 NOTICE lxc_start - exec'ing '/usr/sbin/httpd'
lxc-start 1409655419.091 NOTICE lxc_start - '/usr/sbin/httpd' started with pid '1504'
lxc-start 1409655419.157 DEBUG lxc_start - container init process exited
指定した/usr/の実行は行われ、
このような場合は指定したコマンドが終了しなければ良いので、/sbin/をフォアグラウンドで起動すれば良いのです。
# lxc-start -d -n apache01 -o log -l INFO -- /usr/sbin/httpd -D FOREGROUND # lxc-ls --fancy NAME STATE IPV4 IPV6 AUTOSTART ---------------------------------------------- apache01 RUNNING 10.0.3.200 - NO
このようにきちんと実行されます。
lxc-executeによるアプリケーションコンテナの実行
以上のようにフォアグラウンドで起動させるためにちょっと工夫が必要なコマンドをコンテナとして実行する際に便利な場合があるコマンドがlxc-executeです。
lxc-executeはlxc-startと同様にコンテナを起動するためのコマンドです。lxc-startとの違いは、lxc-executeはアプリケーションコンテナを起動させるためのコマンドであるという点です。
lxc-executeは内部的な処理はlxc-startと同じです。違いはコンテナのinitとしてLXCが提供する簡易的なinitプログラムであるlxc.を起動し、
これを確認してみましょう。以下ではUbuntuコンテナにApacheをインストールして実行しています。
# lxc-execute -n apache01 -o log -l INFO -- /usr/sbin/apache2ctl start & [1] 7612 # lxc-ls --fancy NAME STATE IPV4 IPV6 AUTOSTART ---------------------------------------------- apache01 RUNNING 10.0.3.200 - NO
ご覧のように通常通りApacheの起動を行ってもコンテナが終了することなく起動した状態になっています。
このlxc-executeコマンドをpstreeコマンドで見てみましょう。
# pstree -A 7612
lxc-execute---init.lxc---apache2---2*[apache2---26*[{apache2}]]
ご覧のようにinit.というプログラムを挟んでapache2が実行されています。
このinit.はlxc-executeで指定したコマンドの終了を監視し、lxc-stopから送られてくるシグナルを子プロセスに送る役割も果たします。
ここまでご覧になると、lxc-executeが便利なような気がします。しかし実はそうでもありません。LXC 1.lxc-executeを使うには準備が必要です。
前述の例はUbuntu 14.init.をインストールするためです。
$ sudo lxc-attach -n ct01 -- apt-get install lxc
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
apparmor bridge-utils busybox-static ca-certificates cgmanager
cloud-image-utils debootstrap distro-info distro-info-data dnsmasq-base
euca2ools genisoimage iptables libaio1 libapparmor-perl libapparmor1
: (略)
コンテナ内で実行するコマンドはコンテナイメージ内に存在する必要があります。lxc-executeが内部的に実行するinit.であってもこれは同じです。これを手っ取り早く準備するためにinit.が含まれる"lxc"パッケージをインストールしたのです。
ホストOSにインストールした"lxc"パッケージにもinit.コマンドが含まれますので、init.はダイナミックリンクされているため、
そこで"lxc"パッケージをインストールしたわけです。コンテナ内で"lxc"パッケージをインストールすれば依存関係で必要なパッケージがインストールされるので楽です。
しかし、
環境が準備されてしまえばlxc-executeを使うのは簡単ですが、init.を使うためだけに、
なお、lxc-executeが使うinit.はスタティックリンクされ、lxc-executeを実行した時点でホストOSのinit.がコンテナ内に自動でバインドマウントされるようになる予定ですので、
LXCのシステム設定 ~ lxc-config
lxc-configはLXCのシステム設定を確認するためのコマンドです。
まずはlxc-configで確認できる値の一覧を表示してみましょう。
$ lxc-config -l lxc.default_config lxc.lxcpath lxc.bdev.lvm.vg lxc.bdev.lvm.thin_pool lxc.bdev.zfs.root
コンテナのデフォルト設定ファイルとコンテナの保存場所を表示させてみましょう。一覧で出てきた設定を指定するだけです。
$ sudo lxc-config lxc.default_config /etc/lxc/default.conf $ sudo lxc-config lxc.lxcpath /var/lib/lxc
コンテナの一時停止、再開 ~ lxc-freeze,lxc-unfreeze
起動中のコンテナを一時停止させる場合はlxc-freezeを使います。
$ sudo lxc-start -n ct01 -d $ sudo lxc-freeze -n ct01 $ sudo lxc-ls --fancy ct01 NAME STATE IPV4 IPV6 AUTOSTART ---------------------------------------------- ct01 FROZEN 10.0.3.156 - NO
一時停止中のコンテナを再開させる場合はlxc-unfreezeを使います。
$ sudo lxc-ls --fancy ct01 NAME STATE IPV4 IPV6 AUTOSTART ----------------------------------------- ct01 FROZEN 10.0.3.156 - NO $ sudo lxc-unfreeze -n ct01 $ sudo lxc-ls --fancy ct01 NAME STATE IPV4 IPV6 AUTOSTART ------------------------------------------ ct01 RUNNING 10.0.3.156 - NO
コンテナの状態のモニタリング ~ lxc-monitor
lxc-monitorはコンテナの状態をモニタリングします。実行すると、
コンテナの状態はこれまでもlxc-lsとlxc-infoの出力として紹介しました。しかし、
| 状態 | 説明 |
|---|---|
| STOPPED | 停止 |
| STARTING | 起動途中 |
| RUNNING | 実行中 |
| STOPPING | 停止途中 |
| ABORTING | コンテナの初期化に失敗 |
| FREEZING | 一時停止途中 |
| FROZEN | 一時停止 |
| THAWED | 再開 |
コンテナct01の状態をモニタリングしてみましょう。
$ sudo lxc-monitor -n ct01 'ct01' changed state to [STARTING] 'ct01' changed state to [RUNNING] 'ct01' changed state to [FREEZING] 'ct01' changed state to [FROZEN] 'ct01' changed state to [THAWED] 'ct01' changed state to [STOPPING] 'ct01' changed state to [STOPPED]
これはlxc-monitorを実行した後、
$ sudo lxc-start -n ct01 -d $ sudo lxc-freeze -n ct01 $ sudo lxc-unfreeze -n ct01 $ sudo lxc-stop -n ct01
コンテナ名を指定しないで実行すると、
$ sudo lxc-monitor 'ct01' changed state to [STARTING] 'ct01' changed state to [RUNNING] 'ct02' changed state to [STARTING] 'ct02' changed state to [RUNNING] 'ct02' changed state to [STOPPING] 'ct02' changed state to [STOPPED] 'ct01' changed state to [STOPPING] 'ct01' changed state to [STOPPED]
指定したコンテナの状態への待機 ~ lxc-wait
lxc-waitはコンテナが指定した状態になるのを待って終了します。コンテナの状態に応じて何かを行うようなスクリプト中で使えそうですね。
$ sudo lxc-wait -n ct01 -s STOPPED
と実行しておいて、
$ sudo lxc-stop -n ct01
とコンテナを停止させるとlxc-waitの実行は終了します。
Ubuntu 14.04 LTSのcgroup管理
一通りコンテナの管理に必要なコマンドの紹介が済んだ所で、
Ubuntu 12.
$ grep cgroup /proc/mounts cgroup /sys/fs/cgroup tmpfs rw,relatime,mode=755 0 0 cgroup /sys/fs/cgroup/cpuset cgroup rw,relatime,cpuset 0 0 cgroup /sys/fs/cgroup/cpu cgroup rw,relatime,cpu 0 0 cgroup /sys/fs/cgroup/cpuacct cgroup rw,relatime,cpuacct 0 0 cgroup /sys/fs/cgroup/memory cgroup rw,relatime,memory 0 0 cgroup /sys/fs/cgroup/devices cgroup rw,relatime,devices 0 0 cgroup /sys/fs/cgroup/freezer cgroup rw,relatime,freezer 0 0 cgroup /sys/fs/cgroup/blkio cgroup rw,relatime,blkio 0 0 cgroup /sys/fs/cgroup/perf_event cgroup rw,relatime,perf_event 0 0 cgroup /sys/fs/cgroup/hugetlb cgroup rw,relatime,hugetlb 0 0 $ ls /sys/fs/cgroup/ blkio cpu cpuacct cpuset devices freezer hugetlb memory perf_event
起動後、
ところがUbuntu 14.
最近の議論では、
この流れに従い、
このためUbuntu 14./sys/ディレクトリは以下のようにすっきりしています。
$ grep cgroup /proc/mounts none /sys/fs/cgroup tmpfs rw,relatime,size=4k,mode=755 0 0 systemd /sys/fs/cgroup/systemd cgroup rw,nosuid,nodev,noexec,relatime,release_agent=/run/cgmanager/agents/cgm-release-agent.systemd,name=systemd 0 0 $ ls /sys/fs/cgroup cgmanager systemd $ ls -l /sys/fs/cgroup/cgmanager/ total 0 srwxrwxrwx 1 root root 0 Aug 12 18:40 sock
cgmanagerというディレクトリが存在し、
この状態でもLXCを使ってコンテナは起動し、
実はcgmanagerは起動時に新たなマウント名前空間を作成し、
util-linux 2.nsenterというコマンドを使って確認してみましょう。nsenterは任意の名前空間上でコマンドが実行できるコマンドです。実行中のcgmanagerデーモンが属するマウント名前空間を指定してコマンドを実行してみます
$ sudo ./nsenter --target `pgrep cgmanager` --mount -- grep cgroup /proc/mounts none /sys/fs/cgroup tmpfs rw,relatime,size=4k,mode=755 0 0 none,name=systemd /run/cgmanager/fs/none,name=systemd cgroup rw,relatime,release_agent=/run/cgmanager/agents/cgm-release-agent.systemd,name=systemd 0 0 cpuset /run/cgmanager/fs/cpuset cgroup rw,relatime,cpuset,release_agent=/run/cgmanager/agents/cgm-release-agent.cpuset,clone_children 0 0 cpu /run/cgmanager/fs/cpu cgroup rw,relatime,cpu,release_agent=/run/cgmanager/agents/cgm-release-agent.cpu 0 0 cpuacct /run/cgmanager/fs/cpuacct cgroup rw,relatime,cpuacct,release_agent=/run/cgmanager/agents/cgm-release-agent.cpuacct 0 0 memory /run/cgmanager/fs/memory cgroup rw,relatime,memory,release_agent=/run/cgmanager/agents/cgm-release-agent.memory 0 0 devices /run/cgmanager/fs/devices cgroup rw,relatime,devices,release_agent=/run/cgmanager/agents/cgm-release-agent.devices 0 0 freezer /run/cgmanager/fs/freezer cgroup rw,relatime,freezer,release_agent=/run/cgmanager/agents/cgm-release-agent.freezer 0 0 blkio /run/cgmanager/fs/blkio cgroup rw,relatime,blkio,release_agent=/run/cgmanager/agents/cgm-release-agent.blkio 0 0 perf_event /run/cgmanager/fs/perf_event cgroup rw,relatime,perf_event,release_agent=/run/cgmanager/agents/cgm-release-agent.perf_event 0 0 hugetlb /run/cgmanager/fs/hugetlb cgroup rw,relatime,hugetlb,release_agent=/run/cgmanager/agents/cgm-release-agent.hugetlb 0 0 $ sudo ./nsenter --target `pgrep cgmanager` --mount -- ls /run/cgmanager/fs blkio cpu cpuacct cpuset devices freezer hugetlb memory none,name=systemd perf_event
ご覧のように実行中のcgmanagerが属するマウント名前空間では/run/以下にcgroupfsがマウントされているのがわかります。
cgmanagerはホストOSの属する名前空間にあった/sys/経由でDBusのメッセージを受け付けて別の名前空間でマウントされたcgroupfsの操作を行います。
なお、
まとめ
今回はLXCに付属するコマンドのうち、
次回からはLXCの設定について解説していく予定です。
第4回 コンテナ型仮想化の情報交換会@東京
筆者が主催している
この勉強会の資料や動画を以下にまとめました。LinuxやLXCに限らないいろいろなコンテナ関連の技術のお話や活用事例のお話が聞けて非常に勉強になりました。興味のある方はぜひご覧ください。
