Supervision des conteneurs (Kubernetes et Docker)

Un moniteur URL vous dit qu’une application est lente. Un moniteur workload vous dit pourquoi : le Deployment tourne avec 1 réplica sur 3, un pod est en CrashLoopBackOff, le conteneur a été tué pour dépassement mémoire il y a dix minutes. Mugnsoft lit ces informations directement dans l’apiserver Kubernetes ou l’API Docker Engine, depuis une sonde, sans rien installer dans le cluster.

Le modèle

La supervision des conteneurs suit le même modèle équipement avec enfants que les équipements SNMP et WMI.

Objet Ce que c’est Contient
Hôte de conteneurs Un cluster Kubernetes ou un hôte Docker Runtime, endpoint, identifiants, TLS, périmètre de découverte, sondes, planning, tags
Workload Un moniteur par workload adopté Hérite de la connexion, des tags et du planning de son hôte ; une copie par sonde sélectionnée

Un workload est identifié par ce qui survit à un déploiement, jamais par un nom de pod ou un identifiant de conteneur :

Runtime Identité Exemple
Kubernetes <namespace>/<kind>/<name> pour les Deployments, StatefulSets, DaemonSets et CronJobs prod/deployment/checkout-api
Docker, compose <project>/<service>, d’après les labels com.docker.compose.* shop/web
Docker, autonome le nom du conteneur web-demo
Pourquoi l’identité compte. Les noms de pods et les identifiants de conteneurs changent à chaque déploiement, changement d’image ou compose up. Un moniteur fondé sur eux remettrait à zéro sa chronologie et son SLA précisément au moment où l’historique est le plus utile. Fondé sur le workload, un déploiement n’est que quelques secondes de disponibilité réduite sur une série continue.

Avant de commencer

Kubernetes : un ServiceAccount en lecture seule

La sonde n’utilise que get et list. Un ClusterRole, plutôt qu’un Role limité à un namespace, permet de laisser Namespace vide et de voir tous les namespaces.

apiVersion: v1
kind: Namespace
metadata: { name: mugnsoft }
---
apiVersion: v1
kind: ServiceAccount
metadata: { name: mugnsoft-probe, namespace: mugnsoft }
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata: { name: mugnsoft-probe }
rules:
  - apiGroups: [""]
    resources: ["pods", "nodes", "namespaces", "events"]
    verbs: ["get", "list"]
  - apiGroups: ["apps"]
    resources: ["deployments", "statefulsets", "daemonsets"]
    verbs: ["get", "list"]
  - apiGroups: ["batch"]
    resources: ["cronjobs", "jobs"]
    verbs: ["get", "list"]
  - apiGroups: ["metrics.k8s.io"]
    resources: ["pods", "nodes"]
    verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata: { name: mugnsoft-probe }
roleRef: { apiGroup: rbac.authorization.k8s.io, kind: ClusterRole, name: mugnsoft-probe }
subjects:
  - { kind: ServiceAccount, name: mugnsoft-probe, namespace: mugnsoft }
---
# Jeton longue durée. Depuis Kubernetes 1.24, un ServiceAccount n'en reçoit plus automatiquement.
apiVersion: v1
kind: Secret
metadata:
  name: mugnsoft-probe-token
  namespace: mugnsoft
  annotations:
    kubernetes.io/service-account.name: mugnsoft-probe
type: kubernetes.io/service-account-token

Appliquez-le, puis récupérez les trois valeurs demandées par le formulaire :

kubectl apply -f mugnsoft-probe.yaml

# Endpoint
kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}'; echo
# Jeton (une ligne, sans préfixe "Bearer ")
kubectl -n mugnsoft get secret mugnsoft-probe-token -o jsonpath='{.data.token}' | base64 -d; echo
# Certificat CA (PEM)
kubectl -n mugnsoft get secret mugnsoft-probe-token -o jsonpath='{.data.ca\.crt}' | base64 -d
Pourquoi un Secret longue durée plutôt que kubectl create token. Une sonde qui interroge le cluster de l’extérieur ne peut pas renouveler un jeton TokenRequest à expiration : le moniteur tomberait en panne à son échéance. De nombreux fournisseurs managés plafonnent aussi, sans prévenir, la durée demandée. Traitez ce jeton comme un identifiant sensible.

