Skip to content

Latest commit

 

History

History
1487 lines (1113 loc) · 34.4 KB

File metadata and controls

1487 lines (1113 loc) · 34.4 KB

🔝 Retour au Sommaire

19.6.5. Documentation Runbooks

Introduction

Un runbook (ou playbook) est un document opérationnel qui décrit étape par étape comment gérer une situation spécifique : incident, tâche de maintenance, procédure de déploiement, etc.

Pourquoi les runbooks sont critiques :

  1. Réduire le stress : En urgence, avoir un guide clair évite la panique
  2. Accélérer la résolution : Pas besoin de chercher comment faire
  3. Standardiser : Tout le monde suit la même procédure éprouvée
  4. Former : Les nouveaux membres apprennent rapidement
  5. Améliorer : Documenter permet d'optimiser les processus

Analogie : Un runbook est comme une recette de cuisine. Sans recette, vous pouvez cuisiner, mais c'est plus long, plus risqué, et moins reproductible. Avec une bonne recette, même un débutant peut réussir.

Principe clé : En production, à 3h du matin avec un incident critique, vous ne voulez pas réfléchir. Vous voulez suivre un processus éprouvé.

Cette section vous guide pour créer des runbooks efficaces pour PostgreSQL.


1. Anatomie d'un Bon Runbook

1.1. Structure Standard

Un runbook efficace contient toujours :

# RUNBOOK: [Titre descriptif]

## Métadonnées
- **Créé par**: Nom de l'auteur
- **Date création**: YYYY-MM-DD
- **Dernière mise à jour**: YYYY-MM-DD
- **Version**: X.Y
- **Criticité**: [Critique/Élevée/Moyenne/Faible]
- **Fréquence**: [Quotidien/Hebdo/Mensuel/Rare/Urgence]

## Contexte
[Quand utiliser ce runbook ? Quel problème résout-il ?]

## Symptômes
[Comment reconnaître cette situation ?]
- Symptôme 1
- Symptôme 2
- Symptôme 3

## Prérequis
[Accès, permissions, outils nécessaires]
- [ ] Accès SSH au serveur
- [ ] Accès psql en tant que postgres
- [ ] Monitoring dashboard disponible

## Procédure
### Étape 1: [Action]
[Description détaillée]
```bash
# Commande à exécuter

Résultat attendu: [Ce que vous devez voir]
Si échec: [Que faire si ça ne marche pas]

Étape 2: [Action]

...

Validation

[Comment vérifier que le problème est résolu ?]

  • Critère 1
  • Critère 2

Rollback

[Comment annuler les changements si nécessaire]

Prévention

[Comment éviter que ça se reproduise]

Contacts d'urgence

Historique des utilisations

Date Par qui Contexte Résultat
2025-11-23 Alice Prod ✅ OK

### 1.2. Principes de Rédaction

**DO** ✅ :
- Écrire pour quelqu'un qui ne connaît pas le sujet
- Utiliser des commandes copiables-collables
- Indiquer les résultats attendus
- Ajouter des captures d'écran si utile
- Tester le runbook avant de le publier
- Mettre à jour après chaque utilisation

**DON'T** ❌ :
- Supposer des connaissances implicites
- Utiliser du jargon sans l'expliquer
- Omettre les cas d'erreur
- Oublier les contacts d'urgence
- Laisser vieillir sans maintenance

---

## 2. Runbooks Essentiels PostgreSQL

### 2.1. RUNBOOK: Saturation des Connexions

```markdown
# RUNBOOK: Résolution Saturation des Connexions PostgreSQL

## Métadonnées
- **Criticité**: Critique
- **RTO**: 5 minutes
- **Version**: 1.2
- **Dernière MAJ**: 2025-11-23

## Contexte
PostgreSQL refuse de nouvelles connexions car `max_connections` est atteint.  
Applications affichent "FATAL: sorry, too many clients already".  

## Symptômes
- ❌ Applications ne peuvent plus se connecter
- ⚠️ Dashboard monitoring: connexions = max_connections
- ⚠️ Logs PostgreSQL: "too many clients already"

## Prérequis
- [ ] Accès SSH au serveur PostgreSQL
- [ ] Accès psql via socket Unix (bypass limit)
- [ ] Accès monitoring dashboard

## Procédure

### Étape 1: Confirmer le Problème

