Grafana con Tempo, Prometheus y Loki en Docker

Grafana con Tempo, Prometheus y Loki en Docker

En esta entrada veremos cómo conectar Grafana a los diferentes datasources de Tempo, Prometheus y Loki y cómo correlacionarlos entre ellos.

En esta entrada veremos cómo tener Grafana pre-configurado con Tempo, Prometheus y Loki en Docker. También veremos de manera muy breve qué nos solución nos ofrecen los diferentes servicios, anteriormente citados, de los que Grafana sacará esa información.

Grafana

¿Qué es Grafana?

Grafana es uno de los mejores y más completos servicios de monitoring de código abierto, Open Source, donde podemos tener una UI amigable a la vez que poder explotar los datos de las diferentes verticales de la observabilidad, trazas, métricas y logs, desde un mismo punto centralizado y poder correlacionar dichas verticales entre ellas para tener una buena base para la observabilidad de nuestro sistema.

¿Cómo añadir Grafana en Docker?

  • Añadir Grafana en el fichero de docker-compose.
1
2
3
4
5
6
7
8
9
10
11
12
grafana:
    image: grafana/grafana:9.0.1
    container_name: grafana
    environment:
      - GF_AUTH_ANONYMOUS_ENABLED=true
      - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
      - GF_AUTH_DISABLE_LOGIN_FORM=true
    volumes:
      - /etc/localtime:/etc/localtime:ro
    restart: unless-stopped
    ports:
      - 3001:3000

Tempo

¿Qué es Grafana Tempo?

Grafana Tempo es un servicio, altamente escalable y de código abierto, de ingesta de trazas distribuidas. Puede ingerir métricas de gran variedad de protocolos, sobre todo los de código abierto como OpenTelemetry. Tiene una gran integración con Grafana, Prometheus y Loki.

¿Cómo añadir Grafana Tempo en Docker?

  • Añadir Grafana Tempo en el fichero de docker-compose.
1
2
3
4
5
6
7
8
9
10
11
tempo:
    image: grafana/tempo:1.4.1
    container_name: tempo
    command: [ "-config.file=/etc/tempo.yaml" ]
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./configs/tempo.yml:/etc/tempo.yaml
    restart: unless-stopped
    ports:
      - 3200:3200  # tempo
      - 4007:4317  # grpc

En este ejemplo se abre el puerto de tempo para exponer las trazas recibidas y el puerto grpc / http2 para la ingesta de trazas. Este último puerto será donde los diferentes servicios enviarán su telemetría relativa a trazas.

  • Archivo de configuración config/tempo.yml de Grafana Tempo.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
server:
  http_listen_port: 3200

search_enabled: true                   # enable tempo trace search ( beta preview )

distributor:
  receivers:
    otlp:
      protocols:
        http:
        grpc:
          endpoint: tempo:4007

ingester:
  trace_idle_period: 10s               # the length of time after a trace has not received spans to consider it complete and flush it
  max_block_bytes: 1_000_000           # cut the head block when it hits this size or ...
  max_block_duration: 5m               #   this much time passes

compactor:
  compaction:
    compaction_window: 1h              # blocks in this time window will be compacted together
    max_block_bytes: 100_000_000       # maximum size of compacted blocks
    block_retention: 1h
    compacted_block_retention: 10m

storage:
  trace:
    backend: local                     # backend configuration to use
    block:
      bloom_filter_false_positive: .05 # bloom filter false positive rate.  lower values create larger filters but fewer false positives
      index_downsample_bytes: 1000     # number of bytes per index record
      encoding: zstd                   # block encoding/compression.  options: none, gzip, lz4-64k, lz4-256k, lz4-1M, lz4, snappy, zstd, s2
    wal:
      path: /tmp/tempo/wal             # where to store the the wal locally
      encoding: snappy                 # wal encoding/compression.  options: none, gzip, lz4-64k, lz4-256k, lz4-1M, lz4, snappy, zstd, s2
    local:
      path: /tmp/tempo/blocks
    pool:
      max_workers: 100                 # worker pool determines the number of parallel requests to the object store backend
      queue_depth: 10000

Prometheus

¿Qué es Prometheus?

Prometheus es un servicio de ingesta y agregación de métricas. Prometheus tiene la peculariadad respecto a los demás servicios, Tempo y Loki, que usa un sistema pull para la ingesta de métricas es decir que en vez de que los servicios envíen las métricas a Prometheus,sistema push, es Prometheus quien pregunta por las métricas, scrapping, cada cierto tiempo periódicamente.

¿Cómo añadir Prometheus en Docker?

  • Añadir Prometheus en el fichero de docker-compose.
1
2
3
4
5
6
7
8
prometheus:
    image: prom/prometheus:v2.37.0
    container_name: prometheus
    volumes:
      - ./configs/prometheus.yaml:/etc/prometheus/prometheus.yml
    restart: unless-stopped
    ports:
      - "9091:9090"

En este ejemplo se abre el puerto de Prometheus para exponer las métricas recibidas. En este caso no expone puerto para recibir métricas porque Prometheus realiza la ingesta de telemetría mediante scraping, el sistema pull que hemos comentado anteriormente, donde es el servicio de telemetría, en este caso Prometheus, quien extrae los datos generados por otros servicios.

  • Archivo de configuración config/prometheus.yaml de Prometheus.
1
2
3
4
5
6
scrape_configs:
  - job_name: 'scrape_servicename'
    scrape_interval: 10s
    static_configs:
      - targets: ['<DOCKER-SERVICE-NAME>:8889']
      - targets: ['<DOCKER-SERVICE-NAME>:8888']

En este ejemplo Prometheus extrae las métricas, scraping, que expone el servicio especificado en los puertos especificados.

