ユーザーを地球の裏側にルーティングしていませんか?PowerDNSでGeoDNSを構築する

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

静的DNSがパフォーマンスを低下させる理由

静的DNSは、目に見えないパフォーマンスキラーです。私は長年、シンガポールのユーザーがニューヨークのサーバーにルーティングされているようなグローバルスタックを数多く監査してきました。理由は単純で、設定されているIPがそれ一つしかないからです。これにより、すべてのリクエストに約250msの不要なレイテンシが加わります。読み込みに3秒以上かかるサイトは40%のユーザーが離脱すると言われる現代において、このミリ秒単位の遅延は非常に大きな損失です。

AWS Route53やCloudflare Load Balancingのような大手商用サービスはこの問題を解決しますが, 継続的な月額費用とベンダーロックインが伴います。「クラウド税」を払わずに完全な制御を手に入れたいなら、PowerDNSが答えです。私は数百万件のクエリを処理する本番環境で、まさにこの構成をデプロイしてきました。このガイドでは、クエリの送信元に基づいて異なるIPアドレスを返す方法を紹介します。

クイックスタート:5分で稼働させる

大規模なクラスターは必要ありません。1GBのRAMを搭載したUbuntu 22.04または24.04の軽量なVPSがあれば、毎秒数千のリクエストを処理するのに十分です。ここではPowerDNS Authoritative ServerとそのGeoIPバックエンドに焦点を当てます。

1. PowerDNSとGeoIPバックエンドのインストール

まず、コアサーバーと特定のバックエンドモジュールをインストールします。これらは標準のUbuntuリポジトリで利用可能です。

sudo apt update
sudo apt install pdns-server pdns-backend-geoip -y

2. GeoIPデータベースの取得

PowerDNSは、IPと物理的な場所を紐付けるマップを必要とします。MaxMindはGeoLite2という無料版を提供しています。公式サイトで無料アカウントを登録し、ライセンスキーを取得して、CityとCountryの.mmdbファイルをダウンロードしてください。それらを専用のディレクトリに配置します。

# ディレクトリ構成は以下のようになります:
ls /var/lib/GeoIP/
# GeoLite2-City.mmdb  GeoLite2-Country.mmdb

3. 基本設定

/etc/powerdns/pdns.confを開きます。デフォルトのbindバックエンドを無効にし、GeoIPを有効にする必要があります。これにより、PowerDNSにロケーションデータとカスタムルーティングルールの参照先を指示します。

launch=geoip
geoip-database-files=/var/lib/GeoIP/GeoLite2-City.mmdb /var/lib/GeoIP/GeoLite2-Country.mmdb
geoip-zones-file=/etc/powerdns/geoip-zones.yaml

ディープダイブ:PowerDNSがIPを場所にマッピングする仕組み

geoip-zones.yamlファイルは、運用の頭脳となる部分です。硬直化しがちな従来のBindファイルとは異なり、PowerDNSはGeoIPの設定にYAMLを使用します。クリーンで読みやすく、バージョン管理も容易です。

クエリがサーバーに届くと、PowerDNSはMaxMindデータベースと照らし合わせて送信元のIPをチェックします。大陸や国コードを特定し、それをYAMLルールと照合します。一致するものがない場合は、デフォルトのレコードを返します。複雑な問題に対するシンプルなロジックです。

ゾーンファイルの設定

/etc/powerdns/geoip-zones.yamlを作成します。以下は、アジア、欧州、北米にノードを持つグローバルサービス向けの、実戦で検証済みの構造です:

domains:
  - domain: example.com
    ttl: 300
    records:
      example.com:
        - a: 1.2.3.4 # デフォルトのフォールバックIP
      
      app.example.com:
        - a: 1.2.3.4 
    
    services:
      app.example.com:
        # アジア向けのシンガポールノード
        as.continent.geo.example.com: ["103.1.2.3"]
        # 欧州向けのフランクフルトノード
        eu.continent.geo.example.com: ["185.1.2.3"]
        # 北米向けのニューヨークノード
        na.continent.geo.example.com: ["192.1.2.3"]

DNSクエリは多くの場合、ユーザーから直接ではなく、ISPのリゾルバから送られてくることに注意してください。しかし、PowerDNSはEDNS Client Subnet (ECS)をサポートしています。これにより、リゾルバがユーザーの実際のサブネット情報を渡すことができるため、地理的なステアリングが非常に正確になります。

高度な使い方:きめ細かな制御とフェイルオーバー

大陸レベルのルーティングは素晴らしい第一歩ですが、さらに深掘りすることも可能です。例えば、ベトナムのユーザーにはホーチミンのローカルノードにアクセスさせ、他のアジア地域のユーザーは引き続きシンガポールを使用させといった設定が考えられます。

国別のルーティング

ISO 3166-1 alpha-2の国コードを使用することで、ピンポイントな精度を実現できます。これは、現地のデータ法を遵守したり、特定の市場向けに最適化したりするのに最適です。

services:
  app.example.com:
    vn.country.geo.example.com: ["45.1.2.3"] # ベトナムノード
    as.continent.geo.example.com: ["103.1.2.3"] # その他のアジア地域

重み付けルーティングと冗長化

同じリージョンに2つのサーバーがある場合は、両方をリストアップします。PowerDNSは両方のIPを返し、クライアント側で選択できるようにします。これは、単一のデータセンター内で複数のサーバーに負荷を分散させるための、基本的ですが効果的な方法です。

services:
  app.example.com:
    eu.continent.geo.example.com: ["185.1.2.3", "185.1.2.4"]

現場からの実践的なアドバイス

独自のDNSインフラを運用することは、重大な責任を伴います。高トラフィック環境でこれらのセットアップを管理する中で学んだ、いくつかの教訓を共有します。

1. データベース更新の自動化

MaxMindはGeoLite2データを週に2回更新します。データベースが古くなると、ロンドンのユーザーを東京のサーバーに送ってしまうような、誤ったルーティングが発生します。geoipupdateツールとシンプルなcronジョブを使用して、手動介入なしでファイルを最新の状態に保ちましょう。

2. ヘルスチェックの必須化

PowerDNSは、アプリケーションサーバーが稼働しているかどうかをネイティブではチェックしません。フランクフルトのノードがダウンしても、PowerDNSは欧州のユーザーを死んだIPに送り続けてしまいます。ノードを監視し、障害が発生した場合にYAMLファイルを更新して(その後にpdns_control reloadを実行)、トラフィックを切り替えるシンプルなPythonやGoのスクリプトを導入することをお勧めします。

3. DNSのセキュリティ強化

オープンなDNSサーバーは、DDoS増幅攻撃の標的になりやすいです。セキュリティを強化しましょう。ファイアウォールを使用してクエリレートを制限し、UDP/53およびTCP/53のトラフィックのみを許可するようにします。クエリボリュームの急増を監視することで、サーバーが攻撃の踏み台にされるのを防ぐことができます。

4. TTLを低く保つ

GeoDNSの場合、TTLは60秒から300秒の間に設定してください。リージョンノードが故障してトラフィックをシフトする必要がある場合、TTLが高い(例:86400秒)と、ユーザーは丸一日故障したIPに固定されてしまいます。TTLを低く設定することで、変更がインターネット全体に迅速に波及するようにします。

PowerDNSで独自のGeoDNSを構築することで、トラフィックフローを完全に制御できます。これは、ユーザーが世界のどこにいても、可能な限り高速なエクスペリエンスを確実に提供できる、コスト効率の高い高性能な戦略です。

Share: