Santé et monitoring

Santé de la plateforme

Pour monitorer la santé de la plateforme depuis un service externe, vous avez la possibilité d’activer une route de healthcheck sur un ou plusieurs Portail. Cette route vous permet d’afficher un état global de la plateforme. Elle est accessible via l’URL:

https://url-de-votre-portail/api/healthcheck


Exemple de la réponse JSON:

{
    "status": "OK",
    "internalServicesStatus": "OK",
    "globalStatus": "WARNING",
    "certificatesStatus": "OK",
    "version": "2.15.0",
    "globalVersion": "2.15.0",
    "services": {
        "api": {
            "status": "OK",
            "internalServicesStatus": "OK",
            "version": "3.26.1",
            "services": {
                "db": { "status": "OK" },
                "provision-api": { "status": "OK", "version": "3.10.4" },
                "provision-relay-api": { "status": "OK", "version": "1.9.0" },
                "container-providers": [
                    { "status": "OK", "name": "Swarm cluster EU-West - SWARM", "type": "SWARM" }
                ],
                "ws-relays": [
                    { "status": "OK", "name": "Websocket relay EU-West - WS_SWARM", "type": "WS_SWARM" },
                    { "status": "OK", "name": "Websocket relay EU-West - Traefik status", "type": "WS_SWARM" }
                ]
            },
            "relayDiagnostics": [
                {
                    "name": "Websocket relay EU-West",
                    "type": "WS_SWARM",
                    "status": "ERROR",
                    "proxy": {
                        "reachable": true,
                        "url": "http://relay.example.com:8404/stats;json",
                        "backends": [
                            {
                                "name": "relay_swarm_back",
                                "status": "UP",
                                "active": 2,
                                "backup": 0,
                                "sessions": { "current": 2, "max": 4, "limit": 26209, "queue": 0 },
                                "errors": { "connection": 0, "response": 0, "retries": 0, "redispatches": 0 }
                            }
                        ]
                    },
                    "cluster": { "reachable": true, "error": null, "members": 3 },
                    "nodes": [
                        {
                            "address": "10.0.0.13",
                            "hostname": "node2",
                            "state": "NGINX_DOWN",
                            "detail": "no answer on the node address",
                            "role": "manager",
                            "proxyExpected": true,
                            "cluster": { "member": true, "state": "down", "availability": "active", "reachability": "unreachable" },
                            "proxy": [
                                { "backend": "relay_swarm_back", "port": 8375, "status": "DOWN", "check": "L4TOUT", "checkCode": null, "lastCheck": "", "failures": 3, "flaps": 2, "downtime": 154, "since": 154 }
                            ],
                            "engine": { "ping": null, "version": null, "swarm": null, "manager": null, "clusterId": null }
                        }
                    ]
                }
            ],
            "providerDiagnostics": [],
            "ndbDiagnostics": null
        },
        "signals": [
            { "status": "OK", "url": "https://signal.example.com", "certificateExpiration": "2027-04-14 17:29:00", "error": null }
        ]
    },
    "license": { "expiration": "2028-01-01 01:00:00" }
}

La réponse ci-dessus est abrégée : chaque liste contient une entrée par objet de ce type.

Lecture des agrégats

La réponse commence par quatre agrégats. Une supervision externe surveille en général les deux derniers :

  • status — l’API et sa base de données uniquement.

  • internalServicesStatus — tous les services internes sauf la base de données.

  • globalStatus — la plateforme dans son ensemble : ERROR quand l’API, l’un de ses services internes ou tous les serveurs signal sont hors service, WARNING quand seuls une partie des serveurs signal, un fournisseur ou le cluster de base de données sont dégradés.

  • certificatesStatus — les certificats TLS, face aux seuils d’avertissement et d’erreur de l’instance.

La route répond toujours 200, y compris pendant une panne totale : lisez le verdict dans le corps de la réponse plutôt que le code HTTP.

Diagnostic par nœud

relayDiagnostics et providerDiagnostics rapportent chaque cluster machine par machine. Chaque entrée nomme le cluster, son status agrégé (OK, WARNING, ERROR ou UNAVAILABLE), le répartiteur de charge sur lequel il a été lu, et un objet par nœud.

