Aller au contenu

Configuration de check_postgres avec Nagios

Introduction

Ce document présente la configuration de Nagios pour la supervision de serveurs PostgreSQL en réplication.

Liste des sondes

La supervision d’un serveur PostgreSQL passe par la surveillance de sa disponibilité, des indicateurs sur son activité, l’identification des besoins de maintenance, et le suivi de la réplication le cas échéant. Voici les sondes check_postgres à mettre en place sur ces différents aspects.

Disponibilité :

  • connection : réalise un test de connexion pour vérifier que le serveur est accessible.
  • backends : compte le nombre de connexions au serveur comparé au paramètre max_connections.

Vacuum :

  • autovac_freeze : vérifie l’âge des bases de données par rapport au nombre de transactions, cela permet de prédire le déclenchement de l’autovacuum en mode freeze.
  • txn_wraparound : vérifie si l’âge des bases de données est proche d’une valeur qui provoquerait un bouclage des identifiants de transaction.
  • bloat : vérifie le volume de données « mortes » et la fragmentation des tables et des index.
  • last_analyze : vérifie si le dernier analyze (relevé des statistiques relatives aux calculs des plans d’exécution) est trop ancien.
  • last_vacuum : vérifie si le dernier vacuum (relevé des espaces réutilisables dans les tables) est trop ancien.

Activité :

  • locks : vérifie le nombre de verrous ;
  • lockwait : vérifie l’absence de blocages (en attente de verrous) ;
  • wal_files : compte le nombre de segments du journal de transaction présents dans le répertoire pg_wal ;
  • query_time : identifie les requêtes en cours d’exécution depuis trop longtemps.

Configuration :

  • settings_checksum : indique si la configuration a été modifiée depuis la dernière vérification.

Réplication :

  • archive_ready : compte le nombre de segments du journal de transaction en attente d’archivage.
  • hot_standby_delay : calcule le délai de réplication entre un primaire et un secondaire.

Principes

Pour la supervision de PostgreSQL avec Nagios, le programme utilisé est check_postgres.pl. Il s’agit d’un script Perl qui fournit un ensemble de sondes pour surveiller une instance de PostgreSQL.

Il y a deux possibilités d’utilisation de check_postgres.pl. On peut soit l’installer sur le serveur PostgreSQL et l’exécuter à travers une connexion SSH, soit l’installer sur la machine hébergeant Nagios, la connexion à PostgreSQL se fait alors par le réseau :

  • Dans le premier cas, il faut configurer un accès SSH à la machine pour y exécuter des commandes en mode batch. Il faut pour cela créer une paire de clés SSH sans passphrase pour éviter la demande de mot de passe. Il faut donc disposer d’un client SSH pour le lancement des commandes depuis la machine de supervision.
  • Dans le second cas, il faut disposer de Perl et du client PostgreSQL en ligne de commande psql sur le serveur nagios, qui est utilisé par check_postgres pour obtenir les informations du serveur PostgreSQL.

check_postgres.pl doit pouvoir se connecter au serveur PostgreSQL, on doit donc connaître les informations de connexion : nom d’hôte ou adresse IP, port TCP, utilisateur. Le mot de passe est stocké dans le fichier $HOME/.pgpass de l’utilisateur Unix exécutant check_postgres. La connexion doit être autorisée par la configuration du fichier $PGDATA/pg_hba.conf de l’instance. Enfin, une action doit être indiquée à check_postgres, l’action correspondant à la sonde à exécuter.

Installation et configuration système

La dernière version de check_postgres est à télécharger à cette URL : https://bucardo.org/check_postgres/

Connexion directe

Pour lancer check_postgres depuis la machine de supervision, il faut y installer check_postgres.pl dans un répertoire accessible par l’utilisateur système qui lance les commandes Nagios, l’idéal étant de le placer dans le répertoire correspondant à la macro $USER1$. Lancer le programme sans options pour vérifier si des dépendances ne sont pas nécessaires au niveau Perl.

Connexion via SSH