Docker : socket ou endpoint TLS

Emplacement de la sonde Connexion
Sonde Linux sur l’hôte Docker Laissez Endpoint vide : la sonde utilise le socket local /var/run/docker.sock
Toute sonde, hôte distant https://dockerhost:2376 avec le CA, le certificat client et la clé issus de la configuration TLS du daemon

tcp:// suit la convention Docker : TLS lorsqu’un CA ou un certificat client est renseigné ou que le port est 2376, HTTP simple sinon. N’utilisez un port non chiffré que sur un réseau privé de confiance : c’est un accès root non authentifié à l’hôte.

Ou exécuter la sonde dans le cluster

Une sonde installée dans le cluster avec le chart Helm n’a besoin de rien de ce qui précède : elle utilise son propre ServiceAccount, avec le rôle en lecture seule que crée le chart. Choisissez Auth mode inCluster et laissez Endpoint vide. Voir Installer une sonde sur Kubernetes.


Ajouter un hôte de conteneurs

Ouvrez Container hosts et cliquez sur Ajouter. Le formulaire comporte quatre onglets.

Formulaire d'ajout d'un hôte de conteneurs

Settings

Champ Valeur Remarques
Display Name prod-cluster Nomme l’hôte dans l’interface, les rapports et les événements
Runtime Kubernetes ou Docker Change le moteur et les champs affichés
Enabled activé
Push to Probes une ou plusieurs sondes Seuls les composants moniteur activés sont proposés. La joignabilité est testée depuis la sonde
Frequency 5 MIN 1 MIN pendant la mise en place
Tags for linking shop Détermine l’appartenance aux applications et le périmètre des rapports ; hérité par chaque workload
Namespace vide = tous les namespaces Kubernetes uniquement. Vide exige le ClusterRole
Label selector app=checkout Restreint la découverte
Adoption cap 100 Nombre maximal de workloads que le réconciliateur peut proposer
Auto-adopt désactivé Voir Découverte, adoption et dérive

Connection

Champ Remarques
Endpoint https://<apiserver>:6443, https://dockerhost:2376, ou vide pour un socket Docker local ou une sonde in-cluster
Auth mode voir le tableau ci-dessous
Token / Token file / kubeconfig selon le mode d’authentification
Docker API version / socket path Docker uniquement ; vides, ils valent v1.43 et /var/run/docker.sock
CA certificate, client certificate, client key PEM en ligne ou chemin sur la sonde
Timeout (ms) 20000 par défaut
SNI, Proxy optionnels ; un proxy ne s’applique jamais à un socket local
Verify TLS laissez-le activé dès que vous avez le CA
Hôte de conteneurs, onglet Connection
Mode d’authentification À utiliser pour
token Un jeton de ServiceAccount collé en ligne — le choix habituel pour une sonde externe
tokenFile Un fichier de jeton sur l’hôte de la sonde. Relu à chaque contrôle : un jeton renouvelé est pris en compte
clientCert Certificat client et clé (Kubernetes ou TLS Docker)
kubeconfig Un chemin ou un contenu kubeconfig dont l’utilisateur porte un jeton, un fichier de jeton ou un certificat client
inCluster Une sonde qui tourne dans le cluster : le jeton, le CA et le namespace du ServiceAccount monté sont utilisés
none Un socket Docker local, ou un port Docker tcp:// non authentifié
En ligne ou chemin ? Une valeur contenant -----BEGIN ou un saut de ligne est lue comme un PEM en ligne ; toute autre valeur est un chemin de fichier sur l’hôte de la sonde, pas sur le Webserver. Collez le CA en ligne sauf si le fichier existe réellement sur la sonde. Les chemins relatifs d’un kubeconfig sont résolus par rapport au dossier du kubeconfig lui-même, comme avec kubectl.

