Мониторинг IPMI/BMC с помощью Proto Observability

Сбор Prometheus-метрик BMC (информация, состояние шасси, журнал событий SEL, температуры, питание, охлаждение) через ipmi_exporter и Prometheus-чек агента.

На этой странице:

Архитектура

ProtoOBP-агент собирает метрики IPMI не напрямую с BMC, а через ipmi_exporter — служебный экспортёр от Prometheus Community, который обращается к BMC по протоколу RMCP/IPMI (UDP/623), запрашивает данные через инструменты FreeIPMI (bmc-info, ipmi-sensors, ipmi-dcmi, ipmi-sel, ipmi-chassis) и публикует результат в Prometheus-формате на HTTP-порту 9290. ProtoOBP-агент скрейпит этот HTTP-эндпоинт через интеграцию prometheus.

+-------+   RMCP/UDP 623   +---------------+   HTTP 9290    +----------------+
|  BMC  | <--------------- | ipmi_exporter | <------------- | ProtoOBP Agent |
+-------+                  +---------------+    (scrape)    +----------------+

Один экспортёр обслуживает любое число BMC — конкретный BMC передаётся в URL запроса как query: ?target=<bmc-host>&module=<module-name>.

Сбор метрик IPMI

Конфигурация ipmi_exporter

Конфигурация в формате prometheuscommunity/ipmi-exporter: модули задают, как именно опрашивать BMC — collectors, credentials, driver. Документация — ipmi_exporter/configuration.md.

Важно про модули. Модуль в ipmi.yml — это набор настроек (credentials, driver, privilege, набор коллекторов), а не список BMC. Конкретный BMC выбирается на стороне клиента, в URL scrape-запроса (?target=<bmc-host>&module=<module-name>). Поэтому один модуль обслуживает любое количество BMC с одинаковыми настройками — отдельно перечислять устройства в ipmi.yml не нужно. Дополнительные модули заводятся только если у части BMC отличаются credentials / driver / privilege / набор коллекторов (типичные причины — другой вендор, legacy-прошивка без RMCP+, отсутствие поддержки DCMI).

Минимальная конфигурация с одним модулем default — подходит, когда все BMC в парке используют одни и те же учётные данные и поддерживают весь стандартный набор коллекторов:

# /etc/ipmi_exporter/ipmi.yml
modules:
  default:
    user: "ADMIN"
    pass: "ADMIN"
    driver: "LAN_2_0"        # RMCP+ (IPMI 2.0)
    privilege: "admin"
    timeout: 10000
    collectors:
      - bmc                  # ipmi_bmc_info
      - ipmi                 # ipmi_temperature_celsius, ipmi_fan_speed_rpm, ipmi_voltage_volts, ipmi_current_amperes
      - chassis              # ipmi_chassis_power_state, *_fault_state
      - dcmi                 # ipmi_dcmi_power_consumption_current_watts (требует поддержки DCMI на BMC)
      - sel                  # ipmi_sel_logs_count, ipmi_sel_free_space_bytes

Если в парке несколько групп BMC с разными настройками, заведите по модулю на группу. Имена модулей произвольные; для каждого target в дальнейшем выбирается нужный модуль через module= в URL. Пример с тремя группами — стандартный парк, HPE iLO с собственной учётной записью, и старое железо без поддержки DCMI и RMCP+:

# /etc/ipmi_exporter/ipmi.yml
modules:
  default:
    user: "ADMIN"
    pass: "ADMIN"
    driver: "LAN_2_0"
    privilege: "admin"
    timeout: 10000
    collectors: [bmc, ipmi, chassis, dcmi, sel]

  hpe_ilo:
    # HPE iLO часто настроен на «Administrator» вместо «ADMIN».
    user: "Administrator"
    pass: "<see-secret>"
    driver: "LAN_2_0"
    privilege: "admin"
    timeout: 15000
    collectors: [bmc, ipmi, chassis, dcmi, sel]

  legacy:
    # Старое железо: только IPMI 1.5 (`LAN`), DCMI не поддерживается.
    user: "ADMIN"
    pass: "ADMIN"
    driver: "LAN"
    privilege: "admin"
    timeout: 10000
    collectors: [bmc, ipmi, chassis, sel]

Конфигурация ProtoOBP агента

Если агент запускается в виде службы на хосте

В /etc/protoobp-agent/conf.d/prometheus.d/conf.yaml:

init_config:

