TenForward

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

lmctfy を試す (1)

カーネル/VM Advent Calendar 2013 - Qiita のために書いたエントリです.(1) としましたが,(2) があるかどうかは未定です ^^;

既にこのカーネル/VM Advent Calendar] はすごいネタが集まっているので,私も頑張って Namespace の実装の話でも書こうかと思っていたのですが,良く考えると私にはそのような知識も実力もないので,実力に合ったお気楽なお試しのお話を書こうと思います.濃い話は他のかたにお任せします!

lmctfy とは?

さて,lmctfy の話です.あまり情報がないのと,私も表面的な情報を追っただけなので,間違いの指摘は歓迎です!!

lmctfy は Google の開発しているオープンソースのコンテナスタックです.公式ドキュメントに lem-kut-fee と発音するとありますね.「レムクットフィー」?

どちらかというと (現時点では) アプリケーションコンテナで使うことを想定して作られているように思います.最近コンテナ界隈? では docker が話題ですね.docker がバックエンドに LXC を使っていますが,レイヤー的にはその LXC と同じ所に位置するものだと思います.C++ のライブラリと簡単な CLI が実装されています.

現時点では,lmctfy は cgroup の限られたサブシステムに対する制限が出来るだけですが,LXC がどちらかというと名前空間 (Namespace) を使ったコンテナ実装という視点から実装されていて,現時点では cgroup に関しては cgroupfs のファイル名とそこに書く値をそのまま設定ファイルに書くという風なことになっていますが,lmctfy はユーザが cgroupfs の細かい点を理解していなくても,やりたいことが実現できるようなインターフェースを持つことを目的にしているようです.(もちろん将来的には名前空間もサポート予定のようです)

また,1 台のマシンを高密度に利用することを目的としていて,オーバーコミット前提でうまくサーバのリソースを活用できるようにするようです.この辺りは cgroup の階層構造を使う感じなのかな,となんとなく使い方なんかを眺めていて思いました.

この辺は公式ページの説明以外に,以下の質問に対する回答がよくまとまっているように思います.

あと先の Linux Plumbers での発表資料もありますね.

lmctfy のビルド

これは公式リポジトリの "Getting Started" を見れば書いてありますね.ここで注意が必要ですが,コンパイラは g++ の 4.7 以上が必要のようです.4.6 では make はエラーで通りませんし,LLVM も軽く試してみましたがエラーになりました (こちらは色々オプション工夫したらいけるのかも?).(なので Plamo Linux で試せなかった!)

他に,

が必要です.手元では Ubuntu 13.10 で試してみました.

  1. まず必要な諸々をパッケージインストールします (ここは適当なので不要なものも入ってるかも?).
    # apt-get install build-essential pkg-config libgflags2 libgflags-dev protobuf-compiler libprotoc-dev
  2. re2 はパッケージが見当たらないのでコンパイルしました.
    # wget https://re2.googlecode.com/files/re2-20131024.tgz
    # tar xvf re2-20131024.tgz
    # cd re2/
    # make
    # make install
  3. lmctfy とライブラリをコンパイル
    # git clone https://github.com/google/lmctfy.git
    # cd lmctfy
    # make -j3 lmctfy
    # make -j3 liblmctfy.a
    # cp bin/lmctfy/cli/lmctfy /usr/local/bin

初期化

lmctfy を使う前の準備が必要です.これは 2 つ方法があります.

  1. なんらかの方法でサブシステム毎にツリーを持つように cgroupfs をあらかじめ mount しておく.既に使える cgroupfs が存在する場合は,lmctfy が適当にそれを使ってくれます.
    • Ubuntu だと LXC と一緒に入る cgroup-lite パッケージを入れると楽ですね.
    • libcgroup なんかでも可能な気がします (未確認)
    • もちろん自分で mount コマンドでマウントしても
  2. lmctfy init コマンドで初期設定を行う.これで lmctfy が使えるように cgroupfs をマウントしてくれます.

