Aller au contenu
Outils medium

Fluent Bit : Collecteur de logs ultra-léger

14 min de lecture

Fluent Bit est un collecteur de logs ultra-léger, écrit en C, projet CNCF Graduated. Il consomme quelques mégaoctets de mémoire et s'est imposé comme l'agent de collecte de logs de référence sur chaque nœud Kubernetes, avant d'envoyer vers un agrégateur ou un backend comme Loki ou Elasticsearch.

Ce guide s'adresse aux profils intermédiaires et avancés qui exploitent des logs à grande échelle. Vous allez installer Fluent Bit, comprendre son pipeline (input, parser, filter, output), le configurer pour Kubernetes, écrire des parsers et router les logs vers Loki.

  • Comprendre le pipeline Fluent Bit : input, parser, filter, output.
  • Installer Fluent Bit proprement (dépôt signé, image épinglée).
  • Collecter les logs de conteneurs et les enrichir avec les métadonnées Kubernetes.
  • Écrire des parsers pour structurer les logs bruts.
  • Router les logs vers Loki, Elasticsearch ou un agrégateur.

Fluent Bit est conçu pour les environnements contraints en ressources et les architectures cloud-native à grande échelle.

CaractéristiqueDescription
LicenceApache 2.0
MaturitéCNCF Graduated
LangageC
Mémoire~1 MB
Throughput100k+ events/sec
CritèreFluent BitFluentd
Mémoire~1 MB~40 MB
LangageCRuby
Plugins100+ intégrés500+ externes
RôleCollecte (edge)Agrégation (central)
PerformancesPlus rapidePlus flexible
┌─────────────────────────────────────────────────────────────────┐
│ Fluent Bit Pipeline │
│ │
│ ┌────────┐ ┌────────┐ ┌─────────────┐ ┌──────────────────┐ │
│ │ Input │──│ Parser │──│ Filter │──│ Output │ │
│ └────────┘ └────────┘ └─────────────┘ └──────────────────┘ │
│ │
│ - tail - JSON - kubernetes - loki │
│ - systemd - regex - record_modifier - elasticsearch │
│ - forward - logfmt - grep - forward │
│ - syslog - docker - lua - prometheus_exporter│
└─────────────────────────────────────────────────────────────────┘
Fenêtre de terminal
# Clé GPG officielle Fluent Bit (dépôt signé, pas de pipe-to-shell)
sudo mkdir -p /usr/share/keyrings
curl -fsSL https://packages.fluentbit.io/fluentbit.key \
| sudo gpg --dearmor -o /usr/share/keyrings/fluentbit-keyring.gpg
# Dépôt signé (adapter le nom de version : noble, jammy, bookworm...)
echo "deb [signed-by=/usr/share/keyrings/fluentbit-keyring.gpg] https://packages.fluentbit.io/ubuntu/noble noble main" \
| sudo tee /etc/apt/sources.list.d/fluent-bit.list
sudo apt-get update && sudo apt-get install -y fluent-bit
sudo systemctl enable --now fluent-bit
fluent-bit --version

Fluent Bit supporte deux formats de configuration : classique et YAML.

