「Linux コンテナ」の版間の差分
(同期) |
(同期) |
||
17行目: | 17行目: | ||
'''LinuX Containers''' ('''LXC''') はオペレーティングシステムレベルの仮想化手法であり、一つのコントロールホスト (LXC ホスト) で独立した Linux システム (コンテナ) を複数動作させることができます。仮想マシンではありませんが、CPU やメモリ、ブロック I/O、ネットワークなどが個別に用意された仮想環境として使えます。LXC は LXC ホストの Linux カーネルによる [[cgroups]] 機能によって賄われています。chroot に似ていますが、より強力な分離を実現します。 |
'''LinuX Containers''' ('''LXC''') はオペレーティングシステムレベルの仮想化手法であり、一つのコントロールホスト (LXC ホスト) で独立した Linux システム (コンテナ) を複数動作させることができます。仮想マシンではありませんが、CPU やメモリ、ブロック I/O、ネットワークなどが個別に用意された仮想環境として使えます。LXC は LXC ホストの Linux カーネルによる [[cgroups]] 機能によって賄われています。chroot に似ていますが、より強力な分離を実現します。 |
||
− | LXC の代わりとして [[systemd-nspawn]] や [[docker]] でもコンテナを使うことができます。 |
+ | LXC の代わりとして [[systemd-nspawn]] や [[docker]]、{{Pkg|rkt}} でもコンテナを使うことができます。 |
+ | |||
+ | == 特権コンテナと非特権コンテナ == |
||
+ | LXC は特権または非特権で動作するように設定することができます。 |
||
+ | |||
+ | 一般的に、非特権コンテナは特権コンテナよりも安全だとされています [https://www.stgraber.org/2014/01/17/lxc-1-0-unprivileged-containers]。非特権コンテナでは分離の程度が原理上増すからです。非特権コンテナではコンテナの root の UID をホストの root 以外の UID にマッピングすることで、コンテナの中からホスト環境に影響を及ぼすことを難しくします。たとえ攻撃者がコンテナから脱獄しても、ホスト側では攻撃者に権限がありません。 |
||
+ | |||
+ | 現在 Arch のパッケージでは特権コンテナは最初からサポートしています。非特権コンテナはカーネル設定を行わないと利用できません。Arch の {{pkg|linux}} カーネルでは通常ユーザーでユーザー名前空間が無効になっているためです。この記事では特権・非特権両方のコンテナの情報を載せていますが、非特権を使うには設定が必要です。 |
||
+ | |||
+ | === 非特権コンテナの例 === |
||
+ | |||
+ | UID マッピングの能力を説明するために、非特権コンテナで以下のコマンドを実行したときの出力を考えてみましょう。{{ic|ps}} の出力でコンテナ化されたプロセスの所有者が同じくコンテナ化された root ユーザーとなっていることが確認できます: |
||
+ | |||
+ | [root@unprivileged_container /]# ps -ef | head -n 5 |
||
+ | UID PID PPID C STIME TTY TIME CMD |
||
+ | root 1 0 0 17:49 ? 00:00:00 /sbin/init |
||
+ | root 14 1 0 17:49 ? 00:00:00 /usr/lib/systemd/systemd-journald |
||
+ | dbus 25 1 0 17:49 ? 00:00:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation |
||
+ | systemd+ 26 1 0 17:49 ? 00:00:00 /usr/lib/systemd/systemd-networkd |
||
+ | |||
+ | ホスト側では、コンテナ化された root プロセスはマッピングされたユーザー (ID>100000) で動作します。ホストの root ユーザーではありません: |
||
+ | [root@host /]# lxc-info -Ssip --name sandbox |
||
+ | State: RUNNING |
||
+ | PID: 26204 |
||
+ | CPU use: 10.51 seconds |
||
+ | BlkIO use: 244.00 KiB |
||
+ | Memory use: 13.09 MiB |
||
+ | KMem use: 7.21 MiB |
||
+ | |||
+ | [root@host /]# ps -ef | grep 26204 | head -n 5 |
||
+ | UID PID PPID C STIME TTY TIME CMD |
||
+ | 100000 26204 26200 0 12:49 ? 00:00:00 /sbin/init |
||
+ | 100000 26256 26204 0 12:49 ? 00:00:00 /usr/lib/systemd/systemd-journald |
||
+ | 100081 26282 26204 0 12:49 ? 00:00:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation |
||
+ | 100000 26284 26204 0 12:49 ? 00:00:00 /usr/lib/systemd/systemd-logind |
||
== セットアップ == |
== セットアップ == |
||
=== 必要なソフトウェア === |
=== 必要なソフトウェア === |
||
− | + | {{Pkg|lxc}} と {{Pkg|arch-install-scripts}} パッケージをインストールしてください。 |
|
+ | ==== 非特権コンテナのサポートを有効化 (任意) ==== |
||
− | 使用中のカーネルがコンテナを実行できるように正しく設定されているか確認: |
||
+ | 非特権コンテナを使いたい場合、設定を行う必要があります。 |
||
− | $ lxc-checkconfig |
||
+ | まず、カーネルがユーザー名前空間をサポートしていなければなりません。セキュリティへの懸念から、デフォルトの Arch カーネルではユーザー名前空間は ''root'' ユーザーでしか有効になりません。非特権コンテナを使うには {{ic|CONFIG_USER_NS}} が有効になったカーネルを使う必要があります: |
||
− | セキュリティに配慮して、デフォルトの Arch カーネルでは、非特権ユーザーではコンテナを実行できないようになっています。そのため、上記のコマンドを実行すると "User namespaces" の状態が '''missing''' になっているのが確認できます。詳しくは {{Bug|36969}} を見て下さい。 |
||
+ | |||
+ | * {{Pkg|linux}} (v4.14.5 以上) または {{Pkg|linux-hardened}} を使用する場合、非特権コンテナは ''root'' でのみ起動できます。 |
||
+ | * {{Pkg|linux}} (v4.14.5 以上) または {{Pkg|linux-hardened}} を使用して ''sysctl'' の {{ic|kernel.unprivileged_userns_clone}} 設定を有効にすると通常ユーザーで非特権コンテナを起動できます。{{ic|<nowiki>sysctl kernel.unprivileged_userns_clone=1</nowiki>}} で現在のセッションにおいてのみ有効にすることができ、{{man|5|sysctl.d}} で永続的に設定することも可能です。 |
||
+ | * {{AUR|linux-userns}} または {{AUR|linux-lts-userns}} パッケージを使用する。どちらのパッケージも {{ic|CONFIG_USER_NS}} が有効になっています。後者は長期サポート版です。 |
||
+ | * {{ic|CONFIG_USER_NS}} を有効にして自分でカスタムカーネルをコンパイル・インストールする。カスタムカーネルのコンパイルについては[[カーネル/コンパイル/Arch Build System]] を見てください。 |
||
+ | |||
+ | 次に、{{ic|/etc/lxc/default.conf}} に以下の行を記述します: |
||
+ | lxc.idmap = u 0 100000 65536 |
||
+ | lxc.idmap = g 0 100000 65536 |
||
+ | |||
+ | 最後に、{{ic|/etc/subuid}} と {{ic|/etc/subgid}} を作成してコンテナを実行するユーザーのコンテナ化する uid/gid のペアを入力してください。以下は root ユーザーの場合の例です: |
||
+ | |||
+ | {{hc|/etc/subuid|<nowiki> |
||
+ | root:100000:65536 |
||
+ | </nowiki>}} |
||
+ | |||
+ | {{hc|/etc/subgid|<nowiki> |
||
+ | root:100000:65536 |
||
+ | </nowiki>}} |
||
=== ホストネットワークの設定 === |
=== ホストネットワークの設定 === |
||
78行目: | 131行目: | ||
=== コンテナの作成 === |
=== コンテナの作成 === |
||
− | {{ic|/usr/share/lxc/templates}} からコンテナ化するディストロに合わせてテンプレートを選択してください。Arch 以外のディストロをコンテナに入れたい場合、ディストロによってホストにパッケージを追加でインストールする必要があります: |
+ | 特権コンテナの場合、{{ic|/usr/share/lxc/templates}} からコンテナ化するディストロに合わせてテンプレートを選択してください。Arch 以外のディストロをコンテナに入れたい場合、ディストロによってホストにパッケージを追加でインストールする必要があります: |
* Debian ベース: {{Pkg|debootstrap}}。 |
* Debian ベース: {{Pkg|debootstrap}}。 |
||
* Fedora ベース: {{AUR|yum}}。 |
* Fedora ベース: {{AUR|yum}}。 |
||
85行目: | 138行目: | ||
# lxc-create -n playtime -t /usr/share/lxc/templates/lxc-archlinux |
# lxc-create -n playtime -t /usr/share/lxc/templates/lxc-archlinux |
||
+ | 非特権コンテナを使いたい場合は {{ic|-t download}} を使用してイメージを選択してください。例: |
||
− | {{Tip|{{Pkg|haveged}} をインストールして {{ic|haveged.service}} を[[起動]]することで、セットアップ中にシステムエントロピーが作成されるまでシステムが停止するのを回避することができます。haveged を使用しない場合、GPG 鍵を作成するのにしばらく時間がかかるかもしれません。}} |
||
+ | # lxc-create -n playtime -t download |
||
+ | {{Tip| |
||
− | {{Tip|[[Btrfs]] を使っている場合 {{ic|-B btrfs}} を追加することでコンテナ化した rootfs を保存するための Btrfs サブボリュームを作成することができます。{{ic|lxc-clone}} コマンドを使ってコンテナを複製するときに便利です。[[ZFS]] ユーザーは {{ic|-B zfs}} が使えます。}} |
||
+ | * [[haveged]] をインストールして {{ic|haveged.service}} を[[起動]]することで、セットアップ中にシステムエントロピーが作成されるまでシステムが停止するのを回避することができます。haveged を使用しない場合、GPG 鍵を作成するのにしばらく時間がかかるかもしれません。 |
||
− | |||
− | + | * [[Btrfs]] を使っている場合 {{ic|-B btrfs}} を追加することでコンテナ化した rootfs を保存するための Btrfs サブボリュームを作成することができます。{{ic|lxc-clone}} コマンドを使ってコンテナを複製するときに便利です。[[ZFS]] ユーザーは {{ic|-B zfs}} が使えます。}} |
|
=== コンテナの設定 === |
=== コンテナの設定 === |
||
+ | |||
+ | 以下の例は特権コンテナと非特権コンテナどちらでも同じように使えます非特権コンテナの場合、{{ic|1=lxc.idmap = u 0 100000 65536}} and the {{ic|1=lxc.idmap = g 0 100000 65536}} values optionally defined in the [[#非特権コンテナのサポートを有効化 (任意)]]セクションで定義した {{ic|1=lxc.idmap = u 0 100000 65536}} や {{ic|1=lxc.idmap = g 0 100000 65536}} などの値がデフォルトで存在するはずです。 |
||
+ | |||
==== ネットワークの基本設定 ==== |
==== ネットワークの基本設定 ==== |
||
+ | |||
+ | {{Note|lxc-1:2.1.0-1 から、設定オプションの多くが変わりました。既存のコンテナはアップデートする必要があります。変更については [https://discuss.linuxcontainers.org/t/lxc-2-1-has-been-released/487 v2.1 リリースノート] を参照してください。}} |
||
+ | |||
プロセスが {{ic|/var/lib/lxc/CONTAINER_NAME/config}} に定義されたコンテナを使う場合、システムリソースは仮想化され分離されます。デフォルトでは、作成プロセスはネットワークサポートを省いた最小限のセットアップを作成します。以下はネットワークを設定する例です: |
プロセスが {{ic|/var/lib/lxc/CONTAINER_NAME/config}} に定義されたコンテナを使う場合、システムリソースは仮想化され分離されます。デフォルトでは、作成プロセスはネットワークサポートを省いた最小限のセットアップを作成します。以下はネットワークを設定する例です: |
||
101行目: | 161行目: | ||
## default values |
## default values |
||
− | lxc.rootfs = /var/lib/lxc/playtime/rootfs |
+ | lxc.rootfs.path = /var/lib/lxc/playtime/rootfs |
− | lxc. |
+ | lxc.uts.name = playtime |
lxc.arch = x86_64 |
lxc.arch = x86_64 |
||
lxc.include = /usr/share/lxc/config/archlinux.common.conf |
lxc.include = /usr/share/lxc/config/archlinux.common.conf |
||
## network |
## network |
||
− | lxc. |
+ | lxc.net.0.type = veth |
− | lxc. |
+ | lxc.net.0.link = br0 |
− | lxc. |
+ | lxc.net.0.flags = up |
− | lxc. |
+ | lxc.net.0.name = eth0 |
− | lxc. |
+ | lxc.net.0.hwaddr = ee:ec:fa:e9:56:7d |
+ | # uncomment the next two lines if static IP addresses are needed |
||
− | lxc.network.name = eth0 |
||
+ | # leaving these commented will imply DHCP networking |
||
− | |||
− | ## mounts |
||
− | ## specify shared filesystem paths in the format below |
||
− | ## make sure that the mount point exists on the lxc |
||
− | #lxc.mount.entry = /mnt/data/share mnt/data none bind 0 0 |
||
# |
# |
||
+ | #lxc.net.0.ipv4.address = 192.168.0.3/24 |
||
− | # if running the same Arch linux on the same architecture it may be |
||
+ | #lxc.net.0.ipv4.gateway = 192.168.0.1 |
||
− | # adventitious to share the package cache directory |
||
− | #lxc.mount.entry = /var/cache/pacman/pkg var/cache/pacman/pkg none bind 0 0 |
||
</nowiki>}} |
</nowiki>}} |
||
+ | |||
+ | {{Note|lxc.network.hwaddr エントリは任意です。省略した場合、自動的にランダムな MAC アドレスが作成されます。コンテナの MAC アドレスを定義することで DHCP サーバーからコンテナの NIC に常に同じ IP を割り当てることが可能になります。}} |
||
+ | |||
+ | ==== コンテナの中でマウント ==== |
||
+ | 特権コンテナの場合、ホストでディレクトリを選択してコンテナにバインドマウントすることができます。同一アーキテクチャをコンテナ化している場合にホストとコンテナで pacman のパッケージを共有するなどの使用方法が考えられます。また、共有ディレクトリとして使用することもできます。構文は以下の通りです: |
||
+ | |||
+ | lxc.mount.entry = /var/cache/pacman/pkg var/cache/pacman/pkg none bind 0 0 |
||
+ | |||
+ | {{Note|非特権コンテナを使っている場合、ホスト側でファイルシステムのパーミッションを修正しないと上記の設定は機能しません。}} |
||
==== Xorg プログラムの設定 (任意) ==== |
==== Xorg プログラムの設定 (任意) ==== |
||
ホストのディスプレイでプログラムを動かしたい場合、コンテナ化されたプログラムがホストのリソースにアクセスできるようにバインドマウントを定義する必要があります。{{ic|/var/lib/lxc/playtime/config}} に以下のセクションを追加してください: |
ホストのディスプレイでプログラムを動かしたい場合、コンテナ化されたプログラムがホストのリソースにアクセスできるようにバインドマウントを定義する必要があります。{{ic|/var/lib/lxc/playtime/config}} に以下のセクションを追加してください: |
||
## for xorg |
## for xorg |
||
− | ## fix overmounting see: https://github.com/lxc/lxc/issues/434 |
||
− | lxc.mount.entry = tmpfs tmp tmpfs defaults |
||
lxc.mount.entry = /dev/dri dev/dri none bind,optional,create=dir |
lxc.mount.entry = /dev/dri dev/dri none bind,optional,create=dir |
||
lxc.mount.entry = /dev/snd dev/snd none bind,optional,create=dir |
lxc.mount.entry = /dev/snd dev/snd none bind,optional,create=dir |
||
− | lxc.mount.entry = /tmp/.X11-unix tmp/.X11-unix none bind,optional,create=dir |
+ | lxc.mount.entry = /tmp/.X11-unix tmp/.X11-unix none bind,optional,create=dir,ro |
lxc.mount.entry = /dev/video0 dev/video0 none bind,optional,create=file |
lxc.mount.entry = /dev/video0 dev/video0 none bind,optional,create=file |
||
LXC のゲスト側に permission denied エラーが表示される場合、ホスト側で {{ic|xhost +}} を実行してゲストからホストのディスプレイサーバーに接続できるようにする必要があります。このようにディスプレイサーバーを開くことはセキュリティ上問題があるので注意してください。 |
LXC のゲスト側に permission denied エラーが表示される場合、ホスト側で {{ic|xhost +}} を実行してゲストからホストのディスプレイサーバーに接続できるようにする必要があります。このようにディスプレイサーバーを開くことはセキュリティ上問題があるので注意してください。 |
||
+ | |||
+ | {{Note|上記の設定は非特権コンテナでは機能しません。}} |
||
==== OpenVPN の設定 ==== |
==== OpenVPN の設定 ==== |
||
155行目: | 219行目: | ||
コンテナにログインするには: |
コンテナにログインするには: |
||
# lxc-console -n CONTAINER_NAME |
# lxc-console -n CONTAINER_NAME |
||
+ | |||
+ | ログイン時に pts/0 と lxc/tty1 が表示される場合: |
||
+ | # lxc-console -n CONTAINER_NAME -t 0 |
||
ログインしたら、他の linux システムと同じようにコンテナを扱って、root パスワードを設定し、ユーザーを作成、パッケージのインストールなどを行って下さい。 |
ログインしたら、他の linux システムと同じようにコンテナを扱って、root パスワードを設定し、ユーザーを作成、パッケージのインストールなどを行って下さい。 |
||
コンテナにアタッチ: |
コンテナにアタッチ: |
||
− | # lxc-attach -n CONTAINER_NAME |
+ | # lxc-attach -n CONTAINER_NAME --clear-env |
− | lxc-console とほぼ同じですが、自動的にログインを通り越してコンテナの中の root プロンプトにアクセスします。 |
+ | lxc-console とほぼ同じですが、自動的にログインを通り越してコンテナの中の root プロンプトにアクセスします。{{ic| --clear-env}} フラグを指定しなかった場合、ホストは環境変数をコンテナに渡します ({{ic|$PATH}} など、コンテナが他のディストリビューションの場合、一部のコマンドが機能しなくなる可能性があります)。 |
=== 高度な使用方法 === |
=== 高度な使用方法 === |
||
178行目: | 245行目: | ||
スナップショットは他のコンテナと同じように起動・停止できます。以下のコマンドでスナップショットを削除できます (ベースの lxc に変更は加えられません): |
スナップショットは他のコンテナと同じように起動・停止できます。以下のコマンドでスナップショットを削除できます (ベースの lxc に変更は加えられません): |
||
# lxc-destroy -n snap1 -f |
# lxc-destroy -n snap1 -f |
||
+ | |||
+ | [[pi-hole]] と [[OpenVPN]] のスナップショットを管理する systemd ユニットとラッパースクリプトが {{AUR|lxc-snapshots}} パッケージでインストールできます。 |
||
+ | |||
+ | === 特権コンテナを非特権コンテナに変換 === |
||
+ | 非特権コンテナを使うようにシステムを設定したら ([[#非特権コンテナのサポートを有効化 (任意)]] を参照), {{AUR|nsexec-bzr}} に含まれている {{ic|uidmapshift}} という名前のユーティリティで既存の特権コンテナを非特権コンテナに変換できます。イメージの再ビルドは不要です。 |
||
+ | |||
+ | {{Warning| |
||
+ | * ユーティリティを使用する前に既存のイメージをバックアップすることを推奨します。 |
||
+ | * ユーティリティは [[ACL]] の UID と GID をシフトしません。手動でシフトする必要があります。 |
||
+ | }} |
||
+ | |||
+ | 以下のようにコマンドを実行することで変換できます: |
||
+ | # uidmapshift -b /var/lib/lxc/foo 0 100000 65536 |
||
+ | |||
+ | 利用可能なオプションは引数を付けずに {{ic|uidmapshift}} を実行することで確認可能です。 |
||
== Xorg プログラムの実行 == |
== Xorg プログラムの実行 == |
||
223行目: | 305行目: | ||
... |
... |
||
− | lxc. |
+ | lxc.net.0.type = veth |
− | lxc. |
+ | lxc.net.0.name = veth0 |
− | lxc. |
+ | lxc.net.0.flags = up |
− | lxc. |
+ | lxc.net.0.link = {{ic|bridge}} |
... |
... |
||
コンテナの中から IP を割り当てる方法は[[ネットワーク設定#IP アドレスの設定]]を参照。 |
コンテナの中から IP を割り当てる方法は[[ネットワーク設定#IP アドレスの設定]]を参照。 |
||
+ | |||
+ | === Error: unknown command === |
||
+ | |||
+ | ホスト環境とは異なる Linux ディストリビューションのコンテナ (例えば Arch Linux ホスト環境の Debian コンテナ) に接続して基本的なコマンド (''ls'', ''cat'' など) を入力する発生することがあるエラーです。接続時に {{ic|--clear-env}} 引数を使ってください: |
||
+ | |||
+ | # lxc-attach -n ''container_name'' --clear-env |
||
== 参照 == |
== 参照 == |
||
236行目: | 324行目: | ||
* [http://www.ibm.com/developerworks/linux/library/l-lxc-containers/ LXC@developerWorks] |
* [http://www.ibm.com/developerworks/linux/library/l-lxc-containers/ LXC@developerWorks] |
||
* [http://docs.docker.io/en/latest/installation/archlinux/ Docker Installation on ArchLinux] |
* [http://docs.docker.io/en/latest/installation/archlinux/ Docker Installation on ArchLinux] |
||
+ | * [http://l3net.wordpress.com/tag/lxc/ LXC articles on l3net] |
2018年1月27日 (土) 00:45時点における版
関連記事
LinuX Containers (LXC) はオペレーティングシステムレベルの仮想化手法であり、一つのコントロールホスト (LXC ホスト) で独立した Linux システム (コンテナ) を複数動作させることができます。仮想マシンではありませんが、CPU やメモリ、ブロック I/O、ネットワークなどが個別に用意された仮想環境として使えます。LXC は LXC ホストの Linux カーネルによる cgroups 機能によって賄われています。chroot に似ていますが、より強力な分離を実現します。
LXC の代わりとして systemd-nspawn や docker、rkt でもコンテナを使うことができます。
特権コンテナと非特権コンテナ
LXC は特権または非特権で動作するように設定することができます。
一般的に、非特権コンテナは特権コンテナよりも安全だとされています [1]。非特権コンテナでは分離の程度が原理上増すからです。非特権コンテナではコンテナの root の UID をホストの root 以外の UID にマッピングすることで、コンテナの中からホスト環境に影響を及ぼすことを難しくします。たとえ攻撃者がコンテナから脱獄しても、ホスト側では攻撃者に権限がありません。
現在 Arch のパッケージでは特権コンテナは最初からサポートしています。非特権コンテナはカーネル設定を行わないと利用できません。Arch の linux カーネルでは通常ユーザーでユーザー名前空間が無効になっているためです。この記事では特権・非特権両方のコンテナの情報を載せていますが、非特権を使うには設定が必要です。
非特権コンテナの例
UID マッピングの能力を説明するために、非特権コンテナで以下のコマンドを実行したときの出力を考えてみましょう。ps
の出力でコンテナ化されたプロセスの所有者が同じくコンテナ化された root ユーザーとなっていることが確認できます:
[root@unprivileged_container /]# ps -ef | head -n 5 UID PID PPID C STIME TTY TIME CMD root 1 0 0 17:49 ? 00:00:00 /sbin/init root 14 1 0 17:49 ? 00:00:00 /usr/lib/systemd/systemd-journald dbus 25 1 0 17:49 ? 00:00:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation systemd+ 26 1 0 17:49 ? 00:00:00 /usr/lib/systemd/systemd-networkd
ホスト側では、コンテナ化された root プロセスはマッピングされたユーザー (ID>100000) で動作します。ホストの root ユーザーではありません:
[root@host /]# lxc-info -Ssip --name sandbox State: RUNNING PID: 26204 CPU use: 10.51 seconds BlkIO use: 244.00 KiB Memory use: 13.09 MiB KMem use: 7.21 MiB
[root@host /]# ps -ef | grep 26204 | head -n 5 UID PID PPID C STIME TTY TIME CMD 100000 26204 26200 0 12:49 ? 00:00:00 /sbin/init 100000 26256 26204 0 12:49 ? 00:00:00 /usr/lib/systemd/systemd-journald 100081 26282 26204 0 12:49 ? 00:00:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation 100000 26284 26204 0 12:49 ? 00:00:00 /usr/lib/systemd/systemd-logind
セットアップ
必要なソフトウェア
lxc と arch-install-scripts パッケージをインストールしてください。
非特権コンテナのサポートを有効化 (任意)
非特権コンテナを使いたい場合、設定を行う必要があります。
まず、カーネルがユーザー名前空間をサポートしていなければなりません。セキュリティへの懸念から、デフォルトの Arch カーネルではユーザー名前空間は root ユーザーでしか有効になりません。非特権コンテナを使うには CONFIG_USER_NS
が有効になったカーネルを使う必要があります:
- linux (v4.14.5 以上) または linux-hardened を使用する場合、非特権コンテナは root でのみ起動できます。
- linux (v4.14.5 以上) または linux-hardened を使用して sysctl の
kernel.unprivileged_userns_clone
設定を有効にすると通常ユーザーで非特権コンテナを起動できます。sysctl kernel.unprivileged_userns_clone=1
で現在のセッションにおいてのみ有効にすることができ、sysctl.d(5) で永続的に設定することも可能です。 - linux-usernsAUR または linux-lts-usernsAUR パッケージを使用する。どちらのパッケージも
CONFIG_USER_NS
が有効になっています。後者は長期サポート版です。 CONFIG_USER_NS
を有効にして自分でカスタムカーネルをコンパイル・インストールする。カスタムカーネルのコンパイルについてはカーネル/コンパイル/Arch Build System を見てください。
次に、/etc/lxc/default.conf
に以下の行を記述します:
lxc.idmap = u 0 100000 65536 lxc.idmap = g 0 100000 65536
最後に、/etc/subuid
と /etc/subgid
を作成してコンテナを実行するユーザーのコンテナ化する uid/gid のペアを入力してください。以下は root ユーザーの場合の例です:
/etc/subuid
root:100000:65536
/etc/subgid
root:100000:65536
ホストネットワークの設定
LXC は様々なタイプの仮想化ネットワークをサポートしています [2]。仮想ネットワークではほとんどの場合、ホスト側にブリッジデバイスが必要になります。以下で示しているブリッジの作成例に限られることはありません。例証として見て下さい。他のプログラムを使って同じようにネットワークを構築することも可能です。以下では有線と無線の例を示していますが、他のセットアップも可能です。他の方法についてはネットワークブリッジの記事を参照してください。
有線ネットワークの例
以下の例では netctl を使用しています。netctl のブリッジのテンプレートは /etc/netctl/examples
に存在します。ホストネットワークのハードウェアの仕様やホストネットワークの IP の範囲にあわせて編集するようにしてください。以下2つのブリッジの設定例を記載していますが、片方は dhcp を使っており、もう片方は固定 IP で設定しています。
/etc/netctl/lxcbridge
Description="LXC bridge" Interface=br0 Connection=bridge BindsToInterfaces=('eno1') IP=dhcp SkipForwardingDelay=yes
/etc/netctl/lxcbridge
Description="LXC bridge" Interface=br0 Connection=bridge BindsToInterfaces=('eno1') IP=static Address=192.168.0.2/24 Gateway='192.168.0.1' DNS=('192.168.0.1')
ブリッジを開始する前に、ホスト側の既存のネットワークインターフェイスを無効化してブリッジで置き換えるようにしてください。無効化するサービスはどうやってネットワークを設定していたかによって変わってきます。基本的なネットワーク設定についてはネットワーク設定を見てください。
netctl を使ってアダプタを管理していた場合は、switch-to で切り替えて下さい:
# netctl switch-to lxcbridge # netctl enable lxcbridge
次に進む前にホストからネットワークにちゃんと接続されているか確認してください。ping を実行することで確認できます:
$ ping -c 1 www.google.com
無線ネットワークの例
無線ネットワークを直接ブリッジすることはできません。他の方法を使う必要があります。最初に、先の例と同じようにブリッジを作成しますが、インターフェイスは何も定義しないようにしておきます (コンテナ自身の仮想インターフェイスは自動的に定義されます)。ブリッジに固定 IP アドレスを割り当てますがゲートウェイは割り当てないようにしてください。
iptables を使って NAT を行うようにホストを設定:
# iptables -t nat -A POSTROUTING -o wlp3s0 -j MASQUERADE
wlp3s0
は無線インターフェイスの名前に置き換えて下さい。パケット転送はデフォルトでは無効化されているので、カーネルパラメータを変更して有効にします:
# echo 1 > /proc/sys/net/ipv4/ip_forward
再起動するとパラメータがリセットされてしまうので /etc/sysctl.d
に conf ファイルを追加するようにしてください (インターネット共有#パケット転送の有効化の警告を見て下さい)。
残りの作業はほとんど同じですが、コンテナ側では、ゲートウェイはホストの IP アドレスを設定するようにしてください (上記の例では、192.168.0.2 になります)。/var/lib/lxc/container_name/config
で指定することができます (下のセクションを見て下さい)。
コンテナの作成
特権コンテナの場合、/usr/share/lxc/templates
からコンテナ化するディストロに合わせてテンプレートを選択してください。Arch 以外のディストロをコンテナに入れたい場合、ディストロによってホストにパッケージを追加でインストールする必要があります:
- Debian ベース: debootstrap。
- Fedora ベース: yumAUR。
lxc-create
を実行してコンテナを作成します。デフォルトでは LXC の root ファイルシステムは /var/lib/lxc/CONTAINER_NAME/rootfs
にインストールされます。例えば "playtime" という名前の Arch Linux LXC を作成:
# lxc-create -n playtime -t /usr/share/lxc/templates/lxc-archlinux
非特権コンテナを使いたい場合は -t download
を使用してイメージを選択してください。例:
# lxc-create -n playtime -t download
コンテナの設定
以下の例は特権コンテナと非特権コンテナどちらでも同じように使えます非特権コンテナの場合、lxc.idmap = u 0 100000 65536
and the lxc.idmap = g 0 100000 65536
values optionally defined in the #非特権コンテナのサポートを有効化 (任意)セクションで定義した lxc.idmap = u 0 100000 65536
や lxc.idmap = g 0 100000 65536
などの値がデフォルトで存在するはずです。
ネットワークの基本設定
プロセスが /var/lib/lxc/CONTAINER_NAME/config
に定義されたコンテナを使う場合、システムリソースは仮想化され分離されます。デフォルトでは、作成プロセスはネットワークサポートを省いた最小限のセットアップを作成します。以下はネットワークを設定する例です:
/var/lib/lxc/playtime/config
# Template used to create this container: /usr/share/lxc/templates/lxc-archlinux # Parameters passed to the template: # For additional config options, please look at lxc.container.conf(5) ## default values lxc.rootfs.path = /var/lib/lxc/playtime/rootfs lxc.uts.name = playtime lxc.arch = x86_64 lxc.include = /usr/share/lxc/config/archlinux.common.conf ## network lxc.net.0.type = veth lxc.net.0.link = br0 lxc.net.0.flags = up lxc.net.0.name = eth0 lxc.net.0.hwaddr = ee:ec:fa:e9:56:7d # uncomment the next two lines if static IP addresses are needed # leaving these commented will imply DHCP networking # #lxc.net.0.ipv4.address = 192.168.0.3/24 #lxc.net.0.ipv4.gateway = 192.168.0.1
コンテナの中でマウント
特権コンテナの場合、ホストでディレクトリを選択してコンテナにバインドマウントすることができます。同一アーキテクチャをコンテナ化している場合にホストとコンテナで pacman のパッケージを共有するなどの使用方法が考えられます。また、共有ディレクトリとして使用することもできます。構文は以下の通りです:
lxc.mount.entry = /var/cache/pacman/pkg var/cache/pacman/pkg none bind 0 0
Xorg プログラムの設定 (任意)
ホストのディスプレイでプログラムを動かしたい場合、コンテナ化されたプログラムがホストのリソースにアクセスできるようにバインドマウントを定義する必要があります。/var/lib/lxc/playtime/config
に以下のセクションを追加してください:
## for xorg lxc.mount.entry = /dev/dri dev/dri none bind,optional,create=dir lxc.mount.entry = /dev/snd dev/snd none bind,optional,create=dir lxc.mount.entry = /tmp/.X11-unix tmp/.X11-unix none bind,optional,create=dir,ro lxc.mount.entry = /dev/video0 dev/video0 none bind,optional,create=file
LXC のゲスト側に permission denied エラーが表示される場合、ホスト側で xhost +
を実行してゲストからホストのディスプレイサーバーに接続できるようにする必要があります。このようにディスプレイサーバーを開くことはセキュリティ上問題があるので注意してください。
OpenVPN の設定
コンテナで OpenVPN を実行したい場合は Linux Containers で OpenVPN クライアントや Linux Containers で OpenVPN サーバーの記事を読んで下さい。
コンテナの管理
基本的な使用方法
インストール済みの LXC コンテナを確認するには:
# lxc-ls -f
Systemd で lxc@CONTAINER_NAME.service
を使うことで LXC を起動したり停止することができます。lxc@CONTAINER_NAME.service
を有効化するとホストシステムの起動時に LXC が立ち上がるようになります。
systemd を使わずに LXC を起動・停止することも可能です。コンテナを起動:
# lxc-start -n CONTAINER_NAME
コンテナを停止:
# lxc-stop -n CONTAINER_NAME
コンテナにログインするには:
# lxc-console -n CONTAINER_NAME
ログイン時に pts/0 と lxc/tty1 が表示される場合:
# lxc-console -n CONTAINER_NAME -t 0
ログインしたら、他の linux システムと同じようにコンテナを扱って、root パスワードを設定し、ユーザーを作成、パッケージのインストールなどを行って下さい。
コンテナにアタッチ:
# lxc-attach -n CONTAINER_NAME --clear-env
lxc-console とほぼ同じですが、自動的にログインを通り越してコンテナの中の root プロンプトにアクセスします。 --clear-env
フラグを指定しなかった場合、ホストは環境変数をコンテナに渡します ($PATH
など、コンテナが他のディストリビューションの場合、一部のコマンドが機能しなくなる可能性があります)。
高度な使用方法
LXC の複製
同じコンテナを複数実行する必要があるときはスナップショットを使うことで管理を簡単にできます。最新状態にしておくベースコンテナをひとつだけセットアップして、それを必要に応じて複製 (スナップショットを作成) するという方法です。スナップショットは overlayfs を使用してデータの差異部分だけをディスクに書き込むためディスク容量を節約してオーバーヘッドをなくすことができます。ベースシステムは読み取り専用にしてスナップショットにのみ overlayfs で変更を加えられるようにします。
欠点としてスナップショットを作成しているときにベースの lxc を実行することはできません。
上に書いているようにコンテナをセットアップしたら "base" と名前を付けます。以下のコマンドで "base" コンテナのスナップショット ("snap1" と "snap2") を作成します:
# lxc-copy -n base -N snap1 -B overlayfs -s # lxc-copy -n base -N snap2 -B overlayfs -s
スナップショットは他のコンテナと同じように起動・停止できます。以下のコマンドでスナップショットを削除できます (ベースの lxc に変更は加えられません):
# lxc-destroy -n snap1 -f
pi-hole と OpenVPN のスナップショットを管理する systemd ユニットとラッパースクリプトが lxc-snapshotsAUR パッケージでインストールできます。
特権コンテナを非特権コンテナに変換
非特権コンテナを使うようにシステムを設定したら (#非特権コンテナのサポートを有効化 (任意) を参照), nsexec-bzrAUR に含まれている uidmapshift
という名前のユーティリティで既存の特権コンテナを非特権コンテナに変換できます。イメージの再ビルドは不要です。
以下のようにコマンドを実行することで変換できます:
# uidmapshift -b /var/lib/lxc/foo 0 100000 65536
利用可能なオプションは引数を付けずに uidmapshift
を実行することで確認可能です。
Xorg プログラムの実行
対象のコンテナにアタッチまたは SSH でログインしてホストの X セッションの DISPLAY ID をプログラムを呼び出すときに指定します。ほとんどの場合、ディスプレイは常時 0 です。
ホストのディスプレイでコンテナから Firefox を起動する例:
$ DISPLAY=:0 firefox
もしくは、直接コンテナにアタッチしたり接続する代わりに、以下のコマンドを使って自動的にホストにディスプレイを設定することもできます:
# lxc-attach -n playtime --clear-env -- sudo -u YOURUSER env DISPLAY=:0 firefox
トラブルシューティング
root ログインが失敗する
lxc-console を使ってログインしようとすると以下のエラーが表示される場合:
login: root Login incorrect
そしてコンテナの journalctl
で以下のように表示される場合:
pam_securetty(login:auth): access denied: tty 'pts/0' is not secure !
コンテナのファイルシステムにある /etc/securetty
のターミナル名のリストに pts/0
を追加してください。[3] を参照。コンテナの /etc/securetty
を削除することで常時 root ログインを許可することもできます。[4] を参照。
もしくは、lxc-attach に新しいユーザーを作成してシステムにログインするときに使うようにして、それから root に切り替えて下さい。
# lxc-attach -n playtime [root@playtime]# useradd -m -Gwheel newuser [root@playtime]# passwd newuser [root@playtime]# passwd root [root@playtime]# exit # lxc-console -n playtime [newuser@playtime]$ su
コンテナ設定の veth でネットワークに接続できない
/etc/lxc/containername/config
で設定した veth ネットワークインターフェイスで LAN や WAN に接続できないことがあります。仮想インターフェイスには IP が割り当てられてネットワークに接続できるようになっている場合:
ip addr show veth0 inet 192.168.1.111/24
固定 IP の設定を全て無効化して、起動したコンテナ OS の中から普通の方法で IP を設定してみてください。
container/config
の例:
...
lxc.net.0.type = veth
lxc.net.0.name = veth0
lxc.net.0.flags = up
lxc.net.0.link = bridge
...
コンテナの中から IP を割り当てる方法はネットワーク設定#IP アドレスの設定を参照。
Error: unknown command
ホスト環境とは異なる Linux ディストリビューションのコンテナ (例えば Arch Linux ホスト環境の Debian コンテナ) に接続して基本的なコマンド (ls, cat など) を入力する発生することがあるエラーです。接続時に --clear-env
引数を使ってください:
# lxc-attach -n container_name --clear-env