Dev Study
← DNSを運用する側から見る
レッスン 7 / 8·約 9 分·第9期 DNSを運用する側から見る

DNSで振り分ける — 名前で分けられることと、取り消せないこと

リクエストがアプリケーションに届くまで
  1. ブラウザURL入力
  2. DNS名前→IP今ここ
  3. ルータ経路選択
  4. ロードバランサ振り分け
  5. Nginx受け口
  6. アプリ処理
  7. DB保存

第29〜30週のロードバランサは接続ごとに自分で配り先を決めました。DNSが配るのは答えのコピーで、配った後は手が出せません。

まず結論

DNSが配るのは接続ではなく**答えのコピー**です。配った先で保持され、権威から回収する手立てはありません。

だから壊れた実体を消しても、**既に配られたコピーがTTLのあいだそれを指し続けます**。接続ごとに選び直すロードバランサとは、効き始めるまでの時間が違います。

? 読む前に予測

障害のあるサーバのAレコードを消しました。利用者は何秒後に新しい方を使い始めますか。

当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。

抽象原理

配った答えは、回収できない

1つの名前に複数のアドレスを置いて利用者を分け、壊れた実体はレコードから消す——手順としてはそのとおりです。しかし一段下げれば、ロードバランサとは別の仕組みです。DNSは接続を配っていません。答えのコピーを配っています。

権威が返すのは写しで、受け取った側に保持されます。回収する手立てはありません。 帰結は2つ。

  1. どれを使うかは決められない。 選ぶのは受け取った側です。
  2. 外したものがすぐには消えない。 既に出た写しは、有効期間のあいだ古い実体を指し続けます。

第29週『負荷分散の選び方 — どの実体へ配るか』では、ラウンドロビンという語が共通の規格を指さないことを見ました。DNSラウンドロビンはもう一段ずれます。それを扱う RFC 1794 は Informational(April 1995) で、"This memo does not specify an Internet standard of any kind." と自ら書いています。規格が無いだけでなく、接続を配る側にすら立っていないのです。

具体実物

実際に5回引いてみる

複数のAレコードを持つ名前を続けて引きました。

$ dig @elliott.ns.cloudflare.com +noall +answer example.com A(権威に直接、5回)コマンド出力
-- try 1 --
example.com. 300 IN A 104.20.23.154
example.com. 300 IN A 172.66.147.243
-- try 2 --
example.com. 300 IN A 104.20.23.154
example.com. 300 IN A 172.66.147.243
-- try 3 --
example.com. 300 IN A 172.66.147.243
example.com. 300 IN A 104.20.23.154
-- try 4 --
example.com. 300 IN A 172.66.147.243
example.com. 300 IN A 104.20.23.154
-- try 5 --
example.com. 300 IN A 172.66.147.243
example.com. 300 IN A 104.20.23.154

macOS 26.5.2 / DiG 9.10.6 / 2026-09-17 の1例です。返るIPもTTLも環境と時点に依存し、あなたの環境では違う出力になります。

読みどころは順序です。1・2回目は同じ並び、3回目で入れ替わり、以降3回は同じ。きれいな交互のローテーションにはなっていません。

規格の側は、順序に意味を持たせていません。RFC 1034 §3.6 はこう書きます。

The order of RRs in a set is not significant, and need not be preserved by name servers, resolvers, or other parts of the DNS.

入れ替えよとも固定せよとも言っていません。RRset を扱う RFC 2181 §5.4 は見出しが "Receiving RRSets" で、内容はキャッシュとの併合の禁止とデータの信頼度。順序には触れていません。

✓ ここまでの確認

「RFCは複数のAレコードを応答ごとにローテーションさせよと定めている」——この説明の評価は。

抽象原理

「先頭のIPを使う」は、どのリストの先頭か

権威が順序を入れ替えても、接続先の選択に効くにはクライアントが先頭のIPを使うという前提が要ります。

ここに層が挟まります。アプリはDNSパケットを直接受け取らず、getaddrinfo() のようなAPIからリストを受け取ります。RFC 6724(Standards Track)§2 は、そのAPIの実装が §6 で並べ替えることを意図していると述べます。

同じ §2 には「アプリはリストの先頭を試すのが典型的だ」という記述もあり、「先頭を使う」自体は否定されていません。争点は、どのリストの先頭かです。

さらに RFC 8305(Happy Eyeballs v2、Standards Track)§4 は、まず RFC 6724 §6 の宛先アドレス選択で並べ替えなければならない(MUST)と定めます。並行接続まで規定され、「先頭1つを使う」という素朴なモデルは規格の側から崩れます。

具体実物

dig の並びと getaddrinfo の並び

同じ名前を交互に引いた結果。

