Настройка сети для LXC-контейнеров в Debian 8, Centos 7 и Fedora 21

Jan 30, 2017 21:06 · 1019 words · 5 minute read lxc

В Ubuntu сеть для LXC-контейнеров работает «из коробки» благодаря инит-скрипту lxc-net и набору необходимых правил для iptables, но в Debian Jessie, CentOS 7 и Fedora 21 по умолчанию сеть не настроена. Давайте разберемся!

Для настройки сети и корректной работы LXC-контейнеров в Debian 8 (Jessie) следует выполнить ряд простых шагов. Во-первых, установить необходимые пакеты:

aptitude install lxc dnsmasq-base bridge-utils

Создать конфигурационный файл /etc/default/lxc с таким содержимым:

USE_LXC_BRIDGE="true"

Создать инит-скрипт в каталоге /etc/init.d/ (и сделать его исполняемым):

touch /etc/init.d/lxc-net
chmod +x /etc/init.d/lxc-net

Содержимое инит-скрипта должно быть таким:

#!/bin/sh
### BEGIN INIT INFO
# Provides:             lxc-net
# Required-Start:       $syslog $remote_fs
# Required-Stop:        $syslog $remote_fs
# Should-Start:
# Should-Stop:
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    Linux Containers Network Configuration
# Description:          Linux Containers Network Configuration
# X-Start-Before:
# X-Stop-After:
# X-Interactive:        
### END INIT INFO
 
# Ubuntu's lxc-net upstart config adopted for Debian by Flockport.com
# original author: Serge Hallyn <serge.hallyn@canonical.com>
 
USE_LXC_BRIDGE="false"
LXC_BRIDGE="lxcbr0"
LXC_ADDR="10.0.3.1"
LXC_NETMASK="255.255.255.0"
LXC_NETWORK="10.0.3.0/24"
LXC_DHCP_RANGE="10.0.3.2,10.0.3.254"
LXC_DHCP_MAX="253"
LXC_DHCP_CONFILE="/etc/lxc/dnsmasq.conf"
varrun="/var/run/lxc"
LXC_DOMAIN="lxc"
 
. /lib/lsb/init-functions
 
start() {
    [ -f /etc/default/lxc ] && . /etc/default/lxc
 
    [ "x$USE_LXC_BRIDGE" = "xtrue" ] || { exit 0; }
 
    if [ -d /sys/class/net/${LXC_BRIDGE} ]; then
        if [ ! -f ${varrun}/network_up ]; then
            # bridge exists, but we didn't start it
            exit 0;
        fi
        exit 0;
    fi
 
    cleanup() {
        # dnsmasq failed to start, clean up the bridge
        iptables -D INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT
        iptables -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT
        iptables -D INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT
        iptables -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT
        iptables -D FORWARD -i ${LXC_BRIDGE} -j ACCEPT
        iptables -D FORWARD -o ${LXC_BRIDGE} -j ACCEPT
        iptables -t nat -D POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE || true
        iptables -t mangle -D POSTROUTING -o ${LXC_BRIDGE} -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
        ifconfig ${LXC_BRIDGE} down || true
        brctl delbr ${LXC_BRIDGE} || true
    }
 
    # set up the lxc network
    brctl addbr ${LXC_BRIDGE} || { echo "Missing bridge support in kernel"; exit 0; }
    echo 1 > /proc/sys/net/ipv4/ip_forward
    mkdir -p ${varrun}
    ifconfig ${LXC_BRIDGE} ${LXC_ADDR} netmask ${LXC_NETMASK} up
    iptables -I INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT
    iptables -I INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT
    iptables -I INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT
    iptables -I INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT
    iptables -I FORWARD -i ${LXC_BRIDGE} -j ACCEPT
    iptables -I FORWARD -o ${LXC_BRIDGE} -j ACCEPT
    iptables -t nat -A POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE
    iptables -t mangle -A POSTROUTING -o ${LXC_BRIDGE} -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
 
    LXC_DOMAIN_ARG=""
    if [ -n "$LXC_DOMAIN" ]; then
        LXC_DOMAIN_ARG="-s $LXC_DOMAIN"
    fi
    dnsmasq $LXC_DOMAIN_ARG -u dnsmasq --strict-order --bind-interfaces --pid-file=${varrun}/dnsmasq.pid --conf-file=${LXC_DHCP_CONFILE} --listen-address ${LXC_ADDR} --dhcp-range ${LXC_DHCP_RANGE} --dhcp-lease-max=${LXC_DHCP_MAX} --dhcp-no-override --except-interface=lo --interface=${LXC_BRIDGE} --dhcp-leasefile=/var/lib/misc/dnsmasq.${LXC_BRIDGE}.leases --dhcp-authoritative || cleanup
    touch ${varrun}/network_up
}
 
