Nantes, le 30 août 2023

check_patroni est une sonde Nagios conçue pour superviser un cluster haute disponibilité géré par Patroni. Elle existe depuis un peu plus d’un an et atteint désormais la version 1.0.0, marquant ainsi son passage en version stable.

Présentation

Cet outil propose une série de sondes permettant la supervision globale du cluster ainsi que celle de chaque nœud individuellement.

  • Sondes pour le cluster :

    • cluster_config_has_changed : détecte les changements de la configuration dynamique depuis le dernier contrôle ;
    • cluster_has_leader : vérifie la présence d’un leader ou d’un standby leader dans le cluster ;
    • cluster_has_replica : s’assure que le nombre actuel de réplicas correspond au nombre attendu et qu’ils sont synchrones ;
    • cluster_has_scheduled_action : identifie les actions planifiées sur le cluster (switchover ou redémarrage) ;
    • cluster_is_in_maintenance : indique si le cluster est en mode maintenance ;
    • cluster_node_count : vérifie si le nombre de nœuds correspond aux attentes.
  • Sondes pour les nœuds :

    • node_is_alive : vérifie si Patroni est opérationnel sur le nœud ;
    • node_is_leader : identifie si le nœud est un leader (ou un standby leader) ;
    • node_is_pending_restart : détecte si le nœud nécessite un redémarrage pour prendre en compte une configuration ;
    • node_is_primary : indique si le nœud est une instance primaire gérée par Patroni ;
    • node_is_replica : vérifie si le nœud est un réplica, et s’il est synchrone ou asynchrone ;
    • node_patroni_version : vérifie si le nœud utilise la version souhaitée de Patroni ;
    • node_tl_has_changed : détecte les changements récents de timeline sur le nœud.

Chaque sonde fournit également des données complémentaires (perf data) qui permettent d’avoir plus d’informations sur le nœud.

Installation

Installer check_patroni dans un environnement virtuel :

python3 -m venv .venv_check_patroni
. .venv_check_patroni/bin/activate
pip install --upgrade pip
pip install check_patroni

Tester la version :

check_patroni --version
Version 1.0.0

L’aide est accessible pour l’ensemble de la commande ou pour une sonde spécifique :

check_patroni --help
Usage: check_patroni [OPTIONS] COMMAND [ARGS]...

  Nagios plugin that uses Patroni's REST API to monitor a Patroni cluster.

