Intro : le défi de la collecte de logs à l'échelle
Vos serveurs, conteneurs et applications produisent des téraoctets de logs quotidiens. Les centraliser, les parser et les router vers vos outils d'analyse (Elasticsearch, Loki, CloudWatch) devient rapidement un goulot d'étranglement critique.
Fluentd, historiquement, assumait ce rôle—mais sa consommation mémoire (200+ Mo par instance) et son overhead CPU font qu'il n'est pas idéal pour des déploiements lightweight, notamment en edge ou sur Kubernetes. Fluent Bit, réécrit en C par la même communauté, apporte une alternative : 2-3 Mo de RAM, zero-copy buffers, et une latence minimum. Chez SHPV, sur notre backbone AS41652 de 150 Gbps opérant depuis 2012, le monitoring d'infrastructure à l'échelle impose de tels choix.
Cet article vous guide dans le déploiement productif de Fluent Bit : architecture, configuration, intégration Kubernetes, et tuning performance.
Plan de l'article
- Fluent Bit vs Fluentd : quand et pourquoi choisir
- Architecture du pipeline (Input → Parser → Filter → Buffer → Output)
- Installation et structure de configuration
- Sources d'entrée : tail, systemd, Kubernetes, TCP
- Parsing et filtrage : regex, JSON, Lua
- Destinations : Elasticsearch, Loki, S3, Splunk
- Déploiement DaemonSet et enrichissement métadonnées
- Tuning performance et gestion de backpressure
- Monitoring et health checks
- Intégrations complémentaires
Fluent Bit vs Fluentd : lequel choisir ?
| Critère | Fluentd | Fluent Bit |
| Mémoire | 200+ Mo | 2-3 Mo |
| Langage | Ruby | C |
| Latence | Modérée | Ultra-faible |
| Plugins | 500+ | 100+ (essentiels) |
| Overhead CPU | Moyen | Minimal |
| Use case | Agrégation centralisée, grosse infra | Edge, sidecar, volume élevé |
Verdict : Fluent Bit pour les agents de log (DaemonSet, sidecars) ; Fluentd pour l'agrégation centralisée. Les deux cohabitent souvent : Fluent Bit → Fluentd → Storage.
Architecture Fluent Bit : le pipeline
Input → Parser → Filter → Buffer → Output
- Input : lit des logs (fichiers, sockets, systemd)
- Parser : parse les événements en records structurés
- Filter : enrichit, modifie, supprime des champs (record_modifier, grep, Lua)
- Buffer : stockage temporaire en mémoire ou disque (avec backpressure)
- Output : envoie vers destination (Elasticsearch, Loki, HTTP, etc.)
Chaque stage est non-bloquant : si un output est slow, le buffer absorbe sans ralentir les inputs.
Installation et premiers pas
Package manager
# Ubuntu/Debian
curl https://packages.fluentbit.io/fluentbit.key | apt-key add -
echo "deb https://packages.fluentbit.io/ubuntu/jammy jammy main" | tee /etc/apt/sources.list.d/fluentbit.list
apt update && apt install -y fluent-bit
# Alpine (Docker)
apk add fluent-bit
Structure de configuration
/etc/fluent-bit/
├── fluent-bit.conf # Principal
├── parsers.conf # Définitions parsers
├── plugins.conf # Plugins custom
└── inputs/ # Fichiers inputs
├── syslog.conf
├── docker.conf
└── app.conf
Configuration minimale
[SERVICE]
Daemon Off
Flush 5
Log_Level info
Parsers_File parsers.conf
HTTP_Server On
HTTP_Listen 0.0.0.0
HTTP_Port 2020
Health_Check On
[INPUT]
Name tail
Path /var/log/app.log
Parser json
Tag app.*
[OUTPUT]
Name loki
Match app.*
Host loki.monitoring.svc
Port 3100
Inputs : collecter les logs
Tail (fichiers)
[INPUT]
Name tail
Path /var/log/*.log
Parser docker
Tag container.*
Skip_Long_Lines On
Mem_Buf_Limit 50MB
DB /var/log/.flb_kube.db # SQLite state
Systemd
[INPUT]
Name systemd
Tag systemd.*
Read_From_Tail On
Path /var/log/journal
TCP/UDP (application logging)
[INPUT]
Name forward
Listen 0.0.0.0
Port 24224
Tag app.forward
Kubernetes (logs de pod)
[INPUT]
Name tail
Path /var/log/containers/*.log
Tag kube.*
Parser docker
DB /var/log/.flb_kube.db
Mem_Buf_Limit 50MB
Parsers et filtres
Parser JSON simple
[PARSER]
Name json
Format json
Time_Key timestamp
Time_Format %Y-%m-%dT%H:%M:%S.%LZ
Time_Keep On
Parser regex (Apache/Nginx)
[PARSER]
Name nginx
Format regex
Regex ^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$
Time_Key time
Time_Format %d/%b/%Y:%H:%M:%S %z
Multiline (stack traces)
[PARSER]
Name multiline
Format multiline
Multiline_Parser line1, line2, line3
[MULTILINE_PARSER]
Name line1
Flush_timeout 1000
Rule "start_state" "/^\d{4}-\d{2}-\d{2}/" "cont"
Rule "cont" "/^[^\d]/" "cont"
Rule "cont" "/^\d{4}-\d{2}-\d{2}/" "start_state"
Filtres : record_modifier
[FILTER]
Name record_modifier
Match *
Add hostname ${HOSTNAME}
Add service app-backend
Add environment production
Filtres : Lua (logique custom)
[FILTER]
Name lua
Match app.*
Script /etc/fluent-bit/scripts/enrich.lua
Call enrich
# enrich.lua
function enrich(tag, timestamp, record)
record["traced_by"] = "fluent-bit"
record["cluster"] = os.getenv("CLUSTER_NAME")
return 2, timestamp, record
end
Filtres : grep (inclusion/exclusion)
[FILTER]
Name grep
Match app.*
Exclude level DEBUG
Regex message .*ERROR.*
Outputs : router les logs
Elasticsearch
[OUTPUT]
Name es
Match app.*
Host elasticsearch.default.svc
Port 9200
HTTP_User elastic
HTTP_Passwd ${ELASTIC_PASSWORD}
Index my-app-%Y.%m.%d
Type _doc
Retry_Limit 5
Loki (Grafana)
[OUTPUT]
Name loki
Match kube.*
Host loki.monitoring.svc
Port 3100
Labels job=kubernetes, cluster=${CLUSTER}
Remove_Keys kubernetes_namespace_name
S3 (archivage)
[OUTPUT]
Name s3
Match archive.*
Bucket my-logs
Region eu-west-1
S3_Key_Format logs/%Y/%m/%d/%H/
HTTP custom
[OUTPUT]
Name http
Match *
Host webhook.example.com
Port 443
URI /logs
Format json
json_date_key timestamp
json_date_format iso8601
Déploiement Kubernetes
DaemonSet + ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: fluent-bit-config
namespace: monitoring
data:
fluent-bit.conf: |
[SERVICE]
Daemon Off
Flush 5
Log_Level info
HTTP_Server On
HTTP_Listen 0.0.0.0
HTTP_Port 2020
[INPUT]
Name tail
Path /var/log/containers/*.log
Parser docker
Tag kube.*
DB /var/log/.flb_kube.db
Mem_Buf_Limit 50MB
Refresh_Interval 10
[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc:443
Merge_Log On
Keep_Log Off
K8S_Logging_Parser On
[OUTPUT]
Name loki
Match kube.*
Host loki.monitoring.svc
Port 3100
parsers.conf: |
[PARSER]
Name docker
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%LZ
Time_Keep On
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluent-bit
namespace: monitoring
spec:
selector:
matchLabels:
app: fluent-bit
template:
metadata:
labels:
app: fluent-bit
spec:
serviceAccountName: fluent-bit
containers:
- name: fluent-bit
image: fluent/fluent-bit:2.1.8
resources:
limits:
memory: 100Mi
cpu: 100m
requests:
memory: 50Mi
cpu: 50m
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
- name: config
mountPath: /fluent-bit/etc/
livenessProbe:
httpGet:
path: /api/v1/health
port: 2020
initialDelaySeconds: 30
periodSeconds: 10
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- name: config
configMap:
name: fluent-bit-config
tolerations:
- effect: NoSchedule
operator: Exists
RBAC pour Kubernetes filter
apiVersion: v1
kind: ServiceAccount
metadata:
name: fluent-bit
namespace: monitoring
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: fluent-bit
rules:
- apiGroups: ['']
resources:
- namespaces
- pods
- pods/logs
verbs: ['get', 'list', 'watch']
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: fluent-bit
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: fluent-bit
subjects:
- kind: ServiceAccount
name: fluent-bit
namespace: monitoring
Performance et tuning
Gestion du buffer
[SERVICE]
Storage.path /var/log/flb-storage
Storage.sync normal
Storage.checksum off
Storage.max_chunks_up 128
Storage.backlog.mem_limit 5M
[OUTPUT]
Name loki
Match *
Retry_Limit 5
net.dns.mode TCP
net.keepalive on
net.keepalive_idle_timeout 30
Backpressure et throttling
[INPUT]
Name tail
Path /var/log/app.log
Mem_Buf_Limit 50MB # Pause la lecture si buffer > 50MB
Skip_Empty_Lines On
[FILTER]
Name throttle
Match *
Rate 1000 # Max 1000 records/sec
Window 5 # Window de 5 secondes
Print_Status true
Réduction de mémoire
Skip_Long_Lines On: ignore les logs > 32 KBMem_Buf_Limit 50MB: cap mémoire par inputStorage.path: offload sur disque si buffer full
Monitoring Fluent Bit
Endpoint Prometheus natif
curl http://localhost:2020/api/v1/metrics | jq .
Scrape Prometheus
scrape_configs:
- job_name: 'fluent-bit'
static_configs:
- targets: ['localhost:2020']
metrics_path: '/api/v1/metrics'
scrape_interval: 15s
Health check / Readiness
curl -I http://localhost:2020/api/v1/health
# HTTP/1.1 200 OK
Alertes clés
- alert: FluentBitHighMemory
expr: container_memory_usage_bytes{pod="fluent-bit"} > 100000000
for: 5m
- alert: FluentBitOutputErrors
expr: increase(fluentbit_output_errors_total[5m]) > 10
for: 5m
Perspectives complémentaires
Pour approfondir votre stack logging :
- Déployer un cluster Elasticsearch 8 et Kibana : stockage et visualisation centralisés
- Stack Logging : Prometheus, Loki et Grafana : agrégation complète
- Vector en 2026 : alternative moderne à Fluent Bit : quand considérer Vector
Sources
- Fluent Bit Official Docs (https://docs.fluentbit.io) - Documentation exhaustive, configuration, plugins
- Fluent Community (https://www.fluentd.org) - Architecture Fluentd comparée
- CNCF Observability Landscape (https://landscape.cncf.io/card-mode?category=logging) - Contexte industrie
- Kubernetes Logging Architecture (https://kubernetes.io/docs/concepts/cluster-administration/logging/) - Best practices natif K8s
- Loki Documentation (https://grafana.com/docs/loki/) - Configuration Loki output
- OpenTelemetry (https://opentelemetry.io) - Futur des logs structurés
Conclusion
Fluent Bit s'impose comme l'agent de log léger par excellence pour la collecte distribuée. Sa footprint minimal, son pipeline flexible et sa maturité en Kubernetes en font un choix solide pour toute infrastructure moderne.
Chez SHPV, nous l'utilisons pour monitorer notre backbone 150 Gbps et nos services infogérance à travers notre SLA 99.9%+. Déployé en DaemonSet avec Loki en backend, il garantit une visibilité complète sur des millions d'événements quotidiens, sans impacter les performances des applications.
Prochaines étapes :
- Testez en staging avec un volume proche du production
- Tuning du buffer et Mem_Buf_Limit selon votre throughput
- Intégrez healthchecks et monitoring Prometheus
- Escaladez vers Fluentd ou Vector si besoins d'agrégation avancée
Bon logging !