stop() {
    [ -f /etc/default/lxc ] && . /etc/default/lxc
    [ -f "${varrun}/network_up" ] || exit 0;
    # if $LXC_BRIDGE has attached interfaces, don't shut it down
    ls /sys/class/net/${LXC_BRIDGE}/brif/* > /dev/null 2>&1 && exit 0;
 
    if [ -d /sys/class/net/${LXC_BRIDGE} ]; then
        ifconfig ${LXC_BRIDGE} down
        iptables -D INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT
        iptables -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT
        iptables -D INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT
        iptables -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT
        iptables -D FORWARD -i ${LXC_BRIDGE} -j ACCEPT
        iptables -D FORWARD -o ${LXC_BRIDGE} -j ACCEPT
        iptables -t nat -D POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE || true
        iptables -t mangle -D POSTROUTING -o ${LXC_BRIDGE} -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
  pid=`cat ${varrun}/dnsmasq.pid 2>/dev/null` && kill -9 $pid || true
        rm -f ${varrun}/dnsmasq.pid
        brctl delbr ${LXC_BRIDGE}
    fi
    rm -f ${varrun}/network_up
}
 
case "${1}" in
    start)
        log_daemon_msg "Starting Linux Containers"
 
        start
        ;;
 
    stop)
        log_daemon_msg "Stopping Linux Containers"
 
        stop
        ;;
 
    restart|force-reload)
        log_daemon_msg "Restarting Linux Containers"
 
        stop
        start
        ;;
esac

Запускаем lxc-net и добавляем в автозагрузку:

systemctl enable lxc-net
systemctl start lxc-net

Для того, чтобы созданные LXC-контейнеры по умолчанию получали в настройках сети сетевой мост lxcbr0, добавляем в конфигурационный файл /etc/lxc/default.conf следующие строки:

lxc.network.type = veth
lxc.network.link = lxcbr0
lxc.network.flags = up
lxc.network.hwaddr = 00:16:3e:xx:xx:xx

В CentOS 7 и Fedora 21 настройка сети для LXC-контейнеров выглядит несколько иначе — функциональность сетевого моста обеспечивается пакетом libvirt, но вполне можно обойтись и без него. Для этого установим необходимые пакеты:

yum -y install lxc lxc-templates lxc-extras dnsmasq bridge-utils iptables-services

Далее создаем два systemd-юнита — lxc-net.service и lxc-dhcp.service в каталоге /etc/systemd/system/, которые обеспечат функциональность, аналогичную lxc-net в дистрибутивах Ubuntu и Debian:

touch /etc/systemd/system/lxc-net.service
touch /etc/systemd/system/lxc-dhcp.service

Содержимое первого юнита выглядит так:

[Unit]
Description=Bridge interface for LXC Containers
 
[Service]
Type=oneshot
 
# Bring up bridge interface
ExecStart=/sbin/brctl addbr lxcbr0
ExecStart=/sbin/ip address add 10.0.3.1/24 dev lxcbr0
ExecStart=/sbin/ip link set lxcbr0 up
 
RemainAfterExit=yes
 
# Bring bridge interface down
ExecStop=/sbin/ip link set lxcbr0 down
ExecStop=/sbin/brctl delbr lxcbr0

Содержимое второго созданного юнита следующее:

[Unit]
Requires=lxc-net.service
Requires=sys-devices-virtual-net-lxcbr0.device
After=sys-devices-virtual-net-lxcbr0.device
 
[Service]
ExecStart=/sbin/dnsmasq \
            --dhcp-leasefile=/var/run/lxc-dnsmasq.leases \
            --user=nobody \
            --group=nobody \
            --keep-in-foreground \
            --conf-file=/etc/lxc/dnsmasq.conf \
            --listen-address=10.0.3.1 \
            --except-interface=lo \
            --bind-interfaces \
            --dhcp-range=10.0.3.2,10.0.3.254
 
[Install]
WantedBy=default.target

Далее запускаем службы и добавляем их в автозагрузку:

systemctl enable lxc-net.service
systemctl enable lxc-dhcp.service
systemctl start lxc-net.service
systemctl start lxc-dhcp.service
systemctl enable iptables
systemctl start iptables

Также нам необходимо создать несколько правил для iptables (и убедиться, что они останутся после перезагрузки). Для этого создаем файл lxc-net с такими правилами:

iptables -I INPUT -i lxcbr0 -p udp --dport 67 -j ACCEPT
iptables -I INPUT -i lxcbr0 -p tcp --dport 67 -j ACCEPT
iptables -I INPUT -i lxcbr0 -p tcp --dport 53 -j ACCEPT
iptables -I INPUT -i lxcbr0 -p udp --dport 53 -j ACCEPT
iptables -I FORWARD -i lxcbr0 -j ACCEPT
iptables -I FORWARD -o lxcbr0 -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.0.3.0/24 ! -d 10.0.3.0/24 -j MASQUERADE
iptables -t mangle -A POSTROUTING -o lxcbr0 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill

Делаем его исполняемым и запускаем:

chmod +x lxc-net && ./lxc-net

Сохраняем текущие правила iptables:

/sbin/service iptables save

Включаем форвардинг пакетов — добавляем в файл /etc/sysctl.conf следующую строку:

...
net.ipv4.ip_forward = 1

Применяем внесенное изменение:

sysctl -p

После всех проделанных действий можно приступать к созданию контейнеров.

tweet Share