cgroup は将来的には現状の Ubuntu + LXC のようなサブシステム毎のツリーでなく,単一のツリーで管理されるようになるように開発が進められているようですが,現時点では lmctfy はサブシステム毎に別のツリーが必要になるようです

さて,1 の方法だと起動時に自動的に cgroupfs がマウントされていますので,あとは lmctfy init "" と実行するだけです.

root@lmctfy01:~# apt-get install cgroup-lite
root@lmctfy01:~# cd /sys/fs/cgroup/
root@lmctfy01:/sys/fs/cgroup# ls
blkio  cpuacct  devices  hugetlb  perf_event
cpu    cpuset   freezer  memory   systemd
root@lmctfy01:/sys/fs/cgroup# cd cpu
root@lmctfy01:/sys/fs/cgroup/cpu# ls
cgroup.clone_children  cpu.cfs_period_us  cpu.shares         tasks
cgroup.event_control   cpu.cfs_quota_us   cpu.stat
cgroup.procs           cpu.rt_period_us   notify_on_release
cgroup.sane_behavior   cpu.rt_runtime_us  release_agent
root@lmctfy01:/sys/fs/cgroup/cpu# lmctfy init "" (←ここ!! 初期化)
root@lmctfy01:/sys/fs/cgroup/cpu# ls
batch                  cgroup.sane_behavior  cpu.rt_runtime_us  release_agent
cgroup.clone_children  cpu.cfs_period_us     cpu.shares         tasks
cgroup.event_control   cpu.cfs_quota_us      cpu.stat
cgroup.procs           cpu.rt_period_us      notify_on_release
root@lmctfy01:/sys/fs/cgroup/cpu# ls batch/
cgroup.clone_children  cpu.cfs_period_us  cpu.rt_runtime_us  notify_on_release
cgroup.event_control   cpu.cfs_quota_us   cpu.shares         tasks
cgroup.procs           cpu.rt_period_us   cpu.stat

2 の方法だと init コマンドに cgroupfs のマウント情報を書きます.これは protobuf の書式? 現状,以下の 5 つのサブシステム全部を指定しないとエラーになります.ここの指定方法は include/lmctfy.proto を見ると参考になります.

lmctfy init "
  cgroup_mount:{
    mount_path:'/sys/fs/cgroup/cpu'
    hierarchy:CGROUP_CPU
    hierarchy:CGROUP_CPUACCT
  }
  cgroup_mount:{
    mount_path:'/sys/fs/cgroup/cpuset' hierarchy:CGROUP_CPUSET
  }
  cgroup_mount:{
    mount_path:'/sys/fs/cgroup/freezer' hierarchy:CGROUP_FREEZER
  }
  cgroup_mount:{
    mount_path:'/sys/fs/cgroup/memory' hierarchy:CGROUP_MEMORY
  }"

いずれも cpu,cpuacct,cpuset cgroup サブシステム内に batch というグループが作られてますね.(init で設定を指定した場合も同じ.各サブシステムが別々のディレクトリにマウントされて,その中に batch グループが作られる) memory, freezer は作られていません.

コンテナ操作

