Як дозволити вбудованому DHCP призначити статичний IP контейнеру LXC на основі імені, а не MAC-адреси


10

Я знаю, що я можу призначити статичний IP вручну, використовуючи /etc/network/interfaces.

Я також знаю, що я можу прочитати MAC-адресу контейнера LXC (наприклад, шукаючи lxc.network.hwaddrзапис /var/lib/lxc/<container-name>/configта призначити IP-адресу, використовуючи записи dhcp-host=<mac-addr>,10.0.3.3в /etc/dnsmasq.d/<some file>.

У файлі, який /etc/default/lxc-netя прочитав

# Uncomment the next line if you'd like to use a conf-file for the lxcbr0
# dnsmasq.  For instance, you can use 'dhcp-host=mail1,10.0.3.100' to have
# container 'mail1' always get ip address 10.0.3.100.
#LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

Це відповідало б моїм потребам; на жаль, це не має ефекту.


2
Це працює для мене, але зауважте, що вам потрібно перезапустити lxc-net, щоб він набув чинності. І є відома проблема, що lxc-net не перезапускається, якщо якийсь контейнер запущений. Вам потрібно зупинити їх, а потім перезапустити послугу lxc-net.
HRJ

Крім того, мені не вдалося призначити ip-адреси, використовуючи лише ім'я контейнера. Мені довелося жорстко кодувати MAC-адресу для контейнера та для конфігурації DHCP.
HRJ

@HRJ, чи можете ви опублікувати файл dnsmasq.conf, будь ласка?
tonytony

@HRJ У Ubuntu 14.04 перезапуск lxc-netне допоможе, якщо ви не видалите свій міст lxcbr0. Дивіться мою відповідь.
Адам Річковський

Відповіді:


17

Я нещодавно зіткнувся з цим і, думаю, знайшов просте рішення. Я (тільки) протестував його на Ubuntu 14.04.

По-перше, коментуйте цей рядок / etc / default / lxc-net:

LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

У /etc/lxc/dnsmasq.conf визначте dhcp-hostsfile:

dhcp-hostsfile=/etc/lxc/dnsmasq-hosts.conf

Потім додайте записи в /etc/lxc/dnsmasq-hosts.conf так:

mail,10.0.3.16
web,10.0.3.17

Остерігайтеся: зміни стануть ефективними після перезапуску lxc-net (який перезапускає dnsmasq):

service lxc-net restart

Після цього ви можете змінити /etc/lxc/dnsmasq-hosts.conf і надіслати сигнал SIGHUP на dnsmasq:

killall -s SIGHUP dnsmasq

Так що так, вам потрібно перезапустити lxc-net, але лише один раз. Сподіваюсь, це допомагає.


Мені подобається ідея делегування списку хостів у зовнішній файл. Крім того, ваш метод відрізняється від мого через killall -s SIGHUP dnsmasq. Я погоджуюся, що просто "SIGHUP-ing" dnsmasq є більш ефективним, ніж перезапуск цілого демона (особливо, якщо він не працює без виправлення своїх початкових сценаріїв).
Адам Річковський

Перезапуск послуги lxc-netпотрібен лише для того, щоб dnsmasq використовував конфігурацію з /etc/lxc/dnsmasq.conf (і ця інформація міститься в /etc/default/lxc-netневідомому для dnsmasq). Якщо ви його встановлювали раніше, достатньо було б ще одного SIGHUP.
Адам Річковський

Остерігайтеся: lxc-net не перезапустить dnsmasq, якщо є запущені контейнери.
s3v3n

IMO це найкраща відповідь
s3v3n

kill -HUP $(cat /var/run/lxc/dnsmasq.pid)якщо ви не хочете встановлювати killallчи перезавантажувати інші dnsmasqекземпляри
gertas

4

Він прекрасно працює в Ubuntu 14.04.1

Відменшіть цей рядок /etc/default/lxc-net

#LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

зупинити всі контейнери, перезапустити lxc-net:

service lxc-net restart

Налаштуйте ip адреси в /etc/lxc/dnsmasq.conf

dhcp-host={NAME},10.0.3.2

де {NAME}назва вашого контейнера LXC:

/var/lib/lxc/{NAME}

Він працює лише в тому випадку, якщо сценарій може вимкнути мережу lxcbr0 , що виключає випадок, коли працюють інші контейнери lxc. Коротше кажучи, як зараз, ви не можете призначити статичну оренду dhcp без перезавантаження всіх контейнерів.
Адам Річковський

Так, це правда, це зовсім незручно :(. Я знаходжу набагато простіше рішення для редагування /var/lib/lxc/<container-name>/rootfs/etc/network/interfacesфайлу та призначення статичної ip-адреси контейнеру.
Tombart

Щоправда, але тоді вам нічого не захистить від того, щоб дати двом гостям однаковий IP. Дивіться мою прийняту відповідь - це вирішує проблему.
Адам Річковський

1

Відповідь Tombart працює, якщо ви досить терплячі, щоб зачекати оновлення DNS, і ви готові після цього перезапустити контейнер (гість).

Далі йде рецепт, який вимагає закриття всіх інших контейнерів lxc . Якщо ви не можете собі цього дозволити, то я не бачу способу форсувати нову конфігурацію dnsmasq. (Для деяких обґрунтованих сигналів HUP до pns dnsmasq, знайденого в, /run/lxc/dnsmasq.pidтакож не працює.)

Тож якщо ви хочете, щоб щось працювало миттєво, а інших контейнерів lxc не працює, дотримуйтесь моєї відповіді. $name- це ім'я вузла, якому ми хочемо скинути призначення, і $internalifце ім'я мостового адаптера LXC. Ви можете отримати значення $internalifз, наприклад, augtool -L -A --transform "Shellvars incl /etc/default/lxc-net" get "/files/etc/default/lxc-net/LXC_BRIDGE" | sed -En 's/\/.* = (.*)/\1/p'якщо встановити, augeas-toolsале зазвичай це просто lxcbr0.

sudo lxc-stop -n $name >/dev/null
sudo service lxc-net stop >/dev/null
if [ -d /sys/class/net/$internalif ]; then
   sudo brctl delbr $internalif >/dev/null #Why? See below.
fi
sudo rm /var/lib/misc/dnsmasq.$internalif.leases
sudo service lxc-net start >/dev/null
sudo lxc-start -d -n $name >/dev/null
sleep 5

На жаль, /etc/init/lxc-net.confв Ubuntu 14.04 є помилка (функція?), Яка запобігає перезавантаженню, dnsmasqякщо тільки не встановлено пристрій мосту для хоста.


0

Це рішення працює шляхом виправлення скриптів на початку lxc. Це розділяє складну задачу - підняти міст lxcbr0 і запустити a dnsmasqна два окремих завдання. Тепер вам не потрібно перезапускати весь lxc-netміст, щоб просто перезавантажити dnsmasq- перезавантаження sudo service restart lxc-dnsmasqдостатня і не вимагає відключення моста.

  1. Припиніть послугу lxc-net sudo service lxc-net stopі переконайтесь, що немає моста lxcbr0 (або аналогічного) вгору.
  2. Змініть вміст /etc/init/lxc-net.confна наступний вміст:

.

description "lxc network"
author "Serge Hallyn <serge.hallyn@canonical.com>"

start on starting lxc
stop on stopped lxc

env USE_LXC_BRIDGE="true"
env LXC_BRIDGE="lxcbr0"
env LXC_ADDR="10.0.3.1"
env LXC_NETMASK="255.255.255.0"
env LXC_NETWORK="10.0.3.0/24"
env varrun="/run/lxc"
env LXC_DOMAIN=""

pre-start script
    [ -f /etc/default/lxc ] && . /etc/default/lxc

    [ "x$USE_LXC_BRIDGE" = "xtrue" ] || { stop; exit 0; }

    use_iptables_lock="-w"
    iptables -w -L -n > /dev/null 2>&1 || use_iptables_lock=""
    cleanup() {
        # dnsmasq failed to start, clean up the bridge
        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT
        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT
        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT
        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT
        iptables $use_iptables_lock -D FORWARD -i ${LXC_BRIDGE} -j ACCEPT
        iptables $use_iptables_lock -D FORWARD -o ${LXC_BRIDGE} -j ACCEPT
        iptables $use_iptables_lock -t nat -D POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE || true
        iptables $use_iptables_lock -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
    }
    if [ -d /sys/class/net/${LXC_BRIDGE} ]; then
        if [ ! -f ${varrun}/network_up ]; then
            # bridge exists, but we didn't start it
            stop;
        fi
        exit 0;
    fi

    # set up the lxc network
    brctl addbr ${LXC_BRIDGE} || { echo "Missing bridge support in kernel"; stop; exit 0; }
    echo 1 > /proc/sys/net/ipv4/ip_forward
    mkdir -p ${varrun}
    ifconfig ${LXC_BRIDGE} ${LXC_ADDR} netmask ${LXC_NETMASK} up
    iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT
    iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT
    iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT
    iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT
    iptables $use_iptables_lock -I FORWARD -i ${LXC_BRIDGE} -j ACCEPT
    iptables $use_iptables_lock -I FORWARD -o ${LXC_BRIDGE} -j ACCEPT
    iptables $use_iptables_lock -t nat -A POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE
    iptables $use_iptables_lock -t mangle -A POSTROUTING -o ${LXC_BRIDGE} -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill

    touch ${varrun}/network_up
end script

post-stop script
    [ -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
        use_iptables_lock="-w"
        iptables -w -L -n > /dev/null 2>&1 || use_iptables_lock=""
        ifconfig ${LXC_BRIDGE} down
        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT
        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT
        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT
        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT
        iptables $use_iptables_lock -D FORWARD -i ${LXC_BRIDGE} -j ACCEPT
        iptables $use_iptables_lock -D FORWARD -o ${LXC_BRIDGE} -j ACCEPT
        iptables $use_iptables_lock -t nat -D POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE || true
        iptables $use_iptables_lock -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
end script
  1. Додайте ще один файл /etc/init/lxc-dnsmasqіз таким вмістом:

.

description "lxc dnsmasq service"
author "Adam Ryczkowski, ispired by Serge Hallyn <serge.hallyn@canonical.com>"

expect fork

start on started lxc-net
stop on stopped lxc-net

env USE_LXC_BRIDGE="true"
env LXC_BRIDGE="lxcbr0"
env LXC_ADDR="10.0.3.1"
env LXC_NETMASK="255.255.255.0"
env LXC_NETWORK="10.0.3.0/24"
env LXC_DHCP_RANGE="10.0.3.2,10.0.3.254"
env LXC_DHCP_MAX="253"
env LXC_DHCP_CONFILE=""
env varrun="/run/lxc-dnsmasq"
env LXC_DOMAIN=""

pre-start script
    [ -f /etc/default/lxc ] && . /etc/default/lxc

    [ "x$USE_LXC_BRIDGE" = "xtrue" ] || { stop; exit 0; }

    if [ ! -d ${varrun} ]; then
        mkdir -p ${varrun}
    fi
    opts="$LXC_DOMAIN_ARG -u lxc-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/dnsmasq2.${LXC_BRIDGE}.leases --dhcp-authoritative --keep-in-foreground"

    /usr/sbin/dnsmasq $opts &

end script

post-stop script
    if [ -f ${varrun}/dnsmasq.pid ]; then
        PID=`cat ${varrun}/dnsmasq.pid`
        kill $PID
    fi
end script

0

Ось простий скрипт python, який випускає в оренду LXC dnsmasq. Ви можете запустити його з хост-машини або підробити з іншого контейнера - так, це працює !:

#!/usr/bin/env python
from scapy.all import *
conf.checkIPaddr=False
leaseMAC = '00:16:3e:11:71:b0' #container MAC here
releaseIP='10.0.3.33' #container IP here
serverIP='10.0.3.1'
hostname='container-name-here'
rawMAC = leaseMAC.replace(':','').decode('hex')
send(IP(dst=serverIP) / \
     UDP(sport=68,dport=67) / \
     BOOTP(chaddr=rawMAC, ciaddr=releaseIP, xid=RandInt()) / \
     DHCP(options=[('message-type','release'),('server_id',serverIP),('hostname',hostname), ('end')]))

Обов'язковою умовою для цього є скапірована бібліотека пітонів:

pip install scapy

Після запуску ви побачите в системному журналі щось на зразок:

dnsmasq-dhcp[3242]: DHCPRELEASE(lxcbr0) 10.0.3.33 00:16:3e:11:71:b0 container-name-here

Щоб підтвердити, просто перевірте, чи видалено запис із /var/lib/misc/dnsmasq.lxcbr0.leases. Сам контейнер зберігатиме IP, тому його слід зупинити перед запуском нового контейнера, який повинен повторно використовувати IP.


1
Круто! Я навіть не знав, що DHCP це підтримує! Я поверну пропозицію одразу після того, як я підтверджу, що це працює.
Адам Річковський

0

Я усвідомлюю, що моя відповідь запізнилася на роки, але, можливо, це допомагає комусь іншому. Проблема полягала в тому, що ви редагували код, специфічний для пакету ( write_lxc_netфункції) LXC Ubuntu, який мав бути записаний до іншого пункту призначення у вигляді рядка, а не обробляється в межах самого lxc-netсценарію!

Як результат, процес dnsmasq не отримав конфігураційний файл, який ви намагалися передати, не залишивши, як ви говорите, "без ефекту".

Натомість, ви хочете встановити цю змінну біля верхньої частини сценарію, серед решти:

#!/bin/sh -

distrosysconfdir="/etc/default"
varrun="/run/lxc"
varlib="/var/lib"

# These can be overridden in /etc/default/lxc
#   or in /etc/default/lxc-net

USE_LXC_BRIDGE="true"
LXC_BRIDGE="lxcbr0"
LXC_BRIDGE_MAC="00:16:3e:00:00:00"
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"   <-- Here for instance
LXC_DOMAIN=""
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.