postgres_exporter y monitoreo de instancias de PostgreSQL con múltiples bases de datos

UPD: La nota ha perdido su relevancia con el lanzamiento de 0.8.0. Todas las innovaciones se pueden encontrar en el artículo: Nuevas características de postgres_exporter para monitorear PostgreSQL


Buenas tardes, habr lectores!


Prometheus y su ecosistema de exportadores (agentes) es una buena herramienta para cualquier administrador y desarrollador. Facilidad de entrega, configuración de simplicidad (relativa), la capacidad de utilizar el servicio de detección automática.
Pero no se trata tanto de Prometeo, sino de uno de los agentes notables, a saber, postgres_exporter. Le permite recopilar métricas con PostgreSQL. Pero si todo fuera tan simple ...


Desafortunadamente, la documentación de postgres_exporter es bastante ascética y solo afecta a casos generales. Pero, ¿qué sucede si tiene una instancia de un clúster DBMS con varias bases de datos y / o desea recopilar métricas para varias instancias del clúster a la vez?


Propósito


En realidad, sobre el propósito del artículo o más bien las notas. Noto de inmediato que aquí no describiré los procesos de ensamblaje o configuración de Prometheus y postgres_exporter, su interacción. Todo esto se describe en la documentación y en muchas otras fuentes.


Me gustaría referirme a algunos casos especiales de uso de postgres_exporter para resolver problemas específicos, es decir, recopilar métricas de un agente con:


  1. varias bases de datos en una instancia;
  2. varias copias;
  3. múltiples bases de datos en diferentes instancias.

postgres_exporter


Subjetivamente, los pros y los contras.


De los profesionales:


  1. La primera ventaja importante es la facilidad de entrega y configuración del agente. Agente: es un archivo ejecutable (opcionalmente, un archivo yaml con un conjunto de métricas de usuario). Esta es una aplicación autónoma compilada para la distribución y arquitectura necesarias, y no requiere la instalación de paquetes adicionales en el servidor. El agente se puede instalar tanto en el mismo nodo que la instancia del clúster como en un nodo separado;
  2. El agente se conecta al DBMS como un cliente sql normal. Es posible conectarse a través de inet o mediante un socket unix;
  3. La capacidad de recibir métricas por un agente, desde varias instancias de instancias y / o desde varias bases de datos de una instancia;
  4. Las métricas se recopilan con la frecuencia que Prometheus u otro recopilador solicitan;
  5. La capacidad de recibir métricas con una simple solicitud HTTP;
  6. Recibo automático, por parte de un agente, de una lista de bases de datos en una sola instancia de PostgreSQL, con la versión postgres_exporter 0.5.0+, ha aparecido la opción --auto-discover-database.

De las desventajas:


  1. Falta de autorización;
  2. Transferencia de datos solo a través de HTTP. Todas las métricas se transmitirán en texto claro. Y esto es malo, ya que un atacante, cuando es interceptado, puede obtener una lista confiable de bases de datos y roles;
  3. No almacena en caché las métricas. Así, por ejemplo, cuando el agente no está disponible para la red, Prometheus no recibirá los datos del período de indisponibilidad;
  4. Cuando se usa la opción --auto-discover-database, no es posible excluir ciertas bases de datos de la lista. Esto es bastante temporal, ya que en la próxima versión tal posibilidad ya debería aparecer (opción --excluir-bases de datos).

Múltiples bases de datos en una instancia


Bueno, pasemos a practicar. Supongamos que tenemos una instancia de PostgreSQL con varias bases de datos y necesitamos organizar la colección de métricas de instancias y todas las bases de datos.
¿Por qué separé la colección de métricas de la base de datos y la instancia del clúster? Todo es muy simple, el escenario de postgres_exporter trabajando con varias bases de datos en el mismo clúster implica la ejecución del mismo conjunto de consultas SQL en diferentes bases de datos. Y como resultado, al intentar obtener métricas de las vistas pg_stat_replication, pg_stat_activity, pg_stat_statement, etc. Al ser comunes al clúster, siempre entendemos, en la comprensión de postgres_exporter, el mismo conjunto de métricas que conducirán a claves y valores duplicados, lo que conducirá a un error.
Veamos cómo se ve en la práctica.


Tenemos una instancia de prueba con un conjunto de bases de datos:


List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+------------+------------+----------------------- dbtest1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | dbtest2 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | dbtest3 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 | 