instances:
  - prometheus_url: http://<ipmi-exporter-host>:9290/ipmi?target=<bmc-host>&module=default
    namespace: ipmi_exporter
    metrics:
      - "ipmi_*"
    tags:
      - bmc_host:<bmc-host>

Если BMC несколько — добавляйте отдельный instances:-блок на BMC, меняя target= в URL и тег bmc_host.

Перезапустите агента:

sudo systemctl restart protoobp-agent

Если агент запускается в виде Docker контейнера

Добавьте autodiscovery-лейблы к контейнеру с ipmi_exporter:

labels:
  com.protoobp.ad.check_names: '["prometheus"]'
  com.protoobp.ad.init_configs: '[{}]'
  com.protoobp.ad.instances: '[{"prometheus_url": "http://%%host%%:9290/ipmi?target=<bmc-host>&module=default", "namespace": "ipmi_exporter", "metrics": ["ipmi_*"], "tags": ["bmc_host:<bmc-host>"]}]'

%%host%% подставит IP контейнера ipmi_exporter в docker network. Агент и экспортёр должны быть в одной сети.

Если экспортёр опрашивает несколько BMC, перечислите все цели в одном лейбле com.protoobp.ad.instances. Внутренний список становится массивом инстансов одного чека, а внешний массив должен соответствовать длине check_names (в данном случае — 1), поэтому JSON получается вида [[ {...}, {...}, ... ]]:

labels:
  com.protoobp.ad.check_names: '["prometheus"]'
  com.protoobp.ad.init_configs: '[{}]'
  com.protoobp.ad.instances: '[[
    {"prometheus_url": "http://%%host%%:9290/ipmi?target=bmc-01&module=default", "namespace": "ipmi_exporter", "metrics": ["ipmi_*"], "tags": ["bmc_host:bmc-01"]},
    {"prometheus_url": "http://%%host%%:9290/ipmi?target=bmc-02&module=default", "namespace": "ipmi_exporter", "metrics": ["ipmi_*"], "tags": ["bmc_host:bmc-02"]}
  ]]'

Без внешних квадратных скобок агент откажется применять шаблон с ошибкой Template entries don't all have the same length, not using them.

Минимальный docker-compose.yaml

Рабочий минимум для запуска ipmi_exporter рядом с ProtoOBP-агентом. Файл ./ipmi.yml рядом с compose-файлом — это конфигурация ipmi_exporter из раздела Конфигурация ipmi_exporter:

Пример показывает опрос трёх BMC одним экспортёром — типичная production-конфигурация. Если у BMC одинаковые credentials/driver, все target’ы используют один модуль (например, default). Если часть BMC требует других настроек, на каждую группу заведите отдельный модуль в ipmi.yml и подставьте его имя в module= для соответствующих target’ов — как показано ниже для bmc-03.example.com (HPE iLO).

services:
  ipmi-exporter:
    image: prometheuscommunity/ipmi-exporter:v1.10.0
    volumes:
      - ./ipmi.yml:/config/ipmi.yml:ro
    command:
      - --config.file=/config/ipmi.yml
    labels:
      com.protoobp.ad.check_names: '["prometheus"]'
      com.protoobp.ad.init_configs: '[{}]'
      com.protoobp.ad.instances: '[[
        {"prometheus_url": "http://%%host%%:9290/ipmi?target=bmc-01.example.com&module=default", "namespace": "ipmi_exporter", "metrics": ["ipmi_*"], "tags": ["bmc_host:bmc-01.example.com"]},
        {"prometheus_url": "http://%%host%%:9290/ipmi?target=bmc-02.example.com&module=default", "namespace": "ipmi_exporter", "metrics": ["ipmi_*"], "tags": ["bmc_host:bmc-02.example.com"]},
        {"prometheus_url": "http://%%host%%:9290/ipmi?target=bmc-03.example.com&module=hpe_ilo", "namespace": "ipmi_exporter", "metrics": ["ipmi_*"], "tags": ["bmc_host:bmc-03.example.com"]}
      ]]'
    networks:
      - ipmi-net

  protoobp-agent:
    image: registry.git.proto.group/protoobp/protoobp-artifacts/protoobp-agent:7.40.3
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /proc/:/host/proc/:ro
      - /sys/fs/cgroup/:/host/sys/fs/cgroup:ro
    environment:
      - POBP_API_KEY=${POBP_API_KEY}
      - POBP_POBP_URL=${POBP_BACKEND_URL}
    networks:
      - ipmi-net

