[Перевод] Grafana Beyla: автоинструментарий eBPF с открытым исходным кодом для наблюдения за приложением

205a46d9e808df456f21b70786d24eb8.jpeg

Хотите попробовать 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

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. 

  1. Последняя версия есть на GitHub

  2. Для получения последней версии выберите нужный пакет и архитектуру. Вот пример для скачивания заархивированной версии 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
  1. Создайте обычный текстовый файл, например 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")
        }
    }
}
  1. Обратите внимание, что он настроен на сбор метрик по адресу 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

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

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

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

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 и многое другое.

© Habrahabr.ru