```bash
# Se connecter via socket Unix (bypass connexion limit)
sudo -u postgres psql

# Vérifier les connexions actives
SELECT count(*) as current,
       (SELECT setting::int FROM pg_settings WHERE name = 'max_connections') as max
FROM pg_stat_activity;

Résultat attendu:

 current | max
---------+-----
     100 | 100

Si current ≈ max → Problème confirmé, continuer.

Étape 2: Identifier les Connexions

-- Vue d'ensemble
SELECT
  state,
  count(*) as count,
  round(100.0 * count(*) / sum(count(*)) OVER (), 1) as percent
FROM pg_stat_activity  
GROUP BY state  
ORDER BY count DESC;  

Analyser les résultats:

  • Beaucoup de idle → Applications gardent connexions ouvertes
  • Beaucoup de idle in transaction → Transactions non terminées
  • Beaucoup de active → Charge réelle élevée

Étape 3: Tuer les Connexions Idle

-- Lister les connexions idle > 10 minutes
SELECT
  pid,
  usename,
  application_name,
  client_addr,
  state,
  now() - state_change as idle_time,
  query
FROM pg_stat_activity  
WHERE state = 'idle'  
  AND now() - state_change > interval '10 minutes'
ORDER BY idle_time DESC;

-- Tuer ces connexions (REMPLACER LES PID)
SELECT pg_terminate_backend(12345);  
SELECT pg_terminate_backend(12346);  
-- ... répéter pour chaque PID

Résultat attendu: Connexions libérées, applications peuvent se reconnecter.

Étape 4: Tuer les Transactions Bloquées

-- Transactions idle in transaction > 5 minutes
SELECT
  pid,
  usename,
  state,
  now() - xact_start as duration,
  query
FROM pg_stat_activity  
WHERE state = 'idle in transaction'  
  AND now() - xact_start > interval '5 minutes'
ORDER BY duration DESC;

-- Tuer (DANGER: peut causer rollback)
SELECT pg_terminate_backend(PID);

⚠️ ATTENTION: Tuer une transaction provoque un ROLLBACK. Coordonner avec les équipes applicatives si possible.

Étape 5: Solution d'Urgence (Si Toujours Saturé)

-- Augmenter temporairement max_connections
ALTER SYSTEM SET max_connections = 200;

-- Recharger la configuration
SELECT pg_reload_conf();

⚠️ NOTE: Nécessite un RESTART pour prendre effet complet. Planifier un restart en fenêtre de maintenance.

# Restart PostgreSQL
sudo systemctl restart postgresql-18

Validation

  • Connexions libérées: SELECT count(*) FROM pg_stat_activity; < max_connections
  • Applications peuvent se connecter
  • Pas de nouvelles erreurs dans les logs
  • Monitoring dashboard: connexions < 80%

Rollback

-- Si augmentation temporaire de max_connections
ALTER SYSTEM RESET max_connections;
-- Restart requis

Prévention (Action Post-Incident)

  1. Court terme:

    • Installer PgBouncer (connection pooling)
    • Configurer connection timeout dans applications
  2. Moyen terme:

    • Auditer les applications: Qui garde les connexions ?
    • Implémenter connection pooling côté app
    • Monitorer trend des connexions
  3. Long terme:

    • Revoir l'architecture (microservices trop de connexions ?)
    • Dimensionner max_connections approprié
    • Alertes si connexions > 80%

Contacts d'Urgence

  • DBA Principal: +33 6 XX XX XX XX (disponible 24/7)
  • Lead Dev Backend: +33 6 YY YY YY YY
  • Astreinte Ops: ops-oncall@company.com

Historique

Date Qui Contexte Résultat
2025-11-20 Alice Prod - Black Friday ✅ Résolu 8min
2025-10-15 Bob Staging - Test ✅ Résolu 5min

---

### 2.2. RUNBOOK: Requêtes Lentes Bloquant la Production

```markdown
# RUNBOOK: Gestion des Requêtes Lentes

## Métadonnées
- **Criticité**: Élevée
- **RTO**: 10 minutes
- **Version**: 1.1

## Contexte
Une ou plusieurs requêtes lentes saturent les ressources et ralentissent  
toutes les autres opérations.  

## Symptômes
- ⚠️ CPU > 90% de façon soutenue
- ⚠️ Latence applicative élevée (p95 > 1s)
- ⚠️ Monitoring: Requêtes actives avec temps d'exécution élevé

## Procédure

### Étape 1: Identifier les Requêtes Lentes

