Диагностика исчерпания conntrack и проверка изменения лимита
Если новые соединения периодически завершаются по тайм-ауту, но существующие сеансы продолжают передавать данные, а процессы приложения и прослушивание портов работают штатно, стоит проверить таблицу отслеживания соединений Linux. Межсетевые экраны с отслеживанием состояния, трансляция адресов и некоторые контейнерные сети зависят от conntrack. Когда создать новую запись не удаётся, трафик может быть отброшен ещё до того, как достигнет приложения. На примере Debian 12 разберём сбор свидетельств, установление причин, изменение ёмкости таблицы и откат — без изменения правил межсетевого экрана и без удаления существующих соединений.
1. Сначала определите, в каком сетевом пространстве имён возникает сбой
Выделенные серверы CloudDDR оснащены AMD EPYC 7543P и 128 ГБ или 256 ГБ памяти ECC, однако объём памяти сам по себе не определяет лимит conntrack. Проверять нужно ядро системы, сетевое пространство имён и рабочий трафик. После оплаты получите учётные данные в панели управления и подключитесь по SSH; если адресов несколько, используйте первый.
Выполняйте команды в сетевом пространстве имён, которое действительно обрабатывает трафик. Результаты на хосте не отражают состояние гостевой системы. Если контейнерный трафик проходит через трансляцию адресов на хосте, необходимо проверить и хост. Сначала зафиксируйте версию ядра, текущее сетевое пространство имён, количество записей и установленный лимит:
uname -r
readlink /proc/self/ns/net
sudo sysctl net.netfilter.nf_conntrack_count
sudo sysctl net.netfilter.nf_conntrack_max
sudo sysctl net.netfilter.nf_conntrack_buckets
Если ключ отсутствует, соответствующий параметр не доступен в текущем пространстве имён. Само по себе это не означает, что таблица исчерпана. Сначала выясните, загружены ли нужные модули и использует ли рабочий трафик отслеживание соединений. Не включайте новые функции во время сбоя только ради того, чтобы получить полный вывод команд.
Не выполняйте
conntrack -F. Очистка таблицы удаляет состояния отслеживания, может нарушить существующие сеансы и сопоставления трансляции адресов, а также уничтожает данные, необходимые для диагностики.
2. Соберите доказательства по приросту счётчиков
Установка пользовательских инструментов не меняет существующие правила, но должна выполняться по принятой процедуре внесения изменений. Следующие команды считывают текущее состояние и позволяют по двум замерам с интервалом определить, продолжают ли расти счётчики:
sudo apt-get install conntrack
umask 077
sudo conntrack -S > /tmp/conntrack-before.txt
sudo journalctl -k --since "-10 min" --no-pager \
| grep -Ei 'nf_conntrack|table full'
sleep 30
sudo conntrack -S > /tmp/conntrack-after.txt
diff -u /tmp/conntrack-before.txt /tmp/conntrack-after.txt
conntrack -S обычно выводит накопленные счётчики отдельно для каждого CPU. Сопоставляйте строки одного и того же CPU и отслеживайте прирост insert_failed, drop и early_drop. Не принимайте значения, накопленные с момента запуска, за показатели текущего сбоя. Значение счётчиков и набор полей в выводе могут зависеть от ядра; не каждая ошибка добавления записи вызвана нехваткой ёмкости.
Одновременно фиксируйте число тайм-аутов приложения, заполнение таблицы и сообщения ядра. Достаточно убедительная картина складывается, когда заполнение приближается к лимиту, счётчики ошибок растут и одновременно появляются ошибки приложения. Отсутствие подходящих записей в журнале не исключает проблему: вывод сообщений может ограничиваться по частоте. Короткие пики между замерами могут остаться незамеченными. При необходимости сократите интервал наблюдения, но не выгружайте всю таблицу в цикле.
3. Разделяйте количество соединений и скорость их создания
Определите по выборке, почему накапливаются записи
Количество записей не равно числу текущих запросов. Одно TCP-соединение может обслуживать несколько запросов, а UDP тоже занимает записи в таблице отслеживания. После завершения обмена запись может сохраняться до истечения соответствующего тайм-аута. Поэтому важно различать длительные стабильные соединения, всплески коротких соединений и аномальные источники трафика.
Можно однократно получить ограниченную выборку, чтобы не выводить полную таблицу снова и снова во время высокой нагрузки:
sudo timeout 5s conntrack -L -o extended 2>/tmp/conntrack-sample.err \
| head -n 200 > /tmp/conntrack-sample.txt
Эта команда получает лишь ограниченный объём вывода, может завершиться раньше и вернуть ненулевой код завершения. Выборка не является полной статистикой. Файл содержит адресную информацию: ограничьте права на чтение и при необходимости обезличьте данные перед прикреплением к обращению в поддержку. В выводе присутствуют кортежи исходного и ответного направлений; при анализе источников не учитывайте адреса обеих групп как одну совокупность.
Проверьте протокол, состояние TCP, оставшийся тайм-аут и источник в исходном направлении. При большом числе коротких соединений изучите пул соединений приложения и журналы повторных попыток. Если новые потоки постоянно создаёт небольшое число источников, сопоставьте это с журналами обращений. При длительном накоплении записей UDP проверьте фактическую периодичность обмена. Нельзя объявлять происходящее атакой только по названию одного состояния или сводить аномальный трафик к простой нехватке ёмкости.
Если скорость создания соединений не снижается, увеличение таблицы лишь отсрочит повторное достижение лимита. Устранение неограниченных повторных попыток, восстановление повторного использования соединений и работа с аномальными источниками часто требуют отдельной проверки результата, независимо от изменения ёмкости.
4. Оцените память и измените только один параметр
Лимит не означает предварительное выделение памяти и не гарантирует пропускную способность
Увеличение nf_conntrack_max не создаёт сразу все записи, однако дальнейшее заполнение таблицы расходует память ядра. Наблюдайте за памятью и slab с помощью free -h, /proc/meminfo и sudo slabtop -o. Размер объектов в slab-кэше не учитывает все затраты, включая дополнительные поля и накладные расходы выделения памяти, поэтому использовать фиксированную формулу «столько-то байт на соединение» не стоит.
nf_conntrack_buckets — это количество корзин хеш-таблицы, а не ёмкость таблицы соединений. Увеличение только лимита может удлинить цепочки в корзинах и повысить стоимость поиска, поэтому одновременно наблюдайте за CPU и задержками приложения. Возможность изменения числа корзин без перезапуска зависит от ядра и пространства имён; в рамках этой процедуры этот параметр не меняется.
Ниже показано только временное изменение с целевым лимитом 262144. Перед выполнением убедитесь, что это значение выше текущего, укладывается в бюджет памяти и что доступен ещё один административный сеанс. Это не универсальная рекомендация для всех машин. Команды выполняются в оболочке с административными правами:
sudo -i
OLD=$(sysctl -n net.netfilter.nf_conntrack_max)
test "$OLD" -lt 262144 || exit 1
umask 077
printf '%s\n' "$OLD" > /run/conntrack-max.before
sysctl -w net.netfilter.nf_conntrack_max=262144
sysctl -n net.netfilter.nf_conntrack_max
Сохранив исходное значение, повторите те же проверки приложения и замеры счётчиков. Не сокращайте одновременно тайм-аут TCP established: приложение может по-прежнему использовать длительные соединения, которые сейчас простаивают. Глобальное сокращение тайм-аута создаст новую причину разрывов.
5. Разделяйте проверку результата, откат и постоянную настройку
Проверка должна как минимум охватывать трафик, на котором проявлялся исходный сбой, и длительные соединения, возобновляющие обмен после простоя. Проверьте долю успешных новых соединений, прирост счётчиков ошибок, тенденцию роста заполнения, запас памяти, CPU и задержки приложения. Само по себе увеличение лимита не означает, что проблема решена.
Если усиливается давление на память, растёт нагрузка на CPU или ухудшаются задержки, выполните откат к сохранённому значению:
sudo sysctl -w \
net.netfilter.nf_conntrack_max="$(sudo cat /run/conntrack-max.before)"
Снижение лимита не удаляет существующие записи немедленно. Если их количество всё ещё выше восстановленного лимита, создание новых записей может оставаться затруднённым. Нужно дождаться естественного удаления записей и разобраться с источниками трафика. Не очищайте таблицу ради ускорения восстановления.
После успешной проверки временного изменения убедитесь, что в /etc/sysctl.conf и /etc/sysctl.d/ нет уже заданного одноимённого параметра, чтобы разные файлы не переопределяли друг друга. Запишите проверенное значение в отдельный конфигурационный файл под контролем версий, например:
net.netfilter.nf_conntrack_max = 262144
Загрузите только этот файл и повторно проверьте фактическое значение. Во время сбоя не применяйте массово несвязанные параметры. При последующем контролируемом перезапуске также проверьте итоговое значение после загрузки модулей: запись в файл не гарантирует, что настройка обязательно вступит в силу при запуске.
Итоговая запись должна включать источники трафика, счётчики до и после изменения, результаты проверок приложения, наблюдения за памятью, исходное значение и порядок восстановления. Работа с ёмкостью conntrack завершена тогда, когда собранные свидетельства объясняют сбой, а результат изменения воспроизводим, — не тогда, когда лимит записей просто стал больше.
Часто задаваемые вопросы
Доказывает ли почти полная таблица conntrack причину потери пакетов?
Нет. Нужны прирост insert_failed, drop или early_drop, сообщения ядра и сбои приложения за один период наблюдения. Высокое заполнение само по себе указывает только на нагрузку.
Нужно ли сокращать тайм-ауты TCP при увеличении nf_conntrack_max?
Нет, эти изменения следует разделить. Сначала проверяется лимит с учётом доступной памяти. Сокращение общего тайм-аута TCP established может нарушить длительные соединения с периодами простоя.
Выделенный сервер AMD EPYC 7543P — от $447 в месяц.