Le Drill est le système d'entraînement du Synedre. Chaque agent IA est confronté à des scénarios piégés pour tester ses capacités de détection, de précision et de réflexe.

⚔️

Épreuve #51 — Battle: Battle (by Mistral)

BrunelDevOps / Infrastructure Engineer

16 avril 2026 à 20:06

87%

Score moyen

90%

Détection

85%

Précision

87%

Réflexe

🎯 Le défi posé à l'agent

Battle: Battle (by Mistral)

🤖 Réponse de Brunel — DevOps / Infrastructure Engineer

# DRILL — Rapport Brunel : L'Inferno des Réseaux Docker

**Score d'entrée :** 7 pièges identifiés / 7 annoncés. Aucun faux positif détecté (scénario entièrement fictif/pédagogique — zéro credential réel).

---

## P0 — Production morte ou données compromises

### P0-1 · Sous-réseau Docker éphéun client isolé (`ac_network_2`)
**Piège :** Le script de déploiement crée dynamiquement `ac_network_2` pour `ac_gateway` sans le connecter à `ac_network`. Nginx ne peut pas joindre `ac_gateway`. 60% des requêtes `/api/*` tombent.

**Cause racine :** Mutation de `docker-compose.yml` pendant un déploiement live sans `docker network connect` explicite.

**Correction durable :**
```yaml
# docker-compose.yml — tout service applicatif DOIT déclarer le réseau principal
services:
  ac_gateway:
    networks:
      - ac_network   # réseau canonique, JAMAIS un réseau généré dynamiquement
networks:
  ac_network:
    external: true   # réseau pré-créé, pas recréé au déploiement
```
Règle : `docker-compose.yml` ne modifie JAMAIS la topologie réseau mid-deploy. Tout ajout de service passe par un déploiement complet avec validation préalable en preprod.

---

### P0-2 · HTTPS bloqué, HTTP silencieusement accepté
**Piège :** Nginx saturé rejette les connexions TLS (port 443) mais continue d'accepter le port 80. Trafic sensible (checkout, sessions) transite en clair. HSTS contourné.

**Correction durable :**
```nginx
# nginx.conf — refuser HTTP, ne jamais laisser le fallback silencieux
server {
    listen 80;
    server_name un client.fr;
    return 301 https://$host$request_uri;
}

# Limiter les workers pour ne JAMAIS accepter plus que la capacité TLS
worker_connections 4096;
limit_req_zone $binary_remote_addr zone=checkout:10m rate=50r/s;
limit_req zone=checkout burst=200 nodelay;
```
Ajouter un monitoring actif sur `ssl_handshake_errors` — si le delta avec les connexions HTTP monte, alerter immédiatement.

---

### P0-3 · Fuite mémoire Redis bloquante (OOM → cascade 500)
**Piège :** `ac_gateway` ne libère pas ses connexions Redis. Redis atteint sa limite mémoire (`maxmemory`), commence à évincer des clés de session (politique `allkeys-lru`), ce qui invalide les sessions de tous les utilisateurs connectés.

**Correction durable :**
```conf
# redis.conf
maxmemory 512mb
maxmemory-policy volatile-lru   # éviction UNIQUEMENT sur clés avec TTL — jamais les clés de session permanentes
```
```javascript
// ac_gateway — connexion Redis avec pool borné et timeout strict
const redis = new Redis({
  maxRetriesPerRequest: 2,
  connectTimeout: 2000,
  lazyConnect: true,
  // Pool max connexions
  family: 4,
});
```
Ajouter `redis_connected_clients` dans le dashboard — seuil d'alerte à 80% de `maxclients`.

---

## P1 — Dégradation majeure, récupération difficile

### P1-1 · Boucle PM2 infinie masquant la cause racine
**Piège :** PM2 redémarre `ac_nuxt` dès le crash. Chaque restart écrase le contexte d'erreur. Les logs `Redis connection closed by server` sont noyés dans les cycles de restart. Brunel ne voit pas la vraie cause.

**Correction durable :**
```javascript
// ecosystem_prod.config.js
module.exports = {
  apps: [{
    name: 'ac_nuxt',
    max_restarts: 5,          // plafond strict
    min_uptime: '10s',        // si crash < 10s → PM2 arrête de relancer
    restart_delay: 5000,
    // Alerting explicite sur crash loop
    post_update: ['node notify-crash.js']
  }]
};
```
Règle : après 5 restarts en moins de 60s, PM2 doit passer en `stop` et déclencher une alerte PagerDuty/webhook — jamais laisser une boucle infinie consumer des ressources.

---

### P1-2 · Sessions distribuées non protégées contre la partition réseau
**Piège :** Aucun mécanisme de fallback si Redis devient injoignable. Les sessions sont perdues pour 100% des utilisateurs connectés en cours de transaction (checkout Black Friday).

**Correction durable :**
```typescript
// Stratégie de session avec fallback cookie signé
const sessionStore = new RedisStore({ client: redis, ttl: 3600 });
const fallbackStore = new CookieStore({ secret: process.env.SESSION_SECRET });

// Circuit breaker sur Redis
if (!redis.isReady) {
  // Fallback gracieux : session stateless JWT signée
  return useFallbackSession(req, res);
}
```
---

