postgres_exporter et surveillance des instances PostgreSQL avec plusieurs bases de données

UPD: La note a perdu de sa pertinence avec la sortie de 0.8.0. Toutes les innovations se trouvent dans l'article: Nouvelles fonctionnalités de postgres_exporter pour la surveillance de PostgreSQL


Bonjour, chers lecteurs!


Prometheus et son écosystème d'exportateurs (agents) est un bon outil pour tout administrateur et développeur. Facilité de livraison, simplicité (relative) des paramètres, possibilité d'utiliser le service de détection automatique.
Mais ce n'est pas tellement à propos de Prométhée, mais à propos d'un des agents notables, à savoir postgres_exporter. Il vous permet de collecter des métriques avec PostgreSQL. Mais si tout était si simple ...


Malheureusement, la documentation de postgres_exporter est assez ascétique et n'affecte que les cas généraux. Mais que faire si vous obtenez une instance d'un cluster SGBD avec plusieurs bases de données et / ou si vous souhaitez collecter des métriques pour plusieurs instances du cluster à la fois.


But


En fait, sur le but de l'article ou plutôt des notes. Je constate tout de suite qu'ici je ne décrirai pas les processus d'assemblage ou de configuration de Prométhée et postgres_exporter, leur interaction. Tout cela est décrit dans la documentation et dans de nombreuses autres sources.


Je voudrais aborder certains cas particuliers d'utilisation de postgres_exporter pour résoudre des problèmes spécifiques, à savoir la collecte de métriques par un agent avec:


  1. plusieurs bases de données en une seule instance;
  2. plusieurs exemplaires;
  3. plusieurs bases de données sur différentes instances.

postgres_exporter


Subjectivement, les avantages et les inconvénients.


Des pros:


  1. Le premier et important avantage est la facilité de livraison et de configuration de l'agent. Agent - est un fichier exécutable (éventuellement, un fichier yaml avec un ensemble de métriques utilisateur). Il s'agit d'une application autonome compilée pour la distribution et l'architecture nécessaires, et ne nécessite pas l'installation de packages supplémentaires sur le serveur. L'agent peut être installé à la fois sur le même nœud que l'instance de cluster et sur un nœud distinct;
  2. L'agent se connecte au SGBD en tant que client SQL standard. Il est possible de se connecter via inet ou via une prise unix;
  3. La capacité de recevoir des métriques par un agent, à partir de plusieurs instances d'instances et / ou de plusieurs bases de données d'une instance;
  4. Les mesures sont collectées aussi souvent que demandé par Prométhée ou un autre collectionneur;
  5. La possibilité de recevoir des métriques avec une simple requête HTTP;
  6. Réception automatique, par un agent, d'une liste de bases de données sur une seule instance PostgreSQL, avec la version postgres_exporter 0.5.0+, l'option --auto-Discover-Database est apparue.

Des inconvénients:


  1. Absence d'autorisation;
  2. Transfert de données uniquement via HTTP. Toutes les mesures seront transmises en texte clair. Et c'est mauvais, car un attaquant, une fois intercepté, peut obtenir une liste fiable de bases de données et de rôles;
  3. Ne met pas en cache les métriques. Ainsi, par exemple, lorsque l'agent n'est pas disponible pour le réseau, les données pour la période d'indisponibilité ne seront pas reçues par Prometheus;
  4. Lorsque vous utilisez l'option --auto-Discover-Database, il n'est pas possible d'exclure certaines bases de données de la liste. C'est plutôt temporaire, car dans la prochaine version, une telle possibilité devrait déjà apparaître (option --exclude-databases).

Plusieurs bases de données dans une seule instance


Eh bien, passons à la pratique. Supposons que nous ayons une instance de PostgreSQL avec plusieurs bases de données et que nous devons organiser la collecte des métriques d'instance et toutes les bases de données.
Pourquoi ai-je séparé la collection de métriques de base de données et l'instance de cluster, tout est très simple, le scénario de postgres_exporter travaillant avec plusieurs bases de données sur le même cluster implique l'exécution du même ensemble de requêtes SQL dans différentes bases de données. Et par conséquent, lorsque vous essayez d'obtenir des mesures à partir des vues pg_stat_replication, pg_stat_activity, pg_stat_statement, etc. étant commun au cluster, nous obtenons toujours, dans la compréhension de postgres_exporter, le même ensemble de métriques qui conduira à des clés et des valeurs en double, ce qui conduira à une erreur.
Voyons à quoi cela ressemble dans la pratique.


Nous avons une instance de test avec un ensemble de bases de données:


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 | 

Nous démarrons postgres_exporter, avec l'option --auto-discovery-databases (si le nom de la base de données n'est pas spécifié dans la chaîne de connexion, alors la connexion sera établie à la base de données avec le nom d'utilisateur):


 $ 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 d'environnement contenant des paramètres pour la connexion à une instance PostgreSQL

Dans la sortie de l'agent, nous observons une image idyllique, il est lancé et a pu se connecter à toutes les bases de données du cluster (bien qu'il n'écrive pas dans quelles bases de données, mais j'espère que cela sera corrigé):


 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" 

Je pense qu'un lecteur attentif remarquera qu'il y a quatre bases dans le cluster (postgres, dbtest1, dbtest2 et dbtest3, template0 et template1 sont ignorés), et il y a cinq connexions. Dans notre cas, postgres_exporter crée deux connexions à la base de données postgres. Et avec cette fonctionnalité, vous devez être très prudent. Pourquoi? Nous verrons cela un peu plus loin.


Eh bien, continuons et essayons d'obtenir les métriques:


 $ curl http://localhost:9178/metrics 