Workloads

Cliquez sur Discover & Test (onglet Settings ou Workloads). Le bouton envoie le formulaire tel que saisi, pas l’enregistrement sauvegardé : il sert donc aussi de test de connexion.

Hôte de conteneurs, onglet Workloads
OK via probe probe-01
4 workload(s) visible

  default/deployment/web            2/2 ready
  kube-system/deployment/coredns    2/2 ready
  kube-system/daemonset/kube-proxy  3/3 ready
  default/statefulset/pg            1/1 ready

Une ligne ERROR donne la raison : endpoint injoignable, jeton refusé, RBAC manquant, CA inconnu. Une liste vide sous OK signifie que le périmètre ne correspond à rien.

La liste est regroupée par namespace ou projet compose, les conteneurs autonomes en dernier ; la case d’un groupe coche tous ses workloads.

Cocher un workload, c’est décider de l’adopter : son moniteur est créé activé sur chaque sonde sélectionnée à l’enregistrement.

Actions

Les mêmes paramètres de notification qu’un équipement SNMP, appliqués à chaque workload de l’hôte :

Bloc Champs
Notification settings Destinataires email, canal et jeton Slack, webhook Teams, clé d’API PagerDuty, script personnalisé et son timeout
Notify after if worse or equal to un statut, and after x checks, for x checks (0 = illimité), et un interrupteur par canal
Notify on status change Un interrupteur par canal

Enregistrer l’hôte pousse ces paramètres vers tous ses workloads : une seule modification atteint chaque moniteur workload. Sans Integrator, la sonde envoie elle-même les notifications ; avec un Integrator, c’est lui qui s’en charge. L’email exige que le paramétrage SMTP ait été validé.


Découverte, adoption et dérive

  • Ce qui est proposé. Kubernetes : Deployments, StatefulSets, DaemonSets et CronJobs. Les Jobs ne sont pas proposés, car les CronJobs les créent et les suppriment en permanence ; le CronJob lui-même l’est. Docker : conteneurs et services compose. Les conteneurs ponctuels docker compose run sont ignorés.
  • Auto-adopt. Toutes les 10 minutes, le Webserver relance la découverte de chaque hôte dont Auto-adopt est activé :
    • un nouveau workload est proposé, jamais adopté : son moniteur est créé désactivé, dans la limite de l’adoption cap ;
    • un workload disparu est marqué « gone » et son moniteur désactivé. Il n’est jamais supprimé, son historique reste consultable, et il conserve votre décision d’adoption s’il revient.
  • Une réponse partielle ne retire jamais rien. Si la découverte a été interrompue (un type que le jeton ne peut pas lister, un timeout, un très gros cluster), rien n’est marqué disparu.
  • Supprimer un hôte de conteneurs conserve ses moniteurs workload et leur historique. Les retirer est une action explicite sur chaque moniteur.
Tableau des hôtes de conteneurs avec le panneau des workloads de l'hôte sélectionné

Évaluation d’un workload

L’échelle de gravité

ERROR se classe au-dessus de CRITICAL, et c’est voulu : « je n’ai pas pu regarder » ne doit jamais se lire « j’ai regardé et tout va bien », et doit rester distinct de « j’ai regardé et c’est mauvais ».

Statut Déclenché quand
ERROR L’API est injoignable, refuse les identifiants, n’accorde pas la permission, ou le workload n’existe plus
CRITICAL Aucun réplica prêt, ou une faute franche : CrashLoopBackOff, ImagePullBackOff, un OOM kill depuis le contrôle précédent, une éviction, des pods non planifiables, un healthcheck en échec, une erreur de configuration de conteneur, un conteneur arrêté, une exécution de CronJob ou de Job en échec
MAJOR Mise à l’échelle à zéro (sauf si zéro réplica est autorisé), un déploiement qui a dépassé son délai de progression, des réplicas impossibles à créer
MINOR Certains réplicas ne sont pas prêts
OK Tous les réplicas sont prêts et aucune faute

