Skip to content

Résilience, Tests & Déploiement (Agent)

Situation Comportement
Docker indisponible État dégradé, retry borné ; aucun faux snapshot n’est envoyé
API indisponible Reconnexion avec backoff+jitter ; métriques/événements non critiques dans spool borné
Commande timeout Annulation du contexte, résultat explicite deadline_exceeded
gRPC Unavailable Retry seulement pour les RPC idempotents ; nouveau command_id interdit pour rejouer aveuglément une action
Stream logs interrompu Fin propre avec erreur/reconnexion côté UI, sans bufferiser des gigaoctets
Spool plein Politique FIFO/drop des métriques les plus anciennes, alerte heartbeat ; ne jamais supprimer silencieusement un résultat d’action
Certificat expiré/révoqué État unauthenticated, tentative de rotation ou intervention opérateur

Un circuit breaker simple par dépendance (Docker/API) évite de saturer un hôte défaillant : ouverture après plusieurs erreurs, pause bornée, puis probes en demi-ouverture. Le spool local est une file de reprise, pas une base métier ; les événements portent un identifiant et un timestamp pour permettre la déduplication par l’API.

  • Unitaires : parser/validator de configuration, calculs de deltas CPU/RAM/réseau, backoff, circuit breaker, décodeur de logs, règles d’autorisation.
  • Mock Docker SDK : tester discovery, réconciliation, actions et erreurs sans daemon. La suite vérifie notamment qu’un stop avec container absent est traduit de façon déterministe.
  • Tests gRPC : bufconn ou serveur gRPC local avec certificats de test ; vérifier mTLS, deadlines, metadata et annulation d’un stream.
  • Intégration : Docker de test (ou Testcontainers) avec containers éphémères ; vérifier Events, Stats, ContainerLogs(Follow), pull et lifecycle.
  • Résilience : couper API/Docker, remplir le spool, restaurer le réseau et vérifier reprise, ordre acceptable et déduplication.
  • Sécurité : certificat client inconnu refusé, token réutilisé refusé, permissions de fichiers contrôlées, arguments exec hors allow-list rejetés.

Chaque test d’intégration doit être explicitement marqué et désactivable lorsque Docker n’est pas disponible ; les tests unitaires restent exécutables sur la machine de développement.

Le mode recommandé est le binaire unique sous systemd, avec un compte de service dédié. Un container privilégié est possible, mais il doit monter le socket Docker et les certificats en lecture seule ; il élargit le périmètre de confiance et ne doit pas être le choix par défaut.

deploy/berth-agent.service
[Unit]
Description=Berth Docker Agent
After=docker.service network-online.target
Requires=docker.service
[Service]
Type=simple
User=berth-agent
Group=docker
ExecStart=/usr/local/bin/berth-agent --config /etc/berth-agent/config.yaml
Restart=on-failure
RestartSec=5s
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/berth-agent
# Le groupe docker est requis seulement pour l'accès au socket local.
[Install]
WantedBy=multi-user.target

Installation type : créer le compte et /var/lib/berth-agent, installer le binaire signé, déposer une configuration non secrète, déposer les certificats en 0600, réaliser l’enrôlement, puis systemctl enable --now berth-agent. Les logs vont à journald ; les métriques de l’Agent et son statut sont observables via l’API.

Pour un container : monter /var/run/docker.sock:/var/run/docker.sock, /etc/berth-agent:/etc/berth-agent:ro et /var/lib/berth-agent:/var/lib/berth-agent, utiliser un utilisateur adapté au GID du socket et éviter --privileged si le runtime le permet.