Pour lancer check_postgres à travers une connexion SSH, il faut :

  • Créer un utilisateur dédié sur chaque machine PostgreSQL à superviser
  • Installer check_postgres dans un répertoire accessible par cet utilisateur, il doit être dans le PATH.
  • Créer une paire de clés SSH pour l’utilisateur système qui lance les commandes Nagios sur le serveur de supervision, sans passphrase.
  • Ajouter la clé publique SSH, contenue dans $HOME/.ssh/id_rsa.pub de cet utilisateur dans le fichier $HOME/.ssh/authorized_keys de l’utilisateur dédié sur chacune des machines PostgreSQL
  • Tenter la connexion au moins une fois pour accepter la clé SSH de chaque machine (Host key) PostgreSQL

Configuration de PostgreSQL

L’accès aux serveurs PostgreSQL pour la supervision doit se faire par l’intermédiaire d’un superutilisateur de l’instance. Ceci est nécessaire pour la réalisation de certaines actions. Dans la procédure qui suit, x.y.z.t est à remplacer par l’adresse IP de la machine de supervision.

CREATE ROLE nagios SUPERUSER LOGIN PASSWORD 'Eiko5s';
host   all   nagios   x.y.z.t/32   md5
  • Recharger la configuration par un « reload » du service
host:port:nagios:postgres:Eiko5s

Test de connexion

Connexion directe

Pour valider le fonctionnement correct de check_postgres, adapter et lancer la commande suivante depuis la machine de supervision, avec l’utilisateur qui lance les commandes Nagios :

sudo -u nagios_user /chemin/vers/check_postgres.pl --action=connection --host=machine_postgres --port=5432 --dbuser=nagios --perflimit=0 --showtime=0

Un résultat équivalent à celui-ci doit être affiché :

POSTGRES_CONNECTION OK: DB "postgres" (host:machine_postgres) version 9.0.5

Connexion via SSH

Nagios fournit un plugin pour exécuter des commandes par l’intermédiaire de SSH, il s’agit de check_by_ssh, pour tester la connexion au serveur PostgreSQL comme le ferait Nagios, adapter et lancer la commande suivante :

sudo -u utilisateur_nagios /chemin/vers/check_by_ssh -l utilisateur_distant -H hote_distant -C "check_postgres.pl --action=connection --host=machine_postgresql --port=5432 --dbuser=nagios --perflimit=0 --showtime=0"

Comme l’accès direct, cette commande doit afficher un résultat similaire à :

POSTGRES_CONNECTION OK: DB "postgres" (host:machine_postgres) version 9.0.5

Configuration de Nagios

La configuration de Nagios passe par plusieurs étapes. Il faut d’abord créer les commandes (blocs « command ») pour indiquer comment lancer check_postgres, puis définir des services correspondants à chacune des sondes à lancer, définir des groupes d’hôtes pour regrouper les sondes PostgreSQL et enfin configurer les hôtes pour leur ajouter ces groupes et les options particulières pour les sondes.

Selon la configuration de Nagios, les fichiers de configuration définis dans les paragraphes suivants doivent être créés dans un répertoire identifié par une directive cfg_dir où leur chemin doit être déclaré avec des directives cfg_file dans le fichier de configuration principal (nagios.cfg).

Pour factoriser une partie de la configuration, Nagios offre la possibilité de définir des variables (ou macro) au niveau des hôtes, utilisables dans les déclaration de services.

Déclaration des commandes

Connexion directe

define command {
  command_name  check_postgres_autovac_freeze
  command_line  $USER1$/check_postgres.pl --language=en --showtime=0 -H $HOSTADDRESS$ -p $ARG1$ -u $ARG2$ --action=autovac_freeze $ARG3$
}

define command {
  command_name  check_postgres_backends
  command_line  $USER1$/check_postgres.pl --language=en --showtime=0 -H $HOSTADDRESS$ -p $ARG1$ -u $ARG2$ --action=backends
}

