Linux コンテナ
LinuX Containers (LXC) はオペレーティングシステムレベルの仮想化手法であり、一つのコントロールホスト (LXC ホスト) で独立した Linux システム (コンテナ) を複数動作させることができます。仮想マシンではありませんが、CPU やメモリ、ブロック I/O、ネットワークなどが個別に用意された仮想環境として使えます。LXC は LXC ホストの Linux カーネルによる cgroups 機能によって賄われています。chroot に似ていますが、より強力な分離を実現します。
LXC の代わりとして systemd-nspawn や docker でもコンテナを使うことができます。
目次
セットアップ
必要なソフトウェア
公式リポジトリから lxc と arch-install-scripts をインストールしてください。
使用中のカーネルがコンテナを実行できるように正しく設定されているか確認:
$ lxc-checkconfig
セキュリティに配慮して、デフォルトの Arch カーネルでは、非特権ユーザーではコンテナを実行できないようになっています。そのため、上記のコマンドを実行すると "User namespaces" の状態が missing になっているのが確認できます。詳しくは FS#36969 を見て下さい。
ホストネットワークの設定
LXC は様々なタイプの仮想化ネットワークをサポートしています。仮想ネットワークではほとんどの場合、ホスト側にブリッジデバイスが必要になります。以下で示しているブリッジの作成例に限られることはありません。例証として見て下さい。他のプログラムを使って同じようにネットワークを構築することも可能です。以下では有線と無線の例を示していますが、他のセットアップも可能です。他の方法についてはネットワークブリッジの記事を参照してください。
有線ネットワークの例
以下の例では 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
コンテナの設定
ネットワークの基本設定
プロセスが /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 = /var/lib/lxc/playtime/rootfs lxc.utsname = playtime lxc.arch = x86_64 lxc.include = /usr/share/lxc/config/archlinux.common.conf ## network lxc.network.type = veth lxc.network.link = br0 lxc.network.flags = up lxc.network.ipv4 = 192.168.0.3/24 lxc.network.ipv4.gateway = 192.168.0.1 lxc.network.name = eth0 ## 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 # # if running the same Arch linux on the same architecture it may be # adventitious to share the package cache directory #lxc.mount.entry = /var/cache/pacman/pkg var/cache/pacman/pkg none bind 0 0
Xorg プログラムの設定 (任意)
ホストのディスプレイでプログラムを動かしたい場合、コンテナ化されたプログラムがホストのリソースにアクセスできるようにバインドマウントを定義する必要があります。/var/lib/lxc/playtime/config
に以下のセクションを追加してください:
## 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/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 = /dev/video0 dev/video0 none bind,optional,create=file
LXC のゲスト側に permission denied エラーが表示される場合、ホスト側で xhost +
を実行してゲストからホストのディスプレイサーバーに接続できるようにする必要があります。このようにディスプレイサーバーを開くことはセキュリティ上問題があるので注意してください。
OpenVPN の設定
コンテナで 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
ログインしたら、他の linux システムと同じようにコンテナを扱って、root パスワードを設定し、ユーザーを作成、パッケージのインストールなどを行って下さい。
コンテナにアタッチ:
# lxc-attach -n CONTAINER_NAME
lxc-console とほぼ同じですが、自動的にログインを通り越してコンテナの中の root プロンプトにアクセスします。
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
を追加してください。[1] を参照。コンテナの /etc/securetty
を削除することで常時 root ログインを許可することもできます。[2] を参照。
もしくは、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.network.type = veth lxc.network.name = veth0 lxc.network.flags = up lxc.network.link = bridge ...
コンテナの中から IP を割り当てる方法はネットワーク設定#IP アドレスの設定を参照。