IDCFクラウド DNS冗長化 LVS編

IDCFクラウド上のnameサーバは中外兼用のbind。外向きには自分所有のドメインのゾーンを返して、中向きにはローカルゾーンも含めて答える。ダウンタイムは小さくしたいので2台で冗長化させておきたい。IDCFクラウドの仮想ルータはUDPのロードバランスが出来ないので自前で行う必要がある。枯れたやり方としてはLVSを使うことだろう。LVSで2台のbindをロードバランスしてみたところ、外からの問い合わせも中向けの処理が対応するようになってしまった。bindのmatch-clientsで処理分けしていたのだが、外からのものも含めて全てのリクエストソースがLVSサーバになってしまったからである。

対応する方法は幾つか思い付くが、まずやってみたのは中用と外用のVIPを分離すること。LVS上で2種類のルールを作って、一方はグローバルIPとNATさせて、もう一方はクラウド内サーバのresolv.confに書いておく。これで中と外の経路を分離できるので、match-clientsに中用のVIPを書いて、外用はanyにして処理分けを行う。結果から言うと、今度は全て外用で処理されてしまった。面倒くさがらずにnamedのquery.logを書き出してみると、リクエストソースはVIPでなくてLVSが動いているマスターサーバのIPだった。これではmatch-clientsで振り分けることは不可能。

vi /etc/named.conf
  :
logging {
        channel "log_queries" {
                file "/var/named/data/queries.log" versions 3 size 10m;
                severity info;
                print-time yes;
                print-category yes;
        };
        category queries { "log_queries"; };
};

単純に考えればnamedを2つに分けてしまうことが簡単かもしれない。しかし、自分のスタンスとしてポートずらしやバーチャルIPは出来る限り使いたくない。趣味レベルの環境でそういうものを頻繁に使っていると、そのうち設定忘れて事故の元になるし、構成管理ツールでのビルドロジックも複雑化してしまう。既存のnamedは仮想サーバ上のLXCコンテナで動いているので、もう1つコンテナを作ることもできるが、かつかつのリソースでやりくりしているのに、namedのためだけにもう1つというのは避けたい。他に振り分ける方法はないかと調査を続けていると、bindにmatch-destinationsという設定を見つけた。これはリクエストソースではなくて、リクエストを受け付けたdestination側のIPアドレスで振り分けるというもの。これであれば、まだ可能性は残っている。

先ほども言ったように出来ればバーチャルIPは使いたくなかったが、namedを1つで動かしていればIPが2つあることはそれほど気にせずとも運用できる。bind用のLXCコンテナに永続的にセカンダリIPを付けておく必要がある。/var/lib/lxc/$HOST/configにlxc.network.ipv4の設定を2つ書けばセカンダリIP付きで起動することができた。あとは管理構成上、この2つ目のIPアドレスを何にするかと、nameサーバのコンテナのみはセカンダリIP付きで構築するというロジックをlxc-templateの中で作る。やっぱり汚くなってしまうな。。。

LVSサーバ側で中用の振り分けはnameサーバのIPに、外用の振り分けはセカンダリIPに紐付ける。nameサーバのnamed.confでmatch-clientsの設定をmatch-destinationsに修正する。nameサーバのIPに来たら、中用のviewが処理し、それ以外は外用のviewが処理。これでやっとnamedプロセス1つで中外のリクエストを処理分けできるようになった。

vi /etc/named.conf
        :
view "internal" {
        match-destinations { 10.1.0.1; };
        recursion yes;
        allow-query { any; };
        allow-query-cache { any; };
        allow-recursion { DOMAIN.LOCAL; };
        allow-transfer { DOMAIN.LOCAL; };
        zone "." IN {
        :
view "external" {
        match-destinations { any; };
        recursion yes;
        allow-query { any; };
        allow-query-cache { any; };
        allow-recursion { DOMAIN.COM; };
        allow-transfer { DOMAIN.COM; };
        zone "." IN {
        :

これでやりたいことは出来るようになったが、殆ど落ちることもないDNSを冗長化したいというだけの要望からすると、あまりに複雑な構造だと感じた。1度作って作りっきりなら動くだけでもよいかもしれないが、やはり長く動かすものはシンプルに作っておかないと複雑さが複雑さを招き、バッドスパイラルに陥ってしまう。そのままシステムが大きくなってしまって、後戻りができなくなったサービスを幾つも知っている。同じ轍を踏まないためにも、もう少し簡単な方法でDNSの冗長化を実現していきたい。

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)