# Une commande par base
define command {
  command_name  check_postgres_bloat
  command_line  $USER1$/check_postgres.pl --language=en --showtime=0 -H $HOSTADDRESS$ -p $ARG1$ -u $ARG2$ -db $ARG3$ --action=bloat $ARG4$
}

define command {
  command_name  check_postgres_connection
  command_line  $USER1$/check_postgres.pl --language=en --showtime=0 -H $HOSTADDRESS$ -p $ARG1$ -u $ARG2$ --action=connection
}

# donner les listes des bases
define command {
  command_name  check_postgres_last_analyze
  command_line  $USER1$/check_postgres.pl --language=en --showtime=0 -H $HOSTADDRESS$ -p $ARG1$ -u $ARG2$ -db $ARG3$ --action=last_analyze $ARG4$
}

# donner les listes des bases
define command {
  command_name  check_postgres_last_vacuum
  command_line  $USER1$/check_postgres.pl --language=en --showtime=0 -H $HOSTADDRESS$ -p $ARG1$ -u $ARG2$ -db $ARG3$ --action=last_vacuum $ARG4$
}

# donner les listes des bases
define command {
  command_name  check_postgres_locks
  command_line  $USER1$/check_postgres.pl --language=en --showtime=0 -H $HOSTADDRESS$ -p $ARG1$ -u $ARG2$ -db $ARG3$ --action=locks $ARG4$
}

define command {
  command_name    check_postgres_query_time
  command_line    $USER1$/check_postgres.pl --language=en --showtime=0 -H $HOSTADDRESS$ -p $ARG1$ -u $ARG2$ -db postgres --action=query_time $ARG3$
}

define command {
  command_name  check_postgres_settings_checksum
  command_line  $USER1$/check_postgres.pl --language=en --showtime=0 -H $HOSTADDRESS$ -p $ARG1$ -u $ARG2$ -db postgres --action settings_checksum -w $ARG3$
}

define command {
  command_name  check_postgres_txn_wraparound
  command_line  $USER1$/check_postgres.pl --language=en --showtime=0 -H $HOSTADDRESS$ -p $ARG1$ -u $ARG2$ -db postgres --action txn_wraparound
}

define command {
  command_name  check_postgres_wal_files
  command_line  $USER1$/check_postgres.pl --language=en --showtime=0 -H $HOSTADDRESS$ -p $ARG1$ -u $ARG2$ -db postgres --action=wal_files $ARG2$
}

define command {
  command_name  check_postgres_archive_ready
  command_line  $USER1$/check_postgres.pl --language=en --showtime=0 -H $HOSTADDRESS$ -p $ARG1$ -u $ARG2$ -db postgres --action=archive_ready -w $ARG2$ -c $ARG3$
}

define command {
  command_name  check_postgres_hot_standby_delay
  command_line  $USER1$/check_postgres.pl --language=en --showtime=0 -H $HOSTADDRESS$ -H2 $ARG3$ -p $ARG1$ -p2 $ARG4$ -u $ARG2$ -u2 $ARG5$ -db postgres -db2 postgres --action=hot_standby_delay $ARG6$
}

Connexion via SSH

Pour l’utilisation de check_postgres à travers une connexion SSH, les appels au script sont identiques. Par contre, toutes les lignes de commandes doivent être lancés par le plugin check_by_ssh fourni par Nagios, selon le patron suivant :

define command {
  command_name  check_postgres_archive_ready
  command_line  $USER1$/check_by_ssh -t 60 -l $_HOSTSSH_USER$ -H $HOSTADDRESS$ -p $_HOSTSSH_PORT$ -C "<commande check_postgres.pl>"
}

Déclaration des services

Pour chaque commande, un service est déclaré. L’ensemble des services relatifs à la supervision des serveurs PostgreSQL est regroupé dans deux groupes d’hôtes, un groupe pour le serveur maître, le second pour le serveur standby.

Pour faciliter la configuration, un service père est utilisé, dérivé de generic-service, et contient les définitions suivantes :

