[Из песочницы] Изучаем трассировку с помощью eBPF: Руководство и примеры
Привет, Хабр! Предлагаю вашему вниманию перевод статьи Брендана Грегга, посвящённой изучению eBPF
На конференции Linux Plumbers было как минимум 24 выступления по eBPF. Он быстро стал не просто бесценной технологией, но и востребованным навыком. Возможно, вам хотелось бы поставить какую-то цель на новый год — изучите eBPF!
Термин eBPF должен означать что-то существенное, как например Virtual Kernel Instruction Set (VKIS), но по своему происхождению это расширенный Berkeley Packet Filter. Он применим во многих областях, таких как производительность сети, фаерволлы, безопасность, трассировка и драйвера устройств. По некоторым из них есть много свободно доступной информации в интернете — например, по трассировке, а по другим ещё нет. Термин трассировка относится к инструментам анализа производительности и наблюдения, которые могут генерировать информацию по каждому событию. Возможно, вы уже использовали трассировщик — tcpdump и strace являются специализированными трассировщиками.
Этим постом я собираюсь описать процесс изучения использования eBPF в целях трассировки, сгруппированный в разделы для начинающих, опытных и продвинутых пользователей. В итоге:
- Начинающим: запуск инструментов bcc
- Опытным: разработка инструментов bpftrace
- Продвинутым: разработка инструментов bcc, вклад в bcc и bpftrace
1. Что такое eBPF, bcc, bpftrace и iovisor?
eBPF делает для Linux тоже самое, что и JavaScript делает для HTML, ну вроде того. Так, вместо статического сайта на HTML, JavaScript позволяет вам задавать мини-программы, которые выполняются по событиям — вроде щелчка мышкой — которые запускаются в безопасной виртуальной машине в браузере. И с eBPF — вместо правки ядра, вы можете теперь писать мини-программы, которые запускаются при событиях вроде дисковых операций ввода-вывода, на безопасной виртуальной машине в ядре. На самом деле eBPF больше похож на виртуальную машину v8, запускающую JavaScript, чем на сам JavaScript. eBPF является частью ядра Linux.
Программирование напрямую в eBPF невероятно сложно, так же, как и в байт-коде на v8. Но никто не кодит в v8: все пишут на JavaScript, или часто на фреймворке поверх JavaScript (jQuery, Angular, React, и т.д.). Тоже самое и с eBPF. Люди будут использовать его, а писать код — посредством фреймворков. Для трассировки основными являются bcc и bpftrace. Они не живут в кодовой базе ядра, они обитают в проекте Linux Foundation на гитхабе, называющемся iovisor.
2. Можно пример трассировки с помощью eBPF?
Эта основанная на eBPF утилита демонстрирует полностью установленные TCP сессии с их ID процесса (PID), именем команды (COMM), отправленными и полученными байтами (TX_KB, RX_KB), а также длительность в миллисекундах (MS):
# tcplife
PID COMM LADDR LPORT RADDR RPORT TX_KB RX_KB MS 22597 recordProg 127.0.0.1 46644 127.0.0.1 28527 0 0 0.23 3277 redis-serv 127.0.0.1 28527 127.0.0.1 46644 0 0 0.28 22598 curl 100.66.3.172 61620 52.205.89.26 80 0 1 91.79 22604 curl 100.66.3.172 44400 52.204.43.121 80 0 1 121.38 22624 recordProg 127.0.0.1 46648 127.0.0.1 28527 0 0 0.22 3277 redis-serv 127.0.0.1 28527 127.0.0.1 46648 0 0 0.27 22647 recordProg 127.0.0.1 46650 127.0.0.1 28527 0 0 0.21 3277 redis-serv 127.0.0.1 28527 127.0.0.1 46650 0 0 0.26 [...]
Не это eBPF делает возможным — я могу переписать tcplife, чтобы использовать более старые технологии ядра. Но если бы я это сделал, мы бы никогда не запустили такой инструмент в продакшне из-за снижения производительности, проблем с безопасностью или сразу и того и другого. eBPF сделал этот инструмент практичным: он эффективен и безопасен. Например, он не отслеживает каждый пакет, как делалось при прежних подходах и что могло приводить к чрезмерному снижению производительности. Вместо этого он отслеживает лишь события TCP-сессии, которые происходят куда реже. Это делает накладные расходы настолько низкими, что мы можем запустить этот инструмент в режиме 24×7.
3. Как мне это использовать?
Начинающим стоит начать знакомство с bcc. Посмотрите инструкции по установке bcc под вашу операционную систему. Для Ubuntu это выглядит как-то так:
# sudo apt-get update
# sudo apt-get install bpfcc-tools
# sudo /usr/share/bcc/tools/opensnoopPID COMM FD ERR PATH 25548 gnome-shell 33 0 /proc/self/stat 10190 opensnoop -1 2 /usr/lib/python2.7/encodings/ascii.x86_64-linux-gnu.so 10190 opensnoop -1 2 /usr/lib/python2.7/encodings/ascii.so 10190 opensnoop -1 2 /usr/lib/python2.7/encodings/asciimodule.so 10190 opensnoop 18 0 /usr/lib/python2.7/encodings/ascii.py 10190 opensnoop 19 0 /usr/lib/python2.7/encodings/ascii.pyc 25548 gnome-shell 33 0 /proc/self/stat 29588 device poll 4 0 /dev/bus/usb ^C
Здесь я закончил запуском opensnoop, чтобы проверить работоспособность инструментов. Если вы дошли так далеко, вы точно пользовались eBPF!
В таких компаниях, как Netflix и Facebook, bcc установлен на всех серверах по умолчанию. Может быть и вы захотите поступить также.
4. Имеется ли руководство для начинающих?
Да, я написал руководство по bcc, которое является хорошей отправной точкой для новичков в трассировке с помощью eBPF:
Как новичку, вам нет необходимости писать какой-либо код для eBPF. bcc уже содержит более, чем 70 инструментов, которые вы можете сразу использовать. Это руководство проведёт вас по шагам через следующие одиннадцать: execsnoop, opensnoop, ext4slower (или btrfs*, xfs*, zfs*), biolatency, biosnoop, cachestat, tcpconnect, tcpaccept, tcpretrans, runqlat и profile.
После того, как вы их попробовали, вам остаётся просто знать, что существует ещё много других средств:
Они также полностью обеспечены документацией средствами man-страниц и файлами с примерами. Файлы примеров (*_example.txt в bcc/tools) содержат скриншоты с объяснениями: например, biolatency_example.txt. Я написал многие из них (и man-страниц, и инструментов), которые похожи на дополнительные 50 постов в блоге, вы найдёте их в репозитории bcc.
Чего не хватает, так это реальных примеров с продакшна. Я написал эту документацию, когда eBPF был настолько новым, что он был доступен только в наших тестовых средах, так что большинство примеров являются искусственными. Со временем мы добавим примеры из реального мира. Это та область, где новички могут помочь: если вы решаете проблему, подумайте над тем, чтобы написать статью и поделиться скриншотами или добавить их в качестве файлов с примерами.
На этом этапе вы уже должны запустить bcc и опробовать эти инструменты, а также быть заинтересованными в их модификации и написании своих собственных инструментов. Лучший способ — это перейти на bpftrace, содержащий язык высокого уровня, который намного проще изучить. Недостатком является то, что он не так гибок в настройке, как bcc, так что вы можете столкнуться с ограничениями и захотеть вернуться обратно к bcc.
Обратитесь к инструкциям по установке bpftrace. Это более новый проект, поэтому на момент написания этой статьи пакеты собраны еще не для всех систем. В будущем это должно быть просто apt-get install bpftrace или что-то аналогичное.
1. Учебник по bpftrace
Я разработал учебник, который обучает использованию bpftrace через серию однострочников:
Там даётся 12 уроков, которые шаг за шагом обучат вас работе с bpftrace. Вот пример:
# bpftrace -e 'tracepoint: syscalls: sys_enter_open { printf (»%d %s\n», pid, str (args→filename)); }'
Attaching 1 probe... 181 /proc/cpuinfo 181 /proc/stat 1461 /proc/net/dev 1461 /proc/net/if_inet6 ^C
Здесь используется системный вызов open как точка трассировки для отслеживания PID и путей открытых файлов.
2. Справочное руководство по bpftrace
Для получения подробностей о bpftrace, я написал руководство, содержащее примеры синтаксиса, тестов и встроенных команд:
Это ради краткости: я стараюсь разместить заголовок, резюме и скриншот на одной странице. Я думаю, что это слишком долго — если вы ищете что-то и вам нужно несколько раз пролистать страницу.
3. bpftrace в примерах
Есть более 20 инструментов в репозитории bpftrace, которые вы можете рассмотреть на примерах:
Например:
# cat tools/biolatency.bt
[...] BEGIN { printf("Tracing block device I/O... Hit Ctrl-C to end.\n"); } kprobe:blk_account_io_start { @start[arg0] = nsecs; } kprobe:blk_account_io_completion /@start[arg0]/ { @usecs = hist((nsecs - @start[arg0]) / 1000); delete(@start[arg0]); }
Подобно bcc, эти утилиты имеют справочные страницы man pages и файлы примеров. Например, biolatency_example.txt.
1. Изучаем разработку bcc
Я создал два руководства в помощь:
Там также много примеров в bcc/tools/*.py. Инструменты bcc состоят из двух частей: кода BPF для ядра, написанного на C, и инструмента уровня пространства пользователя, написанного на Python (или lua, или C++). Разработка инструментов bcc довольно продвинута и может включать некоторые мелкие компоненты ядра или внутренних прикладных элементов.
2. Участие в разработке
Приветствуется помощь с:
Для bpftrace я создал Руководство по внутренней разработке bpftrace. Это трудно, когда программируешь в llvm IR, но если вы готовы принять вызов…
Есть также ядро eBPF (он же BPF): если вы посмотрите bcc и bpftrace issues, вы увидите там несколько реквестов на улучшения. Например, тэг kernel в bpftrace. Также посмотрите список рассылки netdev на предмет последних разработок ядра BPF, которые добавляются в net-next до их слияния с мейнлайном Linux.
Помимо написания кода, вы также можете принять участие в тестировании, создании пакетов, публикациях в блогах и обсуждениях.
eBPF умеет много разных вещей. В данном посте я рассмотрел освоение eBPF в целях трассировки и анализа производительности. В итоге:
- Начинающим: запуск инструментов bcc
- Опытным: разработка инструментов bpftrace
- Продвинутым: разработка инструментов bcc, вклад в bcc и bpftrace
У меня также есть отдельная страница про Инструменты трассировки eBPF, охватывающая всё это более подробно. Успехов!