Выбрать главу

the Squeeze standard kernel does not allow limiting the amount of memory available to a container; this feature exists, and can be enabled by rebuilding the kernel with the Memory Resource Controller option, but it is still considered somewhat experimental, and it has a (slight) cost on overall system performance, which is why it's disabled by default;

since the kernel is shared among the host system and the containers, processes constrained to containers can still access the kernel messages, which can lead to information leaks if messages are emitted by a container;

for similar reasons, if a container is compromised and a kernel vulnerability is exploited, the other containers may be affected too;

on the filesystem, the kernel checks permissions according to the numerical identifiers for users and groups; these identifiers may designate different users and groups depending on the container, which should be kept in mind if writable parts of the filesystem are shared among containers.

Since we're dealing with isolation and not plain virtualization, setting up LXC containers is more complex than just running debian-installer on a virtual machine. We'll describe a few prerequisites, then go on to the network configuration; we will then be able to actually create the system to be run in the container.

12.2.2.1. Preliminary Steps

The lxc package contains the tools required to run LXC, and must therefore be installed.

LXC also requires the control groups configuration system, which is a virtual filesystem to be mounted on /sys/fs/cgroup. The /etc/fstab should therefore include the following entry:

# /etc/fstab: static file system information.

[...]

cgroup            /sys/fs/cgroup           cgroup    defaults        0       0

/sys/fs/cgroup will then be mounted automatically at boot time; if no immediate reboot is planned, the filesystem should be manually mounted with mount /sys/fs/cgroup.

12.2.2.2. Network Configuration

The goal of installing LXC is to set up virtual machines; while we could of course keep them isolated from the network, and only communicate with them via the filesystem, most use cases involve giving at least minimal network access to the containers. In the typical case, each container will get a virtual network interface, connected to the real network through a bridge. This virtual interface can be plugged either directly onto the host's physical network interface (in which case the container is directly on the network), or onto another virtual interface defined on the host (and the host can then filter or route traffic). In both cases, the bridge-utils package will be required.

The simple case is just a matter of editing /etc/network/interfaces, moving the configuration for the physical interface (for instance eth0) to a bridge interface (usually br0), and configuring the link between them. For instance, if the network interface configuration file initially contains entries such as the following:

auto eth0

iface eth0 inet dhcp

They should be disabled and replaced with the following:

#auto eth0

#iface eth0 inet dhcp

auto br0

iface br0 inet dhcp

  bridge-ports eth0

The effect of this configuration will be similar to what would be obtained if the containers were machines plugged into the same physical network as the host. The “bridge” configuration makes the Ethernet frames on all the bridged interfaces, which includes the physical eth0 as well as the interfaces defined for the containers.

In cases where this configuration cannot be used (for instance if no public IP addresses can be assigned to the containers), a virtual tap interface will be created and connected to the bridge. The equivalent network topology then becomes that of a host with a second network card plugged into a separate switch, with the containers also plugged into that switch. The host must then act as a gateway for the containers if they are meant to communicate with the outside world.

In addition to bridge-utils, this “rich” configuration requires the vde2 package; the /etc/network/interfaces file then becomes:

# Interface eth0 is unchanged

auto eth0

iface eth0 inet dhcp

# Virtual interface

auto tap0

iface tap0 inet manual

  vde2-switch -t tap0

# Bridge for containers

auto br0

iface br0 inet static

  bridge-ports tap0

  address 10.0.0.1

  netmask 255.255.255.0

The network can then be either be set up statically in the containers, or dynamically with DHCP server running on the host. Such a DHCP server will need to be configured to answer queries on the br0 interface.

12.2.2.3. Setting Up the System

Let us now set up the filesystem to be used by the container. Since this “virtual machine” will not run directly on the hardware, some tweaks are required when compared to a standard filesystem, especially as far as the kernel, devices and consoles are concerned. Fortunately, the lxc includes scripts that mostly automate this configuration. For instance, the following commands (which require the debootstrap package) will install a Debian container:

root@scouzmir:~# mkdir /var/lib/lxc/testlxc/

root@scouzmir:~# /usr/lib/lxc/templates/lxc-debian -p /var/lib/lxc/testlxc/

debootstrap is /usr/sbin/debootstrap

Checking cache download in /var/cache/lxc/debian/rootfs-i386 ...

Downloading debian minimal ...

I: Retrieving Release

I: Retrieving Packages

[...]

 Removing any system startup links for /etc/init.d/hwclockfirst.sh ...

   /etc/rcS.d/S08hwclockfirst.sh

Root password is 'root', please change !

root@scouzmir:~#

Note that the filesystem is initially created in /var/cache/lxc, then moved to its destination directory. This allows creating identical containers much more quickly, since only copying is then required.

Note also that the lxc-debian command as shipped in Squeeze unfortunately creates a Lenny system, and not a Squeeze system as one could expect. This problem can be worked around by simply installing a newer version of the package (starting from 0.7.3-1).

The newly-created filesystem now contains a minimal Debian system, adapted to the aforementioned “simple” network configuration. In the “rich” configuration, the /var/lib/lxc/testlxc/rootfs/etc/network/interfaces file will need some modifications; more important, though, is that the network interface that the container sees must not be the host's physical interface. This can be configured by adding a few lxc.network.* entries to the container's configuration file, /var/lib/lxc/testlxc/config:

lxc.network.type = veth

lxc.network.flags = up

lxc.network.link = br0

lxc.network.hwaddr = 4a:49:43:49:79:20

These entries mean, respectively, that a virtual interface will be created in the container; that it will automatically be brought up when said container is started; that it will automatically be connected to the br0 bridge on the host; and that its MAC address will be as specified. Should this last entry be missing or disabled, a random MAC address will be generated.

12.2.2.4. Starting the Container