Come consentire al DHCP incorporato di assegnare un IP statico al contenitore LXC in base al nome, non all'indirizzo MAC


10

So che posso assegnare manualmente un IP statico, usando /etc/network/interfaces.

So anche che posso leggere l'indirizzo MAC del contenitore LXC (ad es. Cercando la lxc.network.hwaddrvoce in entrata /var/lib/lxc/<container-name>/confige assegnando l'IP in base usando le voci dhcp-host=<mac-addr>,10.0.3.3in /etc/dnsmasq.d/<some file>.

Nel file che /etc/default/lxc-netho letto

# 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

Sarebbe adatto alle mie esigenze; purtroppo farlo non ha alcun effetto.


2
Funziona per me, ma nota che devi riavviare lxc-net affinché abbia effetto. E c'è un problema noto che lxc-net non si riavvia se un container è attualmente avviato. È necessario arrestarli tutti e quindi riavviare il servizio lxc-net.
HRJ,

Inoltre, non sono stato in grado di assegnare gli indirizzi IP usando solo il nome del contenitore. Ho dovuto codificare un indirizzo MAC per il contenitore e per la configurazione DHCP.
HRJ,

@HRJ, potresti pubblicare il tuo file dnsmasq.conf per favore?
tonytony,

@HRJ Su Ubuntu 14.04 il riavvio lxc-netnon aiuta se non si rimuove il bridge lxcbr0. Vedi la mia risposta
Adam Ryczkowski,

Risposte:


17

Mi sono imbattuto di recente in questo e penso di aver trovato una soluzione facile. L'ho (solo) testato su Ubuntu 14.04.

Per prima cosa, decommenta questa riga / etc / default / lxc-net:

LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

In /etc/lxc/dnsmasq.conf, definire un file dhcp:

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

Quindi aggiungi le voci in /etc/lxc/dnsmasq-hosts.conf in questo modo:

mail,10.0.3.16
web,10.0.3.17

Attenzione: le modifiche diventeranno effettive dopo aver riavviato lxc-net (che riavvia dnsmasq):

service lxc-net restart

Successivamente puoi modificare /etc/lxc/dnsmasq-hosts.conf e inviare il segnale SIGHUP a dnsmasq:

killall -s SIGHUP dnsmasq

Quindi sì, è necessario riavviare lxc-net, ma solo una volta. Spero che sia di aiuto.


Mi piace l'idea di delegare l'elenco di host a un file esterno. Oltre a ciò, il tuo metodo differisce dal mio a causa del killall -s SIGHUP dnsmasq. Concordo sul fatto che solo "SIGHUP-ing" dnsmasq è più efficiente del riavvio dell'intero demone (specialmente se non funziona senza patchare gli script di avvio).
Adam Ryczkowski l'

Il riavvio del servizio lxc-netè necessario solo per consentire a dnsmasq di utilizzare la configurazione da /etc/lxc/dnsmasq.conf (e questa informazione è presente nella /etc/default/lxc-netquale non è nota dnsmasq). Se lo avevi impostato prima, basta un altro SIGHUP.
Adam Ryczkowski l'

Attenzione: lxc-net non riavvierà dnsmasq se ci sono contenitori in esecuzione.
s3v3n,

IMO questa è la risposta migliore
s3v3n

kill -HUP $(cat /var/run/lxc/dnsmasq.pid)se non vuoi installare killallo ricaricare altre dnsmasqistanze
gertas,

4

Funziona bene in Ubuntu 14.04.1

Annulla commento questa riga /etc/default/lxc-net

#LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

arrestare tutti i contenitori, riavviare lxc-net:

service lxc-net restart

Configura gli indirizzi IP in /etc/lxc/dnsmasq.conf

dhcp-host={NAME},10.0.3.2

dov'è {NAME}il nome del tuo contenitore LXC:

/var/lib/lxc/{NAME}

Funziona solo se lo script può arrestare la rete lxcbr0 , il che esclude il caso in cui sono in esecuzione altri contenitori lxc. In breve, così come è ora, non è possibile assegnare locazioni dhcp statiche senza riavviare tutti i contenitori.
Adam Ryczkowski il