まず入れ物 (コンテナ) を準備して,その中で実行するコマンドを指定するという感じですね.コンテナ名はパスのように与えるようです.以下ではルートコンテナ (/) 以下に test01 というコンテナを作成しています (/test01).コンテナの中にコンテナを入れたりして,リソース制御をうまくやろういう感じですかね.例えば /test01/test01_01 みたいにサブコンテナを作成したりするようです.

  1. 作成.CPU の制限を 1 秒間に 100ms だけ使用に設定しています.ここの指定も init の指定の所と同様に include/lmctfy.proto を見ると参考になります.
    root@lmctfy01:~# lmctfy create /test01 "cpu:{ max_limit:100 }"
  2. 確認
    root@lmctfy01:~# lmctfy list containers /
    name="/test01"
  3. test01 が /sys/fs/cgroup/cpu/batch/ 以下に出来ています.
    root@lmctfy01:~# ls -F /sys/fs/cgroup/cpu/batch/
    cgroup.clone_children cpuacct.usage_percpu cpu.shares
    cgroup.event_control cpu.cfs_period_us cpu.stat
    cgroup.procs cpu.cfs_quota_us notify_on_release
    cpuacct.stat cpu.rt_period_us tasks
    cpuacct.usage cpu.rt_runtime_us test01/
  4. 制限値を確認してみます.CPU の制限の場合 CFS bandwidth controller で行われるようです.ちゃんと設定通り動くようになっていますね.タスクは登録されていません.
    root@lmctfy01:~# cat /sys/fs/cgroup/cpu/batch/test01/cpu.cfs_period_us 
    250000
    root@lmctfy01:~# cat /sys/fs/cgroup/cpu/batch/test01/cpu.cfs_quota_us
    25000
    root@lmctfy01:~# cat /sys/fs/cgroup/cpu/batch/test01/tasks
  5. ここでコンテナ内でプロセスを動作させます.cgroup ご存知の方なら分かるでしょうが,単にコマンドを実行して tasks に登録するという動きをします.
    root@lmctfy01:~# lmctfy run /test01 /bin/bash
    root@lmctfy01:~# cat /sys/fs/cgroup/cpu/batch/test01/tasks
    2029
    2030
    root@lmctfy01:~# ps aux | grep -E "(2029|2030)"
    root 2029 0.0 0.0 4440 612 pts/0 S 15:41 0:00 /bin/sh -c /bin/bash
    root 2030 0.0 0.1 19768 2000 pts/0 S+ 15:41 0:00 /bin/bash
    root 2046 0.0 0.0 8172 928 pts/1 S+ 15:43 0:00 grep --color=auto -E (2029|2030)
    root@lmctfy01:~# lmctfy run /test01 /bin/bash
  6. プロセスを終了させると,当然 tasks からは消えます.これは lmctfy と関係ない普通の cgroup の動きですね.
    root@lmctfy01:~# exit
    exit
    root@lmctfy01:~# cat /sys/fs/cgroup/cpu/batch/test01/tasks
  7. 削除すると,cgroupfs にあった test01 ディレクトリは消滅していますね.
    root@lmctfy01:~# lmctfy destroy /test01
    root@lmctfy01:~# ls -F /sys/fs/cgroup/cpu/batch/
    cgroup.clone_children cpuacct.usage_percpu cpu.shares
    cgroup.event_control cpu.cfs_period_us cpu.stat
    cgroup.procs cpu.cfs_quota_us notify_on_release
    cpuacct.stat cpu.rt_period_us tasks
    cpuacct.usage cpu.rt_runtime_us

以上が CPU リソースの制限を行うコンテナを作成して,タスクを登録してみた例でした.

現時点では CPU とメモリの制限をする機能しか実装されてないようですね.メモリの場合も同様に動きましたが,

  • メモリ制限を行うコンテナを作ると,メモリサブシステム用のディレクトリには batch ディレクトリはなく,直下にコンテナ名のディレクトリが作成されていました.batch がある意味はなんとなくわかりますが,実際どう使うのかはわかりませんね.
  • 指定した CPU, Memory 以外に freezer 以下にも同じコンテナ名のディレクトリが作成されます.

以上,単に使ってみただけの軽い内容でしたが,このあときっともっとすごい人が API 使ったり,色々内部を教えてくれたりすると思います! それを期待して簡単に紹介してみました.楽しみですね.

(おまけ) LXC 側の cgroup 関連の動き

今後の cgroup の変更なども見越して,LXC 側でも cgroup の管理の仕組みを開発しようという話が起こっています.以下にページとリポジトリがありますので,興味のある方はご覧になってみてはいかがでしょう.(私はまだ中身は見てません)

(おまけ2) コンテナの勉強会

既に 2 回開催しているコンテナ型の仮想化に関係する (コンテナ型データセンターとか貨物輸送のコンテナは扱いません! :-) 勉強会の第 3 回の準備をそろそろ始めようと思っています.第 3 回は大阪で開催予定ですので,興味のある方はこのブログなんかをチェックしておいてください.発表者も募集しますので,発表したい方はご連絡ください!!