```sql
-- Requêtes actives > 10 secondes
SELECT
  pid,
  usename,
  application_name,
  state,
  now() - query_start as duration,
  query
FROM pg_stat_activity  
WHERE state = 'active'  
  AND now() - query_start > interval '10 seconds'
ORDER BY duration DESC  
LIMIT 10;  

Noter les PIDs des requêtes problématiques.

Étape 2: Analyser le Plan d'Exécution

-- Se connecter en tant que l'utilisateur problématique
SET ROLE username;

-- EXPLAIN ANALYZE sur la requête (copier depuis pg_stat_activity)
EXPLAIN (ANALYZE, BUFFERS)  
SELECT ... -- COLLER LA REQUÊTE ICI  

Identifier:

  • Sequential Scans sur grosses tables
  • Nested Loops sur tables volumineuses
  • Sorts sans index approprié

Étape 3: Décision Tuer ou Laisser

Critères pour tuer:

  • Durée > 5 minutes ET pas critique métier
  • Bloque d'autres transactions (vérifier locks)
  • Utilise trop de ressources (temp files massifs)

Critères pour laisser:

  • Batch prévu (import, migration)
  • Transaction critique métier
  • Presque terminé (> 90% avancement si visible)

Étape 4: Tuer la Requête (si nécessaire)

-- Tuer gentiment (laisse finir l'instruction en cours)
SELECT pg_cancel_backend(PID);

-- Attendre 30 secondes...

-- Si toujours là, tuer brutalement
SELECT pg_terminate_backend(PID);

Étape 5: Solution Temporaire (Optimiser)

-- Si index manquant est évident
CREATE INDEX CONCURRENTLY idx_table_column ON table(column);

-- Si requête récurrente, augmenter work_mem pour cette session
ALTER USER username SET work_mem = '256MB';

Validation

  • Requête terminée ou tuée
  • CPU redescendu < 70%
  • Latence applicative normale
  • Pas de nouvelles requêtes lentes similaires

Prévention

  1. Analyser la requête avec EXPLAIN
  2. Créer index approprié
  3. Réécrire requête si inefficace
  4. Ajouter monitoring spécifique
  5. Alerter si cette requête redevient lente

Contacts

  • DBA: +33 6 XX XX XX XX
  • Dev Team Lead: +33 6 YY YY YY YY

---

### 2.3. RUNBOOK: Espace Disque Saturé

```markdown
# RUNBOOK: Gestion Espace Disque Critique

## Métadonnées
- **Criticité**: Critique
- **RTO**: 15 minutes
- **Version**: 1.3

## Contexte
Le disque contenant PostgreSQL est plein ou presque plein.  
PostgreSQL peut s'arrêter ou refuser d'écrire.  

## Symptômes
- ❌ PostgreSQL crashe ou refuse écritures
- ⚠️ Monitoring: Disk usage > 90%
- ⚠️ Logs: "No space left on device"

## Prérequis
- [ ] Accès root au serveur
- [ ] Connaissance architecture disques
- [ ] Backup récent disponible

## Procédure

### Étape 1: Vérifier l'Espace Disque

```bash
# Vue d'ensemble
df -h

# Focus sur PostgreSQL
df -h /var/lib/pgsql  
df -h /mnt/wal_archive  # Si WAL archiving  

Noter le pourcentage utilisé.

Étape 2: Identifier les Gros Consommateurs

# Taille répertoire data
sudo du -sh /var/lib/pgsql/18/data

# Top 10 fichiers les plus gros
sudo find /var/lib/pgsql/18/data -type f -exec du -h {} + | sort -rh | head -20

Cas courants:

  • WAL archives non nettoyés
  • Tables/index temporaires énormes
  • Logs PostgreSQL non rotatés

Étape 3: Nettoyage d'Urgence

Option A: Nettoyer les Logs

# Vérifier taille logs
sudo du -sh /var/lib/pgsql/18/data/log

# Archiver et compresser (si possible)
sudo tar -czf /tmp/old_logs_$(date +%Y%m%d).tar.gz /var/lib/pgsql/18/data/log/*.log.1 /var/lib/pgsql/18/data/log/*.log.2  
sudo rm /var/lib/pgsql/18/data/log/*.log.1 /var/lib/pgsql/18/data/log/*.log.2  

# Ou supprimer directement (PERTE D'HISTORIQUE)
sudo rm /var/lib/pgsql/18/data/log/*.log.1

Option B: Nettoyer WAL Archives

# ⚠️ DANGER: Ne supprimer que si backup récent OK
sudo du -sh /mnt/wal_archive

# Garder seulement 3 derniers jours (exemple)
sudo find /mnt/wal_archive -name "*.gz" -mtime +3 -delete  
sudo find /mnt/wal_archive -name "0*" -mtime +3 -delete  

Option C: VACUUM FULL (Attention: LOCK tables)

-- Identifier les tables avec le plus de bloat
SELECT
  schemaname || '.' || tablename as table_name,
  pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size,
  n_dead_tup
FROM pg_stat_user_tables  
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC  
LIMIT 10;  

-- VACUUM FULL sur table spécifique (BLOQUE TOUT)
-- ⚠️ Coordonner avec équipes métier
VACUUM FULL table_with_bloat;

Étape 4: Solution Temporaire (Monter Volume Supplémentaire)

# Si volume supplémentaire disponible
sudo mkdir /mnt/extra_space  
sudo mount /dev/sdX /mnt/extra_space  

# Déplacer WAL archives
sudo mv /mnt/wal_archive/* /mnt/extra_space/wal_archive/  
sudo ln -s /mnt/extra_space/wal_archive /mnt/wal_archive  

Étape 5: Redémarrer PostgreSQL (si nécessaire)

# Vérifier état
sudo systemctl status postgresql-18

# Redémarrer si arrêté
sudo systemctl start postgresql-18

# Vérifier logs
sudo tail -f /var/lib/pgsql/18/data/log/postgresql-*.log

Validation

  • Espace disque libéré (< 80%)
  • PostgreSQL démarré et fonctionnel
  • Applications peuvent écrire
  • Pas d'erreurs dans logs
  • Monitoring disk OK

Prévention

  1. Immédiat:

    • Configurer log rotation aggressive
    • Nettoyer WAL archives automatiquement
    • Alerte à 70% (pas 90%)
  2. Court terme:

    • Augmenter taille volume
    • Archiver logs vers stockage externe
    • VACUUM régulier des grosses tables
  3. Long terme:

    • Partitionnement des grosses tables
    • Archivage données historiques
    • Monitoring proactif espace disque

Contacts

  • Infrastructure: +33 6 XX XX XX XX
  • DBA: +33 6 YY YY YY YY
  • Cloud Support: support@provider.com (si cloud)

---

### 2.4. RUNBOOK: Réplication Cassée

```markdown
# RUNBOOK: Résolution Réplication PostgreSQL