Les règles

Règle Comportement
Disponibilité Réplicas prêts face aux réplicas désirés. Par défaut, tout manque est MINOR et zéro réplica prêt est CRITICAL. Les pods en cours d’arrêt sont ignorés : une mise à jour progressive ne fait pas osciller le statut
CronJob et Job Évalués sur la dernière exécution, jamais sur des réplicas : rien d’actif entre deux exécutions est OK, une exécution en échec est CRITICAL
Fautes franches Chacune est activée par défaut. Un arrêt passé ne compte que s’il est survenu depuis le contrôle précédent : un OOM kill de la semaine dernière ne maintient pas le workload en rouge. Sur Docker, un redémarrage efface l’état du conteneur : les OOM kills et plantages depuis le contrôle précédent sont donc aussi lus dans le journal d’événements du daemon, et trois sorties en échec dans cette fenêtre valent une boucle de plantage
Delta de redémarrages Redémarrages depuis le contrôle précédent. Évalué uniquement si des seuils sont définis ; le premier contrôle n’a pas de référence et reste silencieux
CPU / mémoire en % de la limite, throttling CPU en % Évalués uniquement si des seuils sont définis, et seulement quand chaque conteneur a une limite

Métriques

Chaque contrôle enregistre sept groupes, présentés un panneau par groupe dans le rapport du workload. Chaque clé est écrite à chaque contrôle, à zéro lorsque le runtime n’a pas d’équivalent : un conteneur Docker remonte ainsi les compteurs de phases de pods à 0 plutôt que de laisser des trous dans les séries.

Groupe Métriques
A Disponibilité Réplicas désirés, prêts, disponibles et indisponibles, conteneurs en cours, uptime (réplica le plus ancien)
R Redémarrages et fautes Nombre et delta de redémarrages, OOM kills, pods en boucle de crash, erreurs de récupération d’image, dernier code de sortie
C CPU Millicores, % de la limite, % de la demande, % de throttling, secondes de throttling
M Mémoire Octets, % de la limite, % de la demande, working set, RSS, cache
N Réseau et E/S Octets reçus et envoyés, lectures et écritures bloc
P Phases des pods (Kubernetes) Running, pending, failed, succeeded, evicted, non prêts
E Erreurs de contrôle Erreurs d’API, timeouts, échecs d’authentification, métriques indisponibles, échecs de sonde

Le temps de réponse tracé pour un workload est la latence de l’API pendant le contrôle, pas celle de l’application.


Où apparaissent les résultats

Emplacement Ce que vous obtenez
Page Container hosts Une ligne par hôte avec un statut consolidé. Le panneau de détail liste les workloads (on / proposed / gone) avec un bouton de rapport pour chacun
Page All Tous les moniteurs workload, avec les filtres, le rapport et les actions habituels
Rapport de workload Chronologie des statuts, répartition des statuts, temps de réponse de l’API et les sept panneaux de métriques ; disponible aussi en rapport planifié
Applications Les workloads rejoignent les applications par leurs tags ; la règle métier pondérée comporte un poids Container host
Notifications Email, Slack, Teams, PagerDuty et script personnalisé, réglés une fois dans l’onglet Actions de l’hôte
Integrator Chaque résultat de workload : sorties séries temporelles et fichiers journaux, tickets ServiceNow / GLPI / Jira au changement de statut, corrélation des causes racines
Webserver-front L’équipement hôte de conteneurs et son statut sont répliqués