dig と getaddrinfo(python3)を交互に5回(macOS、2026-09-17)追跡ログ
-- round 1 --
dig : 172.66.147.243 104.20.23.154
getaddrinfo: 2606:4700:10::ac42:93f3 2606:4700:10::6814:179a 104.20.23.154 172.66.147.243
-- round 2 --
dig : 104.20.23.154 172.66.147.243
getaddrinfo: 2606:4700:10::ac42:93f3 2606:4700:10::6814:179a 104.20.23.154 172.66.147.243
-- round 3 〜 5 --
(dig の並びは揺れ、getaddrinfo は round 1 と同じ並びのまま)

dig の並びは揺れ、getaddrinfo() の並びは5回とも同じでした。しかも先頭はIPv6で、dig が返した先頭のAレコードではありません。IPv4に絞った回でも、dig が 172.66.147.243 を先頭に返したのに getaddrinfo() は 104.20.23.154 を先頭に返す食い違いが出ました。

言えるのは「DNS応答の並びと、アプリが受け取る並びは一致しないことが実際にある」までです。 順序が安定した原因は、この観測では切り分けられていません。

逆に**「だから分散しない」とも断定できません**。RFC 6724 §6 の Rule 10 は "Otherwise, leave the order unchanged." で、他の規則で差がつかなければDNSの順序が残ります。効くこともあれば効かないこともあるが正確です。

✓ ここまでの確認

DNS応答に並んだ複数のIPのうち、アプリが最初に接続を試みるのはどれですか。

⇄ 2つを見比べる
具体例 A

DNSからAレコードを消す

1行消せば、その後に届く問い合わせには新しい答えが返ります。しかし配り終えた写しは受け取った側にあり、回収できません。

外す操作が届く範囲表
判断の場所 権威サーバ(問い合わせの応答時)
効く対象 これから来る問い合わせだけ
既存のコピー 回収できない。TTLが切れるまで残り得る
負荷・死活 見ていない
具体例 B

ロードバランサが候補から外す(第30週)

第30週『死活監視 — 壊れた実体を外す仕組み』のとおり、無償版 nginx の監視は in-band(パッシブ)で実リクエストの失敗を数えます。判断は接続の通り道です。

外す操作が届く範囲表
判断の場所 ロードバランサ(接続の到着ごと)
効く対象 次に到着する接続から
既存のコピー そもそも配っていない
負荷・死活 失敗の回数を数えている

どちらも「壊れた実体を外す」操作です。効き始めるまでの時間が違うのはなぜでしょうか。

「外す」と決めた後、決定がどこへ届くかを追ってみてください。片方は手元の表を書き換えるだけです。

抽象原理

図にすると、配り方の違いが見える

答えのコピーを配るDNSと、接続ごとに選ぶロードバランサ
DNS:権威サーバ答えを返す
LB接続を受ける
左は答えの写し / 右は接続
写しが各リゾルバ・各端末へ受け取った側で保持
候補表から1つ選ぶ接続が来るたび、その場で
実体を1つ外すと
既存の写しには届かない期限切れを待つ
次の接続から効く手元の状態を変えるだけ
  • ・DNS側は「消した」のではなく「配る答えを変えた」

なお送信元で返し分ける運用でも、見えるのは再帰リゾルバのIPです(RFC 7871 §1)。

この章のまとめ

  • DNSが配るのは接続ではなく答えのコピーで回収できない。外す操作は「これから来る問い合わせ」にしか届かず、既存のコピーは期限切れを待つ。
  • ロードバランサは接続の到着ごとに選ぶので、外せば次の接続から効く。判断が接続の通り道にあるかが時間を決めている。
  • RRset内の順序に意味は無い(RFC 1034 §3.6: "not significant, and need not be preserved")。並べ替えは実装の裁量で、RFC 1794 は Informational(April 1995)。
  • DNS応答の並びと、アプリが getaddrinfo() から受け取る並びは別のリスト。**「効くこともあれば効かないこともある」**が正確。
  • 名前で返し分ける仕組みが見るのは原則再帰リゾルバのIP(RFC 7871 §1)。

自分の現場で確かめる

読んだだけでは身につきません。手元の環境で実際に見てみてください。

環境:

理解度チェック

読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。

問題 1 / 3正解: 0

「壊れた実体を外す」操作の効き始めが、DNSとロードバランサで違うのはなぜですか。

用語集(4語)
DNSラウンドロビン
1つの名前に複数のA/AAAAレコードを置き、順序を入れ替える運用。RFC 1794(Informational、April 1995)が経緯を記す。順序に意味が無いことは RFC 1034 §3.6 が明記。
答えのコピー
DNSの応答は権威が持つ情報の写し。渡した先で保持され、回収できない。変更が「反映」ではなく「切れるのを待つ」になる理由。
宛先アドレス選択 (RFC 6724)
getaddrinfo() が返すリストを並べ替えるアルゴリズム。Standards Track。Rule 9 は送信元との最長一致プレフィックス、Rule 10 は "leave the order unchanged"。DNSの並びとアプリの並びの間に挟まる。
EDNS Client Subnet (RFC 7871)
発信元の網の情報を権威まで運ぶEDNS0オプション。RFC 7871 は Informational で、既知の欠点を自認している。