Настройка сети для LXC-контейнеров в Debian 8, Centos 7 и Fedora 21
Jan 30, 2017 21:06 · 1019 words · 5 minute read
В 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
После всех проделанных действий можно приступать к созданию контейнеров.