Bare-Metal Performance Diagnostics: Kokpit Prometheus i Grafana dla Raspberry Pi
Część 7 z 7 serii Homelab na Raspberry Pi

Spis treści
Przegląd architektury: Podatności sprzętowe komputerów jednopłytkowych
Komputery jednopłytkowe ARM, takie jak Raspberry Pi 4 i 5, funkcjonują pod rygorystycznymi ograniczeniami termicznymi oraz wejścia/wyjścia (I/O). Długotrwałe obciążenia kontenerowe, częste cykle zapisu baz danych i intensywny ruch sieciowy nierzadko prowadzą do cichej degradacji sprzętu. Wysokie temperatury układu SoC wyzwalają dynamiczny dławienie termiczne (thermal throttling) przez oprogramowanie układowe Broadcom, co obniża taktowanie rdzeni ARM bez generowania jawnych błędów w przestrzeniach aplikacji użytkownika. Podobnie, ciągłe operacje losowego zapisu na kartach MicroSD lub dyskach SSD podłączonych przez USB prowadzą do wyczerpania bloków pamięci flash, zatorów I/O i ostatecznego uszkodzenia systemu plików.
Wdrożenie potoku diagnostyki wydajności Bare-Metal z wykorzystaniem platform Prometheus i Grafana przekształca nieprzejrzyste stany sprzętowe w mierzalne szeregi czasowe. Standardowy demon node_exporter w połączeniu ze specjalizowanym skryptem zbierającym dane plikowe (textfile collector) pozwala pobierać kluczowe wskaźniki fizyczne Raspberry Pi co 15 sekund, analizować je pod kątem przekroczenia progów i wizualizować w kokpitach czasu rzeczywistego. Chodzi o temperatury rdzenia SoC, flagi spadku napięcia, taktowanie, nasycenie pamięci RAM oraz czasy oczekiwania I/O dysku; wartości odczytywane poleceniem vcgencmd są odświeżane przez zaplanowany skrypt kolektora raz na minutę.

