RousselTMLEARNING

Observabilité

Exploiter Loki en production : multi-tenant, limites, cardinalité et supervision

Exploiter Loki : multi-tenancy, limites par tenant, protection contre la cardinalité, diagnostics, supervision avec le mixin, dimensionnement et résolution des problèmes courants.

1. Multi-tenancy #

Isoler les équipes.

Activer les tenants #

Avec auth_enabled: true, chaque requête doit porter l'en-tête X-Scope-OrgID. Loki ne vérifie pas l'identité : placez un proxy d'authentification (nginx, Gateway) qui injecte l'en-tête.

# Envoi et lecture pour le tenant "equipe-a"
curl -H "X-Scope-OrgID: equipe-a" -X POST http://loki:3100/loki/api/v1/push ...
logcli query '{app="api"}' --org-id=equipe-a

# Interroger plusieurs tenants à la fois
logcli query '{app="api"}' --org-id="equipe-a|equipe-b"   # nécessite multi_tenant_queries_enabled: true
# Alloy : tenant dans loki.write
loki.write "default" {
  endpoint {
    url       = "http://loki:3100/loki/api/v1/push"
    tenant_id = "equipe-a"
  }
}

# Limites spécifiques par tenant (runtime_config)
overrides:
  equipe-a:
    ingestion_rate_mb: 20
    max_streams_per_user: 50000
    retention_period: 360h

2. Les limites qui protègent le cluster #

Comprendre les erreurs 429.

limits_config #

Limites usuelles de Loki
Ajustez selon votre volume réel plutôt que de multiplier toutes les valeurs.
limits_config:
  ingestion_rate_mb: 10
  ingestion_burst_size_mb: 20
  per_stream_rate_limit: 5MB
  per_stream_rate_limit_burst: 15MB
  max_streams_per_user: 100000
  max_label_names_per_series: 15
  max_label_value_length: 2048
  reject_old_samples: true
  reject_old_samples_max_age: 168h
  max_query_length: 721h
  max_entries_limit_per_query: 5000
  query_timeout: 2m
Erreur côté agentCause probableAction
429 Too Many Requests: Ingestion rate limit exceededDébit trop élevé pour le tenantAugmenter ingestion_rate_mb ou réduire le bruit
429 ... per stream rate limit exceededUn flux trop bavardAjouter un label (ex. pod) pour répartir
400 ... entry too far behindLogs trop anciensAjuster reject_old_samples_max_age ou corriger l'horloge
max streams limit exceededCardinalité excessiveRevoir les labels

3. Diagnostiquer la cardinalité #

Trouver les labels qui coûtent cher.

Commandes de diagnostic #

# Nombre de valeurs par label
logcli labels --since=24h
logcli labels pod --since=24h | wc -l
logcli series '{app="api"}' --since=1h --analyze-labels      # répartition des labels
logcli stats '{env="prod"}' --since=24h

# Flux actifs côté Loki (Prometheus)
sum(loki_ingester_memory_streams)
topk(10, sum by (tenant) (loki_ingester_memory_streams))
sum by (reason) (rate(loki_discarded_samples_total[5m]))

4. Superviser Loki #

Métriques, mixin et runbook.

Que surveiller ? #

# Santé et latence
histogram_quantile(0.99, sum by (le, route) (rate(loki_request_duration_seconds_bucket{route=~"loki_api_v1_push|loki_api_v1_query_range"}[5m])))

# File d'attente d'écriture et flush
loki_ingester_wal_corruptions_total
rate(loki_ingester_chunks_flushed_total[5m])

# Erreurs
sum by (status_code) (rate(loki_request_duration_seconds_count{status_code=~"5.."}[5m]))
# Dashboards et alertes officiels (mixin)
git clone https://github.com/grafana/loki && cd loki/production/loki-mixin
jb install && mixtool generate all mixin.libsonnet
Erreur Courante : Redémarrer massivement les ingesters sans WAL entraîne une perte des logs non encore flushés : activez le WAL et utilisez replication_factor: 3 en production.

Pour aller plus loin