Monitoraggio di microservizi: tutorial su Prometheus e Grafana
In questo episodio Carlo Ballabio fornisce un tutorial su Prometheus e Grafana composto da due parti:
- Configurazione di un semplice file docker-compose per un progetto comprendente Prometheus, Grafana ed un servizio che espone le metriche.
- Configurazione di Grafana attraverso l’interfaccia Web.
In ultimo viene mostrato come avviare Grafana inizializzandola con datasource e dashboard pronte.
Per un’introduzione ai due strumenti, rimandiamo alla lettura di un precedente articolo.
Trovate il codice, oggetto di questo tutorial, ed altri link di approfondimento nel paragrafo Riferimenti.
Prerequisiti
Per questo tutorial su Prometheus e Grafana si dà per scontata una conoscenza base di Docker/docker-compose, Grafana e Prometheus.
Il progetto che viene realizzato richiede l’utilizzo delle seguenti porte della propria macchina:
- 9090: Prometheus
- 3000: Grafana
- 4000: Servizio che espone le metriche
Configurazione del progetto
Prometheus
Partiamo dalla configurazione di Prometheus, il servizio responsabile di contattare i target da cui recuperare e immagazzinare le metriche.
Va creato il file prometheus.yml nel quale inserire una minima configurazione indispensabile:
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'Prometheus'
scrape_interval: 5s
static_configs:
- targets: ['timer_1:4000']
L’opzione scrape_interval indica ogni quanto Prometheus contatta i target per ottenere le metriche.
Con l’opzione scrap_configs invece si configura la lista di job di Prometheus ognuno dei quali ha una lista targets da cui recuperare le metriche (per l’esempio ci sarà solo il servizio timer_1 che espone le metriche sulla porta 4000). Di default Prometheus cerca di contattare la rotta /metrics.
Un job può avere la lista esplicita di target da contattare (e quindi si dovranno mappare a mano tutti i servizi che si vogliono monitorare) oppure l’indirizzo di un service discovery il quale fornisce la lista di target. Nel secondo è anche possibile definire delle regole per filtrare solo i servizi che si desidera realmente monitorare ignorando quelli che non interessano.
Discovery
Per questo progetto si configurano direttamente i target perché più semplice e perché non richiede componente aggiuntivo.
Per completezza ecco un esempio di configurazione che sfrutta un service discovery.
- job_name: 'consul-discovery'
scrape_interval: 15s
metrics_path: '/actuator/Prometheus'
consul_sd_configs:
- server: 'consul:8500'
relabel_configs:
- source_labels: [__meta_consul_tags]
regex: .*
action: keep
- source_labels: [__meta_consul_service]
target_label: job
Con questa configurazione Prometheus contatta tutti i servizi registrati ad un’istanza di Consul (consul:8500).
docker-compose.yaml
Nel file docker-compose va indicata, oltra all’immagine da usare (immagine prom/prometheus:v2.14.0), quale file di configurazione caricare e la porta da esporre, ovvero la 9090:
prometheus:
image: prom/prometheus:v2.14.0
restart: always
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
command:
- '--config.file=/etc/prometheus/prometheus.yml'
ports:
- '9090:9090'
Qualora si volesse aggiungere la retention (ovvero per quanto tempo Prometheus deve mantenere le metriche) è sufficiente aggiungere alcuni flag:
prometheus:
image: prom/prometheus:v2.14.0
restart: always
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.retention.time=3d'
- '--storage.tsdb.retention.size=200MB'
ports:
- '9090:9090'
In questo modo le metriche avranno una vita massima di tre giorni e, in ogni caso, non supereranno i 200 MB di spazio occupato su disco.
Grafana
Per questo esempio Grafana non necessita di una configurazione particolare. E’ sufficiente configurare la password dell’utente admin ed esporre la porta, ovvero la 3000:
grafana:
image: grafana/grafana:6.5.2
environment:
- GF_SECURITY_ADMIN_PASSWORD=pass
depends_on:
- prometheus
ports:
- "3000:3000"
Timer – servizio che espone le metriche
Manca solo il servizio che esporrà le metriche. Per dimostrazione Carlo ne ha creato uno in Node.Js che ne espone tre diverse:
- Ore
- Minuti
- Secondi
Una volta avviato chiamando la rotta localhost:4000/metrics, il servizio tornerà appunto tre valori. Ad esempio, se sono le 16:24:12, il servizio risponderà con questi dati:
- hours{instance_id=”timer_1″} 16
- minutes{instance_id=”timer_1″} 24
- seconds{instance_id=”timer_1″} 12
Questo permette di avere valori che continuano a cambiare ad ogni chiamata della rotta metrics.
docker-compose.yaml completo
Di seguito il docker compose completo con cui lanciare tutti e tre i servizi del progetto. Per farlo, è sufficiente eseguire il comando docker-compose up
dalla cartella simple-demo.
version: '3'
services:
prometheus:
image: prom/prometheus:v2.14.0
restart: always
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
command:
- '--config.file=/etc/prometheus/prometheus.yml'
ports:
- '9090:9090'
grafana:
image: grafana/grafana:6.5.2
environment:
- GF_SECURITY_ADMIN_PASSWORD=pass
depends_on:
- prometheus
ports:
- "3000:3000"
timer_1:
build:
dockerfile: "./Dockerfile"
context: "./simple-demo/"
ports:
- "4000:4000"
L’unica porta che serve realmente esporre è quella di Grafana, ma a fine dimostrativo si è deciso di esporle tutte.
Esecuzione del progetto
Per eseguire da terminale il sistema precedentemente configurato, posizionarsi alla cartella simple-demo e digitare il comando docker-compose up
.
Interfaccia Prometheus
Una volta avviato, Prometheus mette a disposizione un’interfaccia web all’indirizzo localhost:9090 da cui è possibile visualizzare le metriche, vedere lo stato dei target controllati, la configurazione impostata e molto altro.
L’immagine seguente mostra il grafico della metrica seconds che va da 0 a 60 a gradini di 5 secondi, ovvero ogni quanto Prometheus recupera le metriche da ogni servizio ( opzione scrape_interval configurata in precedenza).