Sì, è vero, è abbastanza scomodo :(. Trovo una soluzione molto più semplice per modificare il /var/lib/lxc/<container-name>/rootfs/etc/network/interfacesfile e assegnare un indirizzo IP statico al contenitore.
Tombart,

Vero, ma non c'è nulla per proteggerti dal dare a due ospiti lo stesso IP. Vedi la mia risposta accettata - risolve il problema.
Adam Ryczkowski,

1

La risposta di Tombart funziona se si è abbastanza pazienti da attendere l'aggiornamento DNS E si è disposti a riavviare il contenitore (il guest) in seguito.

Quella che segue è la ricetta che richiede che tutti gli altri contenitori lxc eventualmente in esecuzione siano chiusi . Se non puoi permetterlo, non vedo alcun modo di forzare la nuova configurazione di dnsmasq. (Per alcuni motivi di segnalazione HUP al pid di dnsmasq trovato in /run/lxc/dnsmasq.pidnon funziona neanche.)

Quindi, se vuoi avere qualcosa che funzioni all'istante e non ci sono altri contenitori lxc in esecuzione, segui la mia risposta. $nameè il nome del nodo per il quale vogliamo ripristinare l'assegnazione ed $internalifè il nome dell'adattatore con bridge dell'LXC. È possibile ottenere il valore di $internalifcon es. augtool -L -A --transform "Shellvars incl /etc/default/lxc-net" get "/files/etc/default/lxc-net/LXC_BRIDGE" | sed -En 's/\/.* = (.*)/\1/p'Se si installa, augeas-toolsma di solito è giusto 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

Sfortunatamente, /etc/init/lxc-net.confin Ubuntu 14.04 è presente un bug (funzionalità?) Che impedisce di ricaricare il dnsmasqdispositivo a meno che il dispositivo bridge non sia inattivo per l'host.


0

Questa soluzione funziona correggendo gli script upstart di lxc. Suddivide il complesso compito di portare in alto il bridge lxcbr0 e di iniziare a dnsmasqin due lavori separati. Ora non è necessario riavviare l'intero lxc-netbridge per ricaricare il dnsmasq- ricaricare sudo service restart lxc-dnsmasqè sufficiente e non è necessario chiudere il bridge.

  1. Arrestare il servizio lxc-net sudo service lxc-net stope assicurarsi che non vi sia alcun ponte lxcbr0 (o equivalente).
  2. Sostituisci il contenuto del /etc/init/lxc-net.confcon il seguente contenuto:

.

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. Aggiungi un altro file, /etc/init/lxc-dnsmasqcon i seguenti contenuti:

.

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

Ecco un semplice script Python che rilascia LXC dnsmasq lease. Puoi eseguirlo dal computer host o forgiarlo da un altro contenitore - sì, funziona !:

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

La perequità di cui sopra è la libreria Python Scapy:

pip install scapy

Una volta eseguito dovresti vedere nel registro di sistema qualcosa come:

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

Per confermare basta controllare se la voce è stata rimossa da /var/lib/misc/dnsmasq.lxcbr0.leases. Il contenitore stesso manterrà l'IP, quindi dovrebbe essere arrestato prima di avviare qualsiasi nuovo contenitore che dovrebbe riutilizzare l'IP.


1
Questo è figo! Non sapevo nemmeno che DHCP lo supporta! Voterò subito dopo aver confermato che funziona.
Adam Ryczkowski il

0

Mi rendo conto che la mia risposta è in ritardo di anni, ma forse aiuta qualcun altro. Il problema era che hai modificato il codice specifico del pacchetto ( write_lxc_netfunzione) di Ubuntu LXC che doveva essere scritto su un'altra destinazione come stringa, non elaborato all'interno dello lxc-netscript stesso!

Di conseguenza, il processo dnsmasq non ha ricevuto il file di configurazione che hai provato a passarlo, lasciandoti senza "effetto", come dici tu.

Invece, ti consigliamo di impostare questa variabile nella parte superiore dello script, tra le altre:

#!/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=""
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.