前回は一般ユーザでコンテナを起動する際に利用するカーネルのユーザ名前空間について紹介しました。
今回はそのユーザ名前空間を使って実現している、一般ユーザによるLXCコンテナの作成や起動の方法について説明します。一般ユーザによるコンテナの利用については第14回にPlamo Linuxでの例を簡単に紹介しています。今回はUbuntu 14.04 LTSを使って改めて整理して説明すると同時に、他のディストリビューションの場合の説明も行います。
一般ユーザでコンテナを利用できるディストリビューション
第16回でユーザ名前空間で複数のIDのマッピングを行うためにshadowに導入された「サブID」を紹介しました。
一般ユーザでLXCコンテナを利用する場合は、ユーザに対して「サブID」を設定し、サブIDを使ってユーザ名前空間用のマッピングを設定できる環境が必要です。
Ubuntu 14.04 LTS以降は当然この対応が済んだshadowを使っていますし、第14回で紹介したようにPlamo Linuxの現在のバージョンである5.3でもサブIDの設定が可能になっています。
筆者は、以上の2つのディストリビューションをコンテナホストとした場合で、一般ユーザでコンテナの利用ができることを確認しています。他に、確認はしていませんが、shadowのバージョンを見る限りではArchとDebianのjessie以上で動きそうです。
一般ユーザでコンテナを利用する場合のOSでの準備
一般ユーザでLXCコンテナを利用する場合は、先に説明したようにサブIDの設定が必要です。
Ubuntu 14.04 LTS以上ではユーザを追加するたびにサブIDが自動的に設定されますのでこの作業を行う必要はありません。
この例はubuntu
というユーザをインストール時に追加したときに設定され
たサブIDです。100000から65536個のIDがubuntu
で使えるように設定されています。
これとは別の範囲をサブIDとして設定したい場合や、サブIDが使える他のディストリビューションで設定する場合は第16回で説明したようにusermod
コマンドを使います。
-v
はUIDのサブIDを、-w
はGIDのサブIDの範囲を設定します。
UbuntuのLXCパッケージ使用時の各種パス
一般ユーザでLXCを使ってコンテナを利用する際の設定ファイルなどの場所について第8回で示したのと同様の表を使って紹介しましょう。
ファイル/ディレクトリ |
root権限の時 |
一般ユーザの時 |
システム設定ファイル |
/etc/lxc/lxc.conf |
~/.config/lxc/lxc.conf |
コンテナのデフォルト設定ファイル |
/etc/lxc/default.conf |
~/.config/lxc/default.conf |
テンプレートファイルの置き場所 |
/usr/share/lxc/config |
(root権限の場合と同じ) |
コンテナ作成時のキャッシュの置き場所 |
/var/cache/lxc |
~/.cache/lxc |
コンテナの保存場所 |
/var/lib/lxc |
~/.local/share/lxc |
ログファイルの出力場所 |
/var/log/lxc |
~/.local/share/lxc/(コンテナ名) |
一般ユーザが使うネットワークインターフェースの設定ファイル |
(なし) |
/etc/lxc/lxc-usernet |
root権限の場合のパスは各ディストリビューションのコンパイル時のオプションに依存します。一方で一般ユーザの場合は、システム設定ファイルでデフォルト値を変更しない限りは、どのディストリビューションでも図のようになるはずです。
テンプレートファイルに関しては、root権限用、一般ユーザ用という区別はなく同じテンプレートを使用しますので、一般ユーザ用のテンプレート置き場は存在しません。
一般ユーザでコンテナを利用する場合のLXCの設定
ネットワークインターフェースの設定
第16回で説明したように、一般ユーザでコンテナを扱うためにユーザ名前空間を作成すると、名前空間内でネットワークインターフェースを作成するといった特権が必要な操作は名前空間内のrootユーザで行えます。
現時点では一般ユーザ権限で起動したコンテナと外部の通信をする際は第6回で説明したvethインターフェースを使う必要があります。
コンテナがこのvethインターフェースを使って外部と通信するためには、vethインターフェースを作成した際にできるペアのインターフェースの片側をホストの名前空間に割り当てますので、その際ににはホストOS上での特権が必要となります。
一般ユーザでこの特権が必要な操作をするために、LXCではlxc-user-nic
というプログラムを使用します。
このlxc-user-nic
はUbuntuでは/usr/lib/x86_64-linux-gnu/lxc/
にインストールされています(amd64版)。以上のようにsetuidすることにより一般ユーザでも特権が必要なホストOS上でvethインターフェースを扱う操作ができるようになっています
このプログラムは、あらかじめホストOSの管理者が設定しておく/etc/lxc/lxc-usernet
というファイルを参照して、ユーザが作成できるインターフェースの数と、作成したインターフェースをホスト上のどのブリッジに接続するかを決めます。
lxc-usernet
ファイルは以下のような書式で1行に1ユーザの設定を記述します。
たとえば、ubuntu
ユーザがvethインターフェースを10個まで作成でき、作成したインターフェースはlxcbr0
に接続する場合は以下のようになります。
現時点ではインターフェースのタイプはveth以外は指定できません。
各ユーザのLXCの設定ファイル
それでは一般ユーザでコンテナを起動するためのLXCの準備をしていきましょう。
第14回でも簡単に方法に触れていますが、ここでもう一度じっくり手順を追ってみます。
まずは設定ファイルを置くディレクトリがない場合は作成しましょう。
Ubuntuではシステム設定ファイルであるlxc.conf
はデフォルトでは使われていません。コンテナイメージが置かれる場所を変えたいなど、必要があれば~/.config/lxc/lxc.conf
ファイルを作成して設定を書いておきましょう。設定についてはman lxc.system.conf
をご覧ください。
次はコンテナのデフォルト設定ファイルであるdefault.conf
です。これはLXCパッケージをインストールしたときに作成されますので、それを元に一般ユーザでコンテナを起動する際に必要な設定を追加すれば良いでしょう。
ここで追加する設定は/etc/subuid
、/etc/subgid
で行ったようなユーザ名前空間を使うときのマッピング情報です。この設定はlxc.id_map
です。
この設定は4つのフィールドから成っています。最初から順に以下のようになります。
- uidのマッピングの場合は"u"、gidのマッピングの場合は"g"の一文字
- あとの3つは第16回で紹介した
/proc/[PID]/uid_map
と/proc/[PID]/gid_map
と同じ書式
たとえばUIDをマッピングする場合で、コンテナ内のrootをコンテナ外で100000のUIDにマッピングし、コンテナ内で65536個のUIDを使う場合は
となります。
GIDにも同様のマッピングをすると、~/.config/lxc/default.conf
は以下のようになります。
コンテナの作成
一般ユーザのコンテナイメージと設定ファイルは、システム設定ファイルで場所を設定していない場合は~/.local/share/lxc
にコンテナ名のディレクトリを作成してそのディレクトリ以下に置かれます。
このディレクトリ(~/.local/share/lxc
)がない場合はコンテナ作成時に自動的に作成されますので、設定ファイルの準備ができたら早速コンテナを作成してみましょう。
一般ユーザ権限の場合は、第7回、第8回で紹介したダウンロードテンプレートを使います。
lxc-ubuntu
、lxc-centos
などの各ディストリビューション用のテンプレートは使えません。これは、テンプレート内でユーザ名前空間内のrootが許可されていない処理を実行する場合が多いためです。
一般ユーザでコンテナを作成する場合もrootで実行する場合と同じようにlxc-create
を使います。使い方もrootで実行する場合と同じです。
以上はUbuntu Trusty(amd64)のコンテナイメージをダウンロードして作成た例です。
作成されたコンテナディレクトリを確認しておきましょう。
以上のようにroot権限で/var/lib/lxc
以下に作成されたコンテナと同様に作成されています。
設定ファイルは以下のようになっています。
root権限で作成したコンテナと一般ユーザで作成したコンテナの違いはubuntu.userns.conf
をincludeしている部分です。これは一般ユーザでコンテナを作成する際に使用する共通の設定をまとめたファイルで、ディストリビューションごとに準備されています。
たとえばubuntuの場合以下のような内容です。デバイスファイルを作成するなどのユーザ名前空間内では実行できない処理の代わりに、ホストOSのファイルをバインドマウントする設定などが書かれています。
一般ユーザでのコンテナの起動
一般ユーザでコンテナを起動するには、ユーザ権限で書き込みできる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行を追加しました。
それでは起動しましょう。
無事実行できましたね。このようにUbuntuだと簡単に一般ユーザ権限でコンテナが実行できます。
この起動したコンテナできちんとcgroupを使ったリソース制限が効いているか確認するために、このコンテナ用のcgroupがどのように作られているか見てみましょう。
CGManagerは新しいマウント名前空間を作成してその中でcgroupfsをマウントしますので、そちらの様子を見てみましょう。他の名前空間に入ってコマンドを実行するにはnsenterコマンドを使うと便利です。しかしUbuntu 14.04 LTSのutil-linuxにはnsenterコマンドは含まれませんので、ここでは他の環境から持ってきて実行しています。
ご覧のようにcgmanagerが作成したマウント名前空間内の/run/cgmanager/fs/cpu/user/1000.user/3.session
以下にct01
というディレクトリがあります。1000.user
や3.session
はログインユーザやログインセッションによって変化します。
Ubuntu 14.04 LTSでは、以下の例のようにログイン時にPAM経由でsystemd-logind
によりユーザのログインセッション用のcgroupが/sys/fs/cgroup/systemd/user
以下に作成されます。CGManagerはそのグループをそのまま使っているようです。
では、先に設定したcgroupの設定がct01
用のcgroupで反映されているか確認してみましょう。
確かに先に設定した通りの値になっています。
以上のように一般ユーザで作成したコンテナがきちんと起動し、cgroupによるリソース制限も有効なのが確認できました。
作成されたコンテナは先に述べたようにアクセスできるユーザやパスワードの設定がされていませんので、必要であればlxc-attach
コマンドを使って設定したり、必要なパッケージをインストールしたりしましょう。
一般ユーザで操作可能なcgroup
Plamo Linuxや、その他ログイン時にユーザ権限で操作可能なcgroupが作られないディストリビューションでは
第14回で紹介したように、ユーザが書き込めるcgroupを作成するためにinitスクリプトを作成して対応します。
このスクリプトは
- memoryサブシステムで階層構造が使えるように設定する
- cpusetサブシステムで親のcgroupの設定を子に引き継ぐように設定する
- ユーザ名のcgroupを作成し、chownする
- cpusetサブシステムが使えるようにcpuset.cpusとcpuset.memsに初期値を入れる
という操作を指定したユーザごとに実行しています。
ユーザ用のcgroupが準備できたら、lxc-start
を実行するシェルで以下のように実行し、シェルのPIDをtasks
に登録します。
これで準備ができたのでコンテナを開始します。
まとめ
今回は一般ユーザでコンテナを作成し、実行する設定や方法を説明しました。
Ubuntuだと各ユーザのサブIDを設定し、ネットワーク用の設定ファイルを作成し、ユーザ用のデフォルト設定ファイルを作成するだけで簡単に一般ユーザでコンテナが起動できました。
一般ユーザによるコンテナの話題は今回で終わりです。次回からは、LXCがコンテナイメージを置くためにサポートしているストレージバックエンドの話題を取り上げ、便利にコンテナを使う方法を紹介していきたいと思います。