Loki

¿Qué es Grafana Loki?

Grafana Loki es un servicio de ingesta de logs. Entre sus características destacan que se trata de un servicio escalable horizontalmente y, por lo tanto, de alta disponibilidad. Tiene una gran integración con Grafana, Tempo y Prometheus.

¿Cómo añadir Grafana Loki en Docker?

  • Añadir Grafana Loki en el fichero de docker-compose.
1
2
3
4
5
6
7
8
9
10
loki:
    endpoint: http://loki:3100/loki/api/v1/push
    tls:
      insecure: true
    format: json
    labels:
      resource:
        service.name: "service_name"
      record:
        traceID: "traceid"

En este ejemplo se indica la dirección de Loki para la ingesta de trazas. Este último puerto será donde los diferentes servicios enviarán su telemetría relativa a logs.

  • Archivo de configuración config/loki.yml de Grafana Loki.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
auth_enabled: false

server:
  http_listen_port: 3100

common:
  path_prefix: /loki
  storage:
    filesystem:
      chunks_directory: /loki/chunks
      rules_directory: /loki/rules
  replication_factor: 1
  ring:
    kvstore:
      store: inmemory

schema_config:
  configs:
    - from: 2020-10-24
      store: boltdb-shipper
      object_store: filesystem
      schema: v11
      index:
        prefix: index_
        period: 24h

Conectar Grafana con datasources

Para conectar Grafana con los diferentes datasources de Tempo, Prometheus y Loki, deberemos primeramente añadir los siguientes volúmenes al servicio de Grafana de nuestro docker-compose.

1
2
- ./configs/grafana/grafana.ini:/etc/grafana/grafana.ini
- ./configs/grafana/provisioning/datasources:/etc/grafana/provisioning/datasources

El primero de ellos, grafana.ini, lo usaremos para activar una feature de Grafana relacionada con Tempo.

1
2
[feature_toggles]
enable = tempoSearch tempoBackendSearch

El segundo de ellos, datasources, se trata de un directorio que contendrá un fichero llamado datasources.yml en la que configuraremos las conexiones de Grafana con Tempo, Prometheus y Loki para poder consultar y explotar su información (iremos introduciendo los datasources en los siguientes pasos).

1
2
3
apiVersion: 1

datasources:

¿Cómo conectar Grafana con Tempo?

En nuestro archivo de datasources.yml añadiremos el datasource de Tempo.

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: 1

datasources:
- name: Tempo
  type: tempo
  uid: tempo
  access: proxy
  url: http://tempo:3200
  basicAuth: false
  isDefault: false
  version: 1
  editable: false

¿Cómo conectar Grafana con Prometheus?

En nuestro archivo de datasources.yml añadiremos el datasource de Prometheus.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: 1

datasources:
- name: Prometheus
  type: prometheus
  uid: prometheus
  access: proxy
  url: http://prometheus:9090
  jsonData:
    timeInterval: 10s
  basicAuth: false
  isDefault: true
  version: 1
  editable: false

¿Cómo conectar Grafana con Loki?

En nuestro archivo de datasources.yml añadiremos el datasource de Loki.

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: 1

datasources:
- name: Loki
  type: loki
  uid: loki
  access: proxy
  url: http://loki:3100
  basicAuth: false
  isDefault: false
  version: 1
  editable: false

¿Cómo correlacionar Grafana Loki (logs) con Tempo (trazas)?

  • Para poder movernos de un log de Loki a la traza de Tempo correspondiente a golpe de ‘clic’ tendremos que añadir campos derivados al datasource de Loki recientemente añadido.
1
2
3
4
5
6
jsonData:
  derivedFields:
    - datasourceUid: tempo
      matcherRegex: "\u0022traceid\u0022:\u0022(\\w+)\u0022"
      name: TraceId
      url: '$${__value.raw}'

La propiedad datasourceUid hace referencia al datasource con ese valor en su propiedad uid.

Con la propiedad matcherRegex específicamos en qué parte del log queremos extraer el id de la traza.

En la propiedad name concretamos el nombre a darle a esa extración del id de la traza a través de la anterior propiedad mencionada matcherRegex.

Y por último con la url establecemos la url donde hacer la consulta, en este caso será el valor del id de la traza en tempo.

Más información en la documentación oficial de Grafana sobre datasources de Grafana Loki.

Integrar Tempo, Prmetheus y Loki con Grafana

El resultado de nuestro archivo de configuración datasources.yml quedará como en el ejemplo de a continuación en el caso de que hayamos configurado los diferentes datasources de Grafana y correlacionado los logs con las trazas.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
apiVersion: 1

datasources:
- name: Tempo
  type: tempo
  uid: tempo
  access: proxy
  url: http://tempo:3200
  basicAuth: false
  isDefault: false
  version: 1
  editable: false
- name: Prometheus
  type: prometheus
  uid: prometheus
  access: proxy
  url: http://prometheus:9090
  jsonData:
    timeInterval: 10s
  basicAuth: false
  isDefault: true
  version: 1
  editable: false
- name: Loki
  type: loki
  uid: loki
  access: proxy
  url: http://loki:3100
  basicAuth: false
  isDefault: false
  version: 1
  editable: false
  jsonData:
    derivedFields:
      - datasourceUid: tempo
        matcherRegex: "\u0022traceid\u0022:\u0022(\\w+)\u0022"
        name: TraceId
        url: '$${__value.raw}'

Et voilà! Ya tendríamos listo nuestra stack de monitorización y observabilidad Open Source con Grafana, Tempo, Prometheus y Loki. Sólo quedaría desde nuestros servicios empezar a enviar telemetría en caso de las trazas y los logs y a exponer telemetría en caso de las métricas

comentarios provistos por Disqus