Oracle Cloud Infrastructure Database mit PostgreSQL mit Prometheus und Grafana überwachen

Einführung

PostgreSQL ist eine der beliebtesten Datenbanken unter Anwendungsentwicklern. Neben der Eliminierung der Verwaltungsgemeinkosten, die Oracle Cloud Infrastructure Database mit PostgreSQL (OCI Database with PostgreSQL) bietet, geht es auch noch einen Schritt weiter, wenn es darum geht, eine einfache Überwachung zu implementieren. Prometheus und Grafana sind ein sehr beliebtes Paar, wenn es darum geht, die Anwendungsleistung für die Datenspeicherung und Visualisierung der Zeitreihen zu überwachen.

In diesem Tutorial zeigen wir, wie Sie eine OCI Database with PostgreSQL überwachen, indem Sie Metriken auf Abfrageebene mit dem PostgreSQL-Exporteur extrahieren, mit Prometheus auswerten, in Grafana visualisieren und Alerts für Bloat-Metriken einrichten.

Architektur - Überblick

Das folgende Schema zeigt den Gesamtansatz. Folgende Komponenten werden verwendet:

Architekturansicht

Hinweis: Während die Architektur aus Gründen der Übersichtlichkeit drei Subnetze anzeigt, verwendet dieses Tutorial nur zwei, und der Sprunghost ist auch die VM, mit der Prometheus und Grafana bereitgestellt werden.

Ziele

Voraussetzungen

Aufgabe 1: Monitoringerweiterungen in OCI Database with PostgreSQL aktivieren

  1. Aktivieren Sie die Erweiterung pg_stat_statements.

    Fügen Sie über die OCI-Konsole pg_stat_statements zu den OCI Database with PostgreSQL-Konfigurationen hinzu. Weitere Informationen finden Sie unter Erweiterungen für eine Datenbank aktivieren.

  2. Monitoringbenutzer erstellen.

    Führen Sie die folgenden Abfragen aus, um den Benutzer mit DBeaver über den Jump-Host zu erstellen und zu verbinden.

    CREATE USER postgres_exporter WITH PASSWORD '<password>';
    GRANT CONNECT ON DATABASE postgres TO postgres_exporter;
    GRANT pg_monitor TO postgres_exporter;
    

    Hinweis: Die Erweiterung pg_stat_io ist ab OCI Database with PostgreSQL v16 verfügbar.

Aufgabe 2: PostgreSQL Exporter für Prometheus installieren

