Linux コンテナ
LinuX Containers (LXC) はオペレーティングシステムレベルの仮想化手法であり、一つのコントロールホスト (LXC ホスト) で独立した Linux システム (コンテナ) を複数動作させることができます。仮想マシンではありませんが、CPU やメモリ、ブロック I/O、ネットワークなどが個別に用意された仮想環境として使えます。LXC は LXC ホストの Linux カーネルによる cgroups 機能によって賄われています。chroot に似ていますが、より強力な分離を実現します。
セットアップ
必要なソフトウェア
公式リポジトリから 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
bridge-utils だけを使用する例
Placeholder for someone using this setup.
無線ネットワークの例
無線ネットワークを直接ブリッジすることはできません。他の方法を使う必要があります。最初に、先の例と同じようにブリッジを作成しますが、インターフェイスは何も定義しないようにしておきます (コンテナ自身の仮想インターフェイスは自動的に定義されます)。ブリッジに固定 IP アドレスを割り当てますがゲートウェイは割り当てないようにしてください。
iptables を使って NAT を行うようにホストを設定:
# iptables -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 ベース: AUR の debootstrapAUR。
- Fedora ベース: AUR の 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
コンテナの設定
ネットワークの基本設定
System resources to be virtualized / isolated when a process is using the container are defined in /var/lib/lxc/CONTAINER_NAME/config
. By default, the creation process will make a minimum setup without networking support. Below is an example config with networking:
/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
Systemd considerations (required)
The following sections explain some quirks that should be addressed. A small bash script is required for this to work which users should create:
/var/lib/lxc/playtime/autodev
#!/bin/bash cd ${LXC_ROOTFS_MOUNT}/dev mkdir net mknod net/tun c 10 200 chmod 0666 net/tun
Make it executable:
# chmod +x /var/lib/lxc/playtime/autodev
Next, modify /var/lib/lxc/playtime/config
to contain this new section:
## systemd within the lxc lxc.autodev = 1 lxc.pts = 1024 lxc.kmsg = 0 lxc.hook.autodev=/var/lib/lxc/playtime/autodev
Systemd conflicts in the /dev tree
To avoid conflicts of systemd and lxc in the /dev tree. It is highly recommended to enable the 'autodev' mode. This will cause LXC to create its own device tree but this also means that the traditional way of manually creating device nodes in the container rootfs /dev tree will not work because /dev is overmounted by LXC.
It is also important to disable services that are not supported inside a container. Either attach to the running LXC or chroot into the container rootfs and mask those services:
ln -s /dev/null /etc/systemd/system/systemd-udevd.service ln -s /dev/null /etc/systemd/system/systemd-udevd-control.socket ln -s /dev/null /etc/systemd/system/systemd-udevd-kernel.socket ln -s /dev/null /etc/systemd/system/proc-sys-fs-binfmt_misc.automount
This disables udev and mounting of /proc/sys/fs/binfmt_misc
.
Maintain devpts consistency
Additionally ensure a pty declaration in the LXC container because the presence of this causes LXC to mount devpts as a new instance. Without this the container gets the host's devpts and that is not a good thing - more strange things will happen!
lxc.pts = 1024
Prevent excess journald activity
By default lxc symlinks /dev/kmsg to /dev/console, this leads to journald running 100% cpu usage all the time. To prevent the symlink, use:
lxc.kmsg = 0
Xorg program considerations (optional)
In order to run programs on the host's display, some bind mounts need to be defined so the containerized programs can access the host's resources. Add the following section to /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
OpenVPN considerations
コンテナで OpenVPN を実行したい場合は OpenVPN in Linux containers の記事を読んで下さい。
コンテナの管理
インストール済みの 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-attach -n CONTAINER_NAME
アタッチしたら、他の linux システム用にコンテナを扱って、root パスワードを設定し、ユーザーを作成、パッケージのインストールなどを行って下さい。
Xorg プログラムの実行
Either attach to or ssh into the target container and prefix the call to the program with the DISPLAY id of the host's X session. For most simple setups, the display is always 0. Example running firefox from the container in the host's display:
$ DISPLAY=:0 firefox
Alternatively, to avoid directly attaching to or connecting to the container, the following can be used on the host to automate the process:
# lxc-attach -n playtime --clear-env -- sudo -u YOURUSER env DISPLAY=0.0 firefox