Running a Service in a Network Namespace

If you want to have the container have its own real IP address (Internet-routable or CMU-internal), you'll need to set up your own network bridge. The lxcbr0 configured by lxc-net.service uses private 10.x.x.x IPs with NAT and dnsmasq.

  1. Install bridge-utils

  2. Edit /etc/network/interfaces; for the to-be-bridged interfaces's stanza:

    1. Change allow-hotplug «if» -> auto br0

    2. Change the stanza iface «if» inet ... -> iface br0 inet ...

    3. Add a bridge_ports «if» directive

Install the lxc package.

The package installation will start lxc-net.service, which creates a NAT-ed network on lxcbr0. That can be stopped with systemctl stop lxc-net.service.

Creation of lxcbr0, the associated iptables rules, and dnsmasq daemon can be disabled on future boots by specifying USE_LXC_BRIDGE="false" in /etc/default/lxc-net.

Use a configuration similar to the following to create the container for the service:

# Common configuration
lxc.include = /usr/share/lxc/config/common.conf

# Container specific configuration
lxc.start.auto = 0
lxc.uts.name = «hostname»
lxc.arch = amd64

lxc.net.0.type = veth
lxc.net.0.name = eth0
lxc.net.0.hwaddr = «mac_address»
lxc.net.0.link = br0

lxc.rootfs.path =

lxc.mount.entry =
lxc.mount.entry = tmpfs run tmpfs defaults 0 0
lxc.mount.entry = /var/lib/dhcp-«hostname» var/lib/dhcp none bind,slave,optional 0 0
lxc.mount.auto = cgroup:mixed:force proc:mixed sys:mixed

lxc.apparmor.profile = unconfined

# [Debian] doesn't support consoles in /dev/lxc/
lxc.tty.dir =

# Play nicely with systemd
lxc.cgroup.relative = 1

# Extra cgroup device access
## rtc
lxc.cgroup2.devices.allow = c 254:0 rm
## hpet
lxc.cgroup2.devices.allow = c 10:228 rwm

Create the container with: lxc-create -n «hostname» -f «config_file» -t none

Define a "virtual" interface stanza for the container's network interface in /etc/network/interfaces:

iface eth0-«hostname»-container inet static
        address «ip_address»/«netmask_len»
        gateway «default_gw»

If the container's networking must be configured using DHCP (not recommended), create a directory for its dhclient lease database, to avoid clashes with the host: mkdir /var/lib/dhcp-«hostname»

Create a systemd drop-in directory and file to override the desired service. E.g., /etc/systemd/system/«service».service.d/10in_container.conf containing:

[Service]
ExecStart=
ExecStart=lxc-execute -n «hostname» -- /bin/sh -c "ifup lo && ifup eth0=eth0-«hostname»-container && exec «normal_exec_start»"
ExecStop=
ExecStop=lxc-attach -n «hostname» -- /bin/sh -c "«normal_exec_stop»; ifdown eth0"
Delegate=yes

Accessing a Shell in the Container

When the service is currently running:

lxc-attach -n «hostname» -- /bin/bash

When the service is not running (network will not be available until the interfaces are manually brought up):

lxc-execute -n «hostname» -s lxc.cgroup.relative=0 -- /bin/bash

kbare at CLUB.CC.CMU.EDU/LXC (last edited 2021-12-28 21:33:34 by kbare@CLUB.CC.CMU.EDU)