networks:
  ipmi-net:
    driver: bridge

Что важно:

  • Подставьте реальные адреса BMC вместо bmc-01.example.com / bmc-02.example.com / bmc-03.example.com — DNS-имена или IP, по которым доступен RMCP-порт BMC (UDP/623) из сети ipmi-net.
  • Один target — это один блок внутри внешнего массива; добавление четвёртого BMC — это лишний объект в том же [[ ... ]]. На каждый target агент создаёт отдельный инстанс чека prometheus, и тег bmc_host:<...> различает метрики между ними.
  • module= в URL ссылается на имя модуля из ipmi.yml. Если в парке только одна группа BMC, оставьте module=default для всех target’ов. При наличии нескольких групп заведите соответствующие модули и пропишите имя нужного модуля в URL каждого target’а.
  • Оба контейнера должны быть в одной docker-сети, чтобы %%host%% в autodiscovery-URL резолвился в IP ipmi-exporter.
  • /var/run/docker.sock смонтирован агенту read-only — без него агент не увидит лейбл-аннотации соседних контейнеров и autodiscovery не запустится.
  • /proc и /sys/fs/cgroup нужны базовым host-чекам агента (cpu, memory, io, …); сам IPMI-чек к ним не привязан.
  • Переменные ${POBP_API_KEY} и ${POBP_BACKEND_URL} подставятся из .env-файла рядом с compose или из окружения, в котором вы запускаете docker compose up.

Проверка

ipmi_exporter отдаёт данные напрямую (полезно для отладки):

curl -s 'http://<ipmi-exporter-host>:9290/ipmi?target=<bmc-host>&module=default' | head -60

Пример вывода ipmi_exporter для одного BMC (модуль default, значения сокращены):

# HELP ipmi_bmc_info Constant metric with value '1' providing details about the BMC.
# TYPE ipmi_bmc_info gauge
ipmi_bmc_info{bmc_url="N/A",firmware_revision="4.40.40",manufacturer_id="Dell Inc. (674)",system_firmware_version="1.18.2"} 1
# HELP ipmi_chassis_cooling_fault_state Current Cooling/fan fault state (1=false, 0=true).
# TYPE ipmi_chassis_cooling_fault_state gauge
ipmi_chassis_cooling_fault_state 1
# HELP ipmi_chassis_drive_fault_state Current drive fault state (1=false, 0=true).
# TYPE ipmi_chassis_drive_fault_state gauge
ipmi_chassis_drive_fault_state 1
# HELP ipmi_chassis_power_state Current power state (1=on, 0=off).
# TYPE ipmi_chassis_power_state gauge
ipmi_chassis_power_state 1
# HELP ipmi_temperature_celsius Temperature reading in degrees Celsius.
# TYPE ipmi_temperature_celsius gauge
ipmi_temperature_celsius{id="1",name="CPU 1 Temp",state="nominal"} 62.5
ipmi_temperature_celsius{id="2",name="CPU 2 Temp",state="nominal"} 60.1
ipmi_temperature_celsius{id="3",name="Inlet Temp",state="nominal"} 24.0
ipmi_temperature_celsius{id="4",name="Exhaust Temp",state="nominal"} 41.0
# HELP ipmi_fan_speed_rpm Fan speed in RPM.
# TYPE ipmi_fan_speed_rpm gauge
ipmi_fan_speed_rpm{id="5",name="Fan 1",state="nominal"} 7800
ipmi_fan_speed_rpm{id="6",name="Fan 2",state="nominal"} 7750
# HELP ipmi_voltage_volts Voltage reading in volts.
# TYPE ipmi_voltage_volts gauge
ipmi_voltage_volts{id="9",name="+3.3V",state="nominal"} 3.30
ipmi_voltage_volts{id="10",name="+5V",state="nominal"} 5.02
ipmi_voltage_volts{id="11",name="+12V",state="nominal"} 12.05
# HELP ipmi_current_amperes Current reading in amperes.
# TYPE ipmi_current_amperes gauge
ipmi_current_amperes{id="12",name="PSU 1 Current",state="nominal"} 1.95
# HELP ipmi_power_watts Power reading in watts.
# TYPE ipmi_power_watts gauge
ipmi_power_watts{id="14",name="PSU 1 Power",state="nominal"} 235.0
# HELP ipmi_dcmi_power_consumption_current_watts Current power consumption in watts.
# TYPE ipmi_dcmi_power_consumption_current_watts gauge
ipmi_dcmi_power_consumption_current_watts 245.0
# HELP ipmi_scrape_duration_seconds Returns how long the scrape took to complete in seconds.
# TYPE ipmi_scrape_duration_seconds gauge
ipmi_scrape_duration_seconds 0.45
# HELP ipmi_sel_free_space_bytes Current free space remaining for new SEL entries.
# TYPE ipmi_sel_free_space_bytes gauge
ipmi_sel_free_space_bytes 15856
# HELP ipmi_sel_logs_count Current number of log entries in the SEL.
# TYPE ipmi_sel_logs_count gauge
ipmi_sel_logs_count 12
# HELP ipmi_up '1' if a scrape of the IPMI device was successful, '0' otherwise.
# TYPE ipmi_up gauge
ipmi_up{collector="bmc"} 1
ipmi_up{collector="chassis"} 1
ipmi_up{collector="dcmi"} 1
ipmi_up{collector="ipmi"} 1
ipmi_up{collector="sel"} 1

