Есть в администрировании такие вечера: процессор не загружен, память есть, метрики ровные, а пользователи жалуются на задержки, и по логам ни слова. Ровно на этом этапе в дело вступают инструменты вроде BCC: это набор небольших однофайловых утилит, каждая из которых загружает в ядро крошечную программу на eBPF и читает события в реальном времени. Никакой пересборки приложений, никаких перезапусков, никаких агентов. В статье разберём практическую сторону набора: установку, два самых полезных инструмента, расширение под другие повседневные задачи и аккуратную эксплуатацию на рабочих серверах.
Что даёт телеметрия ядра на eBPF и почему она безопасна
Смысл инструментов из набора BCC простой и неожиданный по удобству: вместо снятия копий процессов или включения подробного логирования на боевой системе крошечные программы загружаются прямо в ядро и реагируют на выбранные события, будь то запуск процесса или открытие файла. Счётчик, гистограмма или поток сообщений собираются в пространстве ядра, а читаются пользователем по мере необходимости. Перед загрузкой механизм проверки анализирует каждую программу на безопасность, поэтому внедрённый обработчик не может зависнуть, прочитать чужую память или нарушить права.
По сравнению с привычным логированием здесь другое масштабирование: измерение работает круглый год с заметно меньшими накладными расходами, а поиск причины конкретного вопроса не требует перезапуска приложения в отладочном режиме. Загрузил инструмент, посмотрел полторы минуты, запомнил картину и загрузил её. Для старых задач, вроде лечения системных служб, которые падают раз в неделю, именно этот способ покрытия событий выигрывает у иных методик.
Стоит так и отметить важное свойство: основная масса утилит это отдельные скрипты на Python, которые загружают готовый обработчик, и с ними не нужно связываться напрямую. Это делает набор удобным первым делом и для тех, кто с ядром на ты, и для тех, кто с его структурой в деталях.
Установка набора и требования к ядру
Пакет с инструментами ставится из репозитория любого распространённого дистрибутива. На Debian и Ubuntu он называется bpfcc-tools с зависимостью от python3-bpfcc, на Fedora и RHEL поставляется как bcc-tools с дополнительным пакетом python3-bcc. Утилиты от пакетного менеджера после установки появляются в каталоге исполнения:
sudo apt install bpfcc-tools linux-headers-$(uname -r)
ls /usr/sbin/ | grep bpfcc | head
# Fedora или RHEL-совместимые системы
sudo dnf install bcc-tools kernel-devel
Требования не замысловаты: ядро даже свежих stable-линейок достаточно для большинства инструментов, а eBPF-проверка умеет их встраивать. На продакшене с ограничениями по ядру стоит заранее изучить историю предоставления права на трассировку: для части инструментов нужен суперпользователь, для остальных делается возможность через расширенный доступ к BPF. Это стоит сделать до первого тревожного звонка, потому что схема внедрения прав уже требует правильных ролей.
execsnoop и кто запускает новые процессы
Утилита execsnoop показывает новые процессы по мере запуска с полным набором полей: время, предок, пользователь, возвращаемый код и аргументы командной строки. Повод её применения обычно простой: видеть, что запускается на сервере периодически и почему:
execsnoop-bpfcc
# пример вывода
# PCOMM PID PPID RETARGS ARGS
# sh 8021 7923 0 ./collect.sh
# grep 8022 8021 0 -i error /var/log/app.log
# только потомки от конкретного родителя, для точечного наблюдения
execsnoop-bpfcc -P 7923
При инциденте это единственная честная картина: злоупотребляющий спам-скрипт возглавляет список активности, дежурный запуск какой-то службы закрывается быстро, а повторный всплеск в десятом часу объясняется командой из временного задания. Как и в трассировке, здесь работают фильтры по времени и предку, и опыт подсказывает, что меньше пяти процентов всех событий на продакшене действительно представляют интерес, а ключевая привычка это писать отброшенное подмножество на диск потом.
Через один вечер работы с execsnoop вырисовывается привычная карта: cron-задачи, вызовы на почту, журнали ротации и сборщики мусора становятся распознаваемыми, а каждый неожиданный запрос отделяется взглядом. После этого большинство вызовов страницы стартуют с ответа на вопрос, а не с начала расследования, что и есть предметная выгода такого инструмента.
opensnoop и кто читает чужие файлы
Там, где процессы сами по себе невинны, часто предметом разбирательства служит нечужая библиотека. Инструмент opensnoop показывает события открытия файлов с кодами ошибок, тишина которых извещает о несуществующих путях в конфигурациях. Он выделяется одним из полезнейших инструментов для ситуации "кто трогает чужой конфиг": чтение потока событий сразу показывает, что приложение лезет в /etc на чтение или копирует почтовый ящик на неожиданный контент:
opensnoop-bpfcc
# пример вывода
# PID COMM FD ERR PATH
# 8021 sh 4 0 /etc/nginx/nginx.conf
# 8021 sh -1 2 /etc/nginx/ssl/missing.pem
Имя и путь говорят сами за себя, а код ошибки показывает отказ доступа. Для расследования отказов opensnoop отличает виновный процесс от красных метрик на графике: кто именно пытался открыть отсутствующий файл и на каком пути это закончилось ошибкой номер два. Утилита поддерживает фильтрацию и по идентификатору процесса, и по флагу ошибки, и такая проверка запускает расследование в секунды, а не в десятки минут поиска по логам.
Отдельная история для тех, кто работает с программами на сертификатах Ещё одна зона применения это запуск подменных заданий: на машине, общей для нескольких служб, событие неожиданного запуска wget или curl вне расписания почти всегда значит попытку таскать чужой скрипт, и журнал запусков с родительским pid объясняет, чьим заданием это вызвано, задолго до того, как система покажет равнодушные метрики. Тот же след виден при неожиданном чтении ключей из каталога ssh: службы, которым положено, события вызывают по ожиданиям, а каждое другое открытие сразу видно на слое событий, и полнее всего это читается после ограничения наблюдения на конкретную папку.
: события с нулевым допуском на файлы ключей обнаруживаются отдельно, и дополнительное внимание к opensnoop позволяет увидеть, что программа не подбирает приватные ключи по расписанию. За часовой пояс наблюдения это намного полезнее параноидальной блокировки всего и всех.
Карта событий на каждый день администратора
Опытная коллекция утилит выходит за пределы пары упомянутых инструментов, и короткий список применяемых элементов подходит почти любой команде:
- биолатентность регистрирует гистограмму задержек блочного ввода, что помогает отследить узкую очередь устройства, а не интуитивные догадки;
- cachestat показывает соотношение попаданий в кэш страниц и чтений с диска, и это отвечает, держит ли ядро буферную память в порядке;
- runqlat показывает, сколько времени задачи застревают в очереди планировщика до запуска, и немедленно различает медленность системы от недостатка ядер;
- gethostlatency фиксирует запросы на разрешение имён, и можно сделать вывод, являются ли повторные задержки DNS-очередью, а не приложением;
- pidpersec смотрит, как быстро задачи запускаются, и позволяет увидеть сервис, который засирает потоки под собственные логи.
При тех же повседневных применениях отдельная история это работа со старыми пользователями: когда лес журналов под окном журнала месяцами показывает одинаковые явления, лекарственные мутации далее не нуждаются в длительной привычке. Понятно, что наблюдение обострено средой: только очевидное различие системы нормально переносит событие, а расследование приобретает свойства, без которых дело стоит долго.
Такая карта трансформируется в привычный перечень, когда система работает в повседневном режиме: процессы, сетевые соединения, очереди планировщика и задержки ввода читаются одним взглядом, а перечень настраивается с учётом характеристик вашей площадки за одну неделю изучения. Если какое-то наблюдение не показало пользы за неделю, оно убирается добровольно, и комплект остаётся легко управляемым без накопления никогда не нужного инструментария. В таком формате стоит и отчёт о первой проверке: таблица с наиболее любопытными событиями за день, параметры запусков и ошибки ввода, а в конце недели этот материал трансформируется в заметки эксплуатации, и переживает своих авторов.
Разделение сетевых соединений через tcpconnect и tcpaccept
Когда проблема начинается со слов "сервис тормозит" и при этом речи о процессоре нет, ответ часто живёт в сетевом стеке, и здесь BCC работает особенно хорошо. Первый из них показывает новые исходящие соединения с адресом и портом назначения, второй фиксирует свежих слушателей по портам процесса. Различие с привычными утилитами состояния простое: здесь не читается моментальная статистика, а собираются события в порядке появления, и именно эти записи позволяют идти в обратную сторону от ответственной службы к её источникам. Поэтому на задержки вроде медленных HTTPS-вызовов из приложения легче всего смотреть из тела событий, а не из метрик: в выводе видны и порт, и адрес, и даже время самой попытки.
Практика знать о них стоит по той же причине, по которой полагается изучать корпус: связь типового инцидента с отдельным клиентом, от маршрута маршрутизируется через одного клиента, и выясняется это легко. Такой привычный сценарий решается с toolset за пару минут, и именно поэтому список повседневных утилит BCC собирается из рассказов сетевой этнографии, а не из мануалов.
Аккуратность на живых серверах и границы применимости
При работе на загруженной машине стоит держать две привычки: короткие окна наблюдений и предварительные фильтры. Стратегия стандартная: первый запуск всегда самый короткий из доступных на каждой системе, а последующие уже ограничивают события по конкретным ответам. На горизонтально нагруженных системах наблюдения разворачиваются на десятке узлов в сеансе, и именно фильтрация отвечает за то, чтобы очередной запуск обходился без тяжёлых попутных расходов.
Обычно на перегруженных серверах утилиты latency воспринимаются дополнительным фактором, как будто забытый процесс блокировки остался без внимания. Привычка закрывать избыточные окна перед наблюдением стоит в одинаково высоком качестве, и подобная организация записывается в журнал изменений, а не в руководство к размышлениям.
Строго говоря, подобные инструменты не сообщают, что делать с проблемой: они показывают её, а управление этим знанием остаётся процессной работой. Часы на анализ даже элегантной информации легко теряются, когда реальная ошибка лежит в конфигурации приложения, а не в его взаимодействии с ядром, и такие ситуации отбрасывают расследование на начало. Неизменным остаётся эффективный тандем: изменения конфигурации включаются по предмету измерения, а не вместо него. Как только набор устоялся, работа с ним начинает менять очередь расследования: первая помощь перестаёт зависеть от дежурного админа и превращается в будничную задачу, выполняемую мимоходом. Ключевым показателем этого являются вечерние страницы: страница текущего нарушения, вместо страницы размышлений, появляется неожиданно и получается из набора готовых инструментов без колдовства.
Из стимулов системного подхода: следующее происшествие закрывается столь же чисто, как и в первый раз, потому что уже накопленный набор инструментария уже привычен и понятен. И если говорить о том, что хорошего приносит ежедневная диагностика в промышленной эксплуатации, то это прежде всего уверенность команды: история зависаний перестаёт быть анекдотом и становится журналом с разбором. Точно так же собранные события о простых механике ядра постепенно превращаются в эталонный материал для обучения новичков, а не только в коллекцию случайных записей по инцидентам. Причина проста: события, которые когда-то выглядели обрывочно, постепенно складываются в картину нормального поведения системы, и аномалия с ней начинает угадываться раньше, чем доходит до реального сбоя.