如何让内置DHCP根据名称而不是MAC地址为LXC容器分配静态IP

我知道,我可以使用/etc/network/interfaces手动分配静态IP。

我也知道,我可以读取LXC容器的MAC地址(例如,通过查找/var/lib/lxc//config lxc.network.hwaddr条目,并使用条目dhcp-host=,10.0.3.3分配IP dhcp-host=,10.0.3.3 in /etc/dnsmasq.d/

在文件/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 

这符合我的需要; 不幸的是,这样做没有效果。

我最近碰到了这个,我想我找到了一个简单的解决方案。 我(仅)在Ubuntu 14.04上测试过它。

首先,取消注释此行/ etc / default / lxc-net:

 LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf 

在/etc/lxc/dnsmasq.conf中,定义一个dhcp-hosts文件:

 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,但只需要重启一次。 希望这可以帮助。

它在Ubuntu 14.04.1中运行良好

取消注释此行/etc/default/lxc-net

 #LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf 

停止所有容器,重启lxc-net:

 service lxc-net restart 

/etc/lxc/dnsmasq.conf配置ip地址

 dhcp-host={NAME},10.0.3.2 

其中{NAME}是LXC容器的名称:

 /var/lib/lxc/{NAME} 

如果您有足够的耐心等待DNS刷新并且您愿意在之后重新启动容器(访客),那么Tombart的答案就有效。

以下是需要关闭所有其他可能正在运行的lxc容器的配方。 如果你负担不起,那么我认为没有办法强迫新的dnsmasq配置。 (对于某些原因,在/run/lxc/dnsmasq.pid中发现的HUP到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' 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 

不幸的是,Ubuntu 14.04中的/etc/init/lxc-net.conf中存在一个错误(function?),它阻止重新加载dnsmasq除非桥接设备关闭主机。

此解决方案通过修补lxc upstart脚本来工作。 它确实分裂了将lxcbr0桥接起来并将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 " 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 " 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 

这是简单的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')])) 

上面的基本要求是scapy python库:

 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的新容器之前停止它。

我意识到我的答案已经很晚了,但也许它可以帮助别人。 问题在于您编辑了特定于LXC Ubuntu软件包( write_lxc_net函数)的代码,该代码旨在作为字符串写入另一个目标,而不是在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=""