2015年11月13日金曜日

最近話題のLinuxコンテナを試してみました。

Linuxコンテナ

従来の仮想マシンと比較して軽量な仮想環境としてコンテナが注目されています。仮想マシンのようにまるごと物理マシンをエミュレーションした環境を用意するのでなく、ネットワークやプロセスIDなどのみが独立した環境(コンテナ)を用意してその中でプロセスを実行するタイプのOSレベル仮想環境です。今回はそのコンテナについてもっともベースとなる部分を試してみました。

LXCのインストール

最近はコンテナの利用する環境を整えるのにも各ディストリビューションに対応したパッケージをインストールするだけで大丈夫です。 コンテナを利用するための実装にはいくつのかの種類がありますが今回はLXCを利用します。他にはDockerなどが有名です。ただLinuxコンテナの核となる部分はカーネル側の機能なので、実装が違っていてもベースとなる考え方は一緒です。 
 今回はDebian/Jessieを利用しますが、LXCはほとんどのディストリビューションでパッケージ化されていると思います。またカーネルが必要な機能を有効にしてコンパイルされていないとダメなのですが、ディストリビューションの標準カーネルであればまず問題ないはずです。
 DebianのJessieではapt-getでインストールするだけです。
# apt-get install lxc

コンテナの作成 


 ではコンテナを作りましょう。一連の作業はrootで実行する必要があります。コンテナの作成においては、コンテナ用のファイルシステムを作成することがメインです。あとはコンテナを実行するためのLXCの設定ファイルも必要です。

コンテナ用のファイルシステム

コンテナ内のプロセスからはこのファイルシステムがルートファイルシステム(/)として見え、基本的にここにしかアクセスできません。コンテナ内のプロセスはこのルートファイルシステム上で実行されます。

 コンテナを作成するには先ほどインストールしたLXCのユーティリティに含まれるlxc-createコマンドを利用するのが簡単です。

lxc-create -n <コンテナ名> -t <テンプレート名> -- <テンプレートオプション>
例:test1という名前で64bit Debian/Jessieのルートファイルシステムを作成する場合 


# lxc-create -n test1 -t debian -- --arch amd64 --release=jessie

 lxc-create コマンドは-tオプションで指定したテンプレートに従ってルートファイルシステムを作成します。テンプレートは/usr/share/lxc/templates/lxc-<テンプレート名>という名前で実体が用意されています。必ずしもホストのLinuxと同じディストリビューションのファイルシステムでなくてはいけないということはありませんがアーキテクチャは同じでないといけません。ホストが64bitであるならばルートファイルシステムも64bit用のものを用意します。
 debianテンプレートの場合debootstrapコマンドを利用してネットワーク越しにrootfsを取得してきます

# lxc-create -n test1 -t debian -- --arch amd64 --release=jessie

 LXCの標準的な構成であればコンテナの保存場所は/var/lib/lxcになります。その場所の<コンテナ名>ディレクトリ以下にコンテナの一連のファイルが作成されます。

