LXCコンテナを複数作って、開発に使用しているとIPアドレスではなく名前で各コンテナにアクセスしたくなります。
もちろんlxc-consoleを使えば名前でアクセスできるのですがlxc-consoleではC-a
が取られてしまって不便です。
そこで、SSHを使って名前で各コンテナにアクセスできるととても便利です。
dnsmasqを使うと簡単にそのような環境を構築することができるので、その手順を紹介します。 なお、環境はDebian sidを想定しています。
Ubuntuだとlxcを入れるだけでやってくれる内容なのでUbuntu12.04でやっていることを調べてDebian向けにアレンジしています。
必要なパッケージをインストールする
$ sudo apt-get install -y lxc dnsmasq-base bridge-utils
lxcbr0を作成する
$ sudo brctl addbr lxcbr0
lxcbr0が自動起動するように設定する
/etc/network/interfaces:
...
auto lxcbr0
iface lxcbr0 inet static
address 192.168.30.1
netmask 255.255.255.0
pre-up /path/to/lxcbr0-pre-up
post-up /path/to/lxcbr0-post-up
post-down /path/to/lxcbr0-post-down
pre-up, post-up, post-downでそれぞれスクリプトを指定して必要な処理を実行しています。
lxcbr0-pre-up:
#! /bin/bash
brctl show | grep -q lxcbr0
if test $? -ne 0; then
brctl addbr lxcbr0
fi
lxcbr0が存在しなかったら作成するスクリプトです。
lxcbr0-post-up:
#!/bin/sh
# This is the address we assigned to our bridge in /etc/network/interfaces
braddr=192.168.30.1
# ip address range for containers
brrange=192.168.30.2,192.168.30.254
iptables -A FORWARD -i lxcbr0 -s ${braddr}/24 -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A POSTROUTING -t nat -j MASQUERADE
dnsmasq --bind-interfaces --conf-file= \
--bogus-priv \
--domain-needed \
--expand-hosts \
--domain=lxc.localdomain \
--listen-address $braddr \
--except-interface lo \
--dhcp-range $brrange \
--dhcp-lease-max=253 \
--dhcp-no-override \
--pid-file=/tmp/dnsmasq-lxcbr0.pid
このスクリプトが今回の最も重要な部分です。 iptablesでNATの設定をしてからdnsmasqを起動してDHCPサーバとDNSサーバの機能を有効にしています。
同等の設定をデーモンとして起動するdnsmasqに行っても同じことができます。 ただし、その場合iptablesの設定は別の方法で実行する必要があります。
lxcbr0-post-down:
#!/bin/bash
kill $(cat /tmp/dnsmasq-lxcbr0.pid)
rm -f /tmp/dnsmasq-lxcbr0.pid
lxcbr0-post-upで作ったPIDファイルを見てdnsmasqを終了させるだけのスクリプトです。
lxcbr0を起動する
$ sudo ifup lxcbr0
dnsmasqが起動していることを確認します。
$ ps aux | grep dnsmasq
nobody 13187 0.0 0.0 35104 1216 ? S 15:05 0:00 dnsmasq --bind-interfaces --conf-file= --bogus-priv --domain-needed --expand-hosts --domain=lxc.localdomain --listen-address 192.168.30.1 --except-interface lo --dhcp-range 192.168.30.2,192.168.30.254 --dhcp-lease-max=253 --dhcp-no-override
コンテナを作成する
$ sudo lxc-create -t ubuntu -n ubuntu1204 -- --release precise --bind $USER
名前解決の確認をする
$ dig @192.168.30.1 ubuntu1204
; <<>> DiG 9.9.5-3-Debian <<>> @192.168.30.1 ubuntu1204
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56257
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;ubuntu1204. IN A
;; ANSWER SECTION:
ubuntu1204. 0 IN A 192.168.30.201
;; Query time: 0 msec
;; SERVER: 192.168.30.1#53(192.168.30.1)
;; WHEN: Mon Apr 28 15:57:44 JST 2014
;; MSG SIZE rcvd: 55
/etc/resolve.confにnameserverを追加する
このままだとSSHなどを使えないので/etc/resolve.confにnameserverを追加します。
NetworkManagerを使用していない場合は単純に追加しても問題ありませんが、NetworkManagerを使用している場合はNetworkManagerが自動的に/etc/resolve.confを書き換えてしまうのでnamesererの設定が消えてしまうことがあります。 /etc/dhcp/dhclient.confに以下の内容を追加してNetworkManagerを再起動すると、自動的に/etc/resolv.confに反映されます。
/etc/dhcp/dhclient.conf:
...
prepend domain-name-servers 192.168.30.1;
...
SSHでコンテナにアクセスする
$ ssh ubuntu1204
まとめ
LXCコンテナに名前でアクセスする方法を紹介しました。