LXDコンテナで固定IPアドレスを使うための設定
2016-08-12 追記
lxd-bridge
サービスを再起動せずに固定IPアドレス設定を更新できるようにするための設定方法を LXDのdnsmasqの固定IP設定をSIGHUPで更新する · hnakamur’s blog at github に書きました。こちらのほうがお勧めです。
設定まとめ
自分が後から参照することを想定して先に設定方法をまとめます。
LXDコンテナで固定IPアドレスを使うためには以下の設定が必要です。なお、設定にはroot権限が必要です。
まず /etc/dnsmasq.conf
に以下のようにコンテナ名に対するIPアドレスを指定します。
dhcp-host=cent01,10.64.177.101
dhcp-host=cent02,10.64.177.102
lxd-bridge
サービスを再起動します。
sudo systemctl restart lxd-bridge
IPアドレスを変更したコンテナを再起動します。
lxc restart cent01
lxc restart cent02
調査メモ
以下は調査メモです。
まず Persistent IP for Containers · Issue #1168 · lxc/lxd に固定IPアドレスを使うための情報がありました。LXDで特にサポートはないが、各コンテナでDHCPを使わずに静的IPアドレスを使用するか、あるいはホストのDHCPサーバ側で設定すれば実現できるとのことです。
各コンテナで静的IPアドレスを使う方法も試してみたのですが、ホストのコンテナ内から別のコンテナをコンテナ名で参照しようとすると変更前のIPアドレスで通信しようとしてしまいうまく行きませんでした。
これを実現するにはホストのDHCPサーバに各コンテナのIPアドレスを把握してもらう必要があるので、後者のDHCPサーバ側で設定するほうが良いです。
LXDのブリッジインターフェースとdnsmasqの設定ファイル
LXD networking: lxdbr0 explained | Ubuntu Insightsとlxcbr0 is being replaced by lxdbr0によると、 LXCでは lxcbr0
というブリッジインターフェースを使っていましたが、LXDでは lxdbr0
と別のインターフェースを使うように変更されたそうです。
これらの記事を見るとLXCの lxcbr0
はインストール時に固定のアドレスネットワークが設定されて環境によっては既存のネットワークと衝突するという問題があったので、LXD の lxdbr0
ではインストール時にはIPv4やIPv6のサブネットは設定せずに sudo lxd init
を実行したときに設定するように変更されたということのようです。
sudo lxd init
で生成した lxdbr0
用の設定は /etc/default/lxd-bridge
に保存されています。
ファイルの先頭に書かれていますが、変更したい場合は直接編集せずに dpkg-reconfigure -p medium lxd
を実行するのが良いそうです。
$ cat /etc/default/lxd-bridge
# WARNING: This file is generated by a debconf template!
# It is recommended to update it by using "dpkg-reconfigure -p medium lxd"
# Whether to setup a new bridge or use an existing one
USE_LXD_BRIDGE="true"
# Bridge name
# This is still used even if USE_LXD_BRIDGE is set to false
# set to an empty value to fully disable
LXD_BRIDGE="lxdbr0"
# Update the "default" LXD profile
UPDATE_PROFILE="true"
# Path to an extra dnsmasq configuration file
LXD_CONFILE=""
# DNS domain for the bridge
LXD_DOMAIN="lxd"
# IPv4
## IPv4 address (e.g. 10.0.8.1)
LXD_IPV4_ADDR="10.16.29.1"
## IPv4 netmask (e.g. 255.255.255.0)
LXD_IPV4_NETMASK="255.255.255.0"
## IPv4 network (e.g. 10.0.8.0/24)
LXD_IPV4_NETWORK="10.16.29.1/24"
## IPv4 DHCP range (e.g. 10.0.8.2,10.0.8.254)
LXD_IPV4_DHCP_RANGE="10.16.29.2,10.16.29.254"
## IPv4 DHCP number of hosts (e.g. 250)
LXD_IPV4_DHCP_MAX="252"
## NAT IPv4 traffic
LXD_IPV4_NAT="true"
# IPv6
## IPv6 address (e.g. 2001:470:b368:4242::1)
LXD_IPV6_ADDR="fd94:d372:e27f:2987::1"
## IPv6 CIDR mask (e.g. 64)
LXD_IPV6_MASK="64"
## IPv6 network (e.g. 2001:470:b368:4242::/64)
LXD_IPV6_NETWORK="fd94:d372:e27f:2987::1/64"
## NAT IPv6 traffic
LXD_IPV6_NAT="true"
# Run a minimal HTTP PROXY server
LXD_IPV6_PROXY="false"
このブリッジインタフェースを有効にするには lxd-bridge.service
を開始します。サービスの定義ファイルは以下のようになっていました。
$ cat /lib/systemd/system/lxd-bridge.service
[Unit]
Description=LXD - network bridge
Documentation=man:lxd(1)
Before=lxd.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/lib/lxd/lxd-bridge.start
ExecStop=/usr/lib/lxd/lxd-bridge stop
ExecStart
に指定しているスクリプトの中身は以下のようになっていました。
$ cat /usr/lib/lxd/lxd-bridge.start
#!/bin/sh -e
[ ! -e /etc/default/lxd-bridge ] && exit 0
. /etc/default/lxd-bridge
# Start by bringing up the bridge
/usr/lib/lxd/lxd-bridge start
# Switch LXD in setup mode if needed
if [ "${UPDATE_PROFILE:-true}" = "true" ] && [ -e "/var/lib/lxd" ] && \
([ ! -e "/var/lib/lxd-bridge/timestamp" ] || \
[ "/etc/default/lxd-bridge" -nt "/var/lib/lxd-bridge/timestamp" ]); then
mkdir -p /var/lib/lxd-bridge
touch /var/lib/lxd-bridge/timestamp
touch /var/lib/lxd/.setup_mode
fi
exit 0
ここから呼ばれる /usr/lib/lxd/lxd-bridge
を見てみると、initスクリプトになっていて iptables
, ip6tables
, dnsmasq
を実行するようになっていました。また /usr/lib/lxd/lxd-bridge
は上記の /etc/default/lxd-bridge
を読み込むようになっています。
起動された dnsmasq
を ps
で見ると以下のようなコマンドラインになっていました。
$ ps auxww | grep [d]nsmasq lxd 2134 0.0 0.0 49984 388 ? S 09:48 0:00 dnsmasq -s lxd -S /lxd/ -u lxd –strict-order –bind-interfaces –pid-file=/run/lxd-bridge//dnsmasq.pid –dhcp-no-override –except-interface=lo –interface=lxdbr0 –dhcp-leasefile=/var/lib/lxd-bridge//dnsmasq.lxdbr0.leases –dhcp-authoritative –listen-address 10.16.29.1 –dhcp-range 10.16.29.2,10.16.29.254 –dhcp-lease-max=252 –dhcp-range=fd94:d372:e27f:2987::1,ra-only –listen-address fd94:d372:e27f:2987::1
/usr/lib/lxd/lxd-bridge
を見ると /etc/default/lxd-bridge
の LXD_CONFILE
にファイル名を指定しておけば dnsmasq
の --conf-file
オプションを使ってそのファイルを読み込むように書かれています。この方法を使おうかと思ったのですが、一方で /etc/default/lxd-bridge
の設定にかかわらず --dhcp-authoritative
オプションが常に指定されるように書かれています。
man dnsmasq
によると --dhcp-authoritative
オプションはネットワーク内に他にDHCPサーバが無く唯一のDHCPになっているときに指定するオプションとのことです。ホストで稼働する dnsmasq
が1つという前提であれば、デフォルトの設定ファイル /etc/dnsmasq.conf
を作ってそこに設定を書くほうが手っ取り早いので、そうすることにしました。
lxd-bridge.serviceの設定変更はreloadではなくrestartが必要
sudo systemctl reload lxd-bridge
を実行してみると以下のようなエラーが出て失敗しました。
$ sudo systemctl reload lxd-bridge
Failed to reload lxd-bridge.service: Job type reload is not applicable for unit lxd-bridge.service.
See system logs and 'systemctl status lxd-bridge.service' for details.
$ sudo systemctl status lxd-bridge
● lxd-bridge.service - LXD - network bridge
Loaded: loaded (/lib/systemd/system/lxd-bridge.service; static; vendor preset: enabled)
Active: active (exited) since 土 2016-05-07 13:06:06 JST; 6h ago
Docs: man:lxd(1)
Process: 3704 ExecStop=/usr/lib/lxd/lxd-bridge stop (code=exited, status=0/SUCCESS)
Process: 3723 ExecStart=/usr/lib/lxd/lxd-bridge.start (code=exited, status=0/SUCCESS)
Main PID: 3723 (code=exited, status=0/SUCCESS)
Tasks: 1 (limit: 512)
Memory: 412.0K
CPU: 1.293s
CGroup: /system.slice/lxd-bridge.service
└─3755 dnsmasq -s lxd -S /lxd/ -u lxd --strict-order --bind-interfaces --pid-file=/run/lxd-bridge//dnsmasq.pid --dhcp-no-override --except-interface=lo --interface=lxdbr0 --dhcp-leasefile=/var/lib/lxd-bridge//dnsmasq.lxdbr0.leases --dhcp-authoritative --lis
5月 07 18:56:28 express dnsmasq-dhcp[3755]: not giving name cent02 to the DHCP lease of 10.155.92.102 because the name exists in /etc/hosts with address 10.155.92.201
5月 07 19:06:21 express dnsmasq-dhcp[3755]: DHCPREQUEST(lxdbr0) 10.155.92.102 00:16:3e:59:21:d7
5月 07 19:06:21 express dnsmasq-dhcp[3755]: DHCPACK(lxdbr0) 10.155.92.102 00:16:3e:59:21:d7 cent02
5月 07 19:06:21 express dnsmasq-dhcp[3755]: not giving name cent02 to the DHCP lease of 10.155.92.102 because the name exists in /etc/hosts with address 10.155.92.201
5月 07 19:23:24 express dnsmasq-dhcp[3755]: DHCPREQUEST(lxdbr0) 10.155.92.101 00:16:3e:5f:01:7e
5月 07 19:23:24 express dnsmasq-dhcp[3755]: DHCPACK(lxdbr0) 10.155.92.101 00:16:3e:5f:01:7e cent01
5月 07 19:23:24 express dnsmasq-dhcp[3755]: not giving name cent02 to the DHCP lease of 10.155.92.102 because the name exists in /etc/hosts with address 10.155.92.201
5月 07 19:33:08 express dnsmasq-dhcp[3755]: DHCPREQUEST(lxdbr0) 10.155.92.102 00:16:3e:59:21:d7
5月 07 19:33:08 express dnsmasq-dhcp[3755]: DHCPACK(lxdbr0) 10.155.92.102 00:16:3e:59:21:d7 cent02
5月 07 19:33:08 express dnsmasq-dhcp[3755]: not giving name cent02 to the DHCP lease of 10.155.92.102 because the name exists in /etc/hosts with address 10.155.92.201
ということで、設定ファイルを変更反映するにも sudo systemctl restart lxd-bridge
のように再起動する必要があります。
dnsmasqの再起動後、コンテナの再起動が必要
dnsmasqを再起動しただけではコンテナのIPアドレスは変わらないのでネットワークを再起動する必要がありました。
lxc exec cent01 systemctl restart network
lxc exec cent02 systemctl restart network
コンテナごと再起動でも良いと思います。
lxc restart cent01
lxc restart cent02
何回か試してみたところ、作っただけで特に何もしてないコンテナだとネットワーク再起動よりコンテナ自体を再起動するほうが速かったです。
$ time lxc exec cent02 systemctl restart network
real 0m2.878s
user 0m0.008s
sys 0m0.000s
$ time lxc restart cent02
real 0m1.236s
user 0m0.004s
sys 0m0.004s