Comment laisser le DHCP intégré attribuer une IP statique au conteneur LXC en fonction du nom, et non de l'adresse MAC

10

Je sais que je peux attribuer une adresse IP statique manuellement à l'aide de /etc/network/interfaces.

Je sais également que je peux lire l'adresse MAC du conteneur LXC (par exemple en recherchant l' lxc.network.hwaddrentrée dans /var/lib/lxc/<container-name>/configet en attribuant l'IP en utilisant les entrées dhcp-host=<mac-addr>,10.0.3.3dans /etc/dnsmasq.d/<some file>.

Dans le dossier que /etc/default/lxc-netj'ai lu

# 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

Cela conviendrait à mes besoins; malheureusement, cela n'a aucun effet.

Adam Ryczkowski
la source
2
Cela fonctionne pour moi, mais notez que vous devez redémarrer lxc-net pour qu'il prenne effet. Et il existe un problème connu selon lequel lxc-net ne redémarre pas si un conteneur est actuellement démarré. Vous devez tous les arrêter, puis redémarrer le service lxc-net.
HRJ
De plus, je n'ai pas pu attribuer d'adresses IP en utilisant le nom du conteneur seul. J'ai dû coder en dur une adresse MAC pour le conteneur et pour la configuration DHCP.
HRJ
@HRJ, pourriez-vous publier votre fichier dnsmasq.conf s'il vous plaît?
tonytony
@HRJ Sur Ubuntu 14.04, le redémarrage lxc-netn'aide pas si vous ne supprimez pas votre pont lxcbr0. Voir ma réponse.
Adam Ryczkowski

Réponses:

17

Je l'ai rencontré récemment et je pense avoir trouvé une solution simple. Je l'ai (uniquement) testé sur Ubuntu 14.04.

Tout d'abord, décommentez cette ligne / etc / default / lxc-net:

LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

Dans /etc/lxc/dnsmasq.conf, définissez un fichier dhcp-hosts:

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

Ajoutez ensuite des entrées dans /etc/lxc/dnsmasq-hosts.conf comme ceci:

mail,10.0.3.16
web,10.0.3.17

Attention: les modifications ne seront effectives qu'après le redémarrage de lxc-net (qui redémarre dnsmasq):

service lxc-net restart

Ensuite, vous pouvez modifier /etc/lxc/dnsmasq-hosts.conf et envoyer le signal SIGHUP à dnsmasq:

killall -s SIGHUP dnsmasq

Alors oui, vous devez redémarrer lxc-net, mais une seule fois. J'espère que cela t'aides.

mtp
la source
J'aime l'idée de déléguer la liste des hôtes à un fichier externe. En plus de cela, votre méthode diffère de la mienne en raison de la killall -s SIGHUP dnsmasq. Je suis d'accord, que juste "SIGHUP-ing" dnsmasq est plus efficace que de redémarrer tout le démon (surtout s'il ne fonctionne pas sans patcher ses scripts parvenus).
Adam Ryczkowski
Le redémarrage du service lxc-netn'est nécessaire que pour permettre au dnsmasq d'utiliser la configuration à partir de /etc/lxc/dnsmasq.conf (et cette information est présente dans le /etc/default/lxc-netqui est inconnu du dnsmasq). Si vous l'aviez réglé auparavant, un autre SIGHUP devrait suffire.
Adam Ryczkowski
Attention: lxc-net ne redémarrera pas dnsmasq s'il y a des conteneurs en cours d'exécution.
s3v3n
OMI, c'est la meilleure réponse
s3v3n
kill -HUP $(cat /var/run/lxc/dnsmasq.pid)si vous ne voulez pas installer killallou recharger d'autres dnsmasqinstances
gertas
4

Cela fonctionne bien dans Ubuntu 14.04.1

Décommenter cette ligne /etc/default/lxc-net

#LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

arrêtez tous les conteneurs, redémarrez lxc-net:

service lxc-net restart

Configurer les adresses IP dans /etc/lxc/dnsmasq.conf

dhcp-host={NAME},10.0.3.2

{NAME}est le nom de votre conteneur LXC:

