Prometheus captura el servicio de réplica del clúster Docker Swarm

dns_sd_configsEn esta publicación de blog, demostraré cómo hacer esto fácilmente introduciendo una instancia intermedia de Prometheus en Docker Swarm y combinando varias funciones de Prometheus (principalmente federación entre servicios) para recopilar y obtener un poco los datos métricos requeridos.

En un clúster Docker Swarm, las aplicaciones se ejecutan como servicios. Para los hosts externos (específicamente todo lo que está fuera del clúster de enjambre), el servicio parece una instancia a la que se accede a través de un puerto publicado. Pero dentro de un enjambre, normalmente hay varias instancias (réplicas) que ejecutan el servicio. Cuando se produce una solicitud externa no solicitada, Docker Network enruta el puerto del servicio publicado a una de las réplicas en ejecución. Como persona que llama, no tiene idea de que lo están redirigiendo a una instancia específica del servicio.

Si desea tener un servidor Prometheus ejecutándose fuera de Docker swarm para obtener métricas para un servicio, la forma más fácil es hacer que realice monitoreo activo para el servicio publicado. Si el servicio se ejecuta en modo de replicación con múltiples instancias, se mostrarán ejemplos específicos. no puede obtenerse con precisión. Debido a que la llamada al servicio en realidad termina en el balanceador de carga de la red Docker, reenvía la solicitud de recuperación a una instancia en ejecución. Entonces, los datos que obtiene son métricas para una de las instancias de servicio (no sabe cuál). Debido a que Prometheus periódicamente extrae métricas de servicio, y cada solicitud de extracción se enruta independientemente de la solicitud anterior, la siguiente solicitud de extracción puede ser enrutada y respondida por una instancia de servicio diferente que devuelva métricas para esa instancia, etc. Entonces, el peor de los casos es que Prometheus obtenga un conjunto diferente de métricas en cada solicitud de rastreo y no le brinde datos coherentes.

Si Prometheus conoce varias instancias de servicio y puede eliminarlas individualmente, agregará una instanceetiqueta a la métrica y, por lo tanto, almacenará una serie de tiempo diferente para cada métrica e instancia. Docker Swarm hace un buen trabajo al ocultar estos detalles a Prometheus, al menos fuera del enjambre. Por lo tanto, si ejecuta Prometheus como un servicio en Docker swarm, puede usar su dns_sd_configsfuncionalidad con el descubrimiento del servicio DNS de Docker swarm para rastrear todas las instancias individualmente. En combinación con las capacidades de federación entre servicios de Prometheus , puede capturar estas métricas de instancias de servicio desde servidores de Prometheus fuera del enjambre.

En esta publicación de blog, configuraré un clúster Docker Swarm local que ejecuta el servicio de muestra para demostrar cómo se ve.

Configure un enjambre Docker utilizando el servicio de muestra

