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


10

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

我也知道,我可以读取LXC容器的MAC地址(例如,通过在中查找lxc.network.hwaddr条目/var/lib/lxc/<container-name>/config并使用中的条目dhcp-host=<mac-addr>,10.0.3.3来分配IP)/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 2014年

另外,我不能仅使用容器名称来分配IP地址。我必须对容器和DHCP配置的MAC地址进行硬编码。
HRJ 2014年

@HRJ,您可以张贴dnsmasq.conf文件吗?
tonytony 2014年

@HRJ在Ubuntu 14.04 lxc-net上,如果不删除lxcbr0桥,重启将无济于事。看我的答案。
亚当·里奇科夫斯基

Answers:


17

我最近遇到了这个问题,我想我找到了一个简单的解决方案。我(仅)在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。希望这可以帮助。


我喜欢将主机列表委派给外部文件的想法。除此之外,由于,您的方法与我的方法不同killall -s SIGHUP dnsmasq。我同意,只是“ SIGHUP-ing” dnsmasq比重新启动整个守护程序更为有效(特别是如果不修补其新贵脚本就无法运行的话)。
亚当·里奇科夫斯基

lxc-net仅需要重新启动服务,才能使dnsmasq使用/etc/lxc/dnsmasq.conf中的配置(并且这条信息存在于/etc/default/lxc-net未知dnsmasq)中。如果您之前进行过设置,则只需另一个SIGHUP就足够了。
亚当·里奇科夫斯基

注意:如果有正在运行的容器,lxc-net将不会重新启动dnsmasq。
s3v3n 2015年

IMO这是最好的答案
s3v3n 2015年

kill -HUP $(cat /var/run/lxc/dnsmasq.pid)如果您不想安装killall或重新加载其他dnsmasq实例
gertas,2016年

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

如果您有足够的耐心等待DNS刷新并且您随后愿意重新启动容器(来宾),则Tombart的答案有效。

接下来是需要关闭所有其他可能正在运行的lxc容器的方法。如果您负担不起,那么我认为没有办法强制执行新的dnsmasq配置。(出于某些原因,将HUP发送到dnsmasq的pid /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.confUbuntu 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

这是释放LXC dnsmasq租约的简单python脚本。您可以从主机运行它,也可以从另一个容器伪造它-是的,可以使用!:

#!/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的新容器之前将其停止。


1
这很酷!我什至不知道DHCP支持该功能!确认有效后,我将立即投票。
亚当·里奇科夫斯基

0

我知道我的答案迟了几年,但也许对其他人有帮助。问题是您编辑了特定于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=""
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.