Если ipmi_up{collector="ipmi"} или ipmi_up{collector="dcmi"} стабильно возвращают 0 — соответствующий коллектор не смог получить данные. Обычные причины: BMC не поддерживает DCMI (ipmi-dcmi: command invalid or unsupported), несовместимость freeipmi с прошивкой BMC, или неверные credentials/privilege. Проверяйте логи ipmi_exporter (см. раздел «Сбор логов ipmi_exporter» ниже).

Статус интеграции в агенте:

docker exec protoobp-agent agent status | grep -A 10 "^    prometheus"
    prometheus (3.4.0)
    ------------------
      Instance ID: prometheus:ipmi_exporter:db035d028c3af1a8 [OK]
      Configuration Source: container:docker://...
      Total Runs: 12
      Metric Samples: Last Run: 12, Total: 144
      Events: Last Run: 0, Total: 0
      Service Checks: Last Run: 1, Total: 12

Имена собранных метрик в ProtoOBP — <namespace>.<exporter_metric_name>:

docker exec protoobp-agent agent check prometheus | grep '"metric":' | sort -u
"metric": "ipmi_exporter.ipmi_bmc_info"
"metric": "ipmi_exporter.ipmi_chassis_cooling_fault_state"
"metric": "ipmi_exporter.ipmi_chassis_drive_fault_state"
"metric": "ipmi_exporter.ipmi_chassis_power_state"
"metric": "ipmi_exporter.ipmi_current_amperes"
"metric": "ipmi_exporter.ipmi_dcmi_power_consumption_current_watts"
"metric": "ipmi_exporter.ipmi_fan_speed_rpm"
"metric": "ipmi_exporter.ipmi_fan_speed_state"
"metric": "ipmi_exporter.ipmi_power_watts"
"metric": "ipmi_exporter.ipmi_scrape_duration_seconds"
"metric": "ipmi_exporter.ipmi_sel_free_space_bytes"
"metric": "ipmi_exporter.ipmi_sel_logs_count"
"metric": "ipmi_exporter.ipmi_temperature_celsius"
"metric": "ipmi_exporter.ipmi_temperature_state"
"metric": "ipmi_exporter.ipmi_up"
"metric": "ipmi_exporter.ipmi_voltage_state"
"metric": "ipmi_exporter.ipmi_voltage_volts"

Собираемые метрики

Имена ниже приведены без префикса namespace (ipmi_exporter.), как у экспортёра. В ProtoOBP они хранятся под выбранным namespace — например при namespace: ipmi_exporter метрика ipmi_temperature_celsius обращается в ipmi_exporter.ipmi_temperature_celsius.

Лейблы

Общие лейблы добавляются автоматически Docker-интеграцией агента: docker_image, image_name, image_tag, short_image, service, env, host.

ЛейблГдеЗначение
collectoripmi_up, ipmi_scrape_duration_secondsИмя коллектора: bmc / ipmi / chassis / dcmi / sel
namesensor-метрики (ipmi_temperature_celsius, ipmi_fan_speed_rpm, ipmi_voltage_volts, ipmi_current_amperes)Имя датчика (CPU 1 Temp, Fan 1, +3.3V, …)
idsensor-метрикиЧисловой идентификатор датчика
statesensor-метрикиnominal / warning / critical / na
bmc_url / firmware_revision / manufacturer_id / system_firmware_versionipmi_bmc_infoИз ответа bmc-info

Информация о BMC