Champs disponibles pour chaque nœud :

Champ

Contenu

state

OK, NGINX_DOWN, DOCKER_DOWN, SWARM_INACTIVE, NOT_IN_CLUSTER, NOT_BEHIND_PROXY pour un cluster Swarm ; OK, PROXY_DOWN, APISERVER_DOWN, NOT_READY, NOT_IN_CLUSTER, NOT_BEHIND_PROXY pour un cluster Kubernetes.

detail

Une phrase nommant ce qui a conduit à cet état, ou null.

role

manager, worker ou control-plane.

proxyExpected

Indique si le rôle du nœud exige que le répartiteur de charge le serve. Un nœud dans un état autre que OK fait passer le verdict du cluster en ERROR seulement si ce champ vaut true.

proxy

Une entrée par backend du répartiteur de charge servant ce nœud, avec le port et l’état que HAProxy lui donne.

engine / apiServer

Ce que le nœud lui-même a répondu : version du moteur et état du swarm pour Swarm, vivacité du serveur d’API pour Kubernetes.

ndbDiagnostics porte le même niveau de détail pour un cluster MySQL NDB : son verdict (ok, warn, crit, stale ou unknown), les reasons codées qui le motivent et les groupes de nœuds. Il vaut null sur une instance sans supervision de cluster activée.

Note

Ces trois champs contiennent des noms d’hôtes et des adresses de l’infrastructure. Ils font aussi partie de la réponse sur la route anonyme : restreignez cette route par IP.

Activation de la route

Pour activer cette route sur le Portail, vous pouvez utiliser les options:

  • HEALTHCHECK_ENABLE: “true”

  • HEALTHCHECK_RESTRICT_IP: “192.168.1.1,192.168.10.0/24”

Et pour activer cette route sur le Portail Admin:

  • HEALTHCHECK_PORTALADMIN_ENABLE: “true”

  • HEALTHCHECK_PORTALADMIN_RESTRICT_IP: “192.168.1.1,192.168.10.0/24”

Format Prometheus

Si vous souhaitez obtenir ces informations au format Prometheus, elles sont accessibles sur la route https://url-de-votre-portail/api/healthcheck/prometheus

# HELP app_status API and database status (1 = up, 0 = down)
# TYPE app_status gauge
app_status 1

# HELP app_internal_services_status Internal services status (1 = all up, 0 = at least one down)
# TYPE app_internal_services_status gauge
app_internal_services_status 0

# HELP app_service_status Services status (1 = up, 0 = down)
# TYPE app_service_status gauge
app_service_status{service="db"} 1
app_service_status{service="provision-api"} 0
app_service_status{service="provision-relay-api"} 0
app_service_status{service="Mon provider - SWARM", parent="container-providers", type="SWARM"} 0
app_service_status{service="Mon websocket relay 1 - WS_SWARM", parent="ws-relays", type="WS_SWARM"} 0
app_service_status{service="Mon websocket relay 1 - Traefik status", parent="ws-relays", type="WS_SWARM"} 0

# HELP app_service_items Services items numbers
# TYPE app_service_items gauge
app_service_items{service="Mon provider - SWARM", parent="container-providers", type="SWARM"} 12
app_status

L’API et sa base de données. La valeur 1 signifie que les deux répondent.

app_internal_services_status

Les services internes, base de données exclue. La valeur 0 signifie qu’au moins l’un d’eux est hors service.

app_service_status

Indique l’état de chaque service surveillé. La valeur 1 signifie que le service est opérationnel. La valeur 0 signifie qu’il est indisponible.

Une instance dont la base de données tourne sur un cluster MySQL NDB expose aussi le cluster lui-même :

# HELP app_ndb_status NDB cluster verdict (2 = ok, 1 = warn, 0 = crit, stale, unknown or unreachable)
# TYPE app_ndb_status gauge
app_ndb_status 2

# HELP app_ndb_min_redundancy Fewest live nodes in any node group; 1 means the next incident is an outage
# TYPE app_ndb_min_redundancy gauge
app_ndb_min_redundancy 2

# HELP app_ndb_data_nodes Data nodes the cluster reports
# TYPE app_ndb_data_nodes gauge
app_ndb_data_nodes{state="live"} 4
app_ndb_data_nodes{state="total"} 4