Primero, inicializo el modo enjambre para la instancia local de Docker (se puede desactivar nuevamente docker swarm leave --forceusando

docker swarm init

Estoy ejecutando Docker Desktop para Mac, por lo que no necesito otras opciones aquí. Para obtener detalles sobre cómo configurar un enjambre local en otros entornos, consulte el tutorial de Docker Swarm.

Un detalle importante (que desafortunadamente no parece estar descrito en la documentación de Docker swarm) es que el descubrimiento del servicio DNS de Docker swarm no funciona con la red de superposición de ingreso predeterminada (me tomó mucho tiempo resolver esto hasta que encontré esto en Respondido en el foro de Docker ). Entonces comenzaré creando una red superpuesta personalizada.

docker network create \
    --driver overlay \
    --attachable \
    custom-overlay-network

Como servicio de muestra, utilicé una imagen de Docker que contenía una aplicación Spring Boot muy básica con los complementos Actuator y Micrometer Prometheus habilitados.

docker service create \
    --name sample-service \
    --replicas 3 \
    --network custom-overlay-network \
    -p 8080:8080 \
    sample-app:latest

Al enumerar todos los servicios de Docker que se ejecutan en mi enjambre, puedo ver que tengo sample-servicetres instancias en ejecución.

docker service ls

    ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
    kgjaw3vx1tnh        sample-service      replicated          3/3                 sample-app:latest   *:8080->8080/tcp

El puerto 8080 de mi aplicación Spring Boot está publicado, por lo que también puedo acceder al punto final de métricas del actuador.

curl localhost:8080/actuator/prometheus

    # HELP jvm_gc_live_data_size_bytes Size of old generation memory pool after a full GC
    # TYPE jvm_gc_live_data_size_bytes gauge
    jvm_gc_live_data_size_bytes 0.0
    # HELP jvm_classes_loaded_classes The number of classes that are currently loaded in the Java virtual machine
    # TYPE jvm_classes_loaded_classes gauge
    jvm_classes_loaded_classes 7469.0
    ...

Dado que mi enjambre Docker solo contiene un nodo administrador (mi máquina local), puedo ver las tres réplicas de los contenedores Docker en ejecución.

docker ps

    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
    bc26b66080f7        sample-app:latest   "java -Djava.securit…"   6 minutes ago       Up 6 minutes                            sample-service.3.hp0xkndw8mx9yoph24rhh60pl
    b4cb0a313b82        sample-app:latest   "java -Djava.securit…"   6 minutes ago       Up 6 minutes                            sample-service.2.iwbagkwjpx4m6exm4w7bsj5pd
    7621dd38374a        sample-app:latest   "java -Djava.securit…"   6 minutes ago       Up 6 minutes                            sample-service.1.1a208aiqnu5lttkg93j4dptbe

Para ver el descubrimiento del servicio DNS en acción, me conecté a uno de los contenedores que se ejecutan en Docker Swarm. Tengo que instalar dnsutilsel paquete para usarlo nslookup.

docker exec -ti bc26b66080f7 /bin/sh

apt-get update && apt-get install dnsutils -y

Al buscar el nombre del servicio, obtengo una dirección IP virtual

nslookup sample-service

    Server:   127.0.0.11
    Address:  127.0.0.11#53

    Non-authoritative answer:
    Name:     sample-service
    Address:  10.0.1.2

Para resolver las direcciones IP virtuales de todas las réplicas de servicios que se ejecutan en mi enjambre Docker, tengo que buscar tasks.<service name>el nombre de dominio (consulte la documentación de Docker Overlay Networking ).

nslookup tasks.sample-service

    Server:   127.0.0.11
    Address:  127.0.0.11#53

    Non-authoritative answer:
    Name:     tasks.sample-service
    Address:  10.0.1.4
    Name:     tasks.sample-service
    Address:  10.0.1.3
    Name:     tasks.sample-service
    Address:  10.0.1.5

Esta característica de descubrimiento de servicios DNS es lo que una instancia de Prometheus que se ejecuta en un enjambre de Docker puede usar para rastrear todas estas instancias de servicios (mencionaré swarm-prometheusesta instancia en el resto del texto).

Capturar instancias de servicio en enjambre

Para configurar swarm-prometheusel servicio, creé una imagen de Docker basada en la última imagen oficial de Prometheus y agregué mis propios archivos de configuración.

FROM prom/prometheus:latest
ADD prometheus.yml /etc/prometheus/

La parte interesante del archivo de configuración es swarm-serviceel trabajo de rastreo que agregué. Utilizo dns_sd_config(consulte la documentación para obtener más detalles ) para encontrar objetivos de rastreo realizando una consulta DNS. Necesito realizar una consulta DNS de Clase A y, dado que la consulta solo devuelve la dirección IP de la instancia de servicio, tengo que decirle a la instancia de Prometheus en qué puerto está escuchando y la ruta al punto final métrico.

scrape_configs:
  ...
  - job_name: 'swarm-service'
    dns_sd_configs:
      - names:
          - 'tasks.sample-service'
        type: 'A'
        port: 8080
    metrics_path: '/actuator/prometheus'

Después de construir la imagen creé swarm-prometheusel servicio.

docker build -t swarm-prometheus .

docker service create \
    --replicas 1 \
    --name swarm-prometheus \
    --network custom-overlay-network \
    -p 9090:9090 \
    swarm-prometheus:latest

Cuando abro la interfaz de usuario web de Prometheus y navego hasta "Estado -> Objetivos", puedo ver que mi configuración funciona como se esperaba.

Figura 1Figura 1: Estado del trabajo de rastreo configurado en la interfaz de usuario web de swarm-prometheus

Al ejecutar una consulta básica contra una de las métricas escritas en la aplicación de muestra, obtengo tres series de tiempo resultantes, una para cada una de mis instancias. instanceLas etiquetas agregadas por los trabajos de rastreo de Prometheus contienen la IP y el puerto de la instancia de servicio correspondiente.

Figura 2Figura 2: Consulta básica de Prometheus con tres series temporales de resultados

En este punto, las métricas de todas mis instancias de servicio se recopilan en swarm-prometheus. Como siguiente paso, quiero colocarlas en un servidor Prometheus que se ejecute fuera del enjambre ( host-prometheuslo haré referencia aquí).

Utilice federado para obtener métricas de otro Prometheus

Prometheus proporciona un /federatepunto final que se puede utilizar para extraer un conjunto seleccionado de series temporales de otra instancia de Prometheus (consulte la documentación para obtener más detalles ). El punto final requiere uno o más selectores de vectores instantáneos para especificar la serie temporal solicitada.

Quiero llamar y consultar el punto final para todas las series temporales recopiladas por mi trabajo de raspado /federate(uso con y opciones para poder usar valores de parámetros no codificados)swarm-prometheus``swarm-service``curl``-G``--data-urlencode

curl -G "http://localhost:9090/federate" --data-urlencode 'match[]={job="swarm-service"}'

    # TYPE jvm_buffer_count_buffers untyped
    jvm_buffer_count_buffers{
    
    id="direct",instance="10.0.1.3:8080",job="swarm-service"} 10 1586866971856
    jvm_buffer_count_buffers{
    
    id="direct",instance="10.0.1.4:8080",job="swarm-service"} 10 1586866975100
    jvm_buffer_count_buffers{
    
    id="direct",instance="10.0.1.5:8080",job="swarm-service"} 10 1586866976176
    jvm_buffer_count_buffers{
    
    id="mapped",instance="10.0.1.3:8080",job="swarm-service"} 0 1586866971856
    jvm_buffer_count_buffers{
    
    id="mapped",instance="10.0.1.5:8080",job="swarm-service"} 0 1586866976176
    jvm_buffer_count_buffers{
    
    id="mapped",instance="10.0.1.4:8080",job="swarm-service"} 0 1586866975100
    ...

Lo único que tuve que hacer host-prometheusfue agregar un trabajo de raspado apropiado para solicitar ese /federatepunto final.

scrape_configs:
  ...
  - job_name: 'swarm-prometheus'
    honor_labels: true
    metrics_path: '/federate'
    params:
      'match[]':
        - '{job="swarm-service"}'
    static_configs:
      - targets:
        - 'swarm-prometheus:9090'

Como ejecutaré host-prometheusen Docker, conectado a la misma red que mi enjambre, puedo usar swarm-prometheusel nombre del servicio como nombre de host. En un entorno del mundo real, es posible que tenga que encontrar otra swarm-prometheusforma de acceder al servicio, como utilizar la dirección IP y el puerto publicado de un nodo Docker Swarm.

El indicador de activación garantiza que Prometheus conserve las etiquetas y honor_labelsya incluidas en las métricas rastreadas y no las sobrescriba con sus propios valores (consulte la documentación para obtener más detalles ).jobinstancescrape_config

Una vez que esté compilado y en ejecución, host-prometheuspuedo verificar la página de estado del destino nuevamente para ver si el trabajo de rastreo se ejecutó exitosamente.

docker build -t host-prometheus .

docker run -d \
    --network custom-overlay-network \
    -p 9999:9090 \
    host-prometheus:latest

imagen 3Figura 3: Estado del trabajo de rastreo configurado en la interfaz de usuario web de host-prometheus

host-prometheusAhora puedo ejecutar la misma consulta de Prometheus que antes en mi interfaz de usuario web y obtener tres series temporales resultantes.

Entonces eso ya es todo. Simplemente configurando una instancia intermedia de Prometheus en Docker Swarm y combinando algunas características existentes, es fácil obtener métricas de todas las instancias del servicio Swarm en el servidor Prometheus, incluso si tiene que ejecutarse fuera del Swarm.

mejoramiento

Después de implementar la configuración anterior en mi proyecto actual, se me ocurrieron algunas mejoras que creo que vale la pena compartir.

Si está ejecutando varios servicios Spring Boot diferentes en un enjambre de Docker, todos escuchando en el puerto predeterminado 8080, entonces configurar un swarm-prometheustrabajo de raspado dedicado para cada servicio es muy redundante. Lo único que debe cambiarse para cada servicio es el nombre de dominio solicitado ( tasks.<service name>). Y, como habrás notado, puedes hacer esto en dns_sd_configs, así podemos configurar un trabajo de scraping que cubra todos los servicios existentes.

scrape_configs:
  ...
  - job_name: 'swarm-services'
    metrics_path: '/actuator/prometheus'
    dns_sd_configs:
      - names:
          - 'tasks.sample-service-1'
          - 'tasks.sample-service-2'
          - ...
        type: 'A'
        port: 8080

Sin embargo, al hacerlo podemos toparnos con otro problema. Con la configuración anterior, había un trabajo de rastreo por servicio y podíamos nombrar los trabajos de rastreo en consecuencia y usar jobetiquetas para identificar/filtrar métricas para diferentes servicios. Ahora que tenemos un trabajo de scraping genérico, tenemos que encontrar otra solución para esto.

Afortunadamente, Micrometer, la biblioteca que utilizamos para proporcionar puntos finales de métricas de Prometheus en nuestra aplicación Spring Boot, se puede configurar fácilmente para agregar etiquetas personalizadas a todas las métricas escritas. Al agregar la siguiente línea al application.propertiesarchivo de configuración de cada uno de nuestros servicios Spring Boot (por ejemplo), se agrega una serviceetiqueta con un valor estático que contiene el nombre del servicio (aquí) a todas las métricas escritas por nuestros servicios.sample-service-1

management.metrics.tags.service=sample-service-1

Finalmente, si está utilizando Grafana sobre Prometheus instance, los valores de etiqueta que contienen la dirección IP y el puerto (por ejemplo) de la instancia de servicio 10.0.1.3:8080resultarán problemáticos. Si desea usarlos como variables del panel (por ejemplo, repetir el panel para todas las instancias o filtrar datos para una instancia específica), esto no funcionará debido a los puntos y dos puntos en los valores (estos valores romperán el solicitud de datos al Prometheus subyacente porque no son URL codificadas en Grafana). Tenemos que convertirlos a un formato menos problemático para usarlos de esta manera. metric_relabel_configsPodemos hacer esto agregando unswarm-prometheus

scrape_configs:
  ...
  - job_name: 'swarm-services'
    metrics_path: '/actuator/prometheus'
    dns_sd_configs:
      - names:
          - 'tasks.sample-service-1'
          - 'tasks.sample-service-2'
          - ...
        type: 'A'
        port: 8080
    metric_relabel_configs:
      - source_labels: [ instance ]
        regex: '^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)\:([0-9]+)$'
        replacement: '${1}_${2}_${3}_${4}'
        target_label: instance

Esta configuración toma todos los valores de source_labels(aquí instance), aplica el valor dado a cada regexvalor y replacementreemplaza el valor con la expresión dada (usando sobrescribir el valor original por) en el indicador. Por lo tanto, los valores antiguos se convierten a valores que son menos problemáticos para Grafana.${1}``${2}``regex``target_label``instance``10.0.1.3:8080``10_0_1_3


Actualización: a partir de Prometheus 2.20, también hay disponible un descubrimiento de servicio Docker Swarm que se puede utilizar en lugar del descubrimiento de servicio DNS descrito en este artículo. Gracias a Julien Pivoto por presentarme la nueva función.

Supongo que te gusta

Origin blog.csdn.net/quuqu/article/details/124151624
Recomendado
Clasificación