Comenzamos postgres_exporter, con la opción --auto-discover-bases de datos (si el nombre de la base de datos no se especifica en la cadena de conexión, la conexión se realizará a la base de datos con el nombre de usuario):


 $ DATA_SOURCE_NAME="postgresql://postgres@127.0.0.1:5432/?sslmode=disable" ./postgres_exporter --auto-discover-databases --log.format=logger:stdout 

  • DATA_SOURCE_NAME: variable de entorno que contiene parámetros para conectarse a una instancia de PostgreSQL

En la salida del agente, observamos una imagen idílica, se lanzó y pudo conectarse a todas las bases de datos del clúster (aunque no escribe en qué bases de datos, pero con suerte esto se solucionará):


 INFO[0000] Established new database connection to "127.0.0.1:5432". source="postgres_exporter.go:788" INFO[0000] Established new database connection to "127.0.0.1:5432". source="postgres_exporter.go:788" INFO[0000] Semantic Version Changed on "127.0.0.1:5432": 0.0.0 -> 11.5.0 source="postgres_exporter.go:1251" INFO[0000] Semantic Version Changed on "127.0.0.1:5432": 0.0.0 -> 11.5.0 source="postgres_exporter.go:1251" INFO[0000] Established new database connection to "127.0.0.1:5432". source="postgres_exporter.go:788" INFO[0000] Semantic Version Changed on "127.0.0.1:5432": 0.0.0 -> 11.5.0 source="postgres_exporter.go:1251" INFO[0000] Established new database connection to "127.0.0.1:5432". source="postgres_exporter.go:788" INFO[0000] Semantic Version Changed on "127.0.0.1:5432": 0.0.0 -> 11.5.0 source="postgres_exporter.go:1251" INFO[0000] Established new database connection to "127.0.0.1:5432". source="postgres_exporter.go:788" INFO[0000] Semantic Version Changed on "127.0.0.1:5432": 0.0.0 -> 11.5.0 source="postgres_exporter.go:1251" INFO[0000] Starting Server: :9187 source="postgres_exporter.go:1490" 

Creo que un lector atento notará que hay cuatro bases en el clúster (postgres, dbtest1, dbtest2 y dbtest3, template0 y template1 se ignoran), y hay cinco conexiones. En nuestro caso, postgres_exporter crea dos conexiones a la base de datos postgres. Y con esta función, debes tener mucho cuidado. Por qué Descubriremos esto un poco más.


Bueno, continuemos e intentemos obtener las métricas:


 $ curl http://localhost:9178/metrics 

Como resultado, en la salida recibimos advertencias sobre duplicados "se recopilaron antes con el mismo nombre y valores de etiqueta" (pero en el registro postgres_exporter no veremos advertencias):


 ... * collected metric pg_stat_activity_max_tx_duration label:<name:"datname" value:"dbtest1" > label:<name:"server" value:"127.0.0.1:5432" > label:<name:"state" value:"fastpath function call" > gauge:<value:0 > was collected before with the same name and label values * collected metric pg_stat_bgwriter_checkpoints_timed label:<name:"server" value:"127.0.0.1:5432" > counter:<value:1 > was collected before with the same name and label values ... 

La única forma de deshacerse de los errores es deshabilitar la recopilación de métricas de forma predeterminada. Hay dos formas de hacer esto: primero establezca las variables de entorno PG_EXPORTER_DISABLE_DEFAULT_METRICS y PG_EXPORTER_DISABLE_SETTINGS_METRICS en verdadero o use las opciones --disable-default-metrics y --disable-settings-metrics


Reinicie postgres_exporter con opciones adicionales:


 $ DATA_SOURCE_NAME="postgresql://postgres@127.0.0.1:5432/?sslmode=disable" ./postgres_exporter --auto-discover-databases --log.format=logger:stdout --disable-default-metrics --disable-settings-metrics 

Intentando obtener las métricas:


 $ curl http://localhost:9178/metrics 

Y así, todo salió según el plan, pero no hay una sola métrica asociada con PostgreSQL en la salida:


 # HELP go_gc_duration_seconds A summary of the GC invocation durations. # TYPE go_gc_duration_seconds summary go_gc_duration_seconds{quantile="0"} 0 go_gc_duration_seconds{quantile="0.25"} 0 go_gc_duration_seconds{quantile="0.5"} 0 go_gc_duration_seconds{quantile="0.75"} 0 go_gc_duration_seconds{quantile="1"} 0 go_gc_duration_seconds_sum 0 go_gc_duration_seconds_count 0 ... # HELP process_virtual_memory_bytes Virtual memory size in bytes. # TYPE process_virtual_memory_bytes gauge process_virtual_memory_bytes 1.3832192e+07 