## Métadonnées
- **Criticité**: Élevée
- **RTO**: 30 minutes
- **Version**: 1.2

## Contexte
La réplication entre primary et standby est cassée ou en retard.

## Symptômes
- ⚠️ Monitoring: Replication lag > 5 minutes
- ⚠️ Standby: "invalid record length"
- ⚠️ Dashboard: Standby status = "disconnected"

## Procédure

### Étape 1: Vérifier l'État de la Réplication

**Sur le Primary**:

```sql
-- Voir les standbys connectés
SELECT
  client_addr,
  state,
  sent_lsn,
  write_lsn,
  flush_lsn,
  replay_lsn,
  sync_state,
  pg_wal_lsn_diff(sent_lsn, replay_lsn) as lag_bytes
FROM pg_stat_replication;

Résultat attendu: Au moins 1 ligne par standby.
Si vide → Standby déconnecté.

Sur le Standby:

SELECT pg_is_in_recovery();
-- Doit retourner 't' (true)

SELECT
  now() - pg_last_xact_replay_timestamp() as replication_lag,
  pg_is_wal_replay_paused();

Étape 2: Diagnostiquer la Cause

Cas A: Standby Déconnecté

# Vérifier logs standby
sudo tail -100 /var/lib/pgsql/18/data/log/postgresql-*.log

# Rechercher erreurs
grep -i "error\|fatal\|could not" /var/lib/pgsql/18/data/log/postgresql-*.log

Erreurs courantes:

  • "invalid record length" → WAL corrompu
  • "requested WAL segment has already been removed" → WAL manquant
  • "could not connect" → Problème réseau

Cas B: Lag Excessif

-- Vérifier activité sur primary
SELECT count(*) FROM pg_stat_activity WHERE state = 'active';

-- Vérifier I/O sur standby
SELECT * FROM pg_stat_io;  -- PG 18

Étape 3: Solutions par Cas

Solution A: WAL Manquant (Recréer Standby)

# Sur le standby - Arrêter PostgreSQL
sudo systemctl stop postgresql-18

# Sauvegarder config
sudo cp /var/lib/pgsql/18/data/postgresql.conf /tmp/  
sudo cp /var/lib/pgsql/18/data/postgresql.auto.conf /tmp/  

# Supprimer data directory
sudo rm -rf /var/lib/pgsql/18/data

# Recréer depuis primary
sudo -u postgres pg_basebackup \
  -h primary.example.com \
  -U replicator \
  -D /var/lib/pgsql/18/data \
  -Fp -Xs -P -R

# Restaurer config locale
sudo cp /tmp/postgresql.conf /var/lib/pgsql/18/data/  
sudo cp /tmp/postgresql.auto.conf /var/lib/pgsql/18/data/  

# Redémarrer
sudo systemctl start postgresql-18

Solution B: Problème Réseau

# Tester connectivité
telnet primary.example.com 5432

# Vérifier pg_hba.conf sur primary
# Doit contenir:
# host    replication     replicator      STANDBY_IP/32   scram-sha-256

# Vérifier firewall
sudo firewall-cmd --list-all

Solution C: Lag Performance (Standby Lent)

-- Sur standby, augmenter ressources
ALTER SYSTEM SET max_parallel_workers = 8;  
ALTER SYSTEM SET hot_standby_feedback = on;  
SELECT pg_reload_conf();  

Étape 4: Vérifier la Reprise

-- Sur primary
SELECT client_addr, state, sync_state  
FROM pg_stat_replication;  
-- État doit être 'streaming'

-- Sur standby
SELECT
  now() - pg_last_xact_replay_timestamp() as lag,
  pg_last_wal_replay_lsn();
-- Lag doit diminuer

Validation

  • Standby visible dans pg_stat_replication
  • State = 'streaming'
  • Lag < 30 secondes
  • Standby logs sans erreurs
  • Tests applicatifs sur standby OK

Prévention

  1. Augmenter wal_keep_size sur primary
  2. Utiliser slots de réplication
  3. Monitorer lag en continu
  4. Alerter si lag > 1 minute
  5. Documentation réseau à jour

Contacts

  • DBA: +33 6 XX XX XX XX
  • Réseau: +33 6 YY YY YY YY

---

### 2.5. RUNBOOK: VACUUM Bloqué

```markdown
# RUNBOOK: Débloquer VACUUM Problématique