define service {
  name                   postgresql-service
  use                    generic-service
  register               0
  max_check_attempts     4
  check_interval         5
  retry_interval         3
  check_period           24x7
  notification_interval  0
  notification_period    24x7
  contacts               contacts
  contact_groups         contact_groups
}

Ensuite, chaque commande est définie de la façon suivante :

define service {
  use                  postgresql-service
  service_description  PGSQL - Autovacuum freeze
  hostgroup_name       postgresql-servers
  check_command        check_postgres_autovac_freeze!$_HOSTOPTIONS_PGPORT$!$_HOSTOPTIONS_PGUSER$!$_HOSTOPTIONS_FREEZE$
}

define service {
  use                  postgresql-service
  service_description  PGSQL - Connections
  hostgroup_name       postgresql-servers,postgresql-servers-standby
  check_command        check_postgres_backends!$_HOSTOPTIONS_PGPORT$!$_HOSTOPTIONS_PGUSER$
}

define service {
  use                  postgresql-service
  service_description  PGSQL - Connection check
  hostgroup_name       postgresql-servers,postgresql-servers-standby
  check_command        check_postgres_connection!$_HOSTOPTIONS_PGPORT$!$_HOSTOPTIONS_PGUSER$
}

define service {
  use                  postgresql-service
  service_description  PGSQL - Last analyze
  hostgroup_name       postgresql-servers
  check_command        check_postgres_last_analyze!$_HOSTOPTIONS_PGPORT$!$_HOSTOPTIONS_PGUSER$!$_HOSTOPTIONS_DBNAMES$!$_HOSTOPTIONS_LASTANALYZE$
}

define service {
  use                  postgresql-service
  service_description  PGSQL - Last vacuum
  hostgroup_name       postgresql-servers
  check_command        check_postgres_last_vacuum!$_HOSTOPTIONS_PGPORT$!$_HOSTOPTIONS_PGUSER$!$_HOSTOPTIONS_DBNAMES$!$_HOSTOPTIONS_LASTVACUUM$
}

define service {
  use                  postgresql-service
  service_description  PGSQL - Locks
  hostgroup_name       postgresql-servers,postgresql-servers-standby
  check_command        check_postgres_locks!$_HOSTOPTIONS_PGPORT$!$_HOSTOPTIONS_PGUSER$!$_HOSTOPTIONS_DBNAMES$!$_HOSTOPTIONS_LOCKS$
}

define service {
  use                  postgresql-service
  service_description  PGSQL - Query time
  hostgroup_name       postgresql-servers,postgresql-servers-standby
  check_command        check_postgres_query_time!$_HOSTOPTIONS_PGPORT$!$_HOSTOPTIONS_PGUSER$!$_HOSTOPTIONS_QUERYTIME
}

define service {
  use                  postgresql-service
  service_description  PGSQL - Settings checksum
  hostgroup_name       postgresql-servers,postgresql-servers-standby
  check_command        check_postgres_settings_checksum!$_HOSTOPTIONS_PGPORT$!$_HOSTOPTIONS_PGUSER$!$_HOSTCONFIG_CHECKSUM
}

define service {
  use                  postgresql-service
  service_description  PGSQL - Transaction wraparound
  hostgroup_name       postgresql-servers
  check_command        check_postgres_txn_wraparound!$_HOSTOPTIONS_PGPORT$!$_HOSTOPTIONS_PGUSER$
}

define service {
  use                  postgresql-service
  service_description  PGSQL - WAL files
  hostgroup_name       postgresql-servers,postgresql-servers-standby
  check_command        check_postgres_wal_files!$_HOSTOPTIONS_PGPORT$!$_HOSTOPTIONS_PGUSER$!$_HOSTOPTIONS_WALFILES$
}

define service {
  use                  postgresql-service
  service_description  PGSQL - Archive ready
  hostgroup_name       postgresql-servers
  check_command        check_postgres_archive_ready!$_HOSTOPTIONS_PGPORT$!$_HOSTOPTIONS_PGUSER$!$_HOSTOPTIONS_ARCHIVEREADY$
}

