Introduction
Les blameless postmortems représentent un pilier fondamental de la pratique SRE (Site Reliability Engineering), popularisés par Google dans leur SRE Book. Contrairement aux revues traditionnelles qui cherchent des coupables, ils se concentrent sur les failles système pour transformer chaque incident en leçon collective. En 2026, avec des systèmes distribués ultra-complexes (Kubernetes, serverless, IA), implémenter des postmortems sans blâme est essentiel pour maintenir une résilience >99.99% et une culture d'apprentissage.
Pourquoi c'est crucial ? Une étude de 2025 par DORA montre que les équipes pratiquant cela déploient 2x plus vite et récupèrent 50% plus rapidement des pannes. Ce tutoriel expert vous fournit des templates structurés, scripts automatisés et intégrations prêtes pour GitHub, Slack et alerting. Vous apprendrez à collecter des données objectives (logs, métriques), générer des rapports et diffuser les learnings. Résultat : des systèmes plus robustes et une équipe motivée, sans peur de l'échec.
Structure progressive : du template de base à l'automatisation complète. Prêt à bookmarker ? (128 mots)
Prérequis
- Expérience SRE/DevOps avancée (Kubernetes, observabilité).
- Outils : GitHub, Python 3.12+, Bash, YAML/JSON.
- Accès à un cluster observabilité (Prometheus/Grafana ou ELK).
- Compte Slack/GitHub pour tests.
- Connaissances en alerting (PagerDuty ou similaire).
Template YAML standard pour postmortem
title: "[POSTMORTEM] Incident du [DATE]"
summary:
what_happened: "Description brève de l'impact (ex: 404 sur 30% users, 2h downtime)."
duration: "Début: YYYY-MM-DD HH:MM | Fin: YYYY-MM-DD HH:MM"
severity: "SEV-1/SEV-2/SEV-3"
timeline:
- time: "YYYY-MM-DD HH:MM"
event: "Détection (alerte PagerDuty)."
- time: "YYYY-MM-DD HH:MM"
event: "Mitigation (rollback)."
root_cause:
trigger: "Événement déclencheur objectif (ex: spike traffic 10x)."
contributing_factors:
- "Factor 1: Absence de circuit breaker."
- "Factor 2: Config limite trop basse."
resolution:
actions_taken: "Rollback v1.2.3, scale pods à 20."
stabilization: "Vérification post-mitigation."
lessons_learned:
- "Action 1: Implémenter circuit breaker (propriétaire: @devops, deadline: 2026-01-15)."
- "Action 2: Alerting préventif sur traffic (propriétaire: @observability)."
timeline_prevention:
tasks:
- task: "Déployer circuit breaker"
assignee: "@team-lead"
due: "2026-01-10"
status: "TODO"
attachments:
logs: "[Lien Grafana dashboard]"
metrics: "[Lien Prometheus query]"
reviewers:
- "@sre-lead"
- "@cto"
blameless_statement: |
Ce postmortem est blameless : focus sur systèmes, pas personnes.
Toute contribution est valorisée.Ce template YAML structuré suit les standards Google SRE : sections objectives (timeline, root_cause) pour éviter les biais. Il est validable, extensible et génère des rapports automatisés. Piège : ne pas remplir 'blameless_statement' qui ancre la culture sans faute.
Utilisation du template de base
Copiez postmortem-template.yaml dans votre repo GitHub (ex: .github/postmortems/). Remplissez-le manuellement pour un incident SEV-1. Analogie : comme un formulaire médical, il force l'objectivité (quoi/ quand/ pourquoi systémique). Validez avec yamllint avant commit. Intégrez-le à votre playbook incident : après mitigation, le Duty Engineer (DE) le remplit en 30min.
Script Python pour valider et générer Markdown
import yaml
import json
import sys
from datetime import datetime
from pathlib import Path
TEMPLATE_PATH = 'postmortem-template.yaml'
OUTPUT_MD = 'postmortem.md'
SECTIONS = ['summary', 'timeline', 'root_cause', 'resolution', 'lessons_learned']
def validate_postmortem(data):
errors = []
if 'summary' not in data or not data['summary'].get('what_happened'):
errors.append("Missing 'summary.what_happened'")
if 'blameless_statement' not in data:
errors.append("Missing 'blameless_statement'")
if 'lessons_learned' not in data or len(data['lessons_learned']) == 0:
errors.append("No 'lessons_learned' actions")
return errors
def yaml_to_markdown(data):
md = f"# {data.get('title', 'Untitled Postmortem')}\n\n"
md += f"**Résumé** : {data['summary']['what_happened']}\n\n"
md += "## Timeline\n"
for event in data.get('timeline', []):
md += f"- **{event['time']}** : {event['event']}\n"
md += "\n## Root Cause & Lessons\n"
for lesson in data.get('lessons_learned', []):
md += f"- {lesson}\n"
md += f"\n**Blameless** : {data['blameless_statement']}\n"
return md
if __name__ == '__main__':
if len(sys.argv) != 2:
print("Usage: python generate_postmortem.py <input.yaml>")
sys.exit(1)
with open(sys.argv[1], 'r') as f:
data = yaml.safe_load(f)
errors = validate_postmortem(data)
if errors:
print("Validation errors:")
for e in errors:
print(f"- {e}")
sys.exit(1)
md_content = yaml_to_markdown(data)
with open(OUTPUT_MD, 'w') as f:
f.write(md_content)
print(f"Postmortem généré : {OUTPUT_MD}")
print("Validation OK : toutes sections critiques présentes.")Ce script valide les sections obligatoires (summary, lessons) et convertit YAML en Markdown lisible pour GitHub/Wiki. Il prévient les postmortems incomplets. Lancez python generate_postmortem.py incident.yaml. Piège : oubliez les dépendances pip install pyyaml.
Automatisation de la validation
Exécutez le script post-mitigation pour générer postmortem.md. Poussez-le en draft GitHub Issue. Avantage expert : audit trail automatique, trackable via Git. Intégrez à votre incident response playbook : DE → script → review.
GitHub Action pour créer un issue postmortem
name: Create Blameless Postmortem Issue
on:
workflow_dispatch:
inputs:
incident_yaml:
description: 'Path to YAML postmortem'
required: true
default: 'postmortems/incident.yaml'
jobs:
create-issue:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Generate Markdown
run: |
pip install pyyaml
python generate_postmortem.py ${{ github.event.inputs.incident_yaml }}
- name: Create Issue
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const md = fs.readFileSync('postmortem.md', 'utf8');
const issue = await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: 'POSTMORTEM: ' + new Date().toISOString().split('T')[0],
body: md,
labels: ['postmortem', 'blameless', 'SEV-2']
});
console.log('Issue created:', issue.data.html_url);Cette Action GitHub, déclenchée manuellement, valide/génère le MD et crée un issue tracké. Labels automatiques pour dashboard. Piège : permissions contents:write, issues:write requises dans repo settings.
Intégration GitHub pour collaboration
Workflow : Post-incident, dispatch l'Action avec YAML path → issue auto-créé avec reviewers. Équipe commente/add actions via GitHub Projects. Analogie : comme un Jira blameless, mais natif Git.
Script Bash pour collecter logs et métriques
#!/bin/bash
INCIDENT_START="$1"
INCIDENT_END="$2"
OUTPUT_DIR="logs/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$OUTPUT_DIR"
# Exemple Prometheus query (adaptez à votre stack)
PROMQL="up{job='app'}[${INCIDENT_START}:${INCIDENT_END}]"
# Collecter métriques Prometheus
echo "Collecte métriques Prometheus..."
curl -s "http://prometheus:9090/api/v1/query_range?query=${PROMQL}&start=${INCIDENT_START}&end=${INCIDENT_END}&step=5m" | jq . > "$OUTPUT_DIR/prometheus.json"
# Collecter logs ELK (adaptez)
echo "Collecte logs..."
# curl -s "http://elk:9200/app-logs/_search?size=1000" > "$OUTPUT_DIR/elk_logs.json"
# Grafana snapshot
echo "Générer snapshot Grafana..."
# curl -X POST -H "Content-Type: application/json" -d '{"dashboard":{"title":"Incident Snapshot"},"from": "'$INCIDENT_START'", "to":"'$INCIDENT_END'"}' http://grafana:3000/api/snapshots > "$OUTPUT_DIR/grafana_snapshot.json"
# Ajouter au YAML
echo "attachments: { logs: '$OUTPUT_DIR/elk_logs.json', metrics: '$OUTPUT_DIR/prometheus.json' }" >> postmortem-template.yaml
echo "Logs collectés dans $OUTPUT_DIR. Ajoutez aux attachments YAML."Ce script bash collecte logs/métriques objectives autour de l'incident (format unix timestamps). Intégrez aux attachments YAML. Piège : adaptez URLs à votre observabilité ; testez en dry-run.
Collecte de données objectives
Appelez ./collect_logs.sh 1704067200 1704081600 (timestamps). Liez les outputs au template. Expert tip : cela rend le root_cause data-driven, évitant les spéculations.
Webhook Node.js pour alerting → Postmortem
import express from 'express';
import { exec } from 'child_process';
import yaml from 'js-yaml';
import fs from 'fs';
const app = express();
app.use(express.json());
const PORT = 3000;
app.post('/alert-postmortem', (req, res) => {
const { alertname, startsAt, endsAt, severity } = req.body;
console.log(`Alerte reçue: ${alertname} (${severity})`);
// Générer YAML template auto-rempli
const template = {
title: `[POSTMORTEM] Alerte ${alertname} ${new Date(startsAt).toISOString().split('T')[0]}`,
summary: {
what_happened: `Alerte ${alertname} déclenchée.`,
duration: `Début: ${startsAt} | Fin: ${endsAt}`,
severity
},
timeline: [{ time: startsAt, event: `Alerte ${alertname} reçue.` }],
blameless_statement: 'Blameless postmortem initié automatiquement.'
};
fs.writeFileSync('auto-incident.yaml', yaml.dump(template));
// Trigger collect_logs
exec(`./collect_logs.sh ${Math.floor(new Date(startsAt).getTime()/1000)} ${Math.floor(new Date(endsAt || Date.now()).getTime()/1000)}`, (err) => {
if (err) console.error('Collect failed:', err);
});
// Trigger GitHub Action via API (ajoutez token)
console.log('YAML généré, lancez GitHub Action manuellement.');
res.status(200).json({ status: 'postmortem_initiated' });
});
app.listen(PORT, () => console.log(`Webhook sur port ${PORT}`));Ce serveur Express TypeScript reçoit webhooks Prometheus/Alertmanager, génère YAML auto et trigger collecte. npm init -y; npm i express js-yaml typescript ts-node. Piège : sécurisez avec HMAC pour prod.
Automatisation complète via alerting
Intégration : Configurez Prometheus Alertmanager webhook vers /alert-postmortem. Incident → alerte → YAML auto → collecte → GitHub issue. Scalable pour 100+ incidents/mois.
Bonnes pratiques
- Toujours blameless : commencez par 'blameless_statement' lu à voix haute en réunion.
- Data-first : 70% temps sur logs/métriques, 30% analyse.
- Actions trackables : utilisez GitHub Projects pour 'timeline_prevention.tasks'.
- Reviews croisées : 2+ reviewers non-impliqués.
- Rituel hebdo : revue postmortems en retro (max 15min/incident).
Erreurs courantes à éviter
- Chercher des coupables : focus 'qui' au lieu de 'quoi' → démotivation équipe.
- Postmortem incomplet : omettre lessons_learned → récidive incidents.
- Pas d'automatisation : manuel → perte données, délai >24h.
- Confidentialité : publier publiquement sans anonymisation → leak sensible.
Pour aller plus loin
- Livre Site Reliability Engineering Google (gratuit en ligne).
- Outils : Blameless (open-source postmortem tool), Firehydrant.
- Formations expertes : Découvrez nos formations SRE Learni.
- Implémentez dans Backstage ou Cortex pour dashboards avancés.