Перейти к содержанию

Глава 9: Инструменты BCC — Глубокая трассировка ядра

Обзор

Коллекторы Tier 1 читают счётчики из /proc — они говорят что происходит (CPU занят на 90%). Но они не могут сказать почему (какой процесс, какая функция, какое распределение задержек).

Здесь на сцену выходят инструменты BCC (BPF Compiler Collection). Они прикрепляют eBPF-программы к функциям ядра и трассируют события в реальном времени, предоставляя гистограммы, детали событий и стек-трейсы.

Пакет internal/executor/ управляет безопасным запуском этих инструментов и парсингом их вывода.

Файлы исходного кода: executor/

Файл Строк Назначение
executor.go 133 BCCExecutor — запуск внешних бинарников с проверками
security.go 133 SecurityChecker — верификация целостности бинарников
registry.go 181 Registry — каталог 20 инструментов BCC
parsers.go 463 Парсеры вывода (гистограммы, таблицы, стеки)
aggregate.go 149 Агрегация событий (top-N, соединения)

Экзекьютор: Как запускаются BCC инструменты

BCCExecutor.Run()

func (e *BCCExecutor) Run(ctx context.Context, toolName string, duration time.Duration) (*model.Result, error) {
    spec, ok := Registry[toolName]                   // Поиск спецификации
    binary := e.security.ResolveBinary(spec.Binary)  // Поиск и проверка пути
    args := spec.BuildArgs(duration)                 // Сборка аргументов CLI
    env := e.security.SanitizeEnv()                  // Очистка окружения

    cmd := exec.CommandContext(ctx, binary, args...)
    cmd.Env = env
    cmd.Stdout = NewLimitedWriter(50 * 1024 * 1024)  // Лимит вывода 50МБ

    cmd.Start()
    cmd.Wait() // Ожидание завершения или таймаута

    result := spec.Parser(output) // Парсинг вывода
}

LimitedWriter — Защита вывода

Некоторые инструменты (например, execsnoop, tcpdrop) генерируют вывод на каждое событие. На нагруженном сервере это могут быть гигабайты. Лимит в 50МБ предотвращает исчерпание памяти.

Модель безопасности

Почему это важно

Инструменты BCC работают от root и могут трассировать ЛЮБУЮ функцию ядра. Скомпрометированные бинарники могут: - Читать произвольную память ядра - Модифицировать системные вызовы - Логировать чувствительные данные

SecurityChecker

  1. Разрешённые пути: Бинарники ищутся только в доверенных директориях (/usr/share/bcc/tools, /usr/sbin, /usr/bin).
  2. Верификация прав: Файл должен принадлежать root (UID 0) и не быть доступным для записи всем (world-writable).
  3. Очистка окружения: Удаляются переменные типа LD_PRELOAD, LD_LIBRARY_PATH, чтобы предотвратить подмену библиотек.

Парсеры вывода

ParseHistogram() — Распределения

Вывод BCC гистограммы:

     usecs               : count    distribution
         4 -> 7          : 15       |****                                    |
         8 -> 15         : 107      |*****************************           |
        16 -> 31         : 145      |****************************************|

Парсер преобразует это в структуру с перцентилями (P50, P90, P99). Перцентили вычисляются путём итерации по бакетам.

ParseFoldedStacks() — Flame Graph

Для профилирования вывод выглядит как "свернутые" стеки:

main;handleRequest;db.Query;net.Write 42

Это парсится в структуру StackTrace, из которой затем строится SVG Flame Graph.

Интерпретация результатов (Thresholds)

runqlat — Очередь CPU

Перцентиль Хорошо Внимание Критично
p50 < 10μs 10-100μs > 100μs
p99 < 100μs 100-1000μs > 1ms

biolatency — Дисковые задержки

Перцентиль SSD HDD Критично
p50 < 100μs < 5ms
p99 < 1ms < 20ms > 50ms

tcpconnlat — Установка соединения

Латентность Значение
< 1ms Тот же датацентр
1-5ms Тот же регион
> 100ms Межконтинентальная сеть или перегрузка
> 1000ms Проблемы с DNS или маршрутизацией

Далее: Глава 10 — Нативный eBPF