Amazon DNSはレートリミットを超えるとNXDOMAINを返すこともある

クラウドでコスト削減はこちら

ども、大瀧です。

Amazon VPCには、同ネットワーク内から名前解決のためのDNSキャッシュサーバー(Amazon DNS)が提供されます。AWSのドキュメントに以下の記述を見つけたので、レートリミットに引っかかるときにどのような挙動になるのか検証してみたのが本ブログです。結果としては、タイトルの通りNXDOMAIN(該当レコードなし)とタイムアウトが観測されました

DNS の制限 各 Amazon EC2 インスタンスは Amazon が提供する DNS サーバーへ送信できるパケット数をネットワークインターフェイスあたり最大 1024 パケット/秒に制限しています。この制限を増やすことはできません。Amazon が提供する DNS サーバーでサポートされる 1 秒あたりの DNS クエリの数は、クエリのタイプ、レスポンスのサイズ、および使用中のプロトコルにより異なります。スケーラブルな DNS アーキテクチャの詳細および推奨については、「Amazon VPC のハイブリッドクラウド DNS ソリューション」ホワイトペーパーを参照してください。

おことわり : 本検証は独自に行ったものであり、AWSの仕様を説明するものではありません。予告なく挙動が変わる可能性がある点をご注意ください。

検証環境

  • OS : Amazon Linux 2 RC
  • インスタンスタイプ : c5.9xlarge

同一ENIからのアクセスとするために、Dockerでコンテナを1000個実行しコンテナでdigを無限ループさせる作戦でやってみました。

  • hostloop.bash : コンテナの中で実行するシェルスクリプト
  • Dockerfile : Dockerイメージの作成で使用
  • docker-run.bash : 作成したDockerイメージで1000個コンテナを実行するシェルスクリプト
hostloop.bash
1
2
3
4
5
6
#!/bin/bash
 
while [ 1 ]
do
  host example.com
done
Dockerfile
1
2
3
4
5
6
FROM amazonlinux:2
 
RUN yum install -y bind-utils
COPY hostloop.bash /hostloop.bash
 
CMD bash /hostloop.bash
docker-run.bash
1
2
3
4
5
#!/bin/bash
 
for i in {0..1000};do
  sudo docker run -d hostloop:latest
done

それぞれのファイルを作成し、以下のコマンドで動かしてみます。

実行するとDNSサーバーへの問い合わせがまともに動かなくなる&キャッシュサーバーに多大な負荷をかけるので、検証用EC2を用意して試すことを強くお奨めします。PCやMacで実行すると、Dockerの後始末含め多分大変です。

$ sudo yum install -y docker
$ sudo service docker start
$ docker build -t hostloop .
  :(略)
$ chmod +x docker-run.bash
$ ./docker-run.bash
597735e291bf
  :(略)
$

実行したコンテナのログを見てみると。。。。

$ sudo docker logs -f 597735e291bf
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
;; connection timed out; trying next origin
Host example.com not found: 3(NXDOMAIN)
;; connection timed out; trying next origin
;; connection timed out; no servers could be reached
socket.c:1937: internal_send: 172.31.0.2#53: Invalid argument
socket.c:1937: internal_send: 172.31.0.2#53: Invalid argument
;; connection timed out; trying next origin
;; connection timed out; no servers could be reached
;; connection timed out; trying next origin
;; connection timed out; no servers could be reached
socket.c:1937: internal_send: 172.31.0.2#53: Invalid argument
socket.c:1937: internal_send: 172.31.0.2#53: Invalid argument
;; connection timed out; trying next origin
socket.c:1937: internal_send: 172.31.0.2#53: Invalid argument
;; connection timed out; no servers could be reached
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946

正常な結果が返ってくる中に、タイムアウトとNXDOMAIN(該当レコードなし)の結果が混じっていました。以下の結果はクライアント(Linux)の制約によるもののようなので、今回の制限とは直接の関連は無さそうです。

socket.c:1937: internal_send: 172.31.0.2#53: Invalid argument

考察とまとめ

Amazon DNSがレートリミットを超えるときの挙動を検証してみました。一般的なDNSクライアントはタイムアウトに対して再問い合わせをする機能があると思いますが、「該当レコードなし」では再問い合わせにはならずネットワークエラーとしてアプリケーション例外に繋がることが多いと思うので注意が必要です。とはいえ、まずはENIあたり秒間1024パケットのラインを越えないように設計するのが最も効果的な対策になるでしょう。

ちなみに、今回検証することになったきっかけは、Amazon ECS環境で同様のエラーになるという相談が社内からあったためです。最近ECSにはコンテナごとにENIを割り当てる構成がサポートされたので、そちらを利用することで回避できるのではと考えます。

Invent2017japan portal