Hinweis: Führen Sie die folgenden Befehle auf Ihrer OCI Compute-Instanz aus.

  1. Installieren Sie PostgreSQL Exporter.

    wget https://github.com/prometheus-community/postgres_exporter/releases/download/v0.15.0/postgres_exporter-0.15.0.linux-amd64.tar.gz
    
    tar -xvf postgres_exporter-0.15.0.linux-amd64.tar.gz
    
    sudo mv postgres_exporter-0.15.0.linux-amd64/postgres_exporter /usr/local/bin/
    
  2. Erstellen Sie ein benutzerdefiniertes queries.yaml.

    nano queries.yaml
    
    # Custom PostgreSQL Query Metrics for Postgres Exporter
    
    # Top 5 slowest SQL statements
    top_sql_statements:
    query: >
    	SELECT query, calls, total_exec_time + total_plan_time AS total_time
    	FROM pg_stat_statements
    	ORDER BY total_time DESC
    	LIMIT 5;
    metrics:
    	- query:
    		usage: "LABEL"
    		description: "SQL query text"
    	- calls:
    		usage: "COUNTER"
    		description: "Number of executions"
    	- total_time:
    		usage: "GAUGE"
    		description: "Total execution + plan time"
    
    # 2. Top users by total execution time
    top_sql_users:
    query: >
    	SELECT usename, SUM(total_exec_time + total_plan_time) AS total_exec_time
    	FROM pg_stat_statements
    	JOIN pg_user ON pg_stat_statements.userid = pg_user.usesysid
    	GROUP BY usename
    	ORDER BY total_exec_time DESC
    	LIMIT 5;
    metrics:
    	- usename:
    		usage: "LABEL"
    		description: "PostgreSQL user"
    	- total_exec_time:
    		usage: "GAUGE"
    		description: "Total execution time by user"
    
    # 3. Top client IPs by connection count
    top_clients:
    query: >
    	SELECT client_addr, COUNT(*) AS connections
    	FROM pg_stat_activity
    	WHERE client_addr IS NOT NULL
    	GROUP BY client_addr
    	ORDER BY connections DESC
    	LIMIT 5;
    metrics:
    	- client_addr:
    		usage: "LABEL"
    		description: "Client IP address"
    	- connections:
    		usage: "GAUGE"
    		description: "Number of active connections"
    
    # 4. Currently running queries by user and IP
    active_queries_by_user_ip:
    query: >
    	SELECT usename, client_addr, COUNT(*) as active_queries
    	FROM pg_stat_activity
    	WHERE state = 'active'
    	GROUP BY usename, client_addr;
    metrics:
    	- usename:
    		usage: "LABEL"
    		description: "User running queries"
    	- client_addr:
    		usage: "LABEL"
    		description: "Client IP address"
    	- active_queries:
    		usage: "GAUGE"
    		description: "Number of currently active queries"
    
    # 5. Query frequency (most called)
    frequent_sql:
    query: >
    	SELECT query, calls
    	FROM pg_stat_statements
    	ORDER BY calls DESC
    	LIMIT 5;
    metrics:
    	- query:
    		usage: "LABEL"
    		description: "SQL query text"
    	- calls:
    		usage: "COUNTER"
    		description: "Number of executions"
    
    # 6. Table bloat statistics
    table_bloat:
    query: >
    	SELECT
    	current_database() AS current_db,
    	schemaname AS schema_name,
    	tblname AS table_name,
    	(bs * tblpages) / 1024 AS actual_table_size_kb,
    	((tblpages - est_tblpages) * bs) / 1024 AS wasted_space_kb,
    	CASE
    		WHEN tblpages > 0 AND tblpages - est_tblpages > 0 THEN 100 * (tblpages - est_tblpages) / tblpages::float
    		ELSE 0
    	END AS wasted_space_percent,
    	fillfactor AS table_fill_factor,
    	CASE
    		WHEN tblpages - est_tblpages_ff > 0 THEN (tblpages - est_tblpages_ff) * bs / 1024
    		ELSE 0
    	END AS bloat_size_kb,
    	CASE
    		WHEN tblpages > 0 AND tblpages - est_tblpages_ff > 0 THEN 100 * (tblpages - est_tblpages_ff) / tblpages::float
    		ELSE 0
    	END AS bloat_size_percent
    	FROM (
    	SELECT
    		ceil(reltuples / ((bs - page_hdr) / tpl_size)) + ceil(toasttuples / 4) AS est_tblpages,
    		ceil(reltuples / ((bs - page_hdr) * fillfactor / (tpl_size * 100))) + ceil(toasttuples / 4) AS est_tblpages_ff,
    		tblpages,
    		fillfactor,
    		bs,
    		schemaname,
    		tblname
    	FROM (
    		SELECT
    		(4 + tpl_hdr_size + tpl_data_size + (2 * ma)
    		- CASE WHEN tpl_hdr_size % ma = 0 THEN ma ELSE tpl_hdr_size % ma END
    		- CASE WHEN ceil(tpl_data_size)::int % ma = 0 THEN ma ELSE ceil(tpl_data_size)::int % ma END
    		) AS tpl_size,
    		(heappages + toastpages) AS tblpages,
    		reltuples,
    		toasttuples,
    		bs,
    		page_hdr,
    		schemaname,
    		tblname,
    		fillfactor,
    		ma,
    		tpl_hdr_size,
    		tpl_data_size
    		FROM (
    		SELECT
    			ns.nspname AS schemaname,
    			tbl.relname AS tblname,
    			tbl.reltuples,
    			tbl.relpages AS heappages,
    			COALESCE(toast.relpages, 0) AS toastpages,
    			COALESCE(toast.reltuples, 0) AS toasttuples,
    			COALESCE(substring(array_to_string(tbl.reloptions, ' ') FROM 'fillfactor=([0-9]+)')::smallint, 100) AS fillfactor,
    			current_setting('block_size')::numeric AS bs,
    			CASE
    			WHEN version() ~ 'mingw32|64-bit|x86_64|ppc64|ia64|amd64' THEN 8
    			ELSE 4
    			END AS ma,
    			24 AS page_hdr,
    			23 +
    			CASE WHEN MAX(COALESCE(s.null_frac, 0)) > 0 THEN (7 + count(s.attname)) / 8 ELSE 0 END +
    			CASE WHEN bool_or(att.attname = 'oid' AND att.attnum < 0) THEN 4 ELSE 0 END AS tpl_hdr_size,
    			SUM((1 - COALESCE(s.null_frac, 0)) * COALESCE(s.avg_width, 0)) AS tpl_data_size
    		FROM pg_attribute AS att
    		JOIN pg_class AS tbl ON att.attrelid = tbl.oid
    		JOIN pg_namespace AS ns ON ns.oid = tbl.relnamespace
    		LEFT JOIN pg_stats AS s ON s.schemaname = ns.nspname AND s.tablename = tbl.relname AND s.attname = att.attname
    		LEFT JOIN pg_class AS toast ON tbl.reltoastrelid = toast.oid
    		WHERE NOT att.attisdropped
    			AND tbl.relkind IN ('r', 'm')
    		GROUP BY 1, 2, 3, 4, 5, 6, 7, 8, 9
    		) AS inner_subquery
    	) AS mid_subquery
    	) AS bloat_subquery
    	WHERE schemaname = 'public'
    	ORDER BY schema_name, table_name;
    metrics:
    	- schema_name:
    		usage: "LABEL"
    		description: "Schema name"
    	- table_name:
    		usage: "LABEL"
    		description: "Table name"
    	- bloat_size_kb:
    		usage: "GAUGE"
    		description: "Bloat size in KB"
    	- bloat_size_percent:
    		usage: "GAUGE"
    		description: "Bloat size as a percentage"
    
  3. Umgebungsvariable für die Datenquelle festlegen.

    export DATA_SOURCE_NAME="postgresql://postgres_exporter:<password>@<POSTGRES_HOST>:5432/postgres?sslmode=require"
    

    Hinweis: <POSTGRES_HOST> ist der primäre Endpunkt-FQDN. Sie finden sie auf der Seite mit den Clusterdetails PostgreSQL in der OCI-Konsole.

  4. Starten Sie den PostgreSQL Exporter.

    Führen Sie den PostgreSQL Exporter mit der benutzerdefinierten Datei queries.yaml mit dem folgenden Befehl aus. Dadurch wird der Exporteur an Port 9187 gestartet, und die Ausgabe wird in exporter.log protokolliert.

    nohup /usr/local/bin/postgres_exporter --extend.query-path=/home/opc/queries.yaml --web.listen-address=":9187" > exporter.log 2>&1 &
    

    Hinweis: Damit die Vorgänge nach dem Neustart weiterhin ausgeführt werden, sollten Sie den Service mit systemd einrichten.

  5. Exporteur prüfen.

    curl http://localhost:9187/metrics
    