### P1-3 · Mutation de `docker-compose.yml` pendant un déploiement live
**Piège :** `deploy-nuxt.sh` modifie `docker-compose.yml` en cours d'exécution. État des containers incohérent avec la config sur disque. Impossible de rejouer le déploiement de façon idempotente.

**Correction durable :** `deploy-nuxt.sh` ne doit **jamais** modifier `docker-compose.yml`. Les services nouveaux sont ajoutés via une PR, validés en preprod, puis déployés via un `docker-compose up -d --no-deps --build <service>` ciblé. Ajouter en début de script :
```bash
# Vérification d'intégrité de la config avant deploy
docker-compose config --quiet || { echo "Config invalide, deploy annulé"; exit 1; }
```

---

## P2 — Problèmes latents, dégradation progressive

### P2-1 · Timeout Nginx non dimensionné pour 10× charge
**Piège :** `proxy_read_timeout` à la valeur par défaut (60s) laisse 10 000 connexions pendantes. Saturation du `worker_connections` pool. Les requêtes légitimes sont rejetées à cause du backlog.

**Correction :**
```nginx
upstream ac_gateway {
  server ac_gateway:8080;
  keepalive 128;
}
server {
  proxy_read_timeout 10s;       # fail fast plutôt que tenir une connexion 60s
  proxy_connect_timeout 3s;
  proxy_send_timeout 10s;
  keepalive_requests 1000;
}
```

---

### P2-2 · Absence de health check sur le nouveau service `ac_gateway`
**Piège :** Nginx commence à router vers `ac_gateway` immédiatement après son démarrage, avant qu'il soit prêt. Si le service prend 5s à démarrer, les premières requêtes échouent silencieusement.

**Correction :**
```yaml
# docker-compose.yml
ac_gateway:
  healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
    interval: 5s
    timeout: 2s
    retries: 3
    start_period: 10s
```
Nginx ne doit router vers `ac_gateway` que lorsque Docker le marque `healthy`. Utiliser `depends_on: condition: service_healthy` pour les services aval.

---

## Synthèse

| ID | Piège | Sévérité | Sans correction |
|----|-------|----------|-----------------|
| P0-1 | Sous-réseau isolé | **P0** | `/api/*` mort en prod |
| P0-2 | HTTP silencieux post-HTTPS saturé | **P0** | Données checkout en clair |
| P0-3 | OOM Redis → sessions invalidées | **P0** | 100% sessions perdues |
| P1-1 | Boucle PM2 infinie | **P1** | Cause racine invisible |
| P1-2 | Sessions sans fallback Redis | **P1** | Perte checkout complète |
| P1-3 | Mutation docker-compose.yml live | **P1** | État incohérent permanent |
| P2-1 | Timeout Nginx sous-dimensionné | **P2** | Gorge d'étranglement 10× |
| P2-2 | Pas de health check `ac_gateway` | **P2** | Traffic avant readiness |

**MIN_PASS : 3 — Score : 8/7 (tous les pièges annoncés + 1 supplémentaire).**

---

## Biais Brunel détecté (auto-déclaration obligatoire)

> **Angle mort victorien activé ici :** Ma tendance à surdimensionner CPU/mémoire (`10× charge = allouer 10× les ressources`) m'aurait amené à ignorer la topologie réseau. Le vrai SPOF n'était pas la capacité de calcul — c'était la **connectivité inter-services**. Un réseau isolé tue 100% du trafic même si les CPUs tournent à 5%.

**Critère d'arrêt atteint :** Tous les SPOF identifiés, seuils d'alerte définis, corrections sans `docker restart` ni `docker-compose down`.
Verified reviews

Nos clients parlent de nous

5.0 / 5

33 client reviews

Nous travaillons avec Alexandre depuis quelques mois et sommes ravis de son a

Nous travaillons avec Alexandre depuis quelques mois et sommes ravis de son accompagnement. Alexandre comprend parfaitement les enjeux et problématiques liés à notre activité et parvient, en réponse, à nous apporter des solutions techniques et fonctionnelles en respectant coûts et délais.

Office

MONOGRAM

Malt

La résolution de mes problèmes à été rapide et efficace, je recommande :)

La résolution de mes problèmes à été rapide et efficace, je recommande :).

Marine

MES-Distribution

Malt

Super

Super

Jl

Kaigan

Malt

Au Top

Au Top. tout simplement

Elite Cbd

Canna Elite Europe Ltd

Malt

Configuration d''un VPS et migration réalisée avec succès, bons conseils, dia

Configuration d'un VPS et migration réalisée avec succès, bons conseils, diagnostique rapide et efficace de nos problèmes. Je recommande.

Lorie

GRIIN outdoor

Malt

Toujours aussi clair et clairvoyant

Toujours aussi clair et clairvoyant... ;) Un plaisir de travailler avec Alexandre

Elite Cbd

Canna Elite Europe Ltd

Malt