vcgencmd trafiają przez kolektor plikowy, Node Exporter i Prometheusa do Grafany — i wywołują alert powyżej 75 °C lub przy ustawionej bitmasce throttlingu.Instrukcja wdrożenia krok po kroku
Krok 1: Wdrożenie Node Exportera i skryptu Textfile Collector
W celu gromadzenia standardowych danych telemetrycznych jądra Linux oraz własnych statystyk sprzętowych Broadcom, należy zainstalować narzędzie node_exporter i utworzyć dedykowany katalog na pliki metryk:
apt update && apt install -y prometheus-node-exporter
mkdir -p /var/lib/node_exporter/textfile_collector
chmod 755 /var/lib/node_exporter/textfile_collector
Utworzenie skryptu powłoki w ścieżce /opt/scripts/rpi-hardware-metrics.sh, który pobiera temperaturę SoC, napięcie rdzenia i flagi dławienia sprzętowego przy użyciu polecenia vcgencmd:
#!/usr/bin/env bash
# /opt/scripts/rpi-hardware-metrics.sh
# Pobiera metryki fizyczne SoC dla kolektora plikowego Prometheus
TEXTFILE_DIR="/var/lib/node_exporter/textfile_collector"
TMP_FILE="$TEXTFILE_DIR/rpi_metrics.prom.$$"
FINAL_FILE="$TEXTFILE_DIR/rpi_metrics.prom"
# 1. Ekstrakcja temperatury rdzenia CPU (stopnie Celsjusza)
TEMP_C=$(vcgencmd measure_temp | grep -oE '[0-9]+([.][0-9]+)?')
echo "# HELP rpi_soc_temperature_celsius Broadcom SoC Core Temperature" > "$TMP_FILE"
echo "# TYPE rpi_soc_temperature_celsius gauge" >> "$TMP_FILE"
echo "rpi_soc_temperature_celsius $TEMP_C" >> "$TMP_FILE"
# 2. Ekstrakcja napięcia rdzenia SoC (Wolty)
VOLT_V=$(vcgencmd measure_volts core | grep -oE '[0-9]+([.][0-9]+)?')
echo "# HELP rpi_soc_core_voltage_volts Broadcom SoC Core Voltage" >> "$TMP_FILE"
echo "# TYPE rpi_soc_core_voltage_volts gauge" >> "$TMP_FILE"
echo "rpi_soc_core_voltage_volts $VOLT_V" >> "$TMP_FILE"
# 3. Ekstrakcja kodu szesnastkowego dławienia jako maski bitowej
THROTTLE_HEX=$(vcgencmd get_throttled | cut -d'=' -f2)
THROTTLE_DEC=$((THROTTLE_HEX))
echo "# HELP rpi_soc_throttled_bitmask Bitmask representing under-voltage or thermal throttling flags" >> "$TMP_FILE"
echo "# TYPE rpi_soc_throttled_bitmask gauge" >> "$TMP_FILE"
echo "rpi_soc_throttled_bitmask $THROTTLE_DEC" >> "$TMP_FILE"
mv "$TMP_FILE" "$FINAL_FILE"
Nadanie praw wykonywania i zaplanowanie uruchamiania co minutę w harmonogramie cron:
chmod +x /opt/scripts/rpi-hardware-metrics.sh
(crontab -l 2>/dev/null; echo "* * * * * /bin/bash /opt/scripts/rpi-hardware-metrics.sh >/dev/null 2>&1") | crontab -
Krok 2: Rekonfiguracja usługi systemd dla Node Exportera
Modyfikacja konfiguracji systemowej demona node_exporter w celu wskazania katalogu z niestandardowymi plikami metryk:
# /etc/default/prometheus-node-exporter
ARGS="--collector.textfile.directory=/var/lib/node_exporter/textfile_collector --collector.filesystem.mount-points-exclude='^/(dev|proc|sys|run)($|/)'"
Restart usługi celem zastosowania nowych flar: systemctl restart prometheus-node-exporter.
Krok 3: Konfiguracja systemu zbierania danych Prometheus
Wdrożenie bazy Prometheus w środowisku Docker Compose z network_mode: host i 15-sekundowym interwałem odpytywania lokalnego Node Exportera:
# /opt/containers/prometheus/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'raspberry_pi_baremetal'
static_configs:
- targets: ['127.0.0.1:9100']
labels:
instance: 'rpi5-homelab'
Krok 4: Wdrożenie Grafany i import paneli Bare-Metal
Uruchomienie Grafany w kontenerze Docker Compose, również z network_mode: host, dodanie bazy Prometheus (http://127.0.0.1:9090) jako domyślnego źródła danych oraz zdefiniowanie paneli w oparciu o zapytania PromQL:
- Panel temperatury rdzenia SoC:
rpi_soc_temperature_celsius(Próg alarmowy zdefiniowany na > 75°C). - Alarm spadku napięcia i dławienia:
rpi_soc_throttled_bitmask > 0(Wskazuje na słaby zasilacz lub przegrzanie, występujące teraz lub od ostatniego rozruchu; alarm pozostaje aktywny aż do ponownego uruchomienia). - Obciążenie operacjami I/O dysku:
rate(node_disk_io_time_seconds_total[1m]) * 100(Wykrywa zatory kontrolera pamięci flash i zużycie bloków). - Wskaźnik dostępności pamięci RAM:
(node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100.
Krok 5: Kontrola jakości i testy obciążeniowe
W celu potwierdzenia, że potok telemetryczny poprawnie rejestruje wyczerpywanie zasobów, należy przeprowadzić procedurę testów obciążeniowych:
- Walidacja obciążenia I/O: Wykonanie intensywnego testu dysku narzędziem
fio(np.fio --name=test --ioengine=libaio --rw=randwrite --bs=4k --size=1G) i sprawdzenie, czy panel I/O Wait w Grafanie wykazuje skoki opóźnień w czasie rzeczywistym. - Symulacja dławienia termicznego: Obciążenie wszystkich rdzeni ARM poleceniem
stress-ng --cpu 4 --timeout 120sprzy jednoczesnym monitorowaniurpi_soc_temperature_celsiusw bazie Prometheus w celu weryfikacji precyzyjnego pomiaru aż do włączenia wentylatora chłodzącego. - Audyt parsowania metryk plikowych: Wykonanie polecenia
curl -s http://127.0.0.1:9100/metrics | grep rpi_w terminalu, co pozwala upewnić się, że własne metryki napięcia i dławienia są udostępniane bez błędów składniowych.
Podsumowanie i mierzalna wartość dodana
Co da się osiągnąć dzięki instrukcji: Wdrożenie autonomicznego potoku diagnostyki wydajności sprzętowej Bare-Metal na platformie Raspberry Pi z wykorzystaniem bazy Prometheus, skryptów Textfile Collector dla SoC oraz wizualizacji w Grafanie.
Resultujący wartość dodana:
- Wczesne wykrywanie awarii nośników: Ciągłe monitorowanie czasu oczekiwania I/O oraz zużycia bloków pamięci flash pozwala na prewencyjną wymianę karty SD lub dysku SSD przed wystąpieniem awarii systemu plików.
- Zapobieganie dławieniu termicznemu: Widoczność temperatury SoC i masek bitowych dławienia w czasie rzeczywistym gwarantuje, że usługi kontenerowe działają z maksymalną częstotliwością bez cichego spadku wydajności.
- Kontrola jakości zasilania: Natychmiastowe rejestrowanie flag spadku napięcia (bit 0,
bitmask 0x1) pozwala zidentyfikować uszkodzone zasilacze USB-C lub zbyt duże pobory prądu przez peryferia przed wystąpieniem restartu sprzętu.
Pytania i odpowiedzi
Dlaczego alarm dławienia po jednym zdarzeniu pozostaje aktywny aż do ponownego uruchomienia?
Bo get_throttled zwraca dwa rodzaje bitów. Niższe bity opisują stan w danej chwili, między innymi bit 0 dla zbyt niskiego napięcia i bit 2 dla dławienia. Bity od 16 wzwyż odnotowują, że to samo wystąpiło kiedykolwiek od uruchomienia, i pozostają ustawione aż do ponownego uruchomienia Raspberry Pi. Krótki spadek napięcia rano daje więc na przykład 0x50000 (wystąpiło zbyt niskie napięcie i dławienie), dziesiętnie 327680, a ta wartość pozostaje większa od zera przez resztę dnia.
Przy analizie warto rozdzielić jedno od drugiego. PromQL zna operator %, a rpi_soc_throttled_bitmask % 16 > 0 sprawdza tylko cztery niższe bity, czyli bieżący stan; rpi_soc_throttled_bitmask >= 65536 zgłasza, że od uruchomienia coś zaszło. Przejrzyściej jest od razu zlecić skryptowi zapisywanie osobnej metryki dla każdego bitu.
Do tego dochodzi rytm skryptu: działa co minutę, a get_throttled podaje tylko stan z tej chwili. Dławienia trwającego kilka sekund między dwoma przebiegami niższe bity nie pokażą, bity od 16 wzwyż już tak. Zwłaszcza przy krótkich spadkach napięcia odnotowana część jest więc bardziej miarodajna.
Czy Prometheus w kontenerze osiągnie cel 127.0.0.1:9100?
Tylko przy network_mode: host. W zwykłej sieci Dockera 127.0.0.1 to sam kontener, a node_exporter działa poza nim, bezpośrednio na hoście, więc cel pozostaje trwale niedostępny (down). To samo dotyczy Grafany: jeśli oba kontenery dzielą sieć Dockera, adres źródła danych zawiera nazwę usługi Prometheus zamiast 127.0.0.1.
Homelab na Raspberry Pi
- Raspberry Pi 4 i 5: uruchamianie systemu z dysku SSD przez zmianę bootloadera
- Zasilanie awaryjne (UPS) dla Raspberry Pi 4 i 5: Top 5 urządzeń do wymagających projektów
- Lokalny CI/CD dla Raspberry Pi: Automatyzacja wdrożeń Docker Compose
- Autonomiczny serwer domowy Docker-Compose z Traefik, SSL i Watchtower
- Lokalny serwer mediów bez opóźnień: Jellyfin na Raspberry Pi 5 z akceleracją sprzętową
- Raspberry Pi jako utwardzona brama WireGuard VPN ze Split-Tunnelingiem
- Bare-Metal Performance Diagnostics: Kokpit Prometheus i Grafana dla Raspberry Pi