Aufgabe 3: Prometheus installieren und konfigurieren

  1. Installieren Sie Prometheus.

    wget https://github.com/prometheus/prometheus/releases/download/v2.52.0/prometheus-2.52.0.linux-amd64.tar.gz
    
    tar -xvf prometheus-2.52.0.linux-amd64.tar.gz
    
    sudo mv prometheus-2.52.0.linux-amd64/prometheus /usr/local/bin/
    sudo mv prometheus-2.52.0.linux-amd64/promtool /usr/local/bin/
    
  2. Prometheus-Konfiguration erstellen.

    Erstellen Sie die Datei /etc/prometheus/prometheus.yml mit dem folgenden Inhalt.

    global:
    scrape_interval: 15s
    
    scrape_configs:
    - job_name: 'postgres_exporter'
    	static_configs:
    	- targets: ['127.0.0.1:9187']
    
  3. Prometheus starten.

    nohup prometheus --config.file=/etc/prometheus/prometheus.yml > prometheus.log 2>&1 &
    

    Hinweis: Damit die Vorgänge nach dem Neustart weiterhin ausgeführt werden, sollten Sie den Service mit systemd einrichten.

  4. Ziele prüfen.

    Besuchen Sie hier: http://<instance_ip>:9090/targets.

    Prometheus-Dashboard

Aufgabe 4: Grafana installieren und konfigurieren

  1. Grafana installieren.

    sudo yum install -y https://dl.grafana.com/oss/release/grafana-10.4.2-1.x86_64.rpm
    sudo systemctl enable grafana-server
    sudo systemctl start grafana-server
    
  2. Melden Sie sich bei Grafana an.

    Gehen Sie zur folgenden URL: http://<instance_ip>:3000, und geben Sie Username als admin und Password als admin ein.

  3. Datenquelle in Grafana hinzufügen.

    1. Gehen Sie zu Verbindungen, Datenquellen, und klicken Sie auf Datenquelle hinzufügen.

    2. Wählen Sie Prometheus aus.

    3. Geben Sie URL als http://localhost:9090 ein.

    Datenquelle wird hinzugefügt

  4. PostgreSQL-Dashboard importieren.

    1. Wählen Sie Dashboard importieren aus.

    2. Importieren Sie die Dashboard-ID 9628 aus Grafana-Dashboards.

    Postgrate importieren