# cd /var/lib/lxc
# tree -L 1 test1
test1
|-- config
`-- rootfs
rootfs以下が作成されたルートファイルシステムです。configがLXCの設定ファイルになります。rootfs以下にはdebootstrapで作成された(最小インストールの)Debianのルートファイルシステムが作成されています。

# ls test1/rootfs/
bin   dev  home  lib64    mnt  proc  run     selinux  sys  usr
boot  etc  lib     media    opt  root  sbin  srv      tmp  var

 作成されたコンテナの一覧はlxc-lsコマンドで確認できます。

# lxc-ls -f
NAME   STATE    IPV4  IPV6  AUTOSTART 
-------------------------------------
test1  STOPPED  -     -     NO        

まだ、コンテナを作成しただけで実行してはいないのでSTOPPEDになっています。

コンテナの実行

早速コンテナを実行してみましょう。コンテナを実行するとはコンテナ内でなんからのプロセスを実行することです。実行するものはなんでも良いのですが、コンテナ内ではコンテナのルートファイルシステムにしかアクセスできませんので、その上にプロセス本体のファイルが存在していることが必要です。本体の実行にライブラリが必要なのであればそれも同様にルートファイルシステム上に存在している必要ががあります。

 デフォルトで作成される設定ファイルは内容がまだスカスカで実用には十分ではありませんがとりあえずコンテナ内でプロセスを実行することはできるはずです。

 ここではコンテナ内でシェル(bash)を実行してみます。コンテナ内でのプログラムの実行するにはlxc-startコマンドを利用します。

# lxc-start -n test1 -- /bin/bash
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell

 警告が出てしまいますが、シェルをコンテナ内で実行できました。このシェル上で色々確認してみるとこのシェルのプロセスがコンテナ内に閉じ込められていることがわかります。
 ファイルシステムは/var/lib/lxc/test1/rootfs以下の部分にしかアクセスすることができません。そこがコンテナ内ではルートファイルシステム(/)として見えていることが分かります。
root@test1:/# pwd
/
root@test1:/# ls
bin   dev  home  lib64  mnt  proc  run   selinux  sys  usr
boot  etc  lib   media  opt  root  sbin  srv      tmp  var
root@test1:/# cat /etc/hostname
test1

 psでプロセスを確認してみると自身のシェル(とpsコマンド)しか見えないのがわかります。他に大量に動作しているであろうホスト上のプロセスは確認できません。しかもシェルのPIDがなんと1番になっているのがわかります。

root@test1:/# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 05:12 ?        00:00:00 /bin/bash
root        11     1  0 05:40 ?        00:00:00 ps -ef

 ipコマンドでネットワークを確認してみるとネットワーク(eth0)がないことがわかります。ディストリビューションによってはLXCインストール時にコンテナ用のネットワークが用意され有効になっているかもしれません。いずれにしてもホスト上のものとは別のネットワークが見えるはずです。

root@test1:/# ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

 シェルから抜けて終了させてみます。するとコンテナも終了します。lxc-lsコマンドで確認してみてもstoppedになっていると思います。コンテナでは基本的にコンテナ内でPID1番に見えるプロセスが終了するとコンテナ自身も終了します。

 再びコンテナ内でbashを実行して、ホスト上の別端末からlxc-lsコマンドで確認してみます。今度はステータスがRUNNINGになっていると思います。
# lxc-start -n test1 /bin/bash
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
root@test1:/#

別端末から
# lxc-ls -f
NAME   STATE    IPV4  IPV6  AUTOSTART 
-------------------------------------
test1  RUNNING  -     -     NO


 コンテナの外からコンテナ内で実行しているプロセスがどのようにみえているか確認してみます。bashだとどれがコンテナ内のbashなのか確認しにくいのでコンテナ内のbashから適当なプロセスをさらに実行して目印にしておきます。

root@test1:/# tail -f /dev/null

 ホスト上でpsコマンド実行するとコンテナ内のプロセスは普通に確認できることがわかります。プロセスIDも他のプロセスと同様のものがちゃんと振られています。コンテナ実行時のlxc-startが親プロセスとしてコンテナ内のbashを実行し、それがコンテナ内ではPID1番(外側では12146番)として扱われています。

# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
...
root     12142 12081  0 05:47 pts/1    00:00:00 lxc-start -n test1 /bin/bash
root     12146 12142  0 05:47 pts/1    00:00:00 /bin/bash
root     12156 12146  0 05:49 pts/1    00:00:00 tail -f /dev/null

まとめ

Linuxコンテナとは基本的にはこのようにプロセスを他のプロセスやファイルシステム、ネットワークなどから隔離して実行する技術です。隔離する事によりプロセスの予期せぬ動作からシステムや他のプロセスを保護することができます。

0 件のコメント:

コメントを投稿