## Métadonnées
- **Criticité**: Moyenne
- **RTO**: 20 minutes
- **Version**: 1.0

## Contexte
Un VACUUM (manuel ou autovacuum) tourne depuis très longtemps  
ou ne se termine jamais.  

## Symptômes
- ⚠️ VACUUM actif depuis > 2 heures
- ⚠️ Bloat continue d'augmenter
- ⚠️ pg_stat_activity: état "autovacuum"

## Procédure

### Étape 1: Identifier le VACUUM Bloqué

```sql
SELECT
  pid,
  usename,
  state,
  now() - xact_start as duration,
  query
FROM pg_stat_activity  
WHERE query LIKE '%VACUUM%'  
  AND state = 'active'
ORDER BY duration DESC;

Étape 2: Identifier ce qui Bloque

-- Longues transactions bloquant VACUUM
SELECT
  pid,
  usename,
  state,
  now() - xact_start as duration,
  query
FROM pg_stat_activity  
WHERE state IN ('idle in transaction', 'active')  
  AND now() - xact_start > interval '30 minutes'
ORDER BY duration DESC;

Explication: Une transaction longue empêche VACUUM de nettoyer les tuples morts (car ils pourraient encore être visibles par cette transaction).

Étape 3: Tuer les Transactions Bloquantes

-- Vérifier que ce n'est pas une transaction critique
-- Puis tuer
SELECT pg_terminate_backend(PID_TRANSACTION_LONGUE);

Étape 4: Laisser VACUUM Continuer ou Relancer

-- Si VACUUM continue, surveiller progression
SELECT
  pid,
  phase,
  heap_blks_scanned,
  heap_blks_vacuumed,
  round(100.0 * heap_blks_vacuumed / NULLIF(heap_blks_scanned, 0), 1) as percent
FROM pg_stat_progress_vacuum;

-- Si besoin de relancer manuellement
VACUUM (VERBOSE, ANALYZE) table_name;

Validation

  • VACUUM terminé
  • Dead tuples diminué
  • Bloat stabilisé
  • Pas de nouvelles transactions longues

Prévention

  1. Éviter longues transactions "idle in transaction"
  2. Configurer idle_in_transaction_session_timeout
  3. Augmenter autovacuum workers
  4. Monitorer transactions longues

Contacts

  • DBA: +33 6 XX XX XX XX

---

## 3. Templates de Runbooks

### 3.1. Template Vierge

```markdown
# RUNBOOK: [Titre]

## Métadonnées
- **Créé par**:
- **Date création**:
- **Dernière MAJ**:
- **Version**: 1.0
- **Criticité**: [Critique/Élevée/Moyenne/Faible]
- **Fréquence**: [Quotidien/Hebdo/Mensuel/Rare/Urgence]
- **RTO cible**: [Temps max de résolution]

## Contexte
[Description du problème ou de la tâche]

## Symptômes (si incident)
- Symptôme 1
- Symptôme 2

## Prérequis
- [ ] Prérequis 1
- [ ] Prérequis 2

## Procédure

### Étape 1: [Action]
[Description]

```bash
# Commandes

Résultat attendu:
Si échec:

Étape 2: [Action]

...

Validation

  • Critère 1
  • Critère 2

Rollback (si applicable)

[Comment annuler]

Prévention

[Actions pour éviter récurrence]

Contacts

  • Contact 1: [Nom, téléphone, email]
  • Contact 2: [Nom, téléphone, email]

Notes

[Observations, cas particuliers]

Historique

Date Qui Contexte Résultat

### 3.2. Template Incident Critique

```markdown
# RUNBOOK URGENCE: [Titre]

## 🚨 INCIDENT CRITIQUE 🚨

**TEMPS DE RÉSOLUTION CIBLE: [X] MINUTES**

## Quick Actions (Go, No Go)
- [ ] **GO** si [conditions]
- [ ] **NO GO** si [conditions] → Escalader immédiatement

