ProHoster > Блог > Администрирование > /etc/resolv.conf для Kubernetes pods, опция ndots:5, как это может негативно сказаться на производительности приложения
/etc/resolv.conf для Kubernetes pods, опция ndots:5, как это может негативно сказаться на производительности приложения
Не так давно мы запустили Kubernetes 1.9 на AWS с помощью Kops. Вчера, во время плавного выкатывания нового трафика на самый большой из наших Kubernetes кластеров, я начал замечать необычные ошибки разрешения имен DNS, залогированные нашим приложением.
На GitHub довольно долго об этом говорили, поэтому я тоже решил разобраться. В итоге я понял, что в нашем случае это вызвано повышенной нагрузкой на kube-dns и dnsmasq. Самым интересным и новым для меня оказалась сама причина значительного увеличения трафика DNS-запросов. Об этом и о том, что с этим делать, мой пост.
Разрешение DNS внутри контейнера — как и в любой системе Linux — определяется конфигурационным файлом /etc/resolv.conf. По умолчанию Kubernetes dnsPolicy это ClusterFirst, что означает, что любой DNS-запрос будет перенаправлен на dnsmasq, запущенный в поде kube-dns внутри кластера, который, в свою очередь, перенаправит запрос в приложение kube-dns, если имя заканчивается суффиксом кластера, или, в противном случае, к DNS серверу более высокого уровня.
Файл /etc/resolv.conf внутри каждого контейнера по умолчанию будет выглядеть так:
Интересной частью этой конфигурации является то, как локальные поисковые домены и настройки ndots:5 уживаются вместе. Чтобы это понять, необходимо разобраться, как работает разрешение DNS для неполных имен.
Что такое полное имя?
Полностью определенное имя — это имя, для которого не будет выполняться локальный поиск, и имя будет считаться абсолютным во время разрешения имен. По соглашению, программное обеспечение DNS считает имя полностью определенным, если оно заканчивается точкой (.), И не полностью определенным в противном случае. То есть google.com. полностью определено, а google.com — нет.
Как обрабатывается неполное имя?
Когда приложение подключается к удаленному хосту, указанному в имени, разрешение имен DNS обычно выполняется с помощью системного вызова, например, getaddrinfo(). А вот если имя неполное (не заканчивается на .), интересно, попытается ли системный вызов сначала разрешить имя как абсолютное, или сначала пройдет через локальные поисковые домены? Это зависит от опции ndots.
Из мануала по resolv.conf:
ndots:n
устанавливает порог для количества точек, которые должны появиться в имени, прежде чем будет сделан начальный абсолютный запрос. Значение по умолчанию для n равно 1, что означает, что если в имени есть какие-либо точки, имя будет сначала опробовано как абсолютное имя, прежде чем к нему будут добавлены какие-либо элементы списка поиска.
Это означает, что если для ndots задано значение 5, а имя содержит менее 5 точек, системный вызов попытается разрешить его последовательно, сначала пройдя по всем локальным поисковым доменам, и, в случае неудачи, в конце концов разрешит его как абсолютное имя.
Почему же ndots:5 может негативно сказаться на производительность приложения?
Как вы понимаете, если ваше приложение использует много внешнего трафика, для каждого установленного TCP-соединения (или, точнее, для каждого разрешенного имени) оно будет выдавать 5 DNS-запросов, прежде чем имя будет правильно разрешено, потому что оно сначала пройдет через 4 локальных поисковых домена, а в конце выдаст запрос разрешения абсолютного имени.
На следующей диаграмме показан суммарный трафик на наших 3 модулях kube-dns до и после того, как мы переключили несколько имен хостов, настроенных в нашем приложении, на полностью определенные.
На следующей диаграмме показана задержка приложения до и после того, как мы переключили несколько имен хостов, настроенных в нашем приложении, на полные (вертикальная синяя линия это развертывание):
Решение #1 — использовать полностью определенные имена
Если у вас мало статических внешних имен (т. е. определенных в конфигурации приложения), к которым вы создаете большое количество соединений, возможно, самое простое решение — переключить их на полностью определенные, просто добавив. в конце.
Это не окончательное решение, но помогает быстро, пусть и не чисто, улучшить ситуацию. Этот патч мы применили для решения нашей проблемы, результаты чего были показаны на скриншотах выше.
Решение #2 — кастомизация ndots в dnsConfig
В Kubernetes 1.9 в альфа режиме появился функционал (бета-версия v1.10), который позволяет лучше контролировать параметры DNS через свойство пода в dnsConfig. Среди прочего, он позволяет настроить значение ndots для конкретного пода, т.е.