Options:
  --config FILE         Read option defaults from the specified INI file
                        [default: config.ini]
  -e, --endpoints TEXT  Patroni API endpoint. Can be specified multiple times
                        or as a list of comma separated addresses. The node
                        services checks the status of one node, therefore if
                        several addresses are specified they should point to
                        different interfaces on the same node. The cluster
                        services check the status of the cluster, therefore
                        it's better to give a list of all Patroni node
                        addresses.  [default: http://127.0.0.1:8008]
  --cert_file PATH      File with the client certificate.
  --key_file PATH       File with the client key.
  --ca_file PATH        The CA certificate.
  -v, --verbose         Increase verbosity -v (info)/-vv (warning)/-vvv
                        (debug)
  --version
  --timeout INTEGER     Timeout in seconds for the API queries (0 to disable)
                        [default: 2]
  --help                Show this message and exit.

Commands:
  cluster_config_has_changed    Check if the hash of the configuration...
  cluster_has_leader            Check if the cluster has a leader.
  cluster_has_replica           Check if the cluster has healthy replicas...
  cluster_has_scheduled_action  Check if the cluster has a scheduled...
  cluster_is_in_maintenance     Check if the cluster is in maintenance...
  cluster_node_count            Count the number of nodes in the cluster.
  node_is_alive                 Check if the node is alive ie patroni is...
  node_is_leader                Check if the node is a leader node.
  node_is_pending_restart       Check if the node is in pending restart...
  node_is_primary               Check if the node is the primary with the...
  node_is_replica               Check if the node is a running replica...
  node_patroni_version          Check if the version is equal to the input
  node_tl_has_changed           Check if the timeline has changed.

Exemple de la sonde cluster_node_count

Pour obtenir de l’aide sur la sonde cluster_node_count :

check_patroni cluster_node_count --help
Usage: check_patroni cluster_node_count [OPTIONS]

  Count the number of nodes in the cluster.

  The state refers to the state of PostgreSQL. Possible values are:
  * initializing new cluster, initdb failed
  * running custom bootstrap script, custom bootstrap failed
  * starting, start failed
  * restarting, restart failed
  * running, streaming (for a replica V3.0.4)
  * stopping, stopped, stop failed
  * creating replica
  * crashed

  The role refers to the role of the server in the cluster. Possible values
  are:
  * master or leader (V3.0.0+)
  * replica
  * demoted
  * promoted
  * uninitialized

  Check:
  * Compares the number of nodes against the normal and healthy (running + streaming) nodes warning and critical thresholds.
  * `OK`:  If they are not provided.

  Perfdata:
  * `members`: the member count.
  * `healthy_members`: the running and streaming member count.
  * all the roles of the nodes in the cluster with their count (start with "role_").
  * all the statuses of the nodes in the cluster with their count (start with "state_").

Options:
  -w, --warning TEXT       Warning threshold for the number of nodes.
  -c, --critical TEXT      Critical threshold for the number of nodes.
  --healthy-warning TEXT   Warning threshold for the number of healthy nodes
                           (running + streaming).
  --healthy-critical TEXT  Critical threshold for the number of healthy nodes
                           (running + streaming).
  --help                   Show this message and exit.

Voici un exemple d’utilisation de cette sonde :

check_patroni -e http://10.20.30.51:8008 \
              -e http://10.20.30.52:8008 \
              -e http://10.20.30.53:8008 \
              cluster_node_count
CLUSTERNODECOUNT OK - members is 3 | healthy_members=3 members=3 role_leader=1 role_replica=1 role_sync_standby=1 state_running=1 state_streaming=2

Cette sonde indique que le nombre de nœuds est de 3, tous en bonne santé. Il y a un leader, un réplica synchrone et un réplica asynchrone. Le leader est en statut running, les réplicas sont en statut streaming.

Vous pouvez créer un fichier de configuration pour éviter de saisir les mêmes paramètres à chaque fois. Par défaut, le fichier config.ini du répertoire courant est utilisé. Vous pouvez également spécifier un fichier avec l’option –config. Les options du fichier sont écrasées par celles saisies en ligne de commande.

cat << _EOF_ > config.ini
[options]
endpoints=http://10.20.30.51:8008, http://10.20.30.52:8008, http://10.20.30.53:8008
_EOF_

Seuils

Examinons maintenant la configuration avec une alerte warning si un nœud est perdu et une alerte critical en cas de perte de deux nœuds :

check_patroni -vv cluster_node_count \
              --healthy-warning 3: \
              --healthy-critical 2:

L’option -vv permet de séparer les résultats du contrôle et les données de performance sur deux lignes, améliorant ainsi la lisibilité. L’option -vvv active le mode de débogage.

On utilise ici les conditions --healthy-warning et --healthy-critical. En effet, les conditions --warning et --critical vérifient la présence des nœuds quel que soit leur statut. Lorsqu’un nœud sort du cluster, Patroni fait le ménage dans le DCS pour le faire disparaitre, cependant ce n’est pas instantané. On détectera donc quand même la perte d’un nœud mais pas si un nœud est marqué par Patroni avec un statut différent de running ou streaming.

Voici les résultats obtenus :

  • avec un cluster intact :
    CLUSTERNODECOUNT OK - members is 3
    | healthy_members=2;2:;1: members=3 role_leader=1 role_replica=2 state_running=2 state_stopped=1
    
  • en arrêtant un nœud :
    CLUSTERNODECOUNT WARNING - healthy_members is 2 (outside range 3:)
    | healthy_members=2;3:;2: members=2 role_leader=1 role_sync_standby=1 state_running=1 state_streaming=1
    
  • et finalement avec deux nœuds arrêtés :
    CLUSTERNODECOUNT CRITICAL - healthy_members is 1 (outside range 2:)
    | healthy_members=1;3:;2: members=2 role_leader=1 role_replica=1 state_running=1 state_stopped=1
    

Le formatage du check est spécifié avec la syntaxe [@][start:][end]:

  • start : peut être omis si start vaut 0 ;
  • ~: signifie que start vaut -infini ;
  • si la end est omis, on suppose que end vaut +infini ;
  • pour inverser une condition on peut ajouter @ devant l’expression.

Le fonctionnement de la librairie nagiosplugin est un peu surprenant. La condition fournie doit décrire une plage de valeur pour laquelle on ne doit pas déclencher d’erreur, une correspondance est trouvée si on obtient : start ≤ VALUE ≤ end.

Si on reprend l’exemple précédent :

  • --healthy-warning 3: : on souhaite déclencher un warning quand on perd un nœud, autrement dit, l’état normal pour ce contrôle est d’avoir [3;+INF[ nœuds.
  • --healthy-critical 2: : on souhaite déclencher un critical quand on perd deux nœuds, autrement dit, l’état normal pour ce contrôle est d’avoir [2;+INF[ nœuds.

La condition peut aussi être inversée :

check_patroni cluster_node_count --healthy-warning @0:2 --healthy-critical @0:1

Fichier d’état

check_patroni peut utiliser un fichier d’état (state file) pour détecter les changements d’état d’un service. Deux services sont concernés :

  • cluster_config_has_changed : ce service permet de spécifier un hash explicitement (--hash) ou de laisser la sonde se débrouiller en utilisant un fichier d’état (--state-file) ;
  • node_tl_has_changed : ce service permet de spécifier une timeline explicitement (--timeline) ou de laisser la sonde se débrouiller en utilisant un fichier d’état (--state-file).

Exemple d’utilisation de l’option --timeline du service node_tl_has_changed :

check_patroni node_tl_has_changed --timeline 7
NODETLHASCHANGED OK - The timeline is still 7. | is_timeline_changed=0;;@1:1 timeline=7

Exemple d’utilisation de l’option --state-file du service node_tl_has_changed :

check_patroni node_tl_has_changed --state-file check_patroni.state
NODETLHASCHANGED CRITICAL - The expected timeline was None got 7. | is_timeline_changed=1;;@1:1 timeline=7

Le premier lancement renvoie une erreur. En effet, il n’y a pas d’information dans le fichier d’état. Il faut enregistrer/acquitter le changement pour que l’information soit enregistrée et que l’alerte disparaisse. Ce sera le cas pour tout changement de timeline détecté.

check_patroni node_tl_has_changed --state-file check_patroni.state --save
check_patroni node_tl_has_changed --state-file check_patroni.state
NODETLHASCHANGED CRITICAL - The expected timeline was None got 7. | is_timeline_changed=1;;@1:1 timeline=7
NODETLHASCHANGED OK - The timeline is still 7. | is_timeline_changed=0;;@1:1 timeline=7

La configuration par sonde peut également être ajoutée dans le fichier de configuration :

cat << _EOF_ >> config.ini

[options.node_tl_has_changed]
state_file = check_patroni.state
_EOF_

On peut désormais lancer la sonde sans l’option --state-file :

check_patroni node_tl_has_changed
NODETLHASCHANGED CRITICAL - The expected timeline was None got 7. | is_timeline_changed=1;;@1:1 timeline=7

Conclusion

check_patroni met à disposition une série de sondes qui permettent de détecter les changements d’état du cluster afin de les remonter dans Icinga ou Nagios. Les données complémentaires (perf data) peuvent être utilisées dans des outils de métrologie pour suivre l’évolution de l’état du cluster dans le temps.

Si vous trouvez des erreurs, ou souhaitez voir des améliorations implémentées dans l’outil ou en implémenter vous-même, n’hésitez pas à venir échanger sur le tracker du projet.

Un grand merci aux contributeurs qui se sont déjà manifestés et aux collègues qui m’ont aidé.


DALIBO

DALIBO est le spécialiste français de PostgreSQL®. Nous proposons du support, de la formation et du conseil depuis 2005.