## Contacts d'Urgence (Appeler MAINTENANT)
1. **DBA On-Call**: [Nom] - [Téléphone]
2. **Manager**: [Nom] - [Téléphone]
3. **Vendor Support**: [Numéro]

## Procédure d'Urgence (5 minutes max)

### 1️⃣ STOP THE BLEEDING (30 secondes)
```bash
[Commande pour stopper l'hémorragie]

2️⃣ ASSESS (2 minutes)

[Requêtes diagnostiques rapides]

3️⃣ FIX (2 minutes)

[Solution rapide]

4️⃣ VERIFY (30 secondes)

  • [Vérification rapide 1]
  • [Vérification rapide 2]

Post-Incident (Après résolution)

  • Communication stakeholders
  • Post-mortem planifié
  • Documentation incident
  • Actions de prévention

### 3.3. Template Maintenance Planifiée

```markdown
# RUNBOOK MAINTENANCE: [Titre]

## Métadonnées
- **Fenêtre maintenance**: [Date/Heure]
- **Durée estimée**: [X] heures
- **Downtime accepté**: [Oui/Non]
- **Rollback possible**: [Oui/Non]

## Pré-Maintenance (J-1)

### Checklist Préparation
- [ ] Backup complet vérifié
- [ ] Équipes métier notifiées
- [ ] Fenêtre maintenance confirmée
- [ ] Accès vérifiés
- [ ] Procédure de rollback testée
- [ ] Monitoring en place

## Maintenance (Jour J)

### Phase 1: Préparation (T0)
[Actions préparatoires]

### Phase 2: Début maintenance (T0 + 10min)
```bash
# Mettre en maintenance

Phase 3: Opération (T0 + 20min)

[Opérations principales]

Phase 4: Validation (T0 + 40min)

[Tests de validation]

Phase 5: Fin maintenance (T0 + 50min)

# Remettre en service

Validation

  • Service fonctionnel
  • Monitoring OK
  • Tests applicatifs OK
  • Communication fin maintenance

Rollback (Si Problème)

[Procédure complète de rollback]

Post-Maintenance

  • Documentation mise à jour
  • Leçons apprises
  • Monitoring 24h post-maintenance

---

## 4. Gestion des Runbooks

### 4.1. Organisation

**Structure de répertoires recommandée**:

runbooks/ ├── README.md # Index de tous les runbooks ├── templates/ │ ├── incident.md │ ├── maintenance.md │ └── standard.md ├── incidents/ │ ├── 01-saturation-connexions.md │ ├── 02-requetes-lentes.md │ ├── 03-espace-disque.md │ ├── 04-replication-cassee.md │ └── 05-vacuum-bloque.md ├── maintenance/ │ ├── upgrade-postgresql.md │ ├── reindex-database.md │ └── migration-serveur.md ├── operations/ │ ├── backup-restore.md │ ├── failover-manuel.md │ └── ajout-utilisateur.md └── deprecated/ └── [anciens runbooks]


### 4.2. Conventions de Nommage

[ID]-[titre-court].md

Exemples:

  • INC-01-saturation-connexions.md
  • MAINT-05-upgrade-pg18.md
  • OPS-03-backup-restore.md

**Préfixes**:
- `INC` : Incident  
- `MAINT` : Maintenance  
- `OPS` : Opération courante  
- `EMG` : Urgence critique

### 4.3. Versioning

Utilisez Git pour versionner vos runbooks :

```bash
# Initialiser repo
git init runbooks  
cd runbooks  

# Structure de commits
git commit -m "feat: Ajouter runbook saturation connexions"  
git commit -m "fix: Corriger commande dans runbook réplication"  
git commit -m "docs: Mettre à jour contacts d'urgence"  

Tags pour versions stables :

git tag -a v1.0 -m "Version 1.0 - Runbooks production ready"  
git push origin v1.0  

4.4. Review et Validation

Processus de validation :

  1. Création: Auteur rédige le runbook
  2. Review technique: Senior DBA valide techniquement
  3. Test en staging: Exécution complète en environnement test
  4. Review opérationnelle: Équipe ops vérifie clarté
  5. Approbation: Manager signe
  6. Publication: Ajout au repository officiel

Template de Pull Request :

## Nouveau Runbook: [Titre]

### Type
- [ ] Incident
- [ ] Maintenance
- [ ] Opération courante
- [ ] Urgence

### Checklist
- [ ] Testé en environnement staging
- [ ] Validé par senior DBA
- [ ] Contacts à jour
- [ ] Captures d'écran ajoutées (si pertinent)
- [ ] Références documentées

### Contexte
[Pourquoi ce runbook est nécessaire]

### Testeurs
- [ ] @alice : Testé le 2025-11-20, OK
- [ ] @bob : Review le 2025-11-21, suggestions intégrées

5. Outils et Plateformes

5.1. Markdown + Git (Simple et Efficace)

