皆様が普段何気なくアクセスしているWEBサイト。
このQiitaなども例に漏れず、基本的には「https://~」から始まるドメインへアクセスすると、最終的にはサーバーに到着してそのサーバーから情報を返して皆様の元(ブラウザなど)に届いて閲覧が出来る、という流れになっているのはご存知のとおりかと思います。
ところがとある日、WEBシステムの開発中に突然、掲題のように
「半分くらいの確率でサーバーにアクセス出来るが、半分くらいの確率でリクエストタイムアウトになってしまう」
というなんとも不思議な事態に遭遇しました。
まず自分のネットワーク環境が悪いのかと思い他のサイトにアクセスを何度かしてみると、開発中のサイト以外にアクセスする分には問題ない。
「開発中のサーバーに負荷がかかっているのか?」と思ってサーバーのサーバーを確認してみるが負荷もかかってないしディスク容量も万全、Webサーバー(nginx、apacheなど)は起動済でエラーも吐いていない。
AWSを利用していたのですが開発中の当時はWAFなどもかけていなかったためそこで引っかかっているわけでもない…。
ということでどうしてそんな事が発生するのか?が全然わからず困ってしまいました。
上記の原因、実は「ドメイン側」にありました。
ドメイン側の構成について
当時、ドメイン設定は以下のようになっていました。
- 〇〇〇〇.com というドメインはAWSアカウントAで運用
- sub.〇〇〇〇.com はアカウントAからドメイン委任され別アカウントBで運用
- XXX.sub.〇〇〇〇.com はアカウントAからドメイン委任され別アカウントCで運用
図にするとこのような形になります。
一見、親ドメインである 〇〇〇〇.com がどちらに対しても委任しているので設定としては正しそうに見えるのですが、実はこの設定方法だと掲題のように 「たまにアクセス出来てたまにアクセス出来ない」ドメインが爆誕してしまいます。
何故発生するのか
XXX.sub.〇〇〇〇.com のドメインの名前解決をするためには、DNSリゾルバが「最も下位のリゾルバが知っている権威ゾーン」を検索します。
※ 参考:RFC 1034 (Domain Names – Concepts and Facilities) Section 4.3.2 – Algorithm
その際にDNSリゾルバが sub.〇〇〇〇.com を認識している場合、該当ドメイン側にはNSレコードが存在せず、アクセスに失敗することになります。
一方でDNSリゾルバが sub.〇〇〇〇.com を認識していない場合、DNSリゾルバは 〇〇〇〇.com に問い合わせをし、 〇〇〇〇.com が委任した XXX.sub.〇〇〇〇.com へアクセスが可能となります。
こんな感じで問い合わせ先候補が複数あり、どちらが正しいことを言っているのかわからない状態のため問題が発生していたのです。
そもそもどうするべきだったのか
ドメイン委任は原則として、「1階層上のゾーン」が「下位のゾーンのNSレコードを定義し、そのゾーンの管理を委譲する」ことで行われます。
※ 参考:RFC 1034 (Domain Names – Concepts and Facilities) Section 4.2.1 – Zone boundaries
つまり正しい構成は
- 〇〇〇〇.com というドメインはAWSアカウントAで運用
- sub.〇〇〇〇.com はアカウントAからドメイン委任され別アカウントBで運用
- XXX.sub.〇〇〇〇.com は
アカウントAアカウントBからドメイン委任され別アカウントCで運用
となるべきだったのです。
上記のような構成になっていれば 「たまにアクセス出来てたまにアクセス出来ない」ドメインは発生せず、正常に動作するようになります。
普段あまり遭遇しないパターンかつ、私がドメインの知識が浅かったためハマりどころだったのですが、意外とWEBアプリケーションエンジニアをしていても正しく認識出来てない人も多いのでは?という内容だったため、今回執筆させていただきました。
同じような事象に遭遇した誰かの参考になれば幸いです。


