sql_exporter

repository·master·Indexed 20 days ago

https://github.com/burningalchemist/sql_exporter

A configuration-driven Prometheus exporter that allows users to run arbitrary SQL queries against various DBMSs (such as MySQL, PostgreSQL, and MSSQL) and expose the results as Prometheus metrics. It supports Kubernetes secret resolution for DSNs via the k8ssecret:// URI scheme and provides specific deployment patterns for Azure SQL Managed Instance and Basic Authentication.

Tokens
23.9K
Snippets
72
Records
100
Agent score
69%

What's inside sql_exporter

  1. Overview of SQL Exporter

    master

    SQL Exporter is a configuration-driven tool that gathers metrics from various Database Management Systems (DBMSs) and exposes them for Prometheus to scrape.

    Supported Databases:

    • MySQL
    • PostgreSQL
    • Microsoft SQL Server
    • Oracle Database
    • Clickhouse
    • Snowflake
    • Vertica

    Any DBMS with a compatible Go driver can be supported by rebuilding the binary with that driver included.

    Core Concepts:

    • Collectors: Logical groups of SQL queries (e.g., _query_stats_) mapped to specific Prometheus metrics. Collectors can be DBMS-specific or custom for application-specific data quality monitoring.
    • Scraping Model: Scrapes are synchronous (metrics are collected on every /metrics poll). To manage load, you can set a min_interval per collector to cache metrics if queried more frequently than the interval.
  2. Explore SQL Exporter configuration examples

    master

    The examples/ directory provides reference configurations for different database types and security setups. Use these as templates for your own deployments.

    Database-specific Examples

    • PostgreSQL: Located in postgres/, containing collectors and queries specific to PostgreSQL.
    • Microsoft SQL Server: Located in mssql/, containing collectors for MSSQL.
    • Azure SQL Managed Instance: Located in azure-sql-mi/, which includes configurations for Azure SQL MI and corresponding Grafana dashboards.

    Security and Authentication Examples (Helm)

    These examples demonstrate how to configure the Helm chart for different security requirements:

    • TLS + Basic Auth: See tls-auth/ for a combination of TLS encryption and Basic authentication.
    • TLS Only: See tls-only/ for configurations using TLS encryption with certificates sourced from Kubernetes secrets.
    • Basic Auth Only: See auth-only/ for configurations using Basic authentication with bcrypt password hashing.
  3. Understand the design philosophy of sql_exporter

    master

    Unlike other database-agnostic exporters that collect data at fixed intervals independent of Prometheus, sql_exporter is designed to run collections in response to Prometheus scrapes. This approach helps avoid common issues found in interval-based collectors, such as:

    • Jitter
    • Duplicate data points
    • Collected but not scraped data points

    Additionally, sql_exporter provides better control over label application and avoids the 'spammy' base label sets common in other exporters. It also allows for easier configuration reuse across different jobs and instances.

  4. How Basic Authentication works in SQL Exporter

    master

    The Basic Authentication setup uses an init container pattern to securely handle passwords without storing them in plaintext within the main container's configuration.

    Lifecycle

    1. Init Container: An httpd:alpine init container runs at pod startup.
    2. Password Processing: It reads the plaintext password from the Kubernetes secret and hashes it using htpasswd with the bcrypt algorithm.
    3. Config Generation: It writes a web-config.yml file containing the hashed password to an emptyDir volume.
    4. Main Container: The main container mounts this generated web-config.yml and enforces the authentication on the HTTP metrics endpoint.

    Important Implementation Details

    • Health Probes: Because standard httpGet probes do not support passing authentication headers, health probes must be configured to use tcpSocket.
    • Security Warning: In this specific configuration, passwords are transmitted in plaintext because TLS is not enabled. This should only be used in trusted networks. For production, use the tls-auth-dynamic configuration pattern.
  5. How the TLS + Auth Init Container flow works

    master

    To support secure metrics endpoints in Kubernetes, this setup uses a two-container pattern:

    1. Init Container (sql-exporter-init):

      • Reads the plaintext password from the sql-exporter-tls-auth secret.
      • Hashes the password using bcrypt (default cost: 12).
      • Reads a TLS configuration template.
      • Appends a basic_auth_users section containing the hashed password.
      • Writes the final web-config.yml to an emptyDir volume at /etc/web-config/.
    2. Main Container:

      • Loads SQL configuration from /etc/sql_exporter/sql_exporter.yml.
      • Loads web server configuration (TLS + Basic Auth) from /etc/web-config/web-config.yml.
      • Mounts TLS certificates directly from the /tls volume.

    Note on Health Probes: Because Kubernetes httpGet probes cannot pass authentication headers, the deployment uses tcpSocket probes. This will cause harmless TLS handshake error: EOF messages in the logs, which can be mitigated by setting logLevel to info or warn.

  6. Accessing Cross-Namespace Secrets

    master

    You can reference secrets in different namespaces using the format k8ssecret://namespace/secret-name.

    Warning: Accessing secrets from a different namespace is not recommended for production. The default Helm chart does not provide the necessary ClusterRole permissions for cross-namespace access. To enable this, you must manually create a ClusterRole with secrets: get permissions across all namespaces. It is best practice to store secrets in the same namespace as the SQL Exporter pod.

    config:
      target:
        data_source_name: 'k8ssecret://monitoring/db-secret'
        collectors:
          - collector1
  7. Configure TLS and Basic Authentication security features

    master

    The Helm chart supports securing the metrics endpoint using TLS encryption and Basic Authentication via the webConfig object. The configuration file web-config.yml is automatically placed at /etc/sql_exporter/web-config.yml inside the container.

    Key security features:

    • TLS Encryption: Enable HTTPS by configuring webConfig.tls.secretName (supports TLS 1.3).
    • Basic Authentication: Protect metrics using webConfig.basicAuth.enabled. You can provide bcrypt-hashed passwords directly in webConfig.basicAuth.users, or use an init container to automatically hash plaintext passwords from a Kubernetes secret using webConfig.basicAuth.initFromSecret.enabled.
  8. Enable per-query observability metrics

    master

    When global.enable_query_metrics is set to true, the exporter emits two additional gauges for every configured query. These metrics inherit the same constant labels as up and scrape_duration_seconds (including target in multi-target mode).

    • query_duration_seconds{query="<query_name>"}: Wall-clock time the query took during the most recent scrape, including row scanning. This is emitted even if the query errors.
    • query_rows_returned{query="<query_name>"}: The number of rows returned by the database during the most recent scrape. Errored or skipped rows are not counted.
  9. Deploy MSSQL collector using Helm with `collectorFiles`

    master

    When using the Helm chart, you can embed your collector YAML definitions directly into the collectorFiles field of your configuration. This allows you to manage multiple collector files without mounting them as separate volumes.

    collectorFiles:
      mssql_standard.collector.yml: |
        # Contents of mssql_standard.collector.yml
    
    config:
      target:
        data_source_name: "sqlserver://username:password@hostname:1433?database=master"
      collector_files:
        - "*.collector.yml"
  10. Configure PostgreSQL collectors via Helm Chart

    master

    When using the Helm Chart, you can configure PostgreSQL collectors using two primary methods.

    This method keeps your configuration clean by referencing external collector files. You provide the content of the collector files under the collectorFiles key and then point the config.collector_files to those files using a glob pattern.

    Method 2: Using Static Config

    This method involves defining collectors directly within the main configuration block using inline definitions.

    ### Method 1: Using `collectorFiles` (Recommended)
    
    ```yaml
    collectorFiles:
      postgres_database.yml: |
        # Contents of postgres_database.yml
      postgres_server.yml: |
        # Contents of postgres_server.yml
    
    config:
      target:
        data_source_name: "postgres://username:password@hostname:5432/postgres?sslmode=disable"
      collector_files:
        - "*.collector.yml"

    Method 2: Using Static Config

    config:
      target:
        data_source_name: "postgres://username:password@hostname:5432/postgres?sslmode=disable"
        collectors:
          - pg_database
          - pg_stat_activity
      collectors:
        # Inline collector definitions from postgres_database.yml and postgres_server.yml
  11. Set up PostgreSQL permissions for sql_exporter

    master

    The monitoring user requires specific permissions to access statistics and connection views.

    For PostgreSQL 10+ (Recommended): Grant the pg_monitor role to the user.

    For PostgreSQL 9.6 and earlier: You must grant explicit SELECT access to specific system views (pg_stat_database, pg_stat_activity, and pg_stat_replication).

    -- Create monitoring user
    CREATE USER sql_exporter WITH PASSWORD 'secure_password';
    
    -- Grant connection
    GRANT CONNECT ON DATABASE postgres TO sql_exporter;
    
    -- Grant read access to statistics views
    GRANT pg_monitor TO sql_exporter;  -- PostgreSQL 10+
    
    -- For PostgreSQL 9.6 and earlier:
    GRANT SELECT ON pg_stat_database TO sql_exporter;
    GRANT SELECT ON pg_stat_activity TO sql_exporter;
    GRANT SELECT ON pg_stat_replication TO sql_exporter;