Le statut propre de l’hôte de conteneurs combine quatre signaux indépendants, parce qu’ils tombent en panne indépendamment : l’endpoint est joignable, l’API répond sainement (/readyz ou /_ping), la pire condition de nœud (Kubernetes uniquement) et le pire workload. Un jeton expiré se lit donc comme un problème d’API plutôt que comme un cluster en panne. Côté nœuds, une pression mémoire, disque ou PID est MINOR, un nœud NotReady MAJOR, aucun nœud prêt CRITICAL, et un nœud cordonné ne relève jamais la gravité : un drainage de maintenance ne réveille personne.


Limites

Limite Que faire
Les seuils par workload ne sont pas modifiables dans l’interface. Disponibilité et fautes tournent sur leurs valeurs par défaut ; les échelles redémarrages, CPU, mémoire et throttling restent vides S’appuyer sur les valeurs par défaut. Les valeurs posées sur un workload via l’API de la sonde sont conservées au réenregistrement de l’hôte
La santé des nœuds n’alerte jamais. Elle colore l’hôte de conteneurs, mais aucun nœud NotReady ou sous pression ne déclenche d’alerte Superviser les nœuds comme des hôtes avec Ping, Système ou le Sentinel Agent
Le statut de l’hôte de conteneurs n’est pas envoyé à l’Integrator, comme pour les équipements SNMP et WMI Rien n’est perdu : une API injoignable met chaque workload en ERROR, et chacun est envoyé
Pas de socket Docker local sur les sondes Windows Utiliser un endpoint tcp:// / https://, ou une sonde Linux
Les kubeconfig de clusters managés (EKS, GKE, AKS) s’authentifient par des plugins exec ou auth-provider que la sonde ne peut pas exécuter ; ils sont refusés avec une erreur explicite Utiliser un jeton de ServiceAccount. Le insecure-skip-tls-verify d’un kubeconfig est aussi ignoré : c’est l’interrupteur Verify TLS qui décide
Sans metrics-server, les panneaux CPU et mémoire restent à zéro, avec métriques indisponibles positionné Installer metrics-server (fourni par les clusters managés et k3d, pas par kind)
Les Jobs ne peuvent pas être adoptés Adopter le CronJob qui les crée
La découverte est bornée : un Discover & Test liste au plus 500 workloads La restreindre par namespace ou sélecteur de labels
Ce n’est pas une base de métriques. Un échantillon par contrôle, à l’intervalle du moniteur, conservé selon la rétention habituelle Garder Prometheus ou votre plateforme d’observabilité pour l’historique à forte cardinalité
Les workloads ne s’importent pas seuls Importez ou exportez l’hôte de conteneurs : sa ligne porte la sélection de workloads et recrée leurs moniteurs
Écart de versions. Sonde, Webserver et Integrator doivent tous connaître les types conteneurs Les mettre à jour ensemble : un Integrator ancien rejette les résultats workload, une sonde ancienne n’a pas de moteur workload

Dépannage

Symptôme Cause probable
ERROR sur Discover & Test, connection refused ou timeout L’endpoint n’est pas joignable depuis la sonde — pare-feu, liste d’autorisation CIDR de l’apiserver, proxy
ERROR, 401 / authentication Jeton erroné ou expiré, ou préfixe Bearer collé avec
ERROR, 403 / forbidden Il manque au ServiceAccount une permission du ClusterRole ci-dessus
ERROR, certificate CA absent ou chemin de fichier inexistant sur la sonde — collez-le en ligne
Liste vide sous OK Namespace ou sélecteur de labels sans correspondance, ou Role limité à un namespace avec Namespace vide
CPU et mémoire restent à 0 Pas de metrics-server, ou pas de limites — les pourcentages exigent une limite sur chaque conteneur
Un CronJob reste OK alors que ses jobs échouent L’exécution en échec n’a pas encore épuisé ses tentatives ; il passe CRITICAL dès que le Job est marqué Failed
Un workload Docker indique restart and OOM events unavailable Le daemon a refusé son journal /events — typiquement un proxy de socket qui le bloque. Le contrôle évalue toujours ce que montre l’état du conteneur, mais manque les OOM kills et plantages qu’un redémarrage a déjà masqués

Voir aussi

Traductions