UPD: Der Hinweis hat mit der Veröffentlichung von 0.8.0 seine Relevanz verloren. Alle Neuerungen finden Sie im Artikel: Neue Funktionen von postgres_exporter zur Überwachung von PostgreSQL
Guten Tag, habr Leser!
Prometheus und sein Ökosystem von Exporteuren (Agenten) ist ein gutes Werkzeug für jeden Administrator und Entwickler. Einfache Lieferung, einfache (relative) Einstellungen, die Möglichkeit, den automatischen Erkennungsdienst zu nutzen.
Aber es geht nicht so sehr um Prometheus, sondern um einen der bemerkenswerten Agenten, nämlich postgres_exporter. Sie können damit Metriken mit PostgreSQL erfassen. Aber wenn alles so einfach wäre ...
Leider ist die Dokumentation zu postgres_exporter ziemlich asketisch und betrifft nur allgemeine Fälle. Was aber, wenn Sie eine Instanz eines DBMS-Clusters mit mehreren Datenbanken haben und / oder Metriken für mehrere Instanzen des Clusters gleichzeitig erfassen möchten?
Zweck
Eigentlich über den Zweck des Artikels oder eher Notizen. Ich stelle sofort fest, dass ich hier die Montage- oder Konfigurationsprozesse von Prometheus und postgres_exporter, deren Interaktion, nicht beschreiben werde. All dies ist in der Dokumentation und in vielen anderen Quellen beschrieben.
Ich möchte einige Sonderfälle der Verwendung von postgres_exporter zur Lösung spezifischer Probleme ansprechen, nämlich das Sammeln von Metriken durch einen Agenten mit:
- mehrere Datenbanken in einer Instanz;
- mehrere Exemplare;
- mehrere Datenbanken auf verschiedenen Instanzen.
postgres_exporter
Subjektiv sind die Vor- und Nachteile.
Von den Profis:
- Der erste und wichtige Vorteil ist die einfache Lieferung und Konfiguration des Agenten. Agent - ist eine ausführbare Datei (optional eine Yaml-Datei mit einer Reihe von Benutzermetriken). Dies ist eine eigenständige Anwendung, die für die erforderliche Verteilung und Architektur kompiliert wurde und keine Installation zusätzlicher Pakete auf dem Server erfordert. Der Agent kann sowohl auf demselben Knoten wie die Clusterinstanz als auch auf einem separaten Knoten installiert werden.
- Der Agent stellt als regulärer SQL-Client eine Verbindung zum DBMS her. Es ist möglich, eine Verbindung über inet oder über einen Unix-Socket herzustellen.
- Die Fähigkeit, Metriken von einem Agenten von mehreren Instanzen von Instanzen und / oder von mehreren Datenbanken einer Instanz zu empfangen;
- Metriken werden so oft gesammelt, wie von Prometheus oder einem anderen Sammler angefordert.
- Die Fähigkeit, Metriken mit einer einfachen HTTP-Anfrage zu empfangen;
- Beim automatischen Empfang einer Liste von Datenbanken auf einer einzelnen PostgreSQL-Instanz durch einen Agenten mit der Version postgres_exporter 0.5.0+ wurde die Option --auto-Discover-Databases angezeigt.
Von den Minuspunkten:
- Fehlende Genehmigung;
- Datenübertragung nur über HTTP. Alle Metriken werden im Klartext übertragen. Und das ist schlecht, da ein Angreifer, wenn er abgefangen wird, eine zuverlässige Liste von Datenbanken und Rollen erhalten kann.
- Zwischenspeichert keine Metriken. Wenn beispielsweise der Agent für das Netzwerk nicht verfügbar ist, werden Prometheus keine Daten für den Nichtverfügbarkeitszeitraum empfangen.
- Bei Verwendung der Option --auto-Discover-Databases können bestimmte Datenbanken nicht von der Liste ausgeschlossen werden. Dies ist eher vorübergehend, da in der nächsten Version eine solche Möglichkeit bereits auftreten sollte (Option --exclude-database).
Mehrere Datenbanken in einer Instanz
Nun, lass uns weiter üben. Angenommen, wir haben eine Instanz von PostgreSQL mit mehreren Datenbanken und müssen die Sammlung von Instanzmetriken und allen Datenbanken organisieren.
Warum habe ich die Sammlung von Datenbankmetriken und die Clusterinstanz getrennt? Alles ist sehr einfach. Das Szenario, dass postgres_exporter mit mehreren Datenbanken im selben Cluster arbeitet, impliziert die Ausführung derselben Gruppe von SQL-Abfragen in verschiedenen Datenbanken. Wenn Sie versuchen, Metriken aus den Ansichten pg_stat_replication, pg_stat_activity, pg_stat_statement usw. abzurufen. Da wir dem Cluster gemeinsam sind, erhalten wir nach dem Verständnis von postgres_exporter immer die gleichen Metriken, die zu doppelten Schlüsseln und Werten führen, was zu einem Fehler führt.
Mal sehen, wie es in der Praxis aussieht.
Wir haben eine Testinstanz mit einer Reihe von Datenbanken:
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 |
Wir starten postgres_exporter mit der Option --auto-Discover-Databases (wenn der Datenbankname nicht in der Verbindungszeichenfolge angegeben ist, wird die Verbindung zur Datenbank mit dem Benutzernamen hergestellt):
$ DATA_SOURCE_NAME="postgresql://postgres@127.0.0.1:5432/?sslmode=disable" ./postgres_exporter --auto-discover-databases --log.format=logger:stdout
- DATA_SOURCE_NAME - Umgebungsvariable mit Parametern für die Verbindung zu einer PostgreSQL-Instanz
In der Ausgabe des Agenten sehen wir ein idyllisches Bild, es wird gestartet und konnte eine Verbindung zu allen Datenbanken im Cluster herstellen (obwohl es nicht in welche Datenbanken schreibt, aber hoffentlich wird dies behoben):
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"
Ich denke, ein aufmerksamer Leser wird feststellen, dass der Cluster vier Basen enthält (postgres, dbtest1, dbtest2 und dbtest3, template0 und template1 werden ignoriert), und es gibt fünf Verbindungen. In unserem Fall erstellt postgres_exporter zwei Verbindungen zur postgres-Datenbank. Und mit dieser Funktion müssen Sie sehr vorsichtig sein. Warum? Wir werden dies etwas weiter herausfinden.
Nun, lassen Sie uns fortfahren und versuchen, die Metriken zu erhalten:
$ curl http://localhost:9178/metrics
Infolgedessen erhalten wir in der Ausgabe Warnungen vor Duplikaten, die "zuvor mit demselben Namen und denselben Beschriftungswerten gesammelt wurden" (im Protokoll postgres_exporter werden jedoch keine Warnungen angezeigt):
... * 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 ...
Die einzige Möglichkeit, Fehler zu beseitigen, besteht darin, die Erfassung von Metriken standardmäßig zu deaktivieren. Dazu gibt es zwei Möglichkeiten: Setzen Sie zuerst die Umgebungsvariablen PG_EXPORTER_DISABLE_DEFAULT_METRICS und PG_EXPORTER_DISABLE_SETTINGS_METRICS auf true oder verwenden Sie die Optionen --disable-default -metrics und --disable-settings -metrics
Starten Sie postgres_exporter mit zusätzlichen Optionen neu:
$ 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
Der Versuch, die Metriken zu erhalten:
$ curl http://localhost:9178/metrics
Und so lief alles nach Plan, aber es gibt keine einzige Metrik, die mit PostgreSQL in der Ausgabe verknüpft ist:
# 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
Um die Nutzdaten zu erhalten, müssen wir außerdem eine Datei erstellen, die beschreibt, welche Metriken wir empfangen möchten (nicht vergessen, wir können nur datenbankspezifische Metriken sammeln).
Für den Test werden Metriken aus der Beziehung pg_statio_user_tables erfasst. Erstellen Sie dazu eine queries.yaml-Datei mit folgendem Inhalt:
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"
Ich denke, hier ist es notwendig, einen Punkt zu klären, nämlich das Hinzufügen des Namens der Datenbank, in der die Abfrage ausgeführt wird. Dies ist eine zwingende Voraussetzung, und dafür gibt es mindestens zwei Gründe:
- Datenbanken können Tabellen mit demselben Namen haben, was aufgrund doppelter Metriken zu einem Fehler führt.
- Ohne dies können Sie nicht identifizieren, auf welche Datenbank sich die Metrik bezieht, wodurch die gesammelten Daten in Müll umgewandelt werden.
Und so starten wir unseren Agenten mit der Option --extend.query-path (hier wird der Pfad zur yaml-Datei mit der Beschreibung der Metriken angegeben):
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
Wir versuchen, die Metriken zu erhalten (der Klarheit halber nehmen wir nur pg_statio_user_tables_heap_blks_hit):
curl -s http://localhost:9187/metrics | grep pg_statio_user_tables_heap_blks_hit
Als Ergebnis erhalten wir einen eindeutig interpretierten Satz von Metriken:
# 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
Als Ergebnis hatten wir die Möglichkeit, mithilfe der Option --auto-Discover-Databases Metriken aus allen Datenbanken einer Instanz des Clusters zu erfassen. Ein schöner Bonus ist, dass Sie den Agenten beim Hinzufügen einer neuen Datenbank nicht neu starten müssen.
Bei alledem blieben uns jedoch keine Instanzmetriken. Die Lösung besteht derzeit nur darin, verschiedene Agenten zum Sammeln von Datenbank- und Instanzmetriken zu verwenden.
Natürlich sieht es nicht sehr gut aus, aber es ist möglich, dieses Ärgernis durch Gruppieren von Agenten auszugleichen, um Metriken aus mehreren Instanzen zu sammeln. Wir werden dies als eine weitere, ziemlich interessante Gelegenheit betrachten.
Die Antwort auf das Rätsel der "zusätzlichen" VerbindungDenken Sie daran, dass wir zu Beginn auf die "zusätzliche" Verbindung aufmerksam gemacht haben. Dies ist also eine Funktion von postgres_exporter mit der Option --auto-Discover-Databases.
Aber warum kann das viel Ärger verursachen? Tatsächlich ist alles einfach und bereits oben beschrieben, nämlich das Problem ist, dass postgres_exporter Metriken zweimal aus der Postgres-Datenbank sammelt und beginnt, Metriken zu duplizieren. In unserem Fall kann nur das Erscheinen der Option --exclude-database hilfreich sein (wir freuen uns also auf die nächste Version).
Und ja, wenn Sie Benutzertabellen in der Postgres-Datenbank haben, funktioniert das obige Beispiel nicht.
Mehrere Instanzen
Nun, mach weiter. Wir haben herausgefunden, wie Metriken aus mehreren Datenbanken abgerufen werden. Jetzt werden wir die Option in Betracht ziehen, mehrere Instanzen mit einem Agenten zu überwachen. Es ist sehr einfach, dafür reicht es aus, sie in der Umgebungsvariablen DATA_SOURCE_NAME aufzulisten, die durch ein Komma getrennt ist:
$ 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
Hier stellen wir eine Verbindung zu zwei verschiedenen Clusterinstanzen her, die in unserem Fall auf dem lokalen Knoten ausgeführt werden. So sieht es in den Protokollen aus:
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"
Als Nächstes versuchen wir, die Metriken abzurufen (aus Gründen der Übersichtlichkeit beschränken wir uns auf die Metrik pg_stat_database_blk_read_time):
curl -s http://localhost:9187/metrics | grep pg_stat_database_blk_read_time
Als Ergebnis erhalten wir von einem Agenten Metriken für beide Instanzen:
# 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
In diesem Fall war alles etwas einfacher als bei mehreren Datenbanken in einer Instanz. Gleichzeitig haben wir weiterhin die Möglichkeit, globale Metriken von allen Instanzen zu erhalten.
Zusammenfassung
Und so ist der dritte Fall, der für die Zwecke angegeben wird, eine Kombination der beiden oben beschriebenen, daher sehe ich keinen Grund, ihn zu bringen.
Infolgedessen ist postgres_exporter meiner Meinung nach ein ziemlich interessantes und vielversprechendes Administrator-Tool zur Überwachung von Instanzen des PostgreSQL-Clusters und der darauf bereitgestellten Datenbanken. Aber aufgrund seines Alters ist es nicht ohne Mängel, die verstanden und vergeben werden können.
Quellen
- Prometheus [ 1 ] ist eine Open-Source-Anwendung zur Überwachung und Warnung von Ereignissen. Es schreibt Echtzeitmetriken in eine Zeitreihendatenbank, die unter Verwendung des HTTP-Anforderungsmodells erstellt wurde, mit flexiblen Abfragen und Echtzeitwarnungen.
- postgres_exporter ist ein Exporteur von PostgreSQL-Metriken für Prometheus.
Version zum Zeitpunkt des Schreibens, v 0.5.1. Unterstützte Versionen von PostgreSQL 9.4+ (Einschränkung der Version 9.1+ im Quellcode angegeben).