AWS: php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution и dnsmasq

Автор: | 31/05/2018
 

Ночью в AWS регионе us-east-1 в приложении вылезла ошибка:

PDOException: PDO::__construct(): php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution

Приложение запущено на EC2, который расположен в VPC, а база данных – в MariaDB RDS, в той же VPC.

Судя по тексту ошибки – “Temporary failure in name resolution” – возникла проблема с получением IP от DNS.

Т.к. EC2 запущен в VPC – то DNS используется локальный, в той же VPC, который создаётся и управляется Amazon (см. AmazonDNS и DNS AWS), и он же задаётся в настройках EC2 при каждой перезагрузке:

[simterm]

root@ip-172-31-44-158:~# cat /etc/resolv.conf | grep name
nameserver 172.31.0.2

[/simterm]

Сеть VPC 172.31.0.0/16, DNS создан на 172.31.0.2.

Причина ошибки в приложении может быть вызвана либо тем, что DNS на 172.31.0.2 временно ушёл в оффлайн, глюкнул, либо – между ЕС2 и узлом 172.31.0.2 в VPC были проблемы с трафиком.

См. также Domain name resolution.

Т.к. это us-east-1 зона, самая, наверное, проблемная в AWS – то может быть любой из этих вариантов.

Собственно, решение, что бы избежать такой ошибки в будущем, будет заключаться в следующем:

  1. Домен, который создаёт RDS, вида rdsname.cmia1v1jobli.us-east-1.rds.amazonaws.com, имеет TTL только 5 секунд.
    Добавим на AWS Route53 субдомен с TTL 3600 и через CNAME привяжем его к rdsname.cmia1v1jobli.us-east-1.rds.amazonaws.com. Таким образом мы увеличим время кеширования на всех DNS серверах с 5 секунд до часу.
  2. Добавим локальный сервис для кеширования DNS на ЕС2. Можно использовать systemd-resolve, но он, как пишут, глючный, либо использовать dnsmasq – его и возьмём.
    Локальное кеширование DNS запросов поможет в случае если проблема была именно в трафике между EC2 и DNS в VPC.
  3. Обновим resolv.conf на ЕС2, и доабвим сервера для резолва:
    первым добавим 127.0.0.1 – тут будет dnsmasq
    оставим 172.31.0.2
    добавим 1.1.1.1 – DNS от CloudFlare, на случай, если проблема таки возникает на стороне DNS VPC (хотя dnsmasq всё-равно должен будет сработать раньше, чем сервер CloudFlare)

Route53

Тут, собственно, особо нечего описывать.

Добавляем субдомен:

Проверяем TTL:

[simterm]

root@ip-172-31-44-158:~# dig +nocmd +noall +answer @ns-696.awsdns-23.net backendprod-db.domain.tld
backendprod-db.domain.tld. 3600 IN CNAME backendprod.sdcsdc.us-east-1.rds.amazonaws.com.

[/simterm]

3600 – ОК.

dnsmasq

Далее добавляем локальный сервис кеширования, пусть это будет dnsmasq.

Проверим скорость ответа сейчас:

[simterm]

root@ip-172-31-44-158:~# time dig yandex.ru &> /dev/null 
real    0m0.181s

[/simterm]

Интересно, что DNS в VPC тоже кеширует запросы. Если вызвать dig ещё раз – время будет всего 8с:

[simterm]

root@ip-172-31-44-158:~# time dig yandex.ru &> /dev/null 
real    0m0.008s

[/simterm]

Тем не менее – нам всё-равно нужен локальный кеширующий сервер, на случай если ошибка была вызвана проблемами с доступом к серверу 172.31.0.2.

Устанавливаем dnsmasq:

[simterm]

root@ip-172-31-44-158:~# apt install dnsmasq

[/simterm]

Редактируем /etc/dnsmasq.conf, задаём listen-address:

[simterm]

root@ip-172-31-44-158:~# cat /etc/dnsmasq.conf | grep ^listen
listen-address=127.0.0.1

[/simterm]

Там же раскоментируем строку bind-interfaces, иначе dnsmasq будет слушать на всех интерфейсах.

Проверяем:

[simterm]

root@ip-172-31-44-158:~# netstat -anpt | grep dnsm
tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN      2296/dnsmasq

[/simterm]