Par conséquent, dans la sortie, nous obtenons des avertissements sur les doublons "a été collecté auparavant avec le même nom et les mêmes valeurs d'étiquette" (mais dans le journal postgres_exporter nous ne verrons pas d'avertissements):


 ... * 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 seule façon de se débarrasser des erreurs est de désactiver la collection de métriques par défaut. Il existe deux façons de procéder: définissez d'abord les variables d'environnement PG_EXPORTER_DISABLE_DEFAULT_METRICS et PG_EXPORTER_DISABLE_SETTINGS_METRICS sur true ou utilisez les options --disable-default-metrics et --disable-settings-metrics


Redémarrez postgres_exporter avec des options supplémentaires:


 $ 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 

Essayer d'obtenir les métriques:


 $ curl http://localhost:9178/metrics 

Et donc, tout s'est passé comme prévu, mais il n'y a pas une seule métrique associée à PostgreSQL dans la sortie:


 # 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 

De plus, afin d'obtenir la charge utile, nous devons créer un fichier qui décrit les mesures que nous voulons recevoir (n'oubliez pas, nous ne pouvons collecter que des mesures spécifiques à la base de données).


Pour le test, nous collecterons des métriques de la relation pg_statio_user_tables. Pour ce faire, créez un fichier queries.yaml avec le contenu suivant:


 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" 

Je pense ici qu'il est nécessaire de clarifier un point, à savoir l'ajout du nom de la base de données dans laquelle la requête est exécutée. Il s'agit d'une exigence obligatoire, et il y a au moins deux raisons à cela:


  1. Les bases de données peuvent avoir des tables du même nom, ce qui entraînera une erreur en raison de la duplication des métriques;
  2. Sans cela, vous ne pouvez pas identifier la base de données à laquelle la métrique fait référence, ce qui transformera les données collectées en ordures.

Et donc, nous lançons notre agent avec l'option --extend.query-path (ici le chemin vers le fichier yaml avec la description des métriques est indiqué):


 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 

Nous essayons d'obtenir les métriques (pour plus de clarté, nous ne prenons que pg_statio_user_tables_heap_blks_hit):


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

En conséquence, nous obtenons un ensemble de mesures unique interprété:


 # 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 

En conséquence, nous avons eu l'opportunité, en utilisant l'option --auto-discovery-databases, de collecter des métriques à partir de toutes les bases de données d'une instance du cluster. Un bon bonus est que lorsque vous ajoutez une nouvelle base de données, vous n'avez pas besoin de redémarrer l'agent.
Mais avec tout cela, nous nous sommes retrouvés sans métriques d'instance. Pour le moment, la solution n'est qu'une solution: utiliser différents agents pour collecter des métriques de base de données et d'instance.
Bien sûr, cela n'a pas l'air très bien, mais il est possible de niveler cette nuisance en regroupant les agents pour collecter des métriques à partir de plusieurs instances. Nous considérerons ceci, une autre opportunité plutôt intéressante ci-dessous.


La réponse à l'énigme de la connexion «extra»

Rappelez-vous, au début, nous avons attiré l'attention sur la connexion "extra". C'est donc une fonctionnalité de postgres_exporter avec l'option --auto-discovery-databases.
Mais pourquoi cela peut-il causer beaucoup de problèmes? En fait, tout est simple et déjà décrit ci-dessus, à savoir, le problème est que postgres_exporter collectera deux fois les métriques de la base de données postgres et commencera à dupliquer les métriques. Dans notre cas, seule l'apparence de l'option --exclude-databases peut aider (nous attendons donc avec impatience la prochaine version).
Et oui, si vous avez des tables d'utilisateurs dans la base de données postgres, alors l'exemple ci-dessus ne fonctionnera pas.


Plusieurs instances


Bon, continue. Nous avons compris comment obtenir des métriques à partir de plusieurs bases de données, nous allons maintenant examiner la possibilité de surveiller plusieurs instances avec un seul agent. C'est très simple, pour cela il suffit de les lister dans la variable d'environnement DATA_SOURCE_NAME séparés par une virgule:


 $ 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 

Ici, nous nous connectons à deux instances de cluster différentes fonctionnant, dans notre cas, sur le nœud local. Voici à quoi cela ressemble dans les journaux:


 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" 

Ensuite, nous essayons d'obtenir les métriques (pour plus de clarté, nous nous limitons à la métrique pg_stat_database_blk_read_time):


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

Par conséquent, à partir d'un agent, nous obtenons des mesures pour les deux instances:


 # 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 

Dans ce cas, tout était un peu plus simple que dans le cas de plusieurs bases de données sur une seule instance. Dans le même temps, nous avons toujours la possibilité de recevoir des mesures globales de toutes les instances.


Résumé


Et donc, le troisième cas indiqué aux fins est une combinaison des deux décrits ci-dessus, donc je ne vois aucune raison de l'amener.


En conséquence, ce que nous avons en fin de compte, postgres_exporter, à mon avis, est un outil administrateur plutôt intéressant et prometteur pour surveiller les instances du cluster PostgreSQL et les bases de données déployées dessus. Mais en raison de son âge, ce n'est pas sans défauts qui peuvent être compris et pardonnés.


Les sources


  • Prometheus [ 1 ] est une application open source utilisée pour surveiller et alerter les événements. Il écrit des métriques en temps réel dans une base de données de séries chronologiques construite à l'aide du modèle de requête HTTP, avec des requêtes flexibles et des alertes en temps réel.
  • postgres_exporter est un exportateur de métriques PostgreSQL pour Prometheus.

Version, au moment de la rédaction, v 0.5.1. Versions prises en charge de PostgreSQL 9.4+ (restriction de la version 9.1+ notée dans le code source).

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


All Articles