中外共用のbindをどのように冗長化させるか。前回、nginxのudp proxyを使ってみたが、期待していたproxy_protocolの設定がudpだと働かずに断念。別の方法を考える。bindの前段でロードバランスさせてしまうと、どうしても接続元がロードバランスするサーバになってしまうので、接続元によるzoneの切り替えが出来なくなってしまう。やはりbindそのものをネット上にむき出しにするのが最もシンプル。その状態でどのように冗長化を実現するのか。もうVIPによるフェールオーバくらいしかないか。うん?
VIPによるフェールオーバって自分の要件に対して実はものすごく適切な方法ではないだろうか。DNSに負担をかけるような仕組みを作るつもりはないので、DNSを負荷分散するモチベーションはない。冗長化を実現する過程でやむなく負荷分散になってしまっていただけだ。性能的には1台で充分、万一問題があったときだけ別のサーバにフェールオーバしてくれればよい。手元でzoneを書き換えて試験するようなこともあるので、寧ろ普段1台であることはありがたいくらい。しかもインターネットに直結するので、接続元IPに悩むこともない。願ったり叶ったりだ。
VIPによる冗長化というのは今更な冗長化の方法だけど、思考的な死角になっていたのでこの発見は非常に嬉しかった。実はactive/standbyでよいコンポーネントは他にもあるので、VIP冗長化の導入でより管理し易い構造を実現できそうだ。あとは何でVIPのフェールオーバを実現させるかだ。パッと思い付くのはLVSでお世話になったkeepalivedか、pacemakerのようなクラスターソフトを使うか。1つのことを実現するのに複数のミドルウェアを組み合わせたくなかったので、まずはkeepalivedから試してみる。慣れもあるしね。
LVSでの単純な使い方と違って、今回の使い方でやりたいことが幾つかある。1つ目はヘルスチェックをカスタマイズできるか。基本的なheartbeatはvrrpで行われるが、ホストダウン以外にもDNSダウンなどでフェールオーバを実行して欲しいからだ。調べてみると、vrrp_scriptで監視方法を定義してtrack_scriptで定義した監視方法を指定すれば監視内容は自由に拡張できそうだ。なかなか気の利いた機能が用意されていてすばらしい。
次はフェールオーバ発動時に任意のコマンドが発行できるか。実はbindのLISTENアドレスは、その時点でNICが持っているIPに対してLISTENする。0.0.0.0に対してLISTENする事ができない。つまりVIPを持たない状態でbindを上げていると、いざVIPがテイクオーバされてきてもLISTENする事ができない。VIPをもらった後でbindを起動、あるいは再起動する必要がある。これもnotify_master, notify_backup, notify_faultなどで、それぞれのタイミングに応じた処理を実行できる。ほんとkeepalivedいいな。便利。
最後はマルチキャストのVRRPをユニキャストのheartbeatに変更できるかどうか。この機能はIDCFクラウド環境で使うので、若干ネットワーク環境が不安定に感じている。以前、LVSでkeepalivedを仮想ブリッジ内で使った時にはいきなりコンテナが通信不能になった。この環境で起きているネットワーク問題を特定した訳ではないが、とりあえずマルチキャストよりユニキャストの方がまだ安全に稼動できそうだよね。これもunicast_peerという設定でメンバーのIPアドレスをリストすれば出来そう。
結果的にやりたいことはすべて実現できそうなので、もうkeepalivedで充分そう。もう何年も使ってきたけど、こんな便利な機能がいろいろあるとは本当に目から鱗。早速設定して動作確認。今回はkeepalived.confを以下のような設定にした。
vrrp_script check_dns {
script "nslookup 192.168.0.1 localhost"
interval 10
}
vrrp_instance VRRP_DNS {
state MASTER
priority 100
interface eth0
virtual_router_id 77
advert_int 1
authentication {
auth_type PASS
auth_pass xxxx
}
unicast_peer {
192.168.0.1
192.168.0.2
}
virtual_ipaddress {
192.168.0.10/24
}
track_script {
check_dns
}
notify_master "/usr/bin/systemctl restart named"
}
healthcheck対象のIPアドレスやstate, priorityなどはバックアップサーバ側では変わるので注意。この設定でマスターサーバのbindを停止するとバックアップサーバにVIPがテイクオーバされた。VIPをもらうとマスターに昇格するのでnamedのrestartも実行され、ちゃんとVIPの53番をLISTENし始めてくれた。chefやansibleでimmutableな構成管理をしようと思うと複雑な構成はできる限り避けたい。keepalivedによるVIP冗長化は非常に簡潔に構成管理ができるし、サーバ側の構造そのものもシンプルな状態を維持できる。active/standbyで充分なサービスを冗長化するのに極めて適しているのでオススメだ。