La même route porte également app_ndb_data_memory_max_pct, app_ndb_redo_max_pct et app_ndb_snapshot_age_seconds. Un instantané qui cesse de vieillir signifie que le service de supervision ne collecte plus : app_ndb_status retombe alors à 0.

Warning

Le diagnostic par nœud des relais et des fournisseurs de conteneurs n’est pas exposé au format Prometheus. app_service_status ne rapporte que le point d’entrée du cluster. Lisez la route JSON pour obtenir le détail par nœud.

Exemple de supervision

Voici un exemple de mise en place d’une supervision de la santé de la plateforme en utilisant Nagios

Prérequis

Sur le serveur Nagios: avoir les commandes curl et jq disponibles

Command

define command {
    command_name    reemo_healthcheck
    command_line    /usr/lib/nagios/plugins/reemo_healthcheck $ARG1$
}

Script

#!/bin/bash

# Check if an argument (URL) is provided
if [ -z "$1" ]; then
    echo "CRITICAL: No URL provided. Usage: $0 <URL>"
    exit 2
fi

HEALTHCHECK_URL="$1"

# Fetch JSON response
response=$(curl -s "$HEALTHCHECK_URL/api/healthcheck")

# Check if the request was successful
if [ $? -ne 0 ] || [ -z "$response" ]; then
    echo "CRITICAL: Unable to access the health check page ($HEALTHCHECK_URL)"
    exit 2
fi

# Extract service statuses using jq
status=$(echo "$response" | jq -r '.status')
errors=$(echo "$response" | jq -r '.. | objects | select(.status? and .status != "OK")')

# Check if the global status is OK
if [ "$status" != "OK" ]; then
    echo "CRITICAL: Global health check status is $status"
    exit 2
fi

# Check if any sub-services have issues
if [ -n "$errors" ]; then
    echo "WARNING: Some services are not OK:"
    echo "$errors"
    exit 1
fi

# Everything is OK
echo "OK: All services are operational"
exit 0

Service

define service{
    host_name                       < HOSTNAME >
    use                             generic-service         ; Name of service template to use
    service_description             Reemo Healthcheck
    check_command                   reemo_healthcheck!https://< URL >
}

Monitoring Prometheus

Il est possible d’activer Prometheus sur les points d’entrées Traefik, plusieurs options sont disponibles:

Activer Prometheus

Pour activer Prometheus, vous pouvez rajouter l’option TRAEFIK_PROMETHEUS_ENABLE: true dans le fichier inventaire.

Port

Par défaut la page Prometheus sera accessible sur le même port que le Portail, utilisez l’option TRAEFIK_PROMETHEUS_PORT: “<numero du port>” pour le modifier.

URL

Par défaut la page Prometheus sera accessible sur l’url du Portail avec le lien /metrics. Il est possible de spécifier une ou plusieurs url dédiées:

TRAEFIK_PROMETHEUS_URLS:
    - "metrics1.domain.tld"
    - "metrics2.domain.tld"

Note

Dans le cas d’un cluster avec 3 noeuds, il est conseillé de mettre 3 urls pour que Prometheus puisse récupérer les metrics de tous les noeuds.

Filtrage IP

Pour restreindre l’accès à des adresses IP, vous pouvez utiliser l’option TRAEFIK_PROMETHEUS_RESTRICT_IP.

Exemple:

TRAEFIK_PROMETHEUS_RESTRICT_IP: "1.1.1.1,2.2.2.2"

Monitoring Datadog

Pour envoyer les logs de la plateforme vers Datadog, utilisez les options suivantes:

DATADOG_ENABLED: true
DATADOG_API_KEY: "<votre_cle_api_datadog>"
DATADOG_SITE: "datadoghq.eu"
DATADOG_SYSLOG_PREFIX: ""
  • DATADOG_ENABLED: active l’intégration Datadog.

  • DATADOG_API_KEY: votre clé API Datadog, à remplacer par la vôtre.

  • DATADOG_SITE: le site Datadog associé à votre compte (ex. datadoghq.eu), fourni par Datadog.

  • DATADOG_SYSLOG_PREFIX: préfixe optionnel ajouté à chaque ligne de log envoyée.