Además, para obtener la carga útil, necesitamos crear un archivo que describa qué métricas queremos recibir (no se olvide, solo podemos recopilar métricas específicas de la base de datos).


Para la prueba, recopilaremos métricas de la relación pg_statio_user_tables. Para hacer esto, cree un archivo queries.yaml con el siguiente contenido:


 pg_statio_user_tables: query: "SELECT current_database() as datname, schemaname, relname, heap_blks_read, heap_blks_hit FROM pg_statio_user_tables" metrics: - datname: usage: "LABEL" description: "Name of database" - schemaname: usage: "LABEL" description: "Name of the schema that this table is in" - relname: usage: "LABEL" description: "Name of this table" - heap_blks_read: usage: "COUNTER" description: "Number of disk blocks read from this table" - heap_blks_hit: usage: "COUNTER" description: "Number of buffer hits in this table" 

Creo que aquí es necesario aclarar un punto, a saber, agregar el nombre de la base de datos en la que se ejecuta la consulta. Este es un requisito obligatorio, y hay al menos dos razones para esto:


  1. Las bases de datos pueden tener tablas con el mismo nombre, lo que provocará un error debido a la duplicación de métricas;
  2. Sin esto, no puede identificar a qué base de datos se refiere la métrica, lo que convertirá los datos recopilados en basura.

Y así, lanzamos nuestro agente con la opción --extend.query-path (aquí se indica la ruta al archivo yaml con la descripción de las métricas):


 DATA_SOURCE_NAME="postgresql://postgres@127.0.0.1:5432?sslmode=disable" ./postgres_exporter --log.format=logger:stdout --auto-discover-databases --disable-default-metrics --disable-settings-metrics --extend.query-path=./queries.yaml 

Estamos tratando de obtener las métricas (para mayor claridad, solo tomamos pg_statio_user_tables_heap_blks_hit):


 curl -s http://localhost:9187/metrics | grep pg_statio_user_tables_heap_blks_hit 

Como resultado, obtenemos un conjunto de métricas interpretado de forma única:


 # HELP pg_statio_user_tables_heap_blks_hit Number of buffer hits in this table # TYPE pg_statio_user_tables_heap_blks_hit counter pg_statio_user_tables_heap_blks_hit{datname="dbtest1",relname="t1",schemaname="public",server="127.0.0.1:5432"} 0 pg_statio_user_tables_heap_blks_hit{datname="dbtest1",relname="t2",schemaname="public",server="127.0.0.1:5432"} 0 pg_statio_user_tables_heap_blks_hit{datname="dbtest2",relname="t1",schemaname="public",server="127.0.0.1:5432"} 0 pg_statio_user_tables_heap_blks_hit{datname="dbtest2",relname="t2",schemaname="public",server="127.0.0.1:5432"} 0 pg_statio_user_tables_heap_blks_hit{datname="dbtest3",relname="t1",schemaname="public",server="127.0.0.1:5432"} 0 pg_statio_user_tables_heap_blks_hit{datname="dbtest3",relname="t2",schemaname="public",server="127.0.0.1:5432"} 0 

Como resultado, tuvimos la oportunidad, utilizando la opción --auto-discover-bases de datos, de recopilar métricas de todas las bases de datos de una instancia del clúster. Una buena ventaja es que cuando agrega una nueva base de datos, no necesita reiniciar el agente.
Pero con todo esto, nos quedamos sin métricas de instancia. La solución, por el momento, es solo una: utilizar diferentes agentes para recopilar métricas de base de datos e instancias.
Ciertamente no se ve muy bien, pero es posible nivelar esta molestia al agrupar agentes para recopilar métricas de varias instancias. Consideraremos esta, otra oportunidad bastante interesante a continuación.


La respuesta al enigma de la conexión 'extra'