/var/lib/lxc/{NAME}
Tombart
la source
Cela ne fonctionne que si le script peut arrêter le réseau lxcbr0 , ce qui exclut le cas où d'autres conteneurs lxc sont en cours d'exécution. En bref, dans l'état actuel des choses, vous ne pouvez pas attribuer de baux statiques DHCP sans redémarrer tous les conteneurs.
Adam Ryczkowski
Oui, c'est vrai, c'est assez gênant :(. Je trouve une solution beaucoup plus facile pour modifier le /var/lib/lxc/<container-name>/rootfs/etc/network/interfacesfichier et attribuer une adresse IP statique au conteneur.
Tombart
Certes, mais rien ne vous protège contre le fait de donner à deux invités la même adresse IP. Voir ma réponse acceptée - elle résout le problème.
Adam Ryczkowski
1

La réponse de Tombart fonctionne si vous êtes assez patient pour attendre le rafraîchissement DNS ET que vous êtes prêt à redémarrer le conteneur (l'invité) par la suite.

Ce qui suit est la recette qui nécessite que tous les autres conteneurs lxc éventuellement en cours d'exécution soient arrêtés . Si vous ne pouvez pas vous le permettre, je ne vois aucun moyen de forcer une nouvelle configuration dnsmasq. (Pour certains reasone signalant HUP au pid de dnsmasq trouvé dans /run/lxc/dnsmasq.pidne fonctionne pas non plus.)

Donc, si vous voulez que quelque chose fonctionne instantanément et qu'aucun autre conteneur lxc ne fonctionne, suivez ma réponse. $nameest le nom du nœud pour lequel nous voulons réinitialiser l'affectation, et $internalifest le nom de l'adaptateur ponté du LXC. Vous pouvez obtenir la valeur de $internalifavec par exemple augtool -L -A --transform "Shellvars incl /etc/default/lxc-net" get "/files/etc/default/lxc-net/LXC_BRIDGE" | sed -En 's/\/.* = (.*)/\1/p'si vous installez, augeas-toolsmais généralement c'est juste 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

Malheureusement, il existe un bogue (fonctionnalité?) Dans /etc/init/lxc-net.confUbuntu 14.04 qui empêche le rechargement du à dnsmasqmoins que le périphérique de pont ne soit en panne pour l'hôte.

Adam Ryczkowski
la source
0

Cette solution fonctionne en corrigeant les scripts lxc upstart. Il divise la tâche complexe consistant à mettre en place le pont lxcbr0 et à démarrer un dnsmasqen deux travaux distincts. Maintenant, vous n'avez pas besoin de redémarrer l'ensemble du lxc-netpont pour simplement recharger le dnsmasq- recharger le sudo service restart lxc-dnsmasqest suffisant et ne nécessite pas d'arrêter le pont.

  1. Arrêtez le service lxc-net sudo service lxc-net stopet assurez-vous qu'il n'y a pas de pont lxcbr0 (ou équivalent).
  2. Remplacez le contenu du /etc/init/lxc-net.confpar le contenu suivant:

.

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. Ajoutez un autre fichier, /etc/init/lxc-dnsmasqavec le contenu suivant:

.

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
la source
0

Voici un script python simple qui libère le bail LXC dnsmasq. Vous pouvez l'exécuter à partir de la machine hôte ou le forger à partir d'un autre conteneur - oui cela fonctionne!:

#!/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 condition préalable à ce qui précède est la bibliothèque de python scapy:

pip install scapy

Une fois exécuté, vous devriez voir dans le journal système quelque chose comme:

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

Pour confirmer, vérifiez simplement si l'entrée est supprimée de /var/lib/misc/dnsmasq.lxcbr0.leases. Le conteneur lui-même conservera l'IP, il doit donc être arrêté avant de démarrer tout nouveau conteneur qui devrait réutiliser l'IP.

gertas
la source
1
C'est super! Je ne savais même pas que DHCP supporte ça! Je voterai immédiatement après avoir confirmé que cela fonctionne.
Adam Ryczkowski
0

Je réalise que ma réponse a des années de retard, mais peut-être que cela aide quelqu'un d'autre. Le problème était que vous avez édité du code spécifique au package Ubuntu LXC ( write_lxc_netfonction) qui devait être écrit dans une autre destination sous forme de chaîne, non traité dans le lxc-netscript lui-même!

Par conséquent, le processus dnsmasq n'a pas reçu le fichier de configuration que vous avez essayé de le transmettre, vous laissant "sans effet", comme vous le dites.

Au lieu de cela, vous souhaitez définir cette variable près du haut du script, parmi les autres:

#!/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
la source