EC2で、秒間数千回~レベルでElastiCacheやRDSに接続して、名前解決に失敗するときの対策


とある大規模WEBシステムをオンプレからAWSに移行したとき遭遇した題名の件のTIPSです。

データストア(RDSやElastiCahceなど)の接続に、エンドポイント(=固定IPをもたない)を使う、EC2を利用した中~大規模のシステムでは、必須の対策かもです。

システム構成

システム構成としては、よくあるパターンのものとなります。

WEBアプリケーションサーバは、Elastic Beanstalk や Lambdaなどがよいとおもいつつも、WEBアプリケーションの複雑性からEC2をオートスケールで用意しました。

一方で、データストアは、ElastiCacheとAurora Mysqlを利用しています。

EC2及びデータストアは、潤沢なインスタンスサイズを利用していました。

処理量

ざっくりですが、WEBアプリケーションに対するアクセス、そのときに発生するElastiCahce及びAurora Mysqlといったデータストアのエンドポイントへのアクセスが、秒間数千を超えるときがあるレベルです。

事前対策

マネージドサービスであるElastiCacheとAurora Mysqlはパラメータグループを微調整した程度でした。

EC2に関しては、主要ミドルウェアのPHPとApacheの一般的な制限系の項目(memory_limitとかmax_clientなど)の上限値変更と、大規模系のためのカーネルの設定(ipv4.tcp_syncookiesとかipv4.ip_local_port_rangeなど)を行っていました。

事象

今回、下記のようにデータストアに接続しようとしたが名前解決に失敗して接続できなかった旨のエラーが、処理量が多くなるとログに出力されていました。

PHP Warning:  Memcache::connect(): php_network_getaddresses: getaddrinfo failed: Name or service not known

PHP Warning:  PDO::__construct(): php_network_getaddresses: getaddrinfo failed: Name or service not known

PHP Warning:  mysql_connect(): php_network_getaddresses: getaddrinfo failed: Name or service not known

対策

AWSさんが2019年10月に対策を公開してくれたました。

参考:https://aws.amazon.com/jp/premiumsupport/knowledge-center/dns-resolution-failures-ec2-linux/

OSの種類などによって微妙に対策が異なりますが、私の場合は、AmazonLinuxだったので、AutomateDnsmasq.sh をダウンロードして、実行して、ほぼ対策は完了しました。

最初、それだけだと、Linuxのコンソールでローカルで動いているdnsmasqに名前解決にいっても、WEBアプリケーションは利用しないという罠にかかりましたが、これはPHPを再起動したら治りました。

キャッシュの時間は、基本的に、DNSレコードのTTLを利用するそうなので、キャッシュ時間をそれ以上伸ばしたい場合は、下記を利用ください。この設定はうまく動作しないときがあるという情報がありましたが、いじったらキャッシュ時間伸びていたので、この環境では動いているみたいでした。

max-cache-ttl

ただ、もちろん、マネージドサービス側はIPが変わる可能性があるるので、そのリスクは考慮して調整してください。

※基本的には「max-cache-ttl」はいじらない方がいいとおもいます。