Имя метрикиТипОписание
ipmi_bmc_infogaugeМетрика-«ярлык»: значение всегда 1; полезные данные — в лейблах (firmware_revision, manufacturer_id, system_firmware_version).
ipmi_bmc_commercial_infogaugeДополнительные коммерческие/OEM-поля (если BMC отдаёт).

Состояние шасси

Имя метрикиТипОписание
ipmi_chassis_power_stategaugeСостояние питания шасси (1 = on, 0 = off).
ipmi_chassis_cooling_fault_stategaugeПризнак ошибки охлаждения (1 = false / нет ошибки, 0 = true / есть).
ipmi_chassis_drive_fault_stategaugeПризнак ошибки диска (1 = false / нет ошибки, 0 = true / есть).

Температуры, охлаждение, электропитание

Имя метрикиТипОписание
ipmi_temperature_celsiusgaugeТемпература датчика в °C, лейбл name.
ipmi_temperature_stategaugeСостояние датчика температуры (0=nominal, 1=warning, 2=critical).
ipmi_fan_speed_rpmgaugeСкорость вращения вентилятора (RPM).
ipmi_fan_speed_stategaugeСостояние датчика fan.
ipmi_voltage_voltsgaugeНапряжение по линии в вольтах.
ipmi_voltage_stategaugeСостояние датчика напряжения.
ipmi_current_amperesgaugeТок в амперах.
ipmi_power_wattsgaugeМощность по датчику (если такой есть).
ipmi_dcmi_power_consumption_current_wattsgaugeТекущее энергопотребление по DCMI (требует поддержки DCMI на BMC; коллектор dcmi).

System Event Log (SEL)

Имя метрикиТипОписание
ipmi_sel_logs_countgaugeКоличество записей в журнале событий BMC.
ipmi_sel_free_space_bytesgaugeСвободное место в SEL, байт.

Доступность

Имя метрикиТипОписание
ipmi_upgauge1 — экспортёр успешно отработал указанный collector, 0 — нет (см. лейбл collector).
ipmi_scrape_duration_secondsgaugeДлительность сбора метрик по этому target’у.
prometheus.health (service check)checkOK — endpoint доступен, CRITICAL — нет.

Ключевые метрики для дашбордов и алертов

Доступность

  • ipmi_up{collector="ipmi"} == 0 — экспортёр не смог достучаться до BMC через ipmi-sensors/ipmimonitoring (часто причина: неверный driver/ privilege/credentials, либо BMC отверг RMCP+).
  • prometheus.health == CRITICAL — экспортёр недоступен.

Температуры и охлаждение

  • ipmi_temperature_celsius рядом с порогом BMC (ipmi_temperature_state >= 1) — сенсор близок к перегреву.
  • ipmi_fan_speed_rpm per name == 0 при включённом шасси или резкий скачок к максимуму — отказ вентилятора или экстренный режим охлаждения.

Электропитание

  • ipmi_dcmi_power_consumption_current_watts per host — энергопотребление узла, для capacity-планирования.
  • ipmi_voltage_state >= 1 или ipmi_current_state >= 1 — выход напряжения/ тока за номинал.

Шасси

  • ipmi_chassis_power_state == 0 без планового события — узел упал/выключен.
  • ipmi_chassis_cooling_fault_state == 0 или ipmi_chassis_drive_fault_state == 0 — фронт-панельный fault LED горит (в этих метриках 0 означает «есть ошибка»).

SEL

  • Рост ipmi_sel_logs_count (rate > 0 за окно) — BMC регистрирует новые события; алерт на всплеск (увеличение > N за час).
  • ipmi_sel_free_space_bytes стремится к нулю — журнал переполняется, старые записи начнут вытесняться.

Сбор логов ipmi_exporter

Сам ipmi_exporter пишет в stdout короткие json-подобные строки (level=INFO/ ERROR source=collector_<name>.go ...). Эти логи полезны для траблшутинга (видно, какой коллектор по какой причине не получает данные).

В Docker сбор логов настраивается через autodiscovery-лейбл на контейнере ipmi-exporter:

labels:
  com.protoobp.ad.logs: '[{"source": "ipmi_exporter", "service": "ipmi-exporter"}]'

Проверка — секция Logs Agent в agent status:

docker exec protoobp-agent agent status | grep -A 6 "ipmi_exporter"

В выводе должен присутствовать источник Source: ipmi_exporter с ненулевым BytesRead. Принятые записи доступны в Logs Explorer ProtoOBP UI с фильтром source:ipmi_exporter.