Guía Completa de Fluent bit para contenedores
Fluent Bit se ha convertido en el colector de logs estandar para entornos de contenedores y Kubernetes. Con un consumo de memoria de apenas 1-5 MB por instancia, procesa miles de registros por segundo sin impactar el rendimiento de las aplicaciones. A diferencia de soluciones mas pesadas como Logstash o incluso Fluentd, Fluent Bit fue diseñado desde cero para ejecutarse como sidecar o DaemonSet en entornos donde cada megabyte de RAM cuenta.
En esta guía cubriremos la arquitectura interna de Fluent Bit, las diferencias clave con Fluentd, el despliegue en Kubernetes como DaemonSet, la configuración de parsing y routing de logs, y las mejores prácticas de rendimiento.
Fluent Bit vs Fluentd: diferencias clave
Ambos pertenecen al proyecto CNCF Fluentd, pero sirven propositos diferentes:
| Caracteristica | Fluent Bit | Fluentd |
|---|---|---|
| Lenguaje | C | Ruby + C |
| Memoria tipica | 1-5 MB | 30-100 MB |
| Plugins | ~100 built-in | 1000+ (community) |
| Proposito | Colección y forwarding | Colección, procesamiento y agregación |
| Formato config | Nativo o YAML | Ruby-style config |
La recomendación general es usar Fluent Bit como agente ligero en cada nodo (edge) y, si necesitas procesamiento complejo o plugins específicos, agregar Fluentd como agregador centralizado. Esta arquitectura se conoce como el patron “Fluent Bit -> Fluentd -> Backend”.
Sin embargo, para la mayoria de los casos de uso en Kubernetes, Fluent Bit solo es suficiente para recolectar, parsear y enviar logs directamente a Elasticsearch, CloudWatch o S3.
Arquitectura de Fluent Bit
Fluent Bit procesa datos a traves de un pipeline con cuatro etapas:
Inputs (entradas)
Los inputs definen de donde se recolectan los datos. Los mas usados en contenedores:
- tail: lee archivos de log, incluyendo los logs de contenedor almacenados por el kubelet en
/var/log/containers/. - systemd: captura logs del journal de systemd (kubelet, containerd, Docker daemon).
- forward: recibe logs via protocolo Forward de Fluentd (TCP).
- http: recibe logs via HTTP POST, útil para aplicaciones que emiten logs via API.
Parsers (analizadores)
Los parsers transforman logs en texto plano a registros estructurados. Fluent Bit incluye parsers predefinidos para formatos comunes:
[PARSER]
Name docker
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L
Time_Keep On
[PARSER]
Name nginx
Format regex
Regex ^(?<remote>[^ ]*) - (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)
Time_Key time
Time_Format %d/%b/%Y:%H:%M:%S %z
[PARSER]
Name java_multiline
Format regex
Regex ^(?<time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}) (?<level>[A-Z]+) (?<message>.*)$
Time_Key time
Time_Format %Y-%m-%d %H:%M:%S,%L
Filters (filtros)
Los filtros modifican, enriquecen o descartan registros en el pipeline:
- kubernetes: enriquece los logs con metadata del pod (nombre, namespace, labels, annotations).
- modify: agrega, renombra o elimina campos.
- grep: filtra registros basandose en regex (incluir o excluir).
- lua: permite transformaciones arbitrarias usando scripts Lua.
Outputs (salidas)
Los outputs definen el destino final de los logs. Fluent Bit soporta multiples outputs simultaneos:
- es (Elasticsearch/OpenSearch)
- cloudwatch_logs (AWS CloudWatch)
- s3 (AWS S3 para archivado)
- loki (Grafana Loki)
- forward (reenvio a Fluentd)
- kafka (Apache Kafka)
- stdout (para debug)
Despliegue en Kubernetes como DaemonSet
El patron mas comun es desplegar Fluent Bit como DaemonSet, de forma que cada nodo del cluster tenga una instancia que recolecte los logs de todos los contenedores en ese nodo.
Manifiesto base
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluent-bit
namespace: logging
labels:
app.kubernetes.io/name: fluent-bit
spec:
selector:
matchLabels:
app.kubernetes.io/name: fluent-bit
template:
metadata:
labels:
app.kubernetes.io/name: fluent-bit
spec:
serviceAccountName: fluent-bit
tolerations:
- operator: Exists
containers:
- name: fluent-bit
image: cr.fluentbit.io/fluent/fluent-bit:3.1
ports:
- containerPort: 2020
name: metrics
resources:
limits:
memory: 128Mi
cpu: 200m
requests:
memory: 64Mi
cpu: 100m
volumeMounts:
- name: varlog
mountPath: /var/log
readOnly: true
- name: containers
mountPath: /var/lib/docker/containers
readOnly: true
- name: config
mountPath: /fluent-bit/etc/
volumes:
- name: varlog
hostPath:
path: /var/log
- name: containers
hostPath:
path: /var/lib/docker/containers
- name: config
configMap:
name: fluent-bit-config
ConfigMap con la configuración
apiVersion: v1
kind: ConfigMap
metadata:
name: fluent-bit-config
namespace: logging
data:
fluent-bit.conf: |
[SERVICE]
Flush 5
Log_Level info
Daemon off
Parsers_File parsers.conf
HTTP_Server On
HTTP_Listen 0.0.0.0
HTTP_Port 2020
[INPUT]
Name tail
Tag kube.*
Path /var/log/containers/*.log
Parser cri
DB /var/log/flb_kube.db
Mem_Buf_Limit 10MB
Skip_Long_Lines On
Refresh_Interval 10
[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
Kube_Tag_Prefix kube.var.log.containers.
Merge_Log On
Merge_Log_Key log_processed
Keep_Log Off
K8S-Logging.Parser On
K8S-Logging.Exclude On
[OUTPUT]
Name es
Match kube.*
Host elasticsearch.logging.svc
Port 9200
Logstash_Format On
Logstash_Prefix k8s-logs
Retry_Limit 5
Replace_Dots On
tls On
tls.verify Off
parsers.conf: |
[PARSER]
Name cri
Format regex
Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>[^ ]*) (?<message>.*)$
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
[PARSER]
Name json
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L
Routing a multiples destinos
Una de las funcionalidades mas útiles de Fluent Bit es enviar logs a distintos destinos segun el tag o contenido. Por ejemplo, enviar logs de aplicación a Elasticsearch para busqueda rápida y logs de infraestructura a S3 para archivado a bajo costo.
# Logs de aplicacion -> Elasticsearch
[OUTPUT]
Name es
Match kube.var.log.containers.app-*
Host elasticsearch.logging.svc
Port 9200
Logstash_Format On
Logstash_Prefix app-logs
# Logs de infraestructura -> S3 (archivado)
[OUTPUT]
Name s3
Match kube.var.log.containers.infra-*
region us-east-1
bucket my-logs-archive
total_file_size 50M
upload_timeout 10m
s3_key_format /logs/$TAG/%Y/%m/%d/%H_%M_%S.gz
compression gzip
# Logs de seguridad -> CloudWatch
[OUTPUT]
Name cloudwatch_logs
Match kube.var.log.containers.auth-*
region us-east-1
log_group_name /k8s/security
log_stream_prefix from-fluent-bit-
auto_create_group On
# Todos los logs -> Loki (para correlacion con Grafana)
[OUTPUT]
Name loki
Match kube.*
Host loki.monitoring.svc
Port 3100
Labels job=fluent-bit
Auto_Kubernetes_Labels On
Despliegue con Helm
El chart oficial de Fluent Bit simplifica el despliegue y la gestión de configuraciones:
helm repo add fluent https://fluent.github.io/helm-charts
helm repo update
helm install fluent-bit fluent/fluent-bit \
--namespace logging \
--create-namespace \
--set resources.limits.memory=128Mi \
--set resources.limits.cpu=200m \
--set resources.requests.memory=64Mi \
--set resources.requests.cpu=100m \
-f values-custom.yaml
Un archivo values-custom.yaml tipico para enviar logs a Elasticsearch:
config:
service: |
[SERVICE]
Flush 5
Log_Level info
HTTP_Server On
HTTP_Listen 0.0.0.0
HTTP_Port 2020
Parsers_File /fluent-bit/etc/parsers.conf
inputs: |
[INPUT]
Name tail
Tag kube.*
Path /var/log/containers/*.log
Parser cri
DB /var/log/flb_kube.db
Mem_Buf_Limit 10MB
filters: |
[FILTER]
Name kubernetes
Match kube.*
Merge_Log On
Keep_Log Off
K8S-Logging.Parser On
outputs: |
[OUTPUT]
Name es
Match *
Host elasticsearch.logging.svc
Port 9200
Logstash_Format On
tolerations:
- operator: Exists
serviceMonitor:
enabled: true
Tuning de rendimiento
Fluent Bit es eficiente por defecto, pero en clusters con alto volumen de logs (mas de 10,000 registros/segundo por nodo) se requieren ajustes:
Memoria y buffering
[SERVICE]
Flush 5
# Buffer en filesystem en lugar de memoria
storage.path /var/log/flb-storage/
storage.sync normal
storage.checksum off
storage.backlog.mem_limit 10M
[INPUT]
Name tail
Path /var/log/containers/*.log
# Limitar memoria por input
Mem_Buf_Limit 15MB
# Evitar lineas muy largas que consumen memoria
Skip_Long_Lines On
# Buffer en filesystem
storage.type filesystem
Recomendaciones de rendimiento
- Mem_Buf_Limit: define el máximo de memoria que cada input puede usar para buffering. Si se alcanza el límite, Fluent Bit pausa la lectura hasta que se libere espacio.
- storage.path: habilita buffering en disco para evitar perdida de datos si el output esta temporalmente indisponible.
- Flush interval: un valor de 1 segundo genera mas I/O de red pero menor latencia; 5-10 segundos reduce la carga en el backend.
- Workers: para outputs que lo soporten, configura
Workers 2o mas para paralelizar los envios. - Skip_Long_Lines: evita que una linea de log anomalamente larga (por ejemplo, un stack trace de 100 KB) consuma toda la memoria del buffer.
Monitoreo de Fluent Bit
Fluent Bit expone métricas en formato Prometheus en el puerto configurado con HTTP_Server. Las métricas clave a monitorear:
# Registros procesados por input
fluentbit_input_records_total
# Bytes procesados por output
fluentbit_output_proc_bytes_total
# Errores en outputs (retries, drops)
fluentbit_output_errors_total
# Registros retenidos (backpressure)
fluentbit_output_retries_total
Configura alertas cuando fluentbit_output_errors_total crece sostenidamente o cuando fluentbit_output_retries_total aumenta, lo que indica que el backend de destino esta saturado o inaccesible.
Conclusion
Fluent Bit es la opción mas eficiente para recolectar y procesar logs en entornos de contenedores. Su bajo consumo de recursos, su pipeline flexible de inputs-parsers-filters-outputs, y su integración nativa con Kubernetes lo hacen ideal tanto para clusters pequeños como para despliegues a gran escala. La clave para una implementación exitosa esta en configurar correctamente el parsing segun el formato de logs de tus aplicaciones, definir routing inteligente a multiples destinos segun la criticidad de los logs, y monitorear el propio Fluent Bit para detectar problemas de backpressure antes de que resulten en perdida de datos.