Recuerde, al principio, llamamos la atención sobre la conexión "extra". Entonces, esta es una característica de postgres_exporter con la opción --auto-discover-database.
Pero, ¿por qué esto puede causar tantos problemas? De hecho, todo es simple y ya se describió anteriormente, a saber, el problema es que postgres_exporter recopilará métricas de la base de datos de postgres dos veces y comenzará a duplicar métricas. En nuestro caso, solo la apariencia de la opción --exclude-bases de datos puede ayudar (por lo que esperamos la próxima versión).
Y sí, si tiene tablas de usuario en la base de datos postgres, entonces el ejemplo anterior no funcionará.


Instancias múltiples


Bueno, sigue adelante. Descubrimos cómo obtener métricas de varias bases de datos, ahora consideraremos la opción de cómo monitorear varias instancias con un agente. Es muy simple, para esto es suficiente enumerarlos en la variable de entorno DATA_SOURCE_NAME separada por una coma:


 $ DATA_SOURCE_NAME="postgresql://postgres@127.0.0.1:5432/postgres?sslmode=disable,postgresql://postgres@127.0.0.1:5434/postgres?sslmode=disable" ./postgres_exporter --log.format=logger:stdout 

Aquí nos conectamos a dos instancias de clúster diferentes que se ejecutan, en nuestro caso, en el nodo local. Así es como se ve en los registros:


 INFO[0000] Established new database connection to "127.0.0.1:5432". source="postgres_exporter.go:788" INFO[0000] Semantic Version Changed on "127.0.0.1:5432": 0.0.0 -> 11.5.0 source="postgres_exporter.go:1251" INFO[0000] Established new database connection to "127.0.0.1:5434". source="postgres_exporter.go:788" INFO[0000] Semantic Version Changed on "127.0.0.1:5434": 0.0.0 -> 11.5.0 source="postgres_exporter.go:1251" INFO[0000] Starting Server: :9187 source="postgres_exporter.go:1490" 

A continuación, intentamos obtener las métricas (para mayor claridad, nos restringimos a la métrica pg_stat_database_blk_read_time):


 curl -s http://localhost:9187/metrics | grep pg_stat_database_blk_read_time 

Como resultado, de un agente, obtenemos métricas para ambas instancias:


 # HELP pg_stat_database_blk_read_time Time spent reading data file blocks by backends in this database, in milliseconds # TYPE pg_stat_database_blk_read_time counter pg_stat_database_blk_read_time{datid="1",datname="template1",server="127.0.0.1:5432"} 0 pg_stat_database_blk_read_time{datid="1",datname="template1",server="127.0.0.1:5434"} 0 pg_stat_database_blk_read_time{datid="13116",datname="template0",server="127.0.0.1:5432"} 0 pg_stat_database_blk_read_time{datid="13116",datname="template0",server="127.0.0.1:5434"} 0 pg_stat_database_blk_read_time{datid="13117",datname="postgres",server="127.0.0.1:5432"} 0 pg_stat_database_blk_read_time{datid="13117",datname="postgres",server="127.0.0.1:5434"} 0 pg_stat_database_blk_read_time{datid="16384",datname="dbtest1",server="127.0.0.1:5432"} 0 pg_stat_database_blk_read_time{datid="16385",datname="dbtest2",server="127.0.0.1:5432"} 0 pg_stat_database_blk_read_time{datid="16386",datname="dbtest3",server="127.0.0.1:5432"} 0 

En este caso, todo fue algo más simple que en el caso de varias bases de datos en una instancia. Al mismo tiempo, todavía tenemos la oportunidad de recibir métricas globales de todas las instancias.


Resumen


Y así, el tercer caso indicado para fines es una combinación de los dos descritos anteriormente, por lo que no veo ninguna razón para presentarlo.


Como resultado, lo que tenemos en el resultado final, postgres_exporter, en mi opinión, es una herramienta de administrador bastante interesante y prometedora para monitorear instancias del clúster PostgreSQL y las bases de datos implementadas en ellas. Pero debido a su antigüedad, no está exento de defectos que pueden entenderse y perdonarse.


Fuentes


  • Prometheus [ 1 ] es una aplicación de código abierto utilizada para monitorear y alertar eventos. Escribe métricas en tiempo real en una base de datos de series de tiempo construida utilizando el modelo de solicitud HTTP, con consultas flexibles y alertas en tiempo real.
  • postgres_exporter es un exportador de métricas PostgreSQL para Prometheus.

Versión, al momento de escribir, v 0.5.1. Versiones compatibles de PostgreSQL 9.4+ (restricción de la versión 9.1+ indicada en el código fuente).

Source: https://habr.com/ru/post/468573/


All Articles