define service {
  use                  postgresql-service
  service_description  PGSQL - Hot standby delay
  hostgroup_name       postgresql-servers
  check_command        check_postgres_hot_standby_delay!$_HOSTOPTIONS_PGPORT$!$_HOSTOPTIONS_PGUSER$!$_HOSTOPTIONS_STANDBYHOST$!$_HOSTOPTIONS_STANDBYPORT$!$_HOSTOPTIONS_STANDBYUSER$!$_HOSTOPTIONS_STANDBY$
}

Déclaration des groupes d’hôtes

Les services définis précédemment sont liés à des groupes d’hôtes, postgresql-servers et postgresql-servers-standby, il faut les déclarer de la façon suivante :

define hostgroup {
  hostgroup_name  postgresql-servers
  alias           Serveurs PostgreSQL
}

define hostgroup {
  hostgroup_name  postgresql-servers-standby
  alias           Serveurs PostgreSQL Standby
}

Configuration des hôtes

Pour la configuration des hôtes, il faut les positionner dans le bon groupe selon leur rôle dans la réplication : postgresql-servers pour le primaire, et postgresql-servers-standby pour le secondaire.

Les services étant génériques, il faut déclarer l’ensemble des variables au niveau de l’hôte : la variable doit être préfixée par un underscore (ce qui permet d’éviter les conflits de nommage avec le reste de la configuration) sachant que Nagios intercale le mot HOST après cet underscore dans l’utilisation pour les commandes et services, par exemple _OPTIONS_PGPORT devient $_HOSTOPTIONS_PGPORT$

Parmi les sondes définies, les variables suivantes sont à déclarer au niveau des hôtes :

_OPTIONS_PGPORT        5432 ; ou un port alternatif
_OPTIONS_PGUSER        nagios ; ou un autre utilisateur PostgreSQL pour la connexion
_OPTIONS_DBNAMES       base1,base2 ; la liste des bases de données pour certains test
_SSH_USER              nagios ; utilisateur pour l'accès SSH, le cas échéant
_SSH_PORT              22 ; port TCP du serveur SSH, le cas échéant
* Disponibilité : * connection : aucune option supplémentaire n’est nécessaire pour le test de connexion * backends : aucune option supplémentaire n’est nécessaire, les défauts pour warning à 90% et critical à 95% conviennent * Vacuum :

_OPTIONS_FREEZE        -w 100% -c 110%
* txn_wraparound : aucune option supplémentaire n'est nécessaire
_OPTIONS_LASTANALYZE   -w 2d -c 5d
_OPTIONS_LASTVACUUM    -w 7d -c 15d
_OPTIONS_BLOAT         --warning=130%\ and\ 1G --critical=140%\ and\ 1G
  • Activité :
_OPTIONS_LOCKS         -w 300 -c 400
_OPTIONS_WALFILES      -w 50 -c 60
_OPTIONS_QUERYTIME     -w 2min -c 5min
  • Configuration :
_CONFIG_CHECKSUM       4e7ba68eb88915d3d1a36b2009da4acd
  • Réplication :
_OPTIONS_ARCHIVEREADY  -w 3 -c 10
_OPTIONS_STANDBYHOST   ip_esclave
_OPTIONS_STANDBYPORT   port_esclave
_OPTIONS_STANDBYUSER   user_esclave
_OPTIONS_STANDBY       -w 700000 -c 1000000

Le bloat (fragmentation des tables) est à configurer séparemment car la sonde ne fait le calcul que sur une base donnée en paramètre. On définit donc un service par base :

define service {
  use                  postgresql-service
  service_description  PGSQL - Tables and indexes bloat
  hostgroup_name       postgresql-servers,postgresql-servers-standby
  check_command        check_postgres_bloat!$_HOSTOPTIONS_PGPORT$!$_HOSTOPTIONS_PGUSER$!base!$_HOSTOPTIONS_BLOAT$
}

Conclusion

La configuration de Nagios peut être un travail fastidieux, principalement à cause de la nécessité d’ajuster les seuils selon le fonctionnement de l’application en production, qui n’est pas encore connu.