LXCで学ぶコンテナ入門 -軽量仮想化環境を実現する技術

第17回 LXCの構築・活用 [4] ― 一般ユーザによるLXCコンテナの利用

この記事を読むのに必要な時間:およそ 7 分

一般ユーザでのコンテナの起動

一般ユーザでコンテナを起動するには,ユーザ権限で書き込みできるcgroupが存在している必要があります。ディストリビューションによって,このようなcgroupが自動的に作成される場合も,自分で作成する必要がある場合もあります。

Ubuntu 14.04 LTS の場合

Ubuntu 14.04 LTSでは,第10回で説明したように,LXCコンテナのcgroupの管理はCGManagerというcgroup管理ソフトで行っています。このCGManagerが一般ユーザ権限のcgroupを準備してくれますので,lxc-createでコンテナが作成できれば,すぐにlxc-startでコンテナを起動できます。

あとでcgroupの制限が有効になっているのかを確認するために,ct01の設定ファイルにcgroupの設定を足しておきます。以下のような2行を追加しました。

$ grep cgroup .local/share/lxc/ct01/config 
lxc.cgroup.cpu.shares = 1000
lxc.cgroup.memory.limit_in_bytes = 512m

それでは起動しましょう。

$ lxc-ls -f
NAME  STATE    IPV4  IPV6  AUTOSTART  
------------------------------------
ct01  STOPPED  -     -     NO         
$ lxc-start -n ct01 -d
$ lxc-ls -f
NAME  STATE    IPV4        IPV6  AUTOSTART  
------------------------------------------
ct01  RUNNING  10.0.3.218  -     NO         

無事実行できましたね。このようにUbuntuだと簡単に一般ユーザ権限でコンテナが実行できます。

この起動したコンテナできちんとcgroupを使ったリソース制限が効いているか確認するために,このコンテナ用のcgroupがどのように作られているか見てみましょう。

CGManagerは新しいマウント名前空間を作成してその中でcgroupfsをマウントしますので,そちらの様子を見てみましょう。他の名前空間に入ってコマンドを実行するにはnsenterコマンドを使うと便利です。しかしUbuntu 14.04 LTSのutil-linuxにはnsenterコマンドは含まれませんので,ここでは他の環境から持ってきて実行しています。

$ sudo ./nsenter -t `pgrep cgmanager` --mount -- \
> ls -F /run/cgmanager/fs/cpu/user/1000.user/3.session
cgroup.clone_children  cpu.cfs_period_us  cpu.stat       tasks
cgroup.event_control   cpu.cfs_quota_us   ct01/
cgroup.procs           cpu.shares     notify_on_release

ご覧のようにcgmanagerが作成したマウント名前空間内の/run/cgmanager/fs/cpu/user/1000.user/3.session以下にct01というディレクトリがあります。1000.user3.sessionはログインユーザやログインセッションによって変化します。

Ubuntu 14.04 LTSでは,以下の例のようにログイン時にPAM経由でsystemd-logindによりユーザのログインセッション用のcgroupが/sys/fs/cgroup/systemd/user以下に作成されます。CGManagerはそのグループをそのまま使っているようです。

$ ls -ld /sys/fs/cgroup/systemd/user/1000.user/3.session/ (ホストOSの名前空間で実行)
drwxr-xr-x 3 ubuntu ubuntu 0 Jan  6 17:01 /sys/fs/cgroup/systemd/user/1000.user/3.session/

では,先に設定したcgroupの設定がct01用のcgroupで反映されているか確認してみましょう。

$ sudo ./nsenter -t `pgrep cgmanager` --mount -- \
> cat /run/cgmanager/fs/cpu/user/1000.user/3.session/ct01/cpu.shares
1000
$ sudo ./nsenter -t `pgrep cgmanager` --mount -- \
> cat /run/cgmanager/fs/memory/user/1000.user/3.session/ct01/memory.limit_in_bytes
536870912

確かに先に設定した通りの値になっています。

以上のように一般ユーザで作成したコンテナがきちんと起動し,cgroupによるリソース制限も有効なのが確認できました。

作成されたコンテナは先に述べたようにアクセスできるユーザやパスワードの設定がされていませんので,必要であればlxc-attachコマンドを使って設定したり,必要なパッケージをインストールしたりしましょう。

一般ユーザで操作可能なcgroup

Plamo Linuxや,その他ログイン時にユーザ権限で操作可能なcgroupが作られないディストリビューションでは 第14回で紹介したように,ユーザが書き込めるcgroupを作成するためにinitスクリプトを作成して対応します。

$ cat /etc/rc.d/init.d/cgroups-mount-user
#!/bin/sh
# mount cgroup filesystems per subsystem for user name space

USERNS="taro hanako"

start() {
  echo 1 > /sys/fs/cgroup/memory/memory.use_hierarchy
  for c in /sys/fs/cgroup/* ; do
    echo 1 > $c/cgroup.clone_children
    for u in $USERNS ; do
      mkdir -p $c/$u
      chown -R $u $c/$u
      if [ ${c##*/} == cpuset ] ; then
        echo 0 > $c/$u/cpuset.cpus
        echo 0 > $c/$u/cpuset.mems
      fi
    done
  done
}

stop() {
  :
}

case "$1" in
start)
  start
  ;;
stop)
  stop
  ;;
restart)
  stop
  start
  ;;
*)
  echo $"Usage: $0 {start|stop|restart}"
  exit 1
  ;;
esac

このスクリプトは

  • memoryサブシステムで階層構造が使えるように設定する
  • cpusetサブシステムで親のcgroupの設定を子に引き継ぐように設定する
  • ユーザ名のcgroupを作成し,chownする
  • cpusetサブシステムが使えるようにcpuset.cpusとcpuset.memsに初期値を入れる

という操作を指定したユーザごとに実行しています。

ユーザ用のcgroupが準備できたら,lxc-startを実行するシェルで以下のように実行し,シェルのPIDをtasksに登録します。

$ for d in /sys/fs/cgroup/*/${USER}
> do
> echo $$ > $d/tasks
> done

これで準備ができたのでコンテナを開始します。

$ lxc-ls -f
NAME      STATE    IPV4  IPV6  GROUPS  AUTOSTART  
------------------------------------------------
ct01      STOPPED  -     -     -       NO         
$ lxc-start -n ubuntu01
$ lxc-ls -f
NAME      STATE    IPV4          IPV6  GROUPS  AUTOSTART  
--------------------------------------------------------
ct01      RUNNING  10.0.100.188  -     -       NO         

まとめ

今回は一般ユーザでコンテナを作成し,実行する設定や方法を説明しました。

Ubuntuだと各ユーザのサブIDを設定し,ネットワーク用の設定ファイルを作成し,ユーザ用のデフォルト設定ファイルを作成するだけで簡単に一般ユーザでコンテナが起動できました。

一般ユーザによるコンテナの話題は今回で終わりです。次回からは,LXCがコンテナイメージを置くためにサポートしているストレージバックエンドの話題を取り上げ,便利にコンテナを使う方法を紹介していきたいと思います。

著者プロフィール

加藤泰文(かとうやすふみ)

2009年頃にLinuxカーネルのcgroup機能に興味を持って以来,Linuxのコンテナ関連の最新情報を追っかけたり,コンテナの勉強会を開いたりして勉強しています。英語力のない自分用にLXCのmanページを日本語訳していたところ,あっさり本家にマージされてしまい,それ以来日本語訳のパッチを送り続けています。

Plamo Linuxメンテナ

Twitter:@ten_forward
技術系のブログ:http://tenforward.hatenablog.com/