[Перевод] Grafana Beyla: автоинструментарий eBPF с открытым исходным кодом для наблюдения за приложением
Хотите попробовать Grafana для наблюдения за сервисами, но времени на адаптацию приложения не хватает?
Часто для правильной интеграции инструментов мониторинга в приложение приходится добавлять агент мониторинга Observability в развёртывание или пакет. А в таких языках, как Go, нужно вручную добавлять точки трассировки. В любом случае после добавления инструментов придётся выполнить повторное развёртывание в промежуточную или производственную среду.
Автоинструментарий упрощает внедрение Observability. С гордостью представляем Grafana Beyla — автоинструментарий eBPF с открытым исходным кодом, который сейчас в стадии публичного тестирования. Beyla сообщает данные о задержках для основных запросов, а также метрики RED (Rate-Errors-Duration) для сервисов Linux HTTP/S и gRPC — и всё это без модификации кода для ручной вставки зондов.
В этой статье мы рассмотрим, как установить и настроить Grafana Beyla с помощью Grafana Cloud для улучшения наблюдаемости приложений. Ещё поделимся планами на будущее.
Что за название — Beyla?
Как и в других проектах с открытым исходным кодом, мы ориентировались на наши скандинавские корни и взяли имя Beyla из норвежской мифологии.
Что такое eBPF?
eBPF расшифровывается как Extended Berkeley Packet Filter и позволяет подключать собственные программы к различным точкам ядра Linux. Программы eBPF работают в привилегированном режиме, что позволяет проверять информацию о выполнении из разных частей ядра. Речь идёт о системных вызовах, сетевом стеке и даже возможности вставлять зонды в программы из пользовательского пространства.
Программы eBPF безопасны, поскольку компилируются для их собственного набора инструкций виртуальной машины и затем могут работать в песочнице, которая предварительно проверяет каждую загруженную программу на безопасный доступ к памяти и конечность времени выполнения. В отличие от других технологий, таких как старые нативно-скомпилированные Kprobes и Uprobes, здесь плохо запрограммированный зонд не сможет привести к зависанию ядра.
После верификации двоичные файлы eBPF компилируются под родную архитектуру хоста (x86–64, ARM64 и т. д.) в режиме Just-In-Time (JIT). Так обеспечивается скорость и эффективность выполнения.
Код eBPF загружается из обычных программ, выполняющихся в пользовательском пространстве. Работающий в контексте ядра код и программы пользовательского пространства могут обмениваться информацией с помощью механизмов связи, предоставляемых спецификацией eBPF: кольцевые буферы, массивы, хэш-таблицы.
Diagram of eBPF workflow with Linux kernel
Настройка сервиса для наблюдения
Чтобы запустить Grafana Beyla, сначала понадобится сервис для интеграции нового мониторинга. В этом кратком руководстве мы рекомендуем взять любой HTTP-, HTTPS- или gRPC-сервис Go, который использует одну из библиотек:
Кроме того, можно внедрять инструменты наблюдения в HTTP и HTTPs-сервисы, написанные на других языках: NodeJS, Python, Rust, Ruby, Java (только HTTP) и т. п.
Если сейчас у вас нет сервиса, чтобы потренироваться, создайте простой сервис для теста. Создайте текстовый файл server.go
, откройте его в редакторе и вставьте этот код:
package main
import (
"net/http"
"strconv"
"time"
)
func handleRequest(rw http.ResponseWriter, req *http.Request) {
status := 200
for k, v := range req.URL.Query() {
if len(v) == 0 {
continue
}
switch k {
case "status":
if s, err := strconv.Atoi(v[0]); err == nil {
status = s
}
case "delay":
if d, err := time.ParseDuration(v[0]); err == nil {
time.Sleep(d)
}
}
}
rw.WriteHeader(status)
}
func main() {
http.ListenAndServe(":8080",
http.HandlerFunc(handleRequest))
}
Приведённый выше HTTP-сервис принимает любой запрос на порт 8080
и позволяет переопределить поведение с помощью двух аргументов запроса:
status
переопределяет возвращаемый код состояния HTTP (по умолчанию200
). Например, curl -v «http://localhost:8080/foo? status=404» вернёт код состояния404
.delay
искусственно увеличивает время отклика сервиса. Например, с curl «http://localhost:8080/bar? delay=3s» для отправки ответа потребуется 3 секунды.
Запустите файл server.go
с помощью:
$ go run server.go
Скачивание Grafana Beyla
ℹ️ Для простоты мы говорим о запуске Beyla вручную, как обычный процесс ОС. О дополнительных режимах работы можно узнать в документации по запуску Beyla в качестве контейнера Docker или документации по развёртыванию Beyla в Kubernetes.
Исполняемый файл Beyla можно скачать со страницы релизов Beyla в нашем репозитории. Выберите версию, совместимую с вашим процессором. Подробности в документе Run Beyla as a standalone process.
Исполняемый файл Grafana Beyla можно скачать с помощью go install
:
go install github.com/grafana/beyla/cmd/beyla@latest
Внедрение инструментов в работающий сервис
Для работы Beyla нужно как минимум два варианта конфигурации:
Селектор исполняемого файла, в который внедряем инструментарий. Его можно выбрать по имени исполняемого файла (переменная среды
EXECUTABLE_NAME
) или по открытому им порту (переменная средыOPEN_PORT
).Экспортёр метрик. В этом руководстве автоинструментированные метрики будут выложены как стандартные метрики Prometheus (переменная среды
BEYLA_PROMETHEUS_PORT
), а некоторые трассировки будут отправляться на стандартный вывод (переменная средыPRINT_TRACES=true
).
Узнать о настройке других экспортёров, например трассировок и метрик OpenTelemetry, и о дополнительных параметрах настройки можно в документации Beyla в разделе конфигурации.
После запуска сервиса из предыдущего раздела мы можем добавить в него Beyla, выполнив команду beyla. Мы уже скачали её в главе «Скачивание».
Мы настроим Beyla на наблюдение за исполняемым файлом, который работает на порту 8080
. Отправлять трассировки будем через стандартный вывод и отображать метрики RED в конечной точке HTTP localhost:8999/metrics.
Учтите, что для запуска процесса внедрения инструмента нужны права администратора:
$ BEYLA_PROMETHEUS_PORT=8999 PRINT_TRACES=true OPEN_PORT=8080 sudo -E beyla
Теперь можно протестировать сервис инструментирования с другого терминала:
$ curl "http://localhost:8080/hello"
$ curl "http://localhost:8080/bye"
После логов в стандартном выводе Beyla должна появиться информация о трассировке указанных выше запросов:
2023-04-19 13:49:04 (15.22ms[689.9µs]) 200 GET /hello [::1]->[localhost:8080] size:0B
2023-04-19 13:49:07 (2.74ms[135.9µs]) 200 GET /bye [::1]->[localhost:8080] size:0B
Формат следующий:
Request_time (response_duration) status_code http_method path source->destination request_size
Поиграйте с командой curl
, чтобы посмотреть, как она влияет на трассировку. Например, в следующем запросе будет отправлен POST-запрос размером 6 байт, а сервису потребуется 200 мс для ответа:
$ curl -X POST -d "abcdef" "http://localhost:8080/post?delay=200ms"
При этом в стандартном выводе Beyla будет показано:
2023-04-19 15:17:54 (210.91ms[203.28ms]) 200 POST /post [::1]->[localhost:8080] size:6B
Есть другой вариант. В фоновом режиме можно сгенерировать искусственную нагрузку на другом терминале:
$ while true; do curl "http://localhost:8080/service?delay=1s"; done
Поиграв некоторое время с сервером, работающим на порту 8080
, можно запросить метрики Prometheus, открытые на порту 8999
:
$ curl http://localhost:8999/metrics
# HELP http_server_duration_seconds duration of HTTP service calls from the server side, in milliseconds
# TYPE http_server_duration_seconds histogram
http_server_duration_seconds_bucket{http_method="GET",http_status_code="200",service_name="testserver",le="0.005"} 1
http_server_duration_seconds_bucket{http_method="GET",http_status_code="200",service_name="testserver",le="0.005"} 1
http_server_duration_seconds_bucket{http_method="GET",http_status_code="200",service_name="testserver",le="0.01"} 1
(... cutting for the sake of brevity ...)
Полный список метрик, которые может экспортировать Belya, — в соответствующем разделе документации.
Отправка данных в Grafana Cloud
Когда мы убедились, что всё работает, мы можем добавить коллектор Prometheus для считывания метрик автоинструментирования и их передачи в Grafana Cloud. Если у вас еще нет аккаунта Grafana Cloud, вы можете завести его бесплатно.
Существует два метода считывания метрик и их пересылки в Grafana Cloud:
Скачивание и настройка Grafana Agent
⚠️ В этом разделе кратко описаны скачивание и настройка Grafana Agent для интерактивных сред, работающих в ручном режиме. Полное описание процесса установки и настройки Grafana Agent, а также рекомендуемых режимов можно найти в документации по установке Grafana Agent в режиме Flow.
Grafana Agent — сборщик телеметрии. Он облегчает сбор экспортируемых Beyla метрик Prometheus и их отправку в Grafana.
Последняя версия есть на GitHub
Для получения последней версии выберите нужный пакет и архитектуру. Вот пример для скачивания заархивированной версии 0.34.3 для 64-битной архитектуры Intel/AMD:
$ wget https://github.com/grafana/agent/releases/download/v0.34.3/grafana-agent-linux-amd64.zip
$ unzip grafana-agent-linux-amd64.zip
Создайте обычный текстовый файл, например ebpf-tutorial.river, и скопируйте в него текст ниже. Тогда Grafana Agent будет собрать метрики Prometheus из Beyla и передать их в Grafana Cloud.
prometheus.scrape "default" {
targets = [{"__address__" = "localhost:8999"}]
forward_to = [prometheus.remote_write.mimir.receiver]
}
prometheus.remote_write "mimir" {
endpoint {
url = env("MIMIR_ENDPOINT")
basic_auth {
username = env("MIMIR_USER")
password = env("GRAFANA_API_KEY")
}
}
}
Обратите внимание, что он настроен на сбор метрик по адресу
localhost:8999
, совпадающему со значением переменнойBEYLA_PROMETHEUS_PORT
из предыдущего раздела. Кроме того, детали подключения к Grafana Cloud — конечная точка и аутентификация — будут задаваться через переменные среды.
Запуск Grafana Agent с учётными данными Grafana
На портале Grafana Cloud нажмите кнопку Details
в окне Prometheus
. Затем получите конечную точку Grafana Prometheus (Mimir) Remote Write и своё имя пользователя. Сгенерируйте и скопируйте API-ключ Grafana с правами на пуш метрик:
Screenshot of Grafana Cloud UI to set up Prometheus end point
Теперь, используя информацию выше, запустите Grafana Agent для обработки переменных среды MIMIR_ENDPOINT, MIMIR_USER и GRAFANA_API_KEY
:
$ export MIMIR_ENDPOINT="https://prometheus-prod-01-eu-west-0.grafana.net/api/prom/push"
$ export MIMIR_USER="123456"
$ export GRAFANA_API_KEY="your api key here"
$ AGENT_MODE=flow ./grafana-agent-linux-amd64 run ebpf-tutorial.river
ts=2023-06-29T08:02:58.761420514Z level=info msg="now listening for http traffic" addr=127.0.0.1:12345
ts=2023-06-29T08:02:58.761546307Z level=info trace_id=359c08a12e833f29bf21457d95c09a08 msg="starting complete graph evaluation"
(more logs....)
Для проверки верного получения метрик в Grafana выберите вкладку Explore
на левой панели и для источника данных Prometheus укажите http_
в поле ввода Metrics Browser.
После генерации HTTP-нагрузки (например, с помощью curl
, как в предыдущих примерах) во всплывающем окне автозаполнения должны появиться новые имена метрик. Удостоверьтесь, что Beyla по-прежнему выполняется как процесс, отличный от Grafana Agent.
Screenshot of metrics browser in Grafana Cloud
Добавление панели метрик eBPF RED
Теперь можно составлять запросы PromQL для лучшей визуализации автоинструментированных метрик RED. Чтобы сэкономить вам время, мы создали общедоступную панель с базовой информацией.
Чтобы импортировать панель в свою Grafana, в левой панели на странице Dashboards
раскройте выпадающий список New
и выберите Import
:
Screenshot of Grafana Cloud UI to add RED metrics dashboard
В поле Import
можно скопировать идентификатор дашборда Beyla RED: 19077
.
Переименуйте его по своему усмотрению, выберите папку и главное — источник данных во всплывающем окне prometheus-data-source
внизу.
Вуаля! Теперь вы видите свои метрики RED:
Grafana dashboard showing RED metrics collected with Grafana Beyla
Панель состоит из следующих частей:
Самые медленные HTTP-маршруты для всех наблюдаемых сервисов. Поскольку у вас только один сервис, отображается одна запись. Если настроить автоинструментарий на создание отчёта об HTTP-маршрутах, может появиться много записей. Например, по одной на каждый HTTP-маршрут на сервере.
Самые медленные методы gRPC. Наш тестовый сервис обслуживает только HTTP, поэтому эта таблица пуста.
Список метрик RED для входящего (серверного) трафика для каждого наблюдаемого сервера. Он включает:
Количество запросов в секунду, определяемое по коду возврата HTTP или gRPC.
Долю ошибок. Отображается как процент 5xx HTTP-ответов или ненулевых gRPC-ответов от общего количества запросов. Они разделены по коду возврата.
Продолжительность: cредние и верхние процентили для трафика HTTP и gRPC.
Список метрик RED для исходящего (клиентского) трафика для каждого наблюдаемого сервера. На скриншоте выше он пуст, поскольку тестовый сервис выполняет HTTP- или gRPC-вызовы к другим сервисам.
Графики количества запросов, ошибок и длительности аналогичны графикам входящего трафика. Единственная разница заключается в том, что на стороне клиента ошибками считаются также коды возврата 4xx.
В верхней части графика с помощью выпадающего списка Service
можно отфильтровать сервисы, которые вы хотите визуализировать.
Зачем использовать Grafana Beyla для наблюдаемости приложений
eBPF — быстрый, безопасный и надёжный способ наблюдения за некоторыми основными показателями сервисов. Grafana Beyla не заменит агенты мониторинга, но сократит необходимое для обеспечения наблюдаемости приложений время. Приложению не нужны модификация, перекомпиляция или переупаковка. Просто запустите её со своим сервисом.
Кроме того, eBPF позволяет увидеть некоторые детали, которые не видны при внедрении инструментов вручную. Например, Beyla может показать, сколько времени запрос находится в очереди после установления соединения и до фактического выполнения его кода. Для этого нужно экспортировать трассировку OpenTelemetry, но здесь мы не рассматриваем эту функцию.
У Grafana Beyla есть свои ограничения. Поскольку пока она предоставляет общие метрики и диапазоны без распределённых трассировок, мы по-прежнему рекомендуем использовать агенты Observability и ручную настройку мониторинга. Тогда вы сможете задать гранулярность каждой части кода, подлежащей мониторингу, и сосредоточиться на критически важных операциях.
Еще одно ограничение: для работы Beyla нужны расширенные права. Необязательно запускать от root, но как минимум работать с правами CAP_SYS_ADMIN
. Если вы запускаете Belya как контейнер (Docker, Kubernetes и т. д.), то либо он должен обладать привилегиями, либо нужно добавить возможность CAP_SYS_ADMIN
.
Будущее Grafana Beyla
Сейчас Grafana Beyla в стадии публичного тестирования. В будущем мы планируем добавлять метрики для других популярных протоколов, таких как соединение с базами данных или очередями сообщений.
Также важно работать над распредёленной трассировкой, чтобы вы получали не только изолированные диапазоны, но и могли связывать их с запросами от других сервисов (например, веба, баз данных, служб обмена сообщениями). Это сложно из-за необходимости переделывать заголовки на стороне клиента и помещать их в тот же контекст, что и запросы на стороне сервера. Но мы планируем постепенно двигаться к распределённой трассировке.
Еще одна будущая задача — уменьшить количество кода, требующего прав администратора. Мы планируем решить это небольшим загрузчиком eBPF с привилегиями root или CAP_SYS_ADMIN.
При этом остальная часть обработки/экспозиции данных будет происходить с правами обычного пользователя.
Чтобы узнать больше, ознакомьтесь с Grafana Beyla на GitHub и пройдитесь по документации. Она включает руководство по развёртыванию Beyla в Kubernetes и многое другое.