Aufgabe 5: OCI Database with PostgreSQL-Metriken in Grafana kennenlernen

Die folgenden Bilder zeigen die endgültigen Dashboards.

Dashboard-Beispiel

Dashboard-Beispiel

Aufgabe 6: Alert für OCI Database with PostgreSQL Bloat-Metriken in Grafana einrichten

  1. Bloat-Metrik erfassen.

    • Eine benutzerdefinierte SQL-Abfrage wurde verwendet, um die Tabellenblüte basierend auf PostgreSQL-Systemkatalogansichten wie pg_class, pg_namespace, pg_attribute und pg_stats zu schätzen.

    • Diese Abfrage wurde als benutzerdefinierte Metrik über einen PostgreSQL-Exporter bereitgestellt, indem sie der Datei queries.yaml hinzugefügt wurde, wie in Aufgabe 2.2 gezeigt, und anschließend von Prometheus als Scraping verwendet wurde.

  2. Alertregel konfigurieren.

    1. Navigieren Sie zu Alerting, und klicken Sie in Grafana auf Alertregeln.

    2. Klicken Sie auf + Neue Alert-Regel.

      Neue Alertregel

    3. Geben Sie einen Namen für die Alertregel an.

    4. Wählen Sie Prometheus als Datenquelle aus.

    5. Geben Sie im Abschnitt Abfrage- und Alertbedingung definieren die folgenden Informationen ein.

      • Suchen Sie nach der Metrik table_bloat_bloat_size_percent.

      • Geben Sie im Builder für die Alertbedingung die folgenden Informationen ein.

        • Eingabe festlegen: Wählen Sie A aus.

        • Bedingung: Wählen Sie IS ABOVE 30 aus.

        Hinweis: Sie können auf Vorschau klicken, um zu prüfen, ob der Alert unter aktuellen Bedingungen ausgelöst wird.

        Define_query

    6. Geben Sie im Abschnitt Bewertungsverhalten festlegen die folgenden Informationen ein.

      1. Klicken Sie auf + Neue Bewertungsgruppe.

      2. Auswertungsgruppe: Geben Sie postgres-bloat-alerts ein.

      3. Auswertungsintervall: Wählen Sie 5m aus (dadurch wird definiert, wie oft Grafana die Alertregel auswertet).

      4. Ausstehender Zeitraum: Setzen Sie diesen Wert auf 5m (der Alert muss 5 Minuten lang gültig bleiben, bevor er ausgelöst wird). Dies sollte gleich oder länger als das Auswertungsintervall sein).

    7. Klicken Sie auf Regel speichern, und beenden, um den Alert zu aktivieren.

      Bewertungsverhalten

      Bewertungsgruppe

  3. Konfigurieren Sie E-Mail-Alerting über SMTP (Gmail).

    Um E-Mail-Benachrichtigungen für Alerts in Grafana zu aktivieren, konfigurieren Sie den Abschnitt smtp der Datei grafana.ini.

    1. Bearbeiten Sie die Grafana-Konfigurationsdatei in der OCI Compute-Instanz, in der Sie Grafana installiert haben.

      sudo nano /etc/grafana/grafana.ini
      
    2. Entfernen Sie die Kommentarzeichen, und aktualisieren Sie den Abschnitt smtp mit dem folgenden Inhalt.

      [smtp]
      enabled = true
      host = smtp.gmail.com:587
      user = your_email@gmail.com
      password = ***************
      skip_verify = true
      from_address = your_email@gmail.com
      from_name = Grafana
      ehlo_identity = localhost
      startTLS_policy = OpportunisticStartTLS
      enable_tracing = false
      

      Hinweis: Um Gmail zu verwenden, müssen Sie die 2-Schritt-Verifizierung aktivieren und ein App-Kennwort aus Ihren Google-Kontoeinstellungen generieren. Verwenden Sie Ihr normales Gmail-Passwort nicht.

    3. Starten Sie nach dem Speichern der Konfiguration Grafana neu, um die Änderungen mit dem folgenden Befehl anzuwenden.

      sudo systemctl restart grafana-server
      
  4. Kommunikation für Alertbenachrichtigungen einrichten.

    Kontaktpunkte definieren, wo und wie Grafana Alerts sendet, wenn eine Regel ausgelöst wird, z.B. E-Mail, Slack, Webhook usw.

    1. Navigieren Sie zu Alerting, und klicken Sie in Grafana auf Kontaktpunkte.

    2. Klicken Sie auf + Neue Kontaktmöglichkeit, um eine zu erstellen, oder wählen Sie eine vorhandene Kontaktmöglichkeit aus, und bearbeiten Sie sie.

    3. Geben Sie die folgenden Informationen ein, um eine E-Mail-Kommunikation zu konfigurieren.

      • Name: Geben Sie den Namen der Kontaktmöglichkeit ein (Beispiel: grafana-default-email).

      • Integration: Wählen Sie E-Mail aus.

      • Adressen: Geben Sie eine oder mehrere E-Mail-Adressen ein.

    4. Klicken Sie auf Testen, um die E-Mail-Zustellung zu prüfen.

    5. Klicken Sie auf Kontaktmöglichkeit speichern.

    Kontaktpunkte

  5. Benachrichtigungs-Policy konfigurieren

    Benachrichtigungs-Policys in Grafana steuern, wie und wann Alerts an Kontaktpunkte weitergeleitet werden. Nachdem Sie eine Kontaktmöglichkeit eingerichtet haben, müssen Sie eine Benachrichtigungs-Policy erstellen, um Alerts mit dieser Kontaktmöglichkeit zu verbinden.

    1. Navigieren Sie zu Alerting, und klicken Sie in Grafana auf Benachrichtigungs-Policys.

    2. Klicken Sie in der Standard-Policy auf Bearbeiten oder auf + Neue Policy.

    3. Wählen Sie unter Standardkontaktmöglichkeit Ihren Kontakt aus (grafana-default-email).

    4. Unter Gruppieren nach können Sie Alerts basierend auf Labelwerten gruppieren, wie:

      • grafana_folder

      • alertname

    5. Klicken Sie auf Timing-Optionen, und geben Sie die folgenden Informationen an.

      • Gruppenwartezeit: Wählen Sie 30s aus. Dies ist die Zeit, die gewartet werden muss, bevor der erste Alert in einer Gruppe gesendet wird.

      • Gruppenintervall: Wählen Sie 5m aus. Dies ist die Zeit zwischen Batches gruppierter Alerts.

      • Wiederholungsintervall: Wählen Sie 30m aus. Dies ist die Zeit, nach der der derselbe Alert erneut gesendet wird, wenn er noch ausgelöst wird.

    6. Klicken Sie zum Speichern auf Standard-Policy aktualisieren.

    Benachrichtigungs-Policy

  6. Alert auslösen und prüfen.

    1. Simulieren Sie einen Schwellenwertverstoß (optional).

      Zum Testen von Alert-Triggern können Sie:

      • Verringern Sie den Alertschwellenwert vorübergehend (Beispiel: bloat_size_percent > 0).

        oder

      • Führen Sie Blähungen durch, indem Sie wiederholte UPDATE- oder DELETE-Vorgänge an einer großen Testtabelle durchführen.

    2. Warten Sie auf die Bewertung.

      Grafana prüft Alert-Bedingungen in Ihrem definierten Auswertungsintervall (z.B. alle 5 Minuten). Wenn die Bedingung für den ausstehenden Zeitraum wahr ist (z.B. 5 Minuten), wird der Alert ausgelöst.

    3. Email Delivery Check.

      Beim Auslösen wird der Alert über den konfigurierten SMTP-Kontaktpunkt (z.B. Gmail) gesendet. Prüfen Sie den Posteingang der Empfängeradresse auf eine Benachrichtigungs-E-Mail von Grafana.

      E-Mail-Alert

    4. Grafana-UI-Feedback.

      Navigieren Sie zu Alerting, und klicken Sie auf Alertregeln, um den Alertstatus anzuzeigen. Statusindikatoren wie Auslösend werden auf der Seite Alertregeln angezeigt.

      E-Mail-Alert

Bestätigungen

Weitere Lernressourcen

Sehen Sie sich weitere Übungen zu docs.oracle.com/learn an, oder greifen Sie auf weitere kostenlose Lerninhalte im Oracle Learning YouTube-Kanal zu. Besuchen Sie außerdem education.oracle.com/learning-explorer, um ein Oracle Learning Explorer zu werden.

Die Produktdokumentation finden Sie im Oracle Help Center.