Привет, Хабр! Предлагаю вашему вниманию перевод статьи Брендана Грегга, посвящённой изучению 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):
# tcplifePID 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-сессии, которые происходят куда реже. Это делает накладные расходы настолько низкими, что мы можем запустить этот инструмент в режиме 24x7.
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, охватывающая всё это более подробно. Успехов!