Проверяем время ответа на первый запрос:

[simterm]

root@ip-172-31-44-158:~# time dig @localhost rtfm.co.ua &> /dev/null 
real    0m0.263s

[/simterm]

И на второй:

[simterm]

root@ip-172-31-44-158:~# time dig @localhost rtfm.co.ua &> /dev/null 
real    0m0.008s

[/simterm]

Проверяем кеш dnsmasq.

Проверка кеша dnsmasq

Очень “оригинальный” способ посмотреть статус dnsmasq.

Убиваем его:

[simterm]

root@ip-172-31-44-158:~# pkill -USR1 dnsmasq

[/simterm]

Проверяем лог:

May 31 10:21:10 ip-172-31-44-158 dnsmasq[2296]: time 1527762070
May 31 10:21:10 ip-172-31-44-158 dnsmasq[2296]: cache size 150, 0/2 cache insertions re-used unexpired cache entries.
May 31 10:21:10 ip-172-31-44-158 dnsmasq[2296]: queries forwarded 2, queries answered locally 3
May 31 10:21:10 ip-172-31-44-158 dnsmasq[2296]: queries for authoritative zones 0
May 31 10:21:10 ip-172-31-44-158 dnsmasq[2296]: server 172.31.0.2#53: queries sent 2, retried or failed 0

Собственно queries forwarded 2, queries answered locally 3 – ОК, кеширование работает.

Можно ещё несколько раз запустить-запросить-убить dnsmasq, что бы проверить как работает его кеш.

resolv.conf

Далее надо обновить список DNS, которыми будет пользоваться NSS и glibc.

Т.к. это EC2 – то resolv.conf будет перезаписан при перезапуске сервера. Что бы задать свои сервера – бновляем /etc/dhcp/dhclient.conf (работает для Debian, в Ubuntu resolv.conf перезаписывается иначе, наверно с помощью resolvconf), добавляем в конце строку:

...
supersede domain-name-servers 127.0.0.1, 172.31.0.2, 1.1.1.1;

Первым задаём наш dnsmasq, вторым – DNS в VPC, и третьим – CloudFlare (или Google – 8.8.8.8).

Перезагружаем машину:

[simterm]

root@ip-172-31-44-158:~# reboot
Connection to 52.14.213.3 closed by remote host.
Connection to 52.14.213.3 closed.

[/simterm]

Проверяем:

[simterm]

root@ip-172-31-44-158:~# cat /etc/resolv.conf 
domain us-east-2.compute.internal
search us-east-2.compute.internal
nameserver 127.0.0.1
nameserver 172.31.0.2
nameserver 1.1.1.1

[/simterm]

И логи dnsmasq:

[simterm]

root@ip-172-31-44-158:~# journalctl -u dnsmasq
-- Logs begin at Thu 2018-05-31 11:20:34 UTC, end at Thu 2018-05-31 11:36:43 UTC. --
May 31 11:20:39 ip-172-31-44-158 dnsmasq[470]: dnsmasq: syntax check OK.
May 31 11:20:39 ip-172-31-44-158 dnsmasq[508]: started, version 2.76 cachesize 150
May 31 11:20:39 ip-172-31-44-158 dnsmasq[508]: compile time options: IPv6 GNU-getopt DBus i18n IDN DHCP DHCPv6 no-Lua TFTP conntrack ipset auth DNSSEC loop-detect inotify
May 31 11:20:39 ip-172-31-44-158 dnsmasq[508]: reading /etc/resolv.conf
May 31 11:20:39 ip-172-31-44-158 dnsmasq[508]: ignoring nameserver 127.0.0.1 - local interface
May 31 11:20:39 ip-172-31-44-158 dnsmasq[508]: using nameserver 172.31.0.2#53
May 31 11:20:39 ip-172-31-44-158 dnsmasq[508]: using nameserver 1.1.1.1#53
May 31 11:20:39 ip-172-31-44-158 dnsmasq[508]: read /etc/hosts - 8 addresses
May 31 11:20:39 ip-172-31-44-158 systemd[1]: Starting dnsmasq - A lightweight DHCP and caching DNS server...
May 31 11:20:39 ip-172-31-44-158 systemd[1]: Started dnsmasq - A lightweight DHCP and caching DNS server.

[/simterm]

Готово.