fluent-bit.conf
[SERVICE]
flush 1
log_level info
parsers_file parsers.conf
[INPUT]
name tail
path /var/log/containers/*.log
tag kube.*
parser docker
[FILTER]
name kubernetes
match kube.*
[OUTPUT]
name stdout
match *
fluent-bit.yaml
service:
flush: 1
log_level: info
pipeline:
inputs:
- name: tail
path: /var/log/containers/*.log
tag: kube.*
parser: cri
filters:
- name: kubernetes
match: kube.*
merge_log: on
k8s-logging.parser: on
outputs:
- name: loki
match: "*"
host: loki-gateway
port: 3100
labels: job=fluentbit
values.yaml
config:
service: |
[SERVICE]
Daemon Off
Flush 1
Log_Level info
Parsers_File parsers.conf
HTTP_Server On
HTTP_Listen 0.0.0.0
HTTP_Port 2020
Health_Check On
inputs: |
[INPUT]
Name tail
Path /var/log/containers/*.log
multiline.parser docker, cri
Tag kube.*
Mem_Buf_Limit 50MB
Skip_Long_Lines On
Refresh_Interval 10
filters: |
[FILTER]
Name kubernetes
Match kube.*
Merge_Log On
Keep_Log Off
K8S-Logging.Parser On
K8S-Logging.Exclude On
Labels On
Annotations Off
[FILTER]
Name nest
Match kube.*
Operation lift
Nested_under kubernetes
Add_prefix kubernetes_
outputs: |
[OUTPUT]
Name loki
Match kube.*
Host loki-gateway.logging.svc
Port 3100
Labels job=fluentbit, namespace=$kubernetes_namespace_name
Remove_keys kubernetes_container_hash,kubernetes_docker_id
customParsers: |
[PARSER]
Name json
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
fluent-bit-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluent-bit
namespace: logging
spec:
selector:
matchLabels:
app: fluent-bit
template:
metadata:
labels:
app: fluent-bit
spec:
serviceAccountName: fluent-bit
containers:
- name: fluent-bit
image: fluent/fluent-bit:4.0.5
ports:
- containerPort: 2020
volumeMounts:
- name: varlog
mountPath: /var/log
readOnly: true
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
- name: config
mountPath: /fluent-bit/etc/
resources:
limits:
memory: 100Mi
cpu: 100m
requests:
memory: 50Mi
cpu: 50m
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- name: config
configMap:
name: fluent-bit-config

Les parsers transforment les logs bruts en structure JSON.

parsers.conf
[PARSER]
Name docker
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
[PARSER]
Name cri
Format regex
Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>[^ ]*) (?<log>.*)$
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
[PARSER]
Name syslog-rfc3164
Format regex
Regex /^\<(?<pri>[0-9]+)\>(?<time>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$/
Time_Key time
Time_Format %b %d %H:%M:%S
[PARSER]
Name json_logs
Format json
Time_Key timestamp
Time_Format %Y-%m-%dT%H:%M:%S.%LZ
[PARSER]
Name nginx_access
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

Enrichit chaque log avec les métadonnées du pod.

[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc:443
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
Merge_Log On
K8S-Logging.Parser On
K8S-Logging.Exclude On
Labels On
Annotations Off
[FILTER]
Name record_modifier
Match *
Record cluster production-us-east-1
Record environment prod
# Exclure les logs de health checks
[FILTER]
Name grep
Match kube.*
Exclude log /health|/ready|/metrics/
# Garder seulement les erreurs
[FILTER]
Name grep
Match kube.*
Regex level (error|fatal|critical)
[FILTER]
Name lua
Match *
script /fluent-bit/scripts/transform.lua
call transform
# transform.lua
function transform(tag, timestamp, record)
if record["level"] == nil then
record["level"] = "info"
end
return 1, timestamp, record
end
[OUTPUT]
Name loki
Match *
Host loki-gateway
Port 3100
Labels job=fluentbit, app=$kubernetes_labels['app']
Line_Format json
Auto_Kubernetes_Labels on
[OUTPUT]
Name es
Match *
Host elasticsearch
Port 9200
Index logs-%Y.%m.%d
Type _doc
Suppress_Type_Name On
Logstash_Format On
Retry_Limit 5
[OUTPUT]
Name forward
Match *
Host fluentd-aggregator
Port 24224
Require_ack_response True
# Dupliquer vers plusieurs destinations
[OUTPUT]
Name loki
Match *
Host loki
[OUTPUT]
Name s3
Match *
bucket my-logs-bucket
region eu-west-1
total_file_size 50M

Gérer les logs multi-lignes (stack traces Java, Python).

[MULTILINE_PARSER]
name java_multiline
type regex
flush_timeout 1000
rule "start_state" "^(\d{4}-\d{2}-\d{2})" "cont"
rule "cont" "^(?!\d{4}-\d{2}-\d{2})" "cont"
[INPUT]
name tail
path /var/log/app/*.log
multiline.parser java_multiline
[SERVICE]
HTTP_Server On
HTTP_Listen 0.0.0.0
HTTP_Port 2020
# Endpoints disponibles :
# GET /api/v1/health
# GET /api/v1/metrics
# GET /api/v1/metrics/prometheus
servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: fluent-bit
namespace: logging
spec:
selector:
matchLabels:
app: fluent-bit
endpoints:
- port: http
path: /api/v1/metrics/prometheus
interval: 30s
  1. Limitez la mémoire

    Configurez Mem_Buf_Limit pour éviter les OOM.

    [INPUT]
    Name tail
    Mem_Buf_Limit 50MB
  2. Activez les health checks

    [SERVICE]
    Health_Check On
  3. Utilisez des labels Kubernetes

    Filtrez par namespace pour ne pas tout envoyer.

    [FILTER]
    Name grep
    Match kube.*
    Regex kubernetes_namespace_name ^(prod-|staging-)
  4. Gérez le backpressure

    En cas de destination lente, évitez d'accumuler en mémoire.

SymptômeCause probableSolution
Logs manquantsPath incorrectVérifier le pattern glob
Parser échoueFormat non reconnuTester avec fluent-bit -c ... -i dummy
Mémoire élevéeBuffer pleinRéduire Mem_Buf_Limit
Connection refusedOutput downVérifier la destination
Fenêtre de terminal
# Test de configuration
fluent-bit -c /etc/fluent-bit/fluent-bit.conf --dry-run
# Mode debug
fluent-bit -c /etc/fluent-bit/fluent-bit.conf -vvv
# Parser test
echo '{"level":"info","msg":"test"}' | fluent-bit -i stdin -o stdout -p format=json
  • Ultra-léger : ~1 MB de mémoire
  • CNCF Graduated : standard Kubernetes
  • Parser CRI/Docker : natif pour les conteneurs
  • Kubernetes filter : enrichissement auto des métadonnées
  • Multi-output : dupliquer vers plusieurs destinations

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn