У меня возникают случайные проблемы с преобразователем DNS, работающим под управлением BIND 9.8.2 (RHEL6) за балансировщиком нагрузки.
Балансировщик нагрузки активно проверяет сервер с помощью DNS-запроса, чтобы определить, жив ли он, и то и дело получает сообщение «В соединении отказано» (ICMP) для порта 53, что на короткое время делает сервер недоступным для обслуживания в пуле серверов балансировщика нагрузки.
Это происходит периодически (LB проверяет каждые 10 секунд, и мы обычно видим 1 или 2 сбоя, за которыми следуют успехи) в течение нескольких минут за раз, а затем останавливается, это происходит во время пиковой нагрузки, но было обнаружено, когда трафик на самом низком.
Когда возникает проблема, BIND запущен и работает, что сбивает с толку сообщение «Соединение отказано», я бы ожидал, что это будет от сервера без службы прослушивания на порту 53, что не так. Даже если разрешение DNS для записи зондирования не удалось, ответом будет NXDOMAIN или SERVFAIL, а не категорическое отклонение UDP.
Журналы запросов не показывают неисправные зонды, что означает, что пакет UDP отклоняется перед доставкой в BIND для обработки.
Я предполагаю, что это вызвано каким-то исчерпанием ресурсов, но я не могу понять, что именно. Мы отслеживаем открытые файловые дескрипторы, net.netfilter.nf_conntrack_count
, Процессор, память, recursive-clients
и т. д., и ни один из этих индикаторов даже не приближается к пределу, когда возникает проблема.
Ни в одном из файлов журнала нет соответствующих сообщений об ошибках на момент возникновения проблемы.
Итак, мой вопрос: какие сетевые показатели / параметры мне следует изучить?
Конфигурация
/ и т.д. / sysconfig / с именем
OPTIONS="-4 -n10 -S 8096 "
named.conf
options {
directory "/var/named";
pid-file "/var/run/named/named.pid";
statistics-file "/var/named/named.stats";
dump-file "/var/named/named_dump.db";
zone-statistics yes;
version "Not disclosed";
listen-on-v6 { any; };
allow-query { clients; privatenets; };
recursion yes; // default
allow-recursion { clients; privatenets; };
allow-query-cache { clients; privatenets; };
recursive-clients 10000;
resolver-query-timeout 5;
dnssec-validation no;
//querylog no;
allow-transfer { xfer; };
transfer-format many-answers;
max-transfer-time-in 10;
notify yes; // default
blackhole { bogusnets; };
// avoid reserved ports
avoid-v4-udp-ports { 1935; 2605; 4321; 6514; range 8610 8614; };
avoid-v6-udp-ports { 1935; 2605; 4321; 6514; range 8610 8614; };
max-cache-ttl 10800; // 3h
response-policy {
zone "rpz";
zone "rpz2";
zone "static";
};
rate-limit {
window 2; // seconds rolling window
ipv4-prefix-length 32;
nxdomains-per-second 5;
nodata-per-second 3;
errors-per-second 3;
};
};
Изменить: UDP получать ошибки
$ netstat -su
IcmpMsg:
InType3: 1031554
InType8: 115696
InType11: 178078
OutType0: 115696
OutType3: 502911
OutType11: 3
Udp:
27777696664 packets received
498707 packets to unknown port received.
262343581 packet receive errors
53292481120 packets sent
RcvbufErrors: 273483
SndbufErrors: 3266
UdpLite:
IpExt:
InMcastPkts: 6
InOctets: 2371795573882
OutOctets: 13360262499718
InMcastOctets: 216
Редактировать 2: размер сетевой памяти
$ cat /proc/sys/net/core/rmem_max
67108864
$ cat /proc/sys/net/ipv4/udp_mem
752928 1003904 1505856
Изменить 3: нет проблем с UdpInErrors
Произошло событие сбоя зонда без соответствующего увеличения количества ошибок приема пакетов UDP, так что это, похоже, исключено как причина.
Изменить 4: здесь могут быть 2 проблемы, некоторые экземпляры сбоев имеют соответствующее увеличение UdpInErrors, а некоторые нет
Я нашел случай, который коррелирует с проблемой с ошибками приема UDP:
Я уже увеличил значения памяти ядра до:
# cat /proc/sys/net/core/wmem_max
67108864
# cat /proc/sys/net/core/rmem_max
67108864
# cat /proc/sys/net/ipv4/udp_rmem_min
8192
# cat /proc/sys/net/ipv4/udp_wmem_min
8192
Кажется, это не связано с нагрузкой, аналогичные серверы с такими же и даже большими рабочими нагрузками не показывают проблем, в то время как другой сервер за тем же балансировщиком нагрузки показал точно такое же поведение в течение этого периода времени.
Изменить 5: обнаружены некоторые свидетельства проблем TCP в данных статистических каналов BIND
Обнаружена корреляция между высокими ошибками приема пакетов UDP и TCP4ConnFail
и TCP4SendErr
метрики от BIND статистические каналы данные.
Хотя увеличение не имеет того же масштаба, что и UDPInErrors, оно сильно коррелирует с ним, поскольку в другое время этого эффекта нет.
Изменить 6: сюжет сгущается ... syslog, похоже, способствует
Затронутые DNS-серверы настроены на регистрацию журналов запросов в системный журнал. local0
средство, которое, в свою очередь, перенаправляет их через UDP на удаленный сервер. Это было причиной проблем с производительностью в прошлом, на самом деле мы не включали его на самых загруженных DNS-серверах по этой причине.
Я попытался отключить ведение журнала запросов, и, похоже, udpInErrors
проблемы исчезают, поэтому я поставил эксперимент. У нас есть 2 сервера за одним и тем же балансировщиком нагрузки, я сохранил serverA с активным ведением журнала запросов в качестве элемента управления и отключил ведение журнала запросов (и, следовательно, пересылку системного журнала) на serverB. Проблема перестала возникать на обоих серверах в то же самое время.
Затем я снова включил ведение журнала запросов на serverB, и проблема снова возникла. на обоих серверах!
Это было испробовано в двух разных случаях: один раз при небольшой нагрузке, другой - в самое загруженное время, и это проявлялось только в самое загруженное время, поэтому, похоже, это частично связано с нагрузкой.
На графиках ниже показана взаимосвязь между сетевым трафиком и ошибками приема UDP.
ServerB
ServerA
Такой же эффект увеличения можно найти и в индикаторах TCP, упомянутых в редакции 5.
Итак, основная причина, по-видимому, связана с сетью, которая каскадирует и создает все показанные симптомы. Сложность заключается в том, что эти серверы (на самом деле виртуальные машины) работают в отдельной инфраструктуре (иногда в разных стойках, даже комнатах), поэтому между ними не должно быть никакого распространения эффекта.
Похоже, что это не связано с ведением журнала запросов, иначе эффекты не распространялись бы между серверами.
Одна вещь, которая пришла мне в голову, заключается в том, что получающий сервер системного журнала не имеет обратной маршрутизации на эти серверы, поэтому мы никогда не получаем никаких ответных пакетов (если они есть), поэтому системный журнал действует по принципу «выстрелил и забыл». . Может ли это быть причиной?
Udp:
27777696664 packets received
...
262343581 packet receive errors
105,88 датаграмм, полученных на каждую 1 ошибку приема UDP, - это чрезвычайно высокий коэффициент потери пакетов DNS, и это указывает на то, что у вас есть узкое место в программном обеспечении. Если очередь приема, связанная с сокетом UDP, заполнена, когда ядро пытается передать пакет, пакет теряется, и этот счетчик увеличивается. Это означает, что вы проиграли более двухсот миллионов пакетов к этому явлению с момента последней перезагрузки только на этом сервере.
Полная очередь приема означает, что программное обеспечение не удаляет пакеты из ядра достаточно быстро, создавая отставание, которое в конечном итоге превышает размер буфера. Следующим шагом должно быть определение Зачем очередь слишком высока. Как пример, один из наших пользователей обнаружил, что система была переполнена iowait из-за большого количества журналов на диске. Я не могу предоставить исчерпывающего руководства для определения основной причины, кроме как предложить вам просмотреть все свои метрики производительности SNMP и найти корреляцию. Если вы не можете найти никакой корреляции, возможно, вы работаете на полную мощность своего аппаратного + программного стека, и проблему лучше решить, добавив к ней больше серверов.
В качестве примечания, можно увеличить размер очереди приема, но это лучше всего рассматривать как вашу способность справляться с пакетным трафиком. Если бурный трафик не является почему вы испытываете переполнение очереди, больший размер очереди приведет к увеличению времени обработки трафика, который вы делать accept, что, вероятно, нежелательно. BIND будет использовать глубину очереди приема до 32 КБ, но ограничено значением, указанным в /proc/sys/net/rmem_max
. Это число можно увеличить, перекомпилировав BIND с --with-tuning = большой вариант, что увеличивает максимальный потенциал с 32К до 16М.