Avantages:

  • ✅ Versionning natif
  • ✅ Diff et merge faciles
  • ✅ Gratuit
  • ✅ Accessible partout

Outils:

  • GitHub/GitLab/Bitbucket
  • Markdown editors (Typora, MarkText, VSCode)

5.2. Wiki (Confluence, Notion)

Avantages:

  • ✅ Interface graphique
  • ✅ Collaboration temps réel
  • ✅ Recherche puissante
  • ✅ Intégrations (Slack, Jira)

Exemple Confluence :

Runbooks PostgreSQL
├─ 🚨 Incidents Critiques
│  ├─ Saturation des connexions
│  ├─ Espace disque plein
│  └─ Réplication cassée
├─ 🔧 Maintenance
│  ├─ Upgrade PostgreSQL
│  └─ Reindex complet
└─ 📖 Opérations Courantes
   ├─ Backup/Restore
   └─ Ajout utilisateur

5.3. PagerDuty Runbooks

Intégration avec alerting :

# pagerduty_runbook.yaml
runbook_url: "https://wiki.company.com/runbooks/postgres-connections"  
auto_attach: true  

Quand une alerte se déclenche, le runbook est automatiquement lié.

5.4. Runbooks Interactifs (Jupyter, Rundeck)

Jupyter Notebook pour runbooks exécutables :

# Runbook: Check PostgreSQL Health
import psycopg2

# Connexion
conn = psycopg2.connect(
    host="localhost",
    database="myapp",
    user="postgres"
)

# Étape 1: Vérifier connexions
query = """  
SELECT count(*) as current,  
       (SELECT setting::int FROM pg_settings WHERE name='max_connections') as max
FROM pg_stat_activity;
"""
cur = conn.cursor()  
cur.execute(query)  
print(cur.fetchone())  

# Étape 2: ...

Rundeck pour automatisation :

  • Interface web pour exécuter runbooks
  • Logs d'exécution automatiques
  • Contrôle d'accès

6. Maintenance des Runbooks

6.1. Cycle de Vie

Création → Validation → Publication → Utilisation → Review → MAJ → Archivage
                                          ↓
                                    Amélioration Continue

6.2. Triggers de Mise à Jour

Mettre à jour un runbook quand :

  1. Après chaque utilisation

    • Ajouter dans historique
    • Noter problèmes rencontrés
    • Améliorer si procédure imprécise
  2. Changement d'infrastructure

    • Migration cloud
    • Nouvelle version PostgreSQL
    • Changement d'architecture
  3. Incidents

    • Post-mortem identifie lacune
    • Nouvelle procédure découverte
  4. Review planifiée

    • Trimestriel : Review tous runbooks
    • Vérifier obsolescence
    • Valider contacts

6.3. Métriques de Qualité

Indicateurs d'un bon runbook :

Métrique Cible Comment mesurer
Temps de résolution < RTO Comparer durée réelle vs RTO
Taux de succès > 95% % d'exécutions sans escalade
Clarté High Feedback utilisateurs (scale 1-5)
Complétude 100% % d'étapes couvertes vs incidents réels
Freshness < 6 mois Âge depuis dernière MAJ

Dashboard runbooks :

## Runbooks Health Dashboard

| Runbook              | Dernière MAJ | Utilisé (3 mois) | Succès | Notes |
|----------------------|--------------|------------------|--------|-------|
| Saturation connexions| 2025-11-20   | 5 fois           | 100%   | ✅ OK |
| Requêtes lentes      | 2025-10-15   | 12 fois          | 90%    | ⚠️ À améliorer |
| Espace disque        | 2025-09-01   | 1 fois           | 100%   | ⚠️ Vieux |
| Réplication cassée   | 2025-11-18   | 0 fois           | N/A    | ✅ OK |

7. Formation et Onboarding

7.1. Formation Nouveaux Membres

Programme d'onboarding :

Semaine 1 :

  • Lire tous les runbooks incidents critiques
  • Exécuter en staging (simulation)
  • Quiz de validation

Semaine 2 :

  • Participer à une astreinte avec senior
  • Observer résolution d'incident réel
  • Pair programming sur runbooks

Semaine 3 :

  • Première astreinte en autonomie (avec backup)
  • Créer ou améliorer un runbook

Semaine 4 :

  • Validation finale (simulation incident complexe)
  • Certification "Ops ready"

7.2. Simulation d'Incidents (GameDay)

Exercice trimestriel :

# GameDay: Incident PostgreSQL

## Scénario
Il est 14h. Le monitoring alerte :
- CPU 95%
- Connexions: 98/100
- Latence applicative: 5s (vs 50ms normal)

## Objectifs
1. Diagnostiquer en 5 min
2. Résoudre en 15 min
3. Documenter actions

## Évaluation
- Temps de résolution
- Utilisation runbook
- Communication
- Post-mortem qualité

7.3. Certification Interne

Checklist certification "DBA Ops" :

  • Connaît tous les runbooks critiques
  • A résolu 3 incidents en simulation
  • A créé ou amélioré 1 runbook
  • A participé à 2 astreintes
  • A passé le quiz certification (> 80%)

8. Runbooks et Culture DevOps

8.1. Documentation as Code

Traiter les runbooks comme du code :

# .gitlab-ci.yml
runbooks-lint:
  script:
    - markdownlint runbooks/**/*.md
    - check-links runbooks/**/*.md

runbooks-test:
  script:
    - python test_runbooks.py

runbooks-publish:
  script:
    - mkdocs build
    - aws s3 sync site/ s3://runbooks.company.com/
  only:
    - main

8.2. Blameless Post-Mortems

Après chaque incident :

# Post-Mortem: [Titre Incident]

## Timeline
- **14:00**: Alerte monitoring
- **14:02**: Équipe ops notifiée
- **14:05**: Diagnostic initial
- **14:10**: Solution appliquée
- **14:15**: Service rétabli
- **14:30**: Post-mortem débute

## Root Cause
[Cause racine identifiée]

## Pourquoi le runbook n'a pas suffi ?
- Étape X manquait
- Commande Y obsolète
- Contact Z pas à jour

## Actions
1. [ ] Mettre à jour runbook (Owner: Alice, Due: 2025-11-25)
2. [ ] Ajouter alerte préventive (Owner: Bob, Due: 2025-11-27)
3. [ ] Former équipe sur nouveau process (Owner: Charlie, Due: 2025-12-01)

## Lessons Learned
[Ce que nous avons appris]

9. Checklist Runbooks Production

✅ Création et Organisation

  • Repository Git configuré
  • Structure de répertoires définie
  • Templates standardisés
  • Conventions de nommage respectées
  • README.md avec index à jour

✅ Runbooks Essentiels Créés

  • Saturation des connexions
  • Requêtes lentes
  • Espace disque plein
  • Réplication cassée
  • VACUUM bloqué
  • Upgrade PostgreSQL
  • Backup/Restore
  • Failover manuel

✅ Qualité et Validation

  • Tous runbooks testés en staging
  • Review par senior DBA
  • Contacts d'urgence à jour
  • Captures d'écran ajoutées
  • Résultats attendus documentés

✅ Accessibilité

  • Runbooks accessibles 24/7
  • Version imprimée disponible (critiques)
  • Liens dans monitoring/alerting
  • Accès mobile testé

✅ Processus

  • Workflow de création défini
  • Process de review établi
  • Schedule de maintenance (trimestriel)
  • Training nouveaux membres
  • GameDays planifiés

✅ Monitoring

  • Dashboard runbooks santé
  • Métriques d'utilisation trackées
  • Feedback collecté
  • Amélioration continue

10. Ressources et Outils

Documentation et Guides

Outils de Documentation

  • MkDocs : Documentation from Markdown
  • Docusaurus : Documentation websites
  • GitBook : Modern documentation platform
  • Confluence : Enterprise wiki
  • Notion : Collaborative workspace

Outils de Gestion

  • Rundeck : Runbook automation
  • PagerDuty : Incident management
  • OpsGenie : Alert management
  • Jupyter : Interactive runbooks

Standards et Best Practices

  • ITIL : IT Service Management
  • SRE Principles : Google SRE practices
  • DevOps Handbook : DevOps best practices

Conclusion

Les runbooks sont votre filet de sécurité en production. Ils transforment le chaos d'un incident en une procédure claire et reproductible.

Les 7 Principes des Runbooks Efficaces :

  1. Clarté : Écrire pour quelqu'un qui panique à 3h du matin
  2. Complétude : Chaque étape, chaque commande, chaque résultat
  3. Testabilité : Validé en staging avant production
  4. Accessibilité : Disponible 24/7, partout
  5. Maintenabilité : À jour, versionné, revu régulièrement
  6. Actionabilité : Pas de théorie, que de la pratique
  7. Amélioration continue : Apprendre de chaque utilisation

Roadmap de mise en place :

Semaine Actions
1 Créer repository, templates, 3 runbooks critiques
2 Tester runbooks en staging, corriger
3 Former équipe, première simulation
4 Publier runbooks, intégrer monitoring
5-12 Créer runbooks additionnels, amélioration continue

"The difference between a good engineer and a great engineer is documentation."

Avec des runbooks de qualité, votre équipe sera :

  • Plus rapide (temps de résolution réduit)
  • Plus confiante (procédure claire)
  • Plus efficace (moins d'erreurs)
  • Plus résiliente (knowledge distribué)

Investissez dans vos runbooks aujourd'hui. Votre futur vous (et votre équipe) vous remercieront.


⏭️ Drivers, Connexion Applicative et Bonnes Pratiques