Блог AlexZ
Лента Посты Автор
24.02.2021

eBPF-exporter и ошибки памяти станут метрикой

Ошибки железа - популярная тема, когда у вас несколько сотен серверов. Если с дисками всё в целом понятно: они либо вылетают, либо лагают, либо инкрементят счетчики S.M.A.R.T., то с памятью, например, интересней.

EDAC

Ошибки памяти распознаются, а некоторые из них даже исправляются, при помощи алгоритмов ECC. Происходит это в двух случаях:

  1. При чтении данных из памяти.
  2. Во время скраба — периодической проверки, которая заключается в чтении областей памяти и проверке при помощи тех же ECC.

В результате существует два основных типа ошибок — корректируемые и некорректируемые. В первом случае, после возникновения ошибки, данные будут исправлены, но, к сожалению, на это нужно некоторое время. Если серверу постоянно приходится корректировать ошибки, софт будет лагать. К тому же растет вероятность возникновения ошибок, которые ECC не сможет откорректировать. Отсюда появляется задача эти ошибки отлавливать. При возникновении некорректируемых ошибок ядро Linux впадает в панику.

ebpf-exporter

В одной статье я уже описывал как работать с eBPF на примере программы для трейсинга блочного стека Linux. Я много работал с prometheus и появление ebpf-exporter, способного возвращать метрики прямо из eBPF-программ, заинтриговало. Однако никакого действительно серьезного кейса, из-за которого было бы необходимо запустить этот инструмент в продакшен, не возникало до того момента, пока не достали окончательно алерты об ошибках памяти, идущие от системы хранения и обработки логов graylog2.

Проблема в том, что на более-менее большом масштабе сложно предугадать, с какой скоростью будут поступать логи в хранилище. В любой момент можно натолкнуться на какой-нибудь даже не очень критичный баг, но в результате которого будет генерироваться большое количество мусорных сообщений в логах. Эта, а также несколько других проблем, приводят к тому, что алертинг по неструктурированным логам работает плохо. В результате мы имеем систему, которая может отправлять алерты спустя несколько минут, а в случае сбоя и несколько часов, после самого события.

В node-exporter давно был коллектор ошибок памяти, но он использует старый интерфейс sysfs. Для его включения нужно пересобрать ядро с опцией CONFIG_EDAC_LEGACY_SYSFS. Лучше этим не заниматься, а придумать что-то другое.

Чтобы найти другое решение, нужно посмотреть как эта система работает. Тогда, глядя в код, можно обнаружить трейспоинт, который срабатывает как раз тогда, когда ОС получает информацию об ошибке памяти. Стало очевидно, что мы можем использовать его, чтобы превратить количество ошибок памяти в метрику и прекратить парсить логи хотя бы для этого.

Для сбора информации с трейспоинта mc_event изначально был написан rasdaemon. Можно использовать и его, но информацию в результате всё равно придется приводить к нужному виду. А ebpf-exporter может быть использован и для решения других задач.

Дальше дело за малым — сначала собрать ядро с опцией CONFIG_EDAC_DEBUG, написать POC на bpftrace и заинжектить пару ошибок, чтобы убедиться, что мы вообще можем собирать оттуда данные. После этого написать программу с помощью библиотеки bcc и адаптировать её для работы с ebpf-exporter.

Так что теперь, наконец, у нас наступило будущее. И ошибки памяти копятся в виде метрик:

ebpf_exporter_mc_event_total{
	label="CPU_SrcID#0_MC#0_Chan#1_DIMM#0",
	lower_layer="255", mc_index="0",
	middle_layer="0", msg="memory read error",
	top_layer="1", type="err_corrected"} 2
ebpf_exporter_mc_event_total{
	label="CPU_SrcID#0_MC#0_Chan#1_DIMM#0",
	lower_layer="255", mc_index="0",
	middle_layer="0", msg="memory scrubbing error",
	top_layer="1", type="err_corrected"} 1

Что дальше?

Ebpf-exporter позволяет относительно легко собирать очень интересную статистику с сервера. И не только с софта, но и с железа. В репозитории есть пример программы, экспортирующей количество завершенных циклов ЦПУ и выполненных инструкций. Такого рода метрики требуют серьезного погружения в ядро ОС и в архитектуру ЦПУ, но это того стоит.

С помощью таких метрик можно оценивать степень деградации производительности подсистем после обновления. Можно очень точно характеризовать нагрузку. За счет высокой эффективности eBPF, появляется возможность снимать информацию о запуске конкретных функций в ядре на продакшене при поиске причин аномалий.