Cách để DHCP tích hợp gán IP tĩnh cho vùng chứa LXC dựa trên tên, không phải địa chỉ MAC


10

Tôi biết rằng tôi có thể gán IP tĩnh bằng tay, bằng cách sử dụng /etc/network/interfaces.

Tôi cũng biết, tôi có thể đọc địa chỉ MAC của container LXC (ví dụ bằng cách tìm kiếm lxc.network.hwaddrmục trong /var/lib/lxc/<container-name>/configvà gán IP dựa sử dụng các mục dhcp-host=<mac-addr>,10.0.3.3trong /etc/dnsmasq.d/<some file>.

Trong tập tin /etc/default/lxc-nettôi đọc

# 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

Điều đó sẽ phù hợp với nhu cầu của tôi; Thật không may làm như vậy không có hiệu lực.


2
Nó hoạt động với tôi, nhưng lưu ý rằng bạn phải khởi động lại lxc-net để nó có hiệu lực. có một vấn đề được biết rằng lxc-net không khởi động lại nếu bất kỳ container nào hiện đang bắt đầu. Bạn cần dừng tất cả chúng và sau đó khởi động lại dịch vụ lxc-net.
HRJ

Ngoài ra, tôi không thể chỉ định địa chỉ IP bằng tên container. Tôi đã phải mã hóa một địa chỉ MAC cho vùng chứa và cho cấu hình DHCP.
HRJ

@HRJ, bạn có thể gửi tập tin dnsmasq.conf của bạn không?
tonytony

@HRJ Trên Ubuntu 14.04, khởi động lại lxc-netkhông giúp ích gì nếu bạn không xóa cầu nối lxcbr0 của mình. Xem câu trả lời của tôi.
Adam Ryczkowski

Câu trả lời:


17

Tôi đã gặp phải điều này gần đây và tôi nghĩ rằng tôi đã tìm thấy một giải pháp dễ dàng. Tôi (chỉ) đã thử nghiệm nó trên Ubuntu 14.04.

Đầu tiên, bỏ ghi chú dòng này / etc / default / lxc-net:

LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

Trong /etc/lxc/dnsmasq.conf, hãy xác định dhcp-hostsfile:

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

Sau đó thêm các mục trong /etc/lxc/dnsmasq-hosts.conf như thế này:

mail,10.0.3.16
web,10.0.3.17

Chú ý: các thay đổi sẽ có hiệu lực sau khi bạn khởi động lại lxc-net (khởi động lại dnsmasq):

service lxc-net restart

Sau đó, bạn có thể sửa đổi /etc/lxc/dnsmasq-hosts.conf và gửi tín hiệu SIGHUP tới dnsmasq:

killall -s SIGHUP dnsmasq

Vì vậy, có, bạn cần phải khởi động lại lxc-net, nhưng chỉ một lần. Hi vọng điêu nay co ich.


Tôi thích ý tưởng ủy thác danh sách các máy chủ lưu trữ vào một tệp bên ngoài. Bên cạnh đó, phương pháp của bạn khác với tôi vì killall -s SIGHUP dnsmasq. Tôi đồng ý rằng dnsmasq chỉ "SIGHUP-ing" sẽ hiệu quả hơn sau đó khởi động lại toàn bộ trình nền (đặc biệt là nếu nó không hoạt động mà không vá các tập lệnh khởi động của nó).
Adam Ryczkowski

Việc khởi động lại dịch vụ lxc-netchỉ cần thiết để cho dnsmasq sử dụng cấu hình từ /etc/lxc/dnsmasq.conf (và phần thông tin này hiện diện trong /etc/default/lxc-netđó không xác định được dnsmasq). Nếu bạn đã thiết lập nó trước đó, chỉ cần một SIGHUP khác là đủ.
Adam Ryczkowski 8/1/2015

Chú ý: lxc-net sẽ không khởi động lại dnsmasq nếu có container đang chạy.
s3v3n

IMO đây là câu trả lời hay nhất
s3v3n

kill -HUP $(cat /var/run/lxc/dnsmasq.pid)nếu bạn không muốn cài đặt killallhoặc tải lại các dnsmasqphiên bản khác
gertas

4

Nó hoạt động tốt trong Ubuntu 14.04.1

Bỏ dòng này /etc/default/lxc-net

#LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

dừng tất cả các container, khởi động lại lxc-net:

service lxc-net restart

Định cấu hình địa chỉ IP trong /etc/lxc/dnsmasq.conf

dhcp-host={NAME},10.0.3.2

nơi {NAME}là tên của container LXC của bạn:

/var/lib/lxc/{NAME}

chỉ hoạt động nếu tập lệnh có thể tắt mạng lxcbr0 , loại trừ trường hợp khi có các thùng chứa lxc khác đang chạy. Nói tóm lại, vì hiện tại, bạn không thể chỉ định cho thuê dhcp tĩnh mà không khởi động lại tất cả các container.
Adam Ryczkowski

Đúng, đúng vậy, nó khá bất tiện :(. Tôi tìm giải pháp dễ dàng hơn nhiều để chỉnh sửa /var/lib/lxc/<container-name>/rootfs/etc/network/interfacestệp và gán địa chỉ IP tĩnh cho vùng chứa.
Tombart

Đúng, nhưng sau đó không có gì để bảo vệ bạn trước việc cho hai khách cùng một IP. Xem câu trả lời được chấp nhận của tôi - nó giải quyết vấn đề.
Adam Ryczkowski

1

Câu trả lời của Tombart hoạt động nếu bạn đủ kiên nhẫn để chờ làm mới DNS VÀ bạn sẵn sàng khởi động lại container (khách) sau đó.

Những gì sau đây là công thức yêu cầu tất cả các container lxc có thể chạy khác phải được tắt . Nếu bạn không đủ khả năng đó, thì tôi thấy không có cách nào bắt buộc cấu hình dnsmasq mới. (Đối với một số reasone báo hiệu HUP tới pid của dnsmasq được tìm thấy trong /run/lxc/dnsmasq.pidkhông hoạt động.)

Vì vậy, nếu bạn muốn có một cái gì đó hoạt động ngay lập tức và không có container lxc nào khác đang chạy, hãy làm theo câu trả lời của tôi. $namelà tên của nút mà chúng tôi muốn đặt lại bài tập và $internaliflà tên của bộ điều hợp cầu nối của LXC. Bạn có thể nhận được giá trị của $internalifví dụ với augtool -L -A --transform "Shellvars incl /etc/default/lxc-net" get "/files/etc/default/lxc-net/LXC_BRIDGE" | sed -En 's/\/.* = (.*)/\1/p'nếu bạn cài đặt augeas-toolsnhưng thường thì nó chỉ là 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

Thật không may, có một lỗi (tính năng?) /etc/init/lxc-net.confTrong Ubuntu 14.04 ngăn không cho tải lại dnsmasqtrừ khi thiết bị cầu bị hỏng cho máy chủ.


0

Giải pháp này hoạt động bằng cách vá các tập lệnh khởi động lxc. Nó phân chia nhiệm vụ phức tạp là đưa cây cầu lxcbr0 lên và bắt đầu dnsmasqthành hai công việc riêng biệt. Bây giờ bạn không cần phải khởi động lại toàn bộ lxc-netcây cầu để chỉ tải lại dnsmasq- tải lại sudo service restart lxc-dnsmasqlà đủ và không yêu cầu tắt cầu.

  1. Dừng dịch vụ lxc-net sudo service lxc-net stopvà đảm bảo không có cầu nối lxcbr0 (hoặc tương đương).
  2. Thay thế nội dung của các /etc/init/lxc-net.confnội dung sau:

.

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. Thêm một tệp khác, /etc/init/lxc-dnsmasqvới các nội dung sau:

.

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

Đây là kịch bản python đơn giản phát hành cho thuê LXC dnsmasq. Bạn có thể chạy nó từ máy chủ hoặc giả mạo nó từ một container khác - vâng nó hoạt động!:

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

Điều kiện tiên quyết ở trên là thư viện python:

pip install scapy

Sau khi chạy, bạn sẽ thấy trong hệ thống đăng nhập một cái gì đó như:

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

Để xác nhận chỉ cần kiểm tra nếu mục nhập được loại bỏ khỏi /var/lib/misc/dnsmasq.lxcbr0.leases. Bản thân bộ chứa sẽ giữ IP nên nó phải được dừng lại trước khi bắt đầu bất kỳ bộ chứa mới nào nên sử dụng lại IP.


1
Thật tuyệt! Tôi thậm chí còn không biết rằng DHCP hỗ trợ điều đó! Tôi sẽ upvote ngay sau khi tôi xác nhận nó hoạt động.
Adam Ryczkowski

0

Tôi nhận ra câu trả lời của mình là muộn hàng năm, nhưng có lẽ nó giúp được người khác. Vấn đề là bạn đã chỉnh sửa mã cụ thể cho gói ( write_lxc_netchức năng) LXC có nghĩa là được ghi đến một đích khác dưới dạng một chuỗi, không được xử lý trong lxc-netchính tập lệnh!

Do đó, quá trình dnsmasq không nhận được tệp cấu hình mà bạn đã cố gắng vượt qua, khiến bạn không có "hiệu ứng", như bạn nói.

Thay vào đó, bạn muốn đặt biến này ở gần đầu tập lệnh, trong số các phần còn lại:

#!/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=""
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.