Container 無法從 dnsmasq 取得指定 IP

在 container 的 /etc/hostname 中指定名稱, 用 systemd-nspawn --network-macvlan=enp6s0 my-container1 啟動, 並在 dnsmasq 中增加一行設定, 讓 dnsmasq 以 hostname 分配固定 IP address

dhcp-host=my-machine,192.168.0.123,infinite

後來, container 名稱從 my-container1 換成了 my-container2, 但 hostname 沒變 (還是 my-machine), 從此就再也取不到 192.168.0.123 這個 address, 相當不解.

查了查 dnsmasq 的 log

$ journalctl -u dnsmasq -r

發現有這行

May 31 18:25:55 home dnsmasq-dhcp[17985]: not using configured address 192.168.0.123 because it is leased to 12:a4:d6:57:3a:e9

12:a4:d6:57:3a:e9? 但 my-container2 的好像不是這個, 確認一下

# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default 
    link/ether 92:78:73:88:5c:bd brd ff:ff:ff:ff:ff:ff

喔~ 原來, 當 container 的名稱換了以後, systemd-nspawn 就會為它產生一個新的 MAC address, 並且, 因為原先配置 IP 給 my-container1 時的 lease time 為 inifinite, 所以, 雖然 my-container2 的 hostname match 了, 但 dnsmasq 還會 check 當初這個 hostname 對應的 MAC address 是哪個, 發現, 12:a4:d6:57:3a:e9 != 92:78:73:88:5c:bd, dnsmasq 就印出以上 log, 配置一個動態的 IP 給 my-container2, 所以怎麼樣都拿不到希望的 IP address 了.

這個 lease time 應該是一個會保留在 disk 上的檔案, 如果 dnsmasq 一直開著它的話, 我們可以在 /proc 中找到

# ls -l /proc/$(pgrep dnsmasq)/fd
total 0
lrwx------ 1 root root 64 Jun  7 11:04 0 -> /dev/null
lrwx------ 1 root root 64 Jun  7 11:04 1 -> /dev/null
lrwx------ 1 root root 64 Jun  7 11:04 10 -> socket:[3713415]
lrwx------ 1 root root 64 Jun  7 11:04 11 -> socket:[3713416]
lrwx------ 1 root root 64 Jun  7 11:04 12 -> socket:[3713417]
lrwx------ 1 root root 64 Jun  7 11:04 13 -> socket:[3713418]
lrwx------ 1 root root 64 Jun  7 11:04 14 -> socket:[3713419]
lrwx------ 1 root root 64 Jun  7 11:04 15 -> socket:[3713420]
lrwx------ 1 root root 64 Jun  7 11:04 16 -> socket:[3713421]
lrwx------ 1 root root 64 Jun  7 11:04 17 -> socket:[3713422]
lrwx------ 1 root root 64 Jun  7 11:04 18 -> socket:[3713423]
lrwx------ 1 root root 64 Jun  7 11:04 19 -> socket:[3713424]
lrwx------ 1 root root 64 Jun  7 11:04 2 -> /dev/null
lrwx------ 1 root root 64 Jun  7 11:04 20 -> socket:[3713425]
lrwx------ 1 root root 64 Jun  7 11:04 21 -> socket:[3713426]
lrwx------ 1 root root 64 Jun  7 11:04 22 -> socket:[3713427]
lrwx------ 1 root root 64 Jun  7 11:04 23 -> socket:[3713428]
lr-x------ 1 root root 64 Jun  7 11:04 24 -> pipe:[3713429]
l-wx------ 1 root root 64 Jun  7 11:04 25 -> pipe:[3713429]
lrwx------ 1 root root 64 Jun  7 11:06 26 -> socket:[3713431]
lrwx------ 1 root root 64 Jun  7 11:04 3 -> /var/lib/misc/dnsmasq.leases
lrwx------ 1 root root 64 Jun  7 11:04 4 -> socket:[3713408]
lrwx------ 1 root root 64 Jun  7 11:04 5 -> socket:[3713409]
lrwx------ 1 root root 64 Jun  7 11:04 6 -> socket:[3713411]
lrwx------ 1 root root 64 Jun  7 11:04 7 -> socket:[3713412]
lrwx------ 1 root root 64 Jun  7 11:04 8 -> socket:[3713413]
lrwx------ 1 root root 64 Jun  7 11:04 9 -> socket:[3713414]

哈, 很幸運, 不用去翻 source code, 位置在 `/var/lib/misc/dnsmasq.leases`, 停掉 dnsmasq, 從檔案中將包含 12:a4:d6:57:3a:e9 那行去掉, 再重新啟動 dnsmasq, IP address 就能正常取得啦!