So lassen Sie integriertes DHCP dem LXC-Container eine statische IP basierend auf dem Namen und nicht der MAC-Adresse zuweisen

10

Ich weiß, dass ich statische IP manuell mit zuweisen kann /etc/network/interfaces.

Ich weiß auch, dass ich die MAC-Adresse des LXC-Containers lesen kann (z. B. indem ich nach einem lxc.network.hwaddrEintrag in suche /var/lib/lxc/<container-name>/configund die IP anhand von Einträgen dhcp-host=<mac-addr>,10.0.3.3in zuweise /etc/dnsmasq.d/<some file>.

In der Datei habe /etc/default/lxc-netich gelesen

# 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

Das würde meinen Bedürfnissen entsprechen; dies hat leider keine auswirkung.

Adam Ryczkowski
quelle
2
Es funktioniert für mich, aber beachten Sie, dass Sie lxc-net neu starten müssen, damit es wirksam wird. Und es gibt ein bekanntes Problem, dass lxc-net nicht neu gestartet wird, wenn gerade ein Container gestartet wird. Sie müssen alle stoppen und dann den lxc-net-Dienst neu starten.
HRJ
Außerdem konnte ich IP-Adressen nicht allein anhand des Containernamens zuweisen. Ich musste eine MAC-Adresse für den Container und für die DHCP-Konfiguration fest codieren.
HRJ
@HRJ, könnten Sie bitte Ihre Datei dnsmasq.conf posten?
Tonytony
@HRJ Unter Ubuntu 14.04 lxc-nethilft ein Neustart nicht, wenn Sie Ihre lxcbr0-Brücke nicht entfernen. Siehe meine Antwort.
Adam Ryczkowski

Antworten:

17

Ich bin kürzlich darauf gestoßen und denke, ich habe eine einfache Lösung gefunden. Ich habe es (nur) unter Ubuntu 14.04 getestet.

Kommentieren Sie zunächst diese Zeile / etc / default / lxc-net aus:

LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

Definieren Sie in /etc/lxc/dnsmasq.conf eine dhcp-hosts-Datei:

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

Fügen Sie dann Einträge in /etc/lxc/dnsmasq-hosts.conf wie folgt hinzu:

mail,10.0.3.16
web,10.0.3.17

Achtung: Änderungen werden wirksam, nachdem Sie lxc-net neu gestartet haben (wodurch dnsmasq neu gestartet wird):

service lxc-net restart

Anschließend können Sie /etc/lxc/dnsmasq-hosts.conf ändern und das SIGHUP-Signal an dnsmasq senden:

killall -s SIGHUP dnsmasq

Also ja, Sie müssen lxc-net neu starten, aber nur einmal. Hoffe das hilft.

mtp
quelle
Ich mag die Idee, eine Liste von Hosts an eine externe Datei zu delegieren. Außerdem unterscheidet sich Ihre Methode von meiner aufgrund der killall -s SIGHUP dnsmasq. Ich bin damit einverstanden, dass nur "SIGHUP-ing" dnsmasq effizienter ist als ein Neustart des gesamten Daemons (insbesondere, wenn es nicht funktioniert, ohne seine Upstart-Skripte zu patchen).
Adam Ryczkowski
Ein Neustart des Dienstes lxc-netist nur erforderlich, damit der dnsmasq die Konfiguration von /etc/lxc/dnsmasq.conf verwenden kann (und diese Information ist in der vorhanden, die /etc/default/lxc-netdem unbekannt ist dnsmasq). Wenn Sie es schon einmal eingestellt hatten, sollte nur ein weiteres SIGHUP ausreichen.
Adam Ryczkowski
Achtung: lxc-net startet dnsmasq nicht neu, wenn Container ausgeführt werden.
s3v3n
IMO das ist die beste Antwort
s3v3n
kill -HUP $(cat /var/run/lxc/dnsmasq.pid)Wenn Sie keine killallanderen dnsmasqInstanzen installieren oder neu laden möchten
gertas
4

Es funktioniert gut in Ubuntu 14.04.1

Kommentieren Sie diese Zeile aus /etc/default/lxc-net

#LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

Stoppen Sie alle Container und starten Sie lxc-net neu:

service lxc-net restart

Konfigurieren Sie IP-Adressen in /etc/lxc/dnsmasq.conf

dhcp-host={NAME},10.0.3.2

Wo {NAME}ist der Name Ihres LXC-Containers:

/var/lib/lxc/{NAME}
Tombart
quelle
Dies funktioniert nur, wenn das Skript das lxcbr0-Netzwerk herunterfahren kann. Dies schließt den Fall aus, dass andere lxc-Container ausgeführt werden. Kurz gesagt, Sie können derzeit keine statischen DHCP-Leases zuweisen, ohne alle Container neu zu starten.
Adam Ryczkowski
Ja, das stimmt, es ist ziemlich unpraktisch :(. Ich finde eine viel einfachere Lösung, um /var/lib/lxc/<container-name>/rootfs/etc/network/interfacesDateien zu bearbeiten und dem Container eine statische IP-Adresse zuzuweisen.
Tombart
Stimmt, aber nichts schützt Sie davor, zwei Gästen dieselbe IP zu geben. Siehe meine akzeptierte Antwort - es löst das Problem.
Adam Ryczkowski
1

Die Antwort des Tombart funktioniert, wenn Sie geduldig genug sind, um auf die DNS-Aktualisierung zu warten, UND wenn Sie bereit sind, den Container (den Gast) anschließend neu zu starten.

Was folgt, ist das Rezept, das erfordert, dass alle anderen möglicherweise laufenden lxc-Container heruntergefahren werden . Wenn Sie sich das nicht leisten können, sehe ich keine Möglichkeit, eine neue dnsmasq-Konfiguration zu erzwingen. (Aus irgendeinem Grund funktioniert die Signalisierung von HUP an dnsmasqs in gefundene PID /run/lxc/dnsmasq.pidauch nicht.)

Wenn Sie also etwas haben möchten, das sofort funktioniert und keine anderen lxc-Container ausgeführt werden, folgen Sie meiner Antwort. $nameist der Name des Knotens, für den wir die Zuweisung zurücksetzen möchten, und $internalifder Name des überbrückten Adapters des LXC. Sie können den Wert von $internalifmit erhalten, z. B. augtool -L -A --transform "Shellvars incl /etc/default/lxc-net" get "/files/etc/default/lxc-net/LXC_BRIDGE" | sed -En 's/\/.* = (.*)/\1/p'wenn Sie installieren, augeas-toolsaber normalerweise ist es nur so 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

Leider gibt es /etc/init/lxc-net.confin Ubuntu 14.04 einen Fehler (Feature?) , Der das Neuladen verhindert, es dnsmasqsei denn, das Bridge-Gerät ist für den Host ausgefallen.

Adam Ryczkowski
quelle
0

Diese Lösung funktioniert durch Patchen der lxc-Upstart-Skripte. Die komplexe Aufgabe, die lxcbr0-Brücke hochzufahren und a zu starten, wird dnsmasqin zwei separate Jobs aufgeteilt. Jetzt müssen Sie nicht mehr die gesamte lxc-netBrücke neu starten, um nur die Brücke neu zu laden. Das dnsmasqNachladen der Brücke sudo service restart lxc-dnsmasqist ausreichend und erfordert kein Herunterfahren der Brücke.

  1. Beenden Sie den lxc-net-Dienst sudo service lxc-net stopund stellen Sie sicher, dass keine lxcbr0-Brücke (oder eine gleichwertige Brücke) vorhanden ist.
  2. Ersetzen Sie den Inhalt von /etc/init/lxc-net.confdurch den folgenden Inhalt:

.

description "lxc network"
author "Serge Hallyn <[email protected]>"

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. Fügen Sie eine weitere Datei /etc/init/lxc-dnsmasqmit folgendem Inhalt hinzu:

.

description "lxc dnsmasq service"
author "Adam Ryczkowski, ispired by Serge Hallyn <[email protected]>"

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
Adam Ryczkowski
quelle
0

Hier ist ein einfaches Python-Skript, das LXC dnsmasq lease veröffentlicht. Sie können es vom Host-Computer ausführen oder von einem anderen Container aus fälschen - ja, das funktioniert!:

#!/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')]))

Voraussetzung dafür ist die Scapy-Python-Bibliothek:

pip install scapy

Nach dem Ausführen sollte im Systemprotokoll Folgendes angezeigt werden:

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

Zur Bestätigung überprüfen Sie einfach, ob der Eintrag von entfernt wurde /var/lib/misc/dnsmasq.lxcbr0.leases. Der Container selbst behält die IP bei, daher sollte er gestoppt werden, bevor ein neuer Container gestartet wird, der die IP wiederverwenden soll.

gertas
quelle
1
Das ist cool! Ich wusste nicht einmal, dass DHCP das unterstützt! Ich werde sofort nach der Bestätigung, dass es funktioniert, upvoten.
Adam Ryczkowski
0

Mir ist klar, dass meine Antwort Jahre zu spät ist, aber vielleicht hilft sie jemand anderem. Das Problem war, dass Sie Code speziell für das LXC Ubuntu-Paket ( write_lxc_netFunktion) bearbeitet haben, der als Zeichenfolge an ein anderes Ziel geschrieben werden sollte und nicht im lxc-netSkript selbst verarbeitet wurde!

Infolgedessen hat der dnsmasq- Prozess die Konfigurationsdatei, die Sie zu übergeben versucht haben, nicht erhalten, sodass Sie, wie Sie sagen, "keine Auswirkung" haben.

Stattdessen möchten Sie diese Variable unter anderem am oberen Rand des Skripts festlegen:

#!/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=""
Adrian
quelle