Per vedere da quali campi è composta una metrica o per verificare lo stato di tutti i target puntati da Prometheus e dei vari discovery, si può consultare la pagina mostrata nell’immagine successiva.
Vengono mostrati la lista dei target, quando è stata l’ultima volta che è stato eseguito lo scrape (estrazione dati in un formato human-readable) e quanto è durato oltre a segnalare eventuali problemi.

La pagina Service Discovery (immagine seguente) è invece utile per capire perché alcuni target vengono scartati.

Grafana
Per quanto riguarda la visualizzazione delle metriche, aprire Grafana all’url localhost:3000 e loggarsi con l’utente admin/pass (configurato nel docker-compose.yaml) per configurare una prima dashboard.
Configurare il datasource
Come primo step bisogna comunicare a Grafana dove andare a recuperare le metriche. Creare quindi un datasource di tipo Prometheus configurando le coordinate del servizio di interesse.

Step 1 - Cliccare "Add data source"

Step 2 - Selezionare "Prometheus"

Step 3 - Inserire name e URL e salvare
Creazione di una nuova dashboard
Per creare una nuova dashboard, seguire i passi seguenti.

Cliccare l'icona + del menu a sinistra dopodiché selezionare "Dashboard" nel menu che appare in seguito

Cliccare "Add query" per aggiungere le query
Come si può notare dall’immagine, non appena si inizia a scrivere il nome della metrica in automatico vengono suggerite quelle effettivamente disponibili.
Nel grafico di esempio sono state aggiunte tre query diverse (una per ogni metrica): Grafana mostra una curva per ognuna (in caso di due istanze del servizio ci sarebbero state due curve per ogni query).
Per aggiungere un secondo riquadro alla dashboard, cliccare l’icona Add Panel.
Invece che selezionare query cliccare Choose visualization; apparirà così la lista di tipologie di grafici da scegliere (immagine seguente).


Per configurare un gauge inserire ancora le tre query impostando però di voler vedere l'ultimo valore disponibile (toggle Istant)
In questa maniera si ottiene una dashboard con due pannelli che mostrano le stesse metriche ma in modo diverso.

Inizializzazione Grafana con datasource e dashboard già pronti
Finora è stato mostrato come usare una configurazione di Grafana basilare configurando poi manualmente dashboard e datasource.
E’ improbabile che si voglia fare lo stesso in produzione, proseguiamo questo tutorial su Prometheus e Grafana mostrando come si può avviare Grafana con datasource e dashboard pre-configurati.
Per prima cosa bisogna salvare la dashboard ed esportarla. Non appena viene salvata, compare il pulsante di share che va cliccato per far apparire una dialog (immagine seguente).

Selezionare il tab 'Export' e cliccare 'Save to file' per far partire il download del json della dashboard.
A questo punto bisogna stoppare l’esecuzione del sistema perciò eseguire da linea di comando docker-compose down
in modo da cancellare i container e ripartire da zero.
E’ necessario ricreare la seguente struttura di cartelle e file di configurazione.

File: /grafana/provisioning/dashboards/all.yml
Con questo file si specifica in quale cartella del container sono contenuti i file delle dashboard:
- name: 'default'
org_id: 1
folder: ''
type: 'file'
options:
folder: '/var/lib/grafana/dashboards'
File: /grafana/provisioning/datasources/all.yml
Con questo file si indica la lista dei datasource:
datasources:
- name: 'Prometheus'
type: 'Prometheus'
access: 'proxy'
org_id: 1
url: 'http://Prometheus:9090'
is_default: true
version: 1
editable: true
File: simple-demo/grafana/config.ini
Questo file si occupa della cartella di provisioning (sempre all’interno del container):
[paths]
provisioning = /etc/grafana/provisioning
[server]
enable_gzip = true
[users]
default_theme = light
Lo step successivo riguarda la modifica del file docker-compose.yaml aggiungendo i seguenti volumi in modo da caricare i file appena creati (nella versione del docker-compose.yaml sul repository le successive righe sono commentate):
volumes:
- ./grafana/provisioning:/etc/grafana/provisioning:ro
- ./grafana/config.ini:/etc/grafana/config.ini:ro
- ./grafana/dashboards/:/var/lib/grafana/dashboards:ro
Per far ripartire il sistema con le modifiche, da terminale eseguire docker-compose up
.
Aprire quindi un’istanza del browser all’indirizzo localhost:3000 ed effettuare il login. A differenza di prima il datasource risulta già configurato e la dashboard disponibile.
Dashboard
Molti componenti/prodotti software espongono già le metriche in formato Prometheus e mettono a disposizione anche delle dashboard già pronte all’uso (ad esempio Consul o Spring Boot). Alla seguente pagina è disponibile un motore di ricerca per le dashboard.
L’importazione di una dashboard è molto semplice. Cliccando sempre sul pulsante + sul menu di sinistra e selezionando Import apparirà una dialog in cui è possibile importare la dashboard che si vuole copiandone il JSON o utilizzandone l’id. Per maggiori informazioni consultare questa pagina.
Conclusioni
In questo tutorial si può constatare quanto sia semplice configurare Prometheus e Grafana affinché monitorino un servizio.
Prossimamente verrà fornito un esempio leggermente più complesso che sfrutta qualche funzione per analizzare al meglio le metriche.
Qualora aveste qualche consiglio nota o domanda, non esitate a contattare Carlo.
Si ringrazia il collega Francesco Sacchi per il supporto fornito alla stesura di questo tutorial.
Riferimenti
- Prometheus
- Grafana
- Docker
- docker-compose
- Repository GitHub del tutorial, cartella simple-demo.