TenForward

技術ブログ。はてなダイアリーから移転しました

libvirt 経由で lxc を触ろうと思ってハマる (6)

ついにこのシリーズも 6 回目.(^_^;)

前回は,libvirtXML ファイルで定義したメモリ制限が効いてないぞ,というお話でした.

手元では

で試してました.

問題がいくつかあり,それが絡んでわけがわからなくなってましたが,とりあえず解きほぐせた気がします.(前回の実験はミスしてたし ^^;)

cgroup の階層構造がうまく出来ない問題

libvirt は cgroup を使ったリソース制限を,cgroup ファイルシステム内で階層構造を作り,管理します.例えば,/cgroup にマウントしている場合,

# tree -d /cgroup/
/cgroup/
├── 1479
├── 1481
└── libvirt
    ├── lxc
    │   └── vm1
    │   ├── 1559
    │   └── 1563
    └── qemu

こんな感じ.つまり lxc コンテナは libvirt/lxc/vm名 というディレクトリ以下に cgroup の各種ファイルが出来,そこでリソース制限をします.

ところが新しいカーネル (上記で 2.6.32 の Plamo 以外) では,cgroup のサブシステムとして "Block I/O Controller" というものが追加されています.

これには問題 (?) があって,

The problem is probably the 'blkio' controller combined with the 'ns' controller. The 'blkio' controller will refuse to allow creation of any child cgroups. This will cause the libvirt warning you see below. It will also break the 'ns' cgroup, because that *requires* that you can create child cgroups when creating a new container.

https://www.redhat.com/archives/libvir-list/2010-October/msg01219.html

という風になり,新しいカーネルで cgroup ファイルシステムのオプションとして "defaults" という風に fstab に記述してマウントしている場合や blkio を指定している場合は,blkio が有効になって,

# tree -d /cgroup/
/cgroup/
├── 1454
├── 1456
└── libvirt

という風に libvirt 以下に階層構造が作れないため,リソース制限を行うための制御ディレクトリやファイルを作れません.

というわけで,メモリ制限など libvirt から cgroup の仕組みを使って行うリソース制限が効かない状態になっていたわけです.(debug ログ出力見てれば分かったはずだけど,出力多すぎで分からなかった >_<)

例えばこんな感じでサブシステムをずらずら書けば,ちゃんと動きます.(ns, memory, cpuset, device なんかは必須かな)

cgroup			/cgroup			cgroup	cpu,memory,devices,ns,cpuset,freezer,net_cls,cpuacct	0 0

スワップの問題

上記の blkio 問題が片付いても問題が残っているのは,blkio サブシステムのない 2.6.32 な Plamo でもリソース制限が効いていないことから分かります.

これは,

  <memory>65536</memory>

という定義をして "virsh --connect lxc:/// define hoge.xml" などと define すると,

<domain type='lxc'>
  <name>vm1</name>
  <uuid>3366d9b7-c655-2b8d-f4a0-db8b67617082</uuid>
  <memory>65536</memory>
  <currentMemory>65536</currentMemory>
        : (snip)

という定義が作製されます (/etc/libvirt/lxc 以下).

これでコンテナを start すると,上記の例だと cgroup のメモリ制限を行うファイルである /cgroup/libvirt/lxc/vm1/memory.limit_in_bytes ファイルには

# cat memory.limit_in_bytes
67108864

ときちんとした値が設定されます.しかーし,これは物理メモリの使用上限で,比較的新しいカーネルでは,この他に「物理メモリ+スワップ」の制限値を指定するファイルがあります.

# cat memory.memsw.limit_in_bytes 
9223372036854775807

ハイ,これで使用するメモリは青天井 (;_;).つまり物理メモリの使用量はきちっと 64MB 付近で切られていますが,それ以上に使った分は全部スワップへ.

# free
             total       used       free     shared    buffers     cached
Mem:       1025900     174984     850916          0       9540      52720
-/+ buffers/cache:     112724     913176
Swap:      2031612     251684    1779928

物理メモリの使用量は増えないんですが,Swap の数字だけどんどん増えていきました.

  • libvirt で memory.memsw.limit_in_bytes を設定する方法があれば良いわけですね.
  • lxc ツールキットの方は memory.limit_in_bytes と memory.memsw.limit_in_bytes の両方を設定すれば制限がかかりますね.