đ ELK / Elastic Stack â Logs, Recherche & Dashboards
Guide IDEO-Lab densifié : architecture ELK, ingestion (Beats/Logstash), indexation Elasticsearch, dashboards Kibana, sécurité, ILM, scaling, troubleshooting + cheat-sheet.
ELK en bref
Pourquoi ELK, quels usages, et comment penser âlog pipelineâ.
logssearchdashboardsComposants (E/L/K + Beats)
Elasticsearch, Logstash, Kibana, Filebeat/MetricbeatâŠ
ESLogstashKibanaArchitecture type
Agents â ingest â index â queries â dashboards / alerting.
pipelineingestILMInstallation (Docker / Linux)
Docker Compose rapide + checklist prod (sysctl, vm.max_map_count).
dockercomposelinuxFilebeat / Agents
Collecte logs Nginx/Django, multiline, champs, processors.
filebeatnginxdjangoLogstash (parse & enrich)
Grok, mutate, geoip, fingerprint, routing par index.
grokgeoipenrichElasticsearch (indexation)
Mappings, analyzers, shards/replicas, templates, data streams.
mappingshardsqueries3.2 ILM & rétention
Hot/Warm/Cold, rollover, delete, optimiser coût & perf.
ILMretentionKibana (dashboards)
Discover, Lens, dashboards, saved searches, spaces.
discoverlensspaces4.1 Sécurité
TLS, auth, RBAC, API keys, hardening, réseaux.
TLSRBAChardeningScaling & sizing
Volumes, CPU/RAM, shards strategy, ingest throughput.
sizingshardsperfTroubleshooting
Index bloqués, mapping explosion, pipeline drops, slow queries.
errorsmappinglatencyELK (Elastic Stack) sert Ă quoi ?
Centraliser des logs (serveurs, apps, containers) puis permettre : recherche ultra rapide, corrĂ©lation, dashboards, et alerting. Câest lâĂ©quivalent âGoogle pour tes logsâ, mais industrialisĂ©.
Quand ELK est un bon choix ?
- Beaucoup de services / serveurs â besoin dâun âlog hubâ.
- Investigations incidents (500, timeouts, erreurs DB, attaques).
- Besoin dâaudit : âqui a fait quoiâ, âquandâ, âdepuis quelle IPâ.
- Recherche full-text sur logs + filtres structurés (JSON).
ELK vs alternatives rapides
| Stack | Point fort | Quand |
|---|---|---|
| ELK/Elastic | Search + enrich + dashboards riches | Si tu veux âtoutâ + gros volumes |
| EFK | Fluent Bit/Fluentd en K8s | Pipeline Kubernetes standard |
| Loki + Grafana | Simple, souvent moins coûteux | Logs orientés time-series |
| OpenSearch | ĂcosystĂšme proche ES | Si tu veux alternative compatible |
Flux ELK (mental model)
[Apps / Servers / Containers]
â logs (files, stdout, syslog)
âŒ
[Agents]
- Filebeat / Elastic Agent
- Fluent Bit (si K8s)
â
âŒ
[Ingest layer]
- Logstash (grok, enrich, route)
- Elasticsearch ingest pipelines (option)
â
âŒ
[Elasticsearch]
- index / data stream
- mappings + analyzers
- shards + replicas
- ILM (retention)
â
âŒ
[Kibana]
- Discover (recherche)
- Dashboards (Lens)
- Alerting
Objectif : rĂ©duire le temps âincident â cause â fixâ en rendant les logs consultables en 10 secondes.
Use-cases infra / web
- Nginx : top 404/500, latences, IPs, user-agents suspects.
- SystĂšme : auth.log, sudo, ssh brute-force, kernel messages.
- K8s : logs pods + events, corrélations par namespace/app.
Use-cases app (Django)
- Erreurs 500 : stack traces + contexte request.
- Slow endpoints : corrĂ©ler logs app â logs DB â Nginx.
- Traçabilité :
request_id/trace_iddu front au back.
Use-cases sécurité
- Audit : âquel user a modifiĂ© quoiâ (admin/backoffice).
- DĂ©tection anomalies : spikes dâĂ©checs login, scans URL.
- GeoIP + reputation (enrich) â dashboards âattaqueâ.
KPI simples
- Errors/minute (5xx)
- Top endpoints (p95 latency)
- Top IPs / countries
- Volume logs / jour (coût)
PiÚges classiques (et comment les éviter)
| PiĂšge | SymptĂŽme | Solution |
|---|---|---|
| Mapping explosion | trop de champs uniques | Logs JSON maßtrisés, dynamic templates |
| Trop de shards | cluster lent / instable | shards raisonnables + ILM rollover |
| Grok trop lourd | CPU Logstash high | préférer logs JSON + parse léger |
| Rétention oubliée | disque explose | ILM + delete policy |
Elasticsearch (E)
- Moteur dâindexation + recherche (full-text + filtres).
- Stockage âdocumentâ (JSON) avec mapping (types).
- Distribué : shards (scaling) + replicas (HA).
Logstash (L)
- Pipeline ingestion : input â filter â output.
- Parse (grok), enrich (geoip), normalise, route vers index.
- TrÚs flexible mais peut coûter cher en CPU si mal réglé.
Kibana (K)
- Interface web : Discover, Lens, dashboards, alerting.
- Gestion index patterns / data views, spaces.
- Outil principal dâanalyse incident (timepicker + filtres).
Beats / Agents (collecte)
| Agent | RĂŽle | Exemple |
|---|---|---|
| Filebeat | logs fichiers | /var/log/nginx/access.log |
| Metricbeat | metrics systĂšme | CPU, RAM, FS, process |
| Heartbeat | uptime probes | HTTP/ICMP checks |
| Auditbeat | audit sécurité | syscalls, file integrity |
3 patterns courants
| Pattern | Flux | Quand |
|---|---|---|
| Direct to ES | Beats â Elasticsearch | Simple, faible parsing |
| Via Logstash | Beats â Logstash â ES | Parsing/enrich avancĂ© |
| Ingest pipelines ES | Beats â ES (pipeline) | Moins de briques, parsing modĂ©rĂ© |
Rule of thumb:
- Si tu peux: logs JSON â Beats â ES (pipeline lĂ©ger)
- Si tu dois: formats hĂ©tĂ©rogĂšnes â Logstash (grok + enrich)
Nommage dâindex (lisible + ILM)
Exemples:
- logs-nginx-prod-YYYY.MM.DD
- logs-django-prod-YYYY.MM.DD
- logs-system-dev-YYYY.MM.DD
Ou en data streams (recommandé):
- logs-nginx-prod (data stream) -> backing indices gérés par rollover/ILM
But : query facile + rétention facile (ILM) + séparation prod/dev.
Champs standard (minimum viable schema)
| Champ | Usage | Exemple |
|---|---|---|
| @timestamp | time picker | 2026-01-10T09:15:12Z |
| service.name | filtre service | django-api |
| env | prod/dev | prod |
| log.level | INFO/WARN/ERROR | ERROR |
| http.response.status_code | 5xx dashboards | 500 |
| trace.id / request_id | corrélation | 2f3a⊠|
QualitĂ© des donnĂ©es (ELK âproâ)
- Décider : JSON logs ou texte + grok (JSON recommandé).
- Normaliser niveaux : DEBUG/INFO/WARN/ERROR.
- Ajouter request_id dans Nginx + app (corrélation).
- Ăviter champs dynamiques (risque mapping explosion).
Docker Compose minimal (lab)
version: "3.8"
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- ES_JAVA_OPTS=-Xms1g -Xmx1g
ulimits:
memlock: { soft: -1, hard: -1 }
ports: ["9200:9200"]
kibana:
image: docker.elastic.co/kibana/kibana:8.12.0
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
ports: ["5601:5601"]
depends_on: [elasticsearch]
logstash:
image: docker.elastic.co/logstash/logstash:8.12.0
ports: ["5044:5044"]
depends_on: [elasticsearch]
Pré-requis Linux (trÚs fréquent)
# Elasticsearch a souvent besoin de :
sudo sysctl -w vm.max_map_count=262144
# (persist: /etc/sysctl.conf)
# Vérifier mémoire/disque:
free -h
df -h
Si ES refuse de démarrer, vm.max_map_count est souvent la cause.
Checklist production
| ThĂšme | Ă faire |
|---|---|
| HA | â„ 3 nodes ES (master/data), replicas > 0 |
| Disque | Surveiller watermark + ILM delete |
| Security | TLS, auth, RBAC, network restrictions |
| Rétention | ILM rollover + delete (jours) |
| Backup | Snapshots repository (S3/NFS) |
Ports courants
9200 : Elasticsearch HTTP API
9300 : Elasticsearch transport (cluster interne)
5601 : Kibana
5044 : Logstash beats input
En prod : Ă©viter dâexposer 9200 publiquement (WAF/VPN + auth + TLS).
Collecte Nginx
filebeat.inputs:
- type: filestream
id: nginx-access
paths:
- /var/log/nginx/access.log
fields:
service: nginx
env: prod
fields_under_root: true
output.logstash:
hosts: ["logstash:5044"]
Idéal : logs Nginx en JSON (sinon grok cÎté Logstash).
Collecte logs app Django
filebeat.inputs:
- type: filestream
id: django-app
paths:
- /opt/app/logs/django.log
fields:
service: django
env: prod
fields_under_root: true
processors:
- add_host_metadata: ~
- add_cloud_metadata: ~
Si tes logs Django sont JSON â tu peux parser directement (moins de grok).
Multiline (stack traces)
parsers:
- multiline:
type: pattern
pattern: '^\['
negate: true
match: after
Objectif : une exception Python = un seul âeventâ indexĂ©.
Best practices agents
- Ajouter service, env, host en champs standard.
- Limiter bruit : DEBUG en prod seulement si nécessaire.
- Rotation logs cÎté OS/app + vérifier permissions.
- Ăviter donnĂ©es sensibles (tokens, passwords) dans logs.
Pipeline type
input {
beats { port => 5044 }
}
filter {
# parse/enrich ici
}
output {
elasticsearch {
hosts => ["http://elasticsearch:9200"]
index => "logs-%{service}-%{env}-%{+YYYY.MM.dd}"
}
}
Grok (si logs texte)
filter {
if [service] == "nginx" {
grok {
match => { "message" => "%{IPORHOST:client_ip} - %{DATA:remote_user} \[%{HTTPDATE:ts}\] \"%{WORD:method} %{DATA:uri} HTTP/%{NUMBER:http_version}\" %{NUMBER:status} %{NUMBER:bytes}" }
}
}
}
Grok est puissant mais coûteux : si possible, préfÚre logs JSON.
Enrichissement (geoip + fingerprint)
filter {
if [client_ip] {
geoip { source => "client_ip" }
}
fingerprint {
source => ["message"]
target => "event_hash"
method => "SHA1"
}
}
Routing vers index différents
output {
if [service] == "django" {
elasticsearch { index => "logs-django-%{env}-%{+YYYY.MM.dd}" }
} else if [service] == "nginx" {
elasticsearch { index => "logs-nginx-%{env}-%{+YYYY.MM.dd}" }
} else {
elasticsearch { index => "logs-misc-%{env}-%{+YYYY.MM.dd}" }
}
}
Objectif : corrélation avec request_id
- Nginx génÚre un
$request_id(ou trace header). - Django récupÚre ce header et le loggue.
- Dans Kibana : filtre sur request_id â tu vois le chemin complet.
Nginx (concept)
# access_log JSON + request_id (idéal)
log_format json escape=json '{ "ts":"$time_iso8601", "request_id":"$request_id",
"status":$status, "method":"$request_method", "uri":"$request_uri",
"ip":"$remote_addr", "ua":"$http_user_agent", "rt":$request_time }';
access_log /var/log/nginx/access.log json;
Django (concept)
# Middleware: inject request_id into logs
# Log JSON: {"service":"django","request_id":"...","level":"ERROR","msg":"..."}
Dashboards Kibana âincidentâ
- Top 5xx (par uri)
- Latence p95 (par endpoint)
- Top IPs / UA
- Erreurs Django (stack traces) + request_id
Concepts essentiels
- Index : collection de documents (JSON)
- Document : event log enrichi
- Mapping : types (keyword/text/date/longâŠ)
- Analyzer : full-text search (tokenization)
Mapping : éviter les surprises
- keyword : filtres exacts (service, env, status)
- text : full-text (message)
- date : @timestamp
- long : bytes, latency_ms
Danger : champs dynamiques non maĂźtrisĂ©s â âmapping explosionâ.
Shards/replicas : lâerreur n°1
- Trop de shards = surcharge metadata + cluster lent.
- Pas assez = index trop gros, queries lentes.
- ILM + rollover = stratĂ©gie moderne (index âpetitsâ).
RequĂȘtes utiles (concept Kibana)
service: nginx AND env: prod AND http.response.status_code: >=500
request_id: "abc123"
message: "timeout" AND NOT uri: "/health"
Pourquoi ILM est indispensable ?
- MaĂźtriser le disque (sinon âELK remplit toutâ).
- Optimiser la perf : récent = hot, ancien = cold.
- Automatiser : rollover + delete.
ILM phases (classique):
- hot : indexation + queries fréquentes
- warm : moins de perf, storage moins cher
- cold : archive
- delete: suppression aprĂšs X jours
RĂšgles simples (pragmatiques)
| Type logs | Rétention | Note |
|---|---|---|
| Access logs | 7â30 jours | utile incidents + stats |
| App errors | 30â90 jours | debug long terme |
| Audit sĂ©curitĂ© | 90â365 jours | compliance (selon besoin) |
Toujours adapter Ă tes volumes (GB/jour) et au budget disque.
Discover = enquĂȘte
- Filtrer par
service,env,status,request_id. - Timepicker : rĂ©duire la fenĂȘtre pour performance.
- Sauvegarder des recherches (saved search) pour réutiliser.
Lens = graphiques rapides
- Time series : erreurs/minute, latence p95.
- Top values : top endpoints, top IPs.
- Breakdown : par env/service.
Dashboards âprod webâ recommandĂ©s
- HTTP 5xx (par endpoint)
- Latence p95 (par endpoint)
- Top IP / UA
- Django ERROR logs (stack traces)
- DB timeouts / slow queries (si loggués)
Alerting (concept)
Alert 1: 5xx rate > threshold for 5 minutes
Alert 2: p95 latency > threshold
Alert 3: login failures spike (security)
Commencer simple, sinon trop dâalertes = ignorĂ©es.
RĂšgles dâor
- Ne pas exposer ES (9200) sur Internet sans contrĂŽle strict.
- Activer auth + TLS (trafic chiffré, credentials protégés).
- RBAC : séparer viewers (Kibana) vs admins cluster.
- Masquer/filtrer données sensibles dans logs.
Segmentation réseau
- ES cluster: réseau privé
- Kibana: accĂšs via VPN / reverse proxy / SSO
- Agents: envoyent vers Logstash/ES via réseau interne
ModĂšle rĂŽles (simple)
| RĂŽle | Droits | Qui |
|---|---|---|
| Viewer | lecture dashboards | dev / support |
| Analyst | Discover + dashboards | SRE / incident |
| Admin | index/templates/ILM | ops plateforme |
Questions Ă poser (dimensionnement)
- GB/jour de logs ? (nginx + app + system)
- Rétention ? (jours)
- Queries ? (combien dâutilisateurs Kibana)
- Parsing ? (grok lourd ou JSON)
Quick estimation (trĂšs simple)
Stock â (GB/jour) * (jours rĂ©tention) * (facteur overhead 1.2 Ă 2.0)
Ex: 20 GB/jour * 30j * 1.5 â 900 GB
Perf : leviers principaux
- ILM + rollover (indices petits et gérables).
- Limiter shards : trop = overhead, pas assez = gros index.
- PrĂ©fĂ©rer logs JSON (moins de grok â plus de throughput).
- Prévoir nodes dédiés (ingest vs data) si gros volumes.
SymptĂŽmes typiques
- Kibana lent / timeouts
- Index en read-only / flood stage disk watermark
- Ingestion qui âdropâ (perte events)
- Mapping explosion (trop de champs)
- Logstash CPU 100% (grok lourd)
Causes fréquentes
| Cause | Effet |
|---|---|
| Disque plein | ES bloque writes (read-only) |
| Trop de shards | cluster overhead énorme |
| Grok trop complexe | ingestion lente |
| Champs dynamiques | mapping explosion |
Fix rapides (pragmatiques)
- Activer ILM + réduire rétention (si disque).
- Réduire shards + rollover (indices plus petits).
- Passer vers logs JSON pour réduire grok.
- Limiter champs dynamiques (templates).
Playbook incident ELK
- Réduire time range + filtre service/env.
- Checker disque + watermark.
- Observer ingestion rate (agents/logstash).
- Identifier index âheavyâ (trop gros / trop shards).
- Appliquer ILM / rollover / delete policy.
RĂšgles dâor
1) Logs JSON si possible (moins de grok)
2) ILM (rollover + delete) dÚs le début
3) Pas d'ES exposé publiquement
4) Shards raisonnables (éviter l'explosion)
5) Champs standards: service/env/@timestamp/request_id
Checklist âGo Liveâ
- Rétention configurée (jours)
- Dashboards incident (5xx, latency, top endpoints)
- RBAC (viewer vs admin)
- Alertes simples (5xx rate, latency)
- Backup snapshots (si requis)
Commandes âconceptâ (tests)
# Test ES
curl -s http://localhost:9200
# Lister indices (cat)
curl -s "http://localhost:9200/_cat/indices?v"
# Health cluster
curl -s "http://localhost:9200/_cluster/health?pretty"
# Kibana
http://localhost:5601
Anti-patterns
- Pas dâILM â disque plein
- Grok partout â CPU Logstash explose
- Logs non structurés sans conventions
- Champs dynamiques incontrÎlés
