Log aggregation: Fluent Bit ou Fluentd para coleta

1. Introdução à Agregação de Logs no Kubernetes

Em ambientes containerizados e orquestrados por Kubernetes, os logs são a principal fonte de visibilidade sobre o comportamento das aplicações. Diferente de servidores tradicionais, onde os logs residem em arquivos estáticos, em clusters Kubernetes os pods são efêmeros — eles podem ser criados, destruídos e escalados horizontalmente a qualquer momento. Essa volatilidade exige uma estratégia robusta de coleta e agregação de logs.

Os desafios são múltiplos: múltiplas fontes de logs (aplicações, sistema, eventos do cluster), formatos heterogêneos (JSON, texto plano, multiline), e a necessidade de encaminhamento para diferentes destinos (Elasticsearch, Loki, S3, sistemas de alerta). O ecossistema CNCF oferece ferramentas maduras para esse cenário, com destaque para Fluentd e Fluent Bit — ambos projetos incubados pela Cloud Native Computing Foundation — além de soluções como Loki e Elastic Stack.

2. Arquitetura e Funcionamento do Fluentd

Fluentd é um coletor de logs de código aberto, escrito em Ruby e C, que utiliza um modelo baseado em plugins para construir pipelines de dados. Sua arquitetura é composta por:

  • Inputs: fontes de dados (tail de arquivos, syslog, HTTP, etc.)
  • Parsers: interpretação de formatos (JSON, regex, apache, nginx)
  • Filters: transformação e enriquecimento (adicionar campos, modificar timestamps)
  • Outputs: destinos (Elasticsearch, S3, Kafka, MongoDB)
  • Buffers: armazenamento temporário para garantir entrega confiável

Características principais incluem alta confiabilidade com buffer baseado em arquivo ou memória, suporte a mais de 500 plugins na comunidade, e capacidade de roteamento complexo com tags. Fluentd é ideal para cenários que exigem transformações avançadas, múltiplos destinos simultâneos e integração com sistemas legados.

# Exemplo de configuração Fluentd para coleta de logs em Kubernetes
<source>
  @type tail
  path /var/log/containers/*.log
  pos_file /var/log/fluentd-containers.log.pos
  tag kubernetes.*
  format json
  time_format %Y-%m-%dT%H:%M:%S.%NZ
</source>

<filter kubernetes.**>
  @type kubernetes_metadata
</filter>

<match kubernetes.**>
  @type elasticsearch
  host elasticsearch-logging
  port 9200
  logstash_format true
  buffer_type file
  buffer_path /var/log/fluentd-buffer
  flush_interval 5s
</match>

3. Arquitetura e Funcionamento do Fluent Bit

Fluent Bit é um coletor de logs leve e eficiente, escrito em C, projetado para ambientes com recursos limitados. Sua arquitetura minimalista oferece:

  • Inputs: tail, systemd, TCP/UDP, metrics
  • Parsers: JSON, regex, ltsv, csv
  • Filters: kubernetes, modify, throttle, nest
  • Outputs: Elasticsearch, Loki, S3, Kafka, stdout
  • Buffers: memória ou arquivo (modo storage)

Com consumo típico de 5-10 MB de RAM e baixo uso de CPU, Fluent Bit é ideal para coleta em edge nodes, sidecar containers e ambientes serverless. Seus plugins nativos para Kubernetes — como o filtro kubernetes que enriquece logs com metadados do pod — simplificam a configuração.

# Exemplo de configuração Fluent Bit para Kubernetes
[SERVICE]
    flush        5
    log_level    info
    parsers_file parsers.conf

[INPUT]
    name              tail
    path              /var/log/containers/*.log
    multiline.parser  docker, cri
    tag               kube.*
    mem_buf_limit     50MB
    skip_long_lines   on

[FILTER]
    name                kubernetes
    match               kube.*
    kube_url            https://kubernetes.default.svc
    kube_ca_file        /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    kube_token_file     /var/run/secrets/kubernetes.io/serviceaccount/token
    merge_log           on
    keep_log            on

[OUTPUT]
    name              es
    match             kube.*
    host              elasticsearch-logging
    port              9200
    index             kubernetes_cluster
    type              flb_es
    trace_output      off
    retry_limit       5

4. Comparação Detalhada: Fluentd vs Fluent Bit

Característica Fluentd Fluent Bit
Linguagem Ruby + C C
Consumo de RAM 40-150 MB 5-15 MB
Throughput ~50.000 eventos/s (1 CPU) ~100.000 eventos/s (1 CPU)
Plugins disponíveis 500+ 70+
Buffer persistente Sim (arquivo, memória) Sim (memória, arquivo)
Maturidade Estável (desde 2011) Maduro (desde 2015)
Curva de aprendizado Moderada a alta Baixa a moderada
Ideal para Pipelines complexos, múltiplos destinos Coleta leve, edge, sidecars

Fluentd oferece maior flexibilidade com seu ecossistema de plugins, mas consome mais recursos. Fluent Bit prioriza performance e simplicidade, sendo até 5x mais eficiente em throughput por núcleo de CPU.

5. Implementação no Kubernetes com Helm

Instalação do Fluent Bit via Helm

# Adicionar repositório Helm
helm repo add fluent https://fluent.github.io/helm-charts
helm repo update

# Instalar Fluent Bit como DaemonSet
helm upgrade --install fluent-bit fluent/fluent-bit \
  --namespace logging \
  --create-namespace \
  --values fluent-bit-values.yaml

Exemplo de values.yaml para Fluent Bit com saída Elasticsearch

config:
  inputs: |
    [INPUT]
        name              tail
        path              /var/log/containers/*.log
        multiline.parser  docker, cri
        tag               kube.*
        mem_buf_limit     50MB
        skip_long_lines   on

  filters: |
    [FILTER]
        name                kubernetes
        match               kube.*
        merge_log           on
        keep_log            on

  outputs: |
    [OUTPUT]
        name              es
        match             kube.*
        host              elasticsearch-logging
        port              9200
        index             kubernetes_cluster

daemonSetVolumeMounts:
  - name: varlog
    mountPath: /var/log
  - name: varlibdockercontainers
    mountPath: /var/lib/docker/containers
    readOnly: true

daemonSetVolumes:
  - name: varlog
    hostPath:
      path: /var/log
  - name: varlibdockercontainers
    hostPath:
      path: /var/lib/docker/containers

Instalação do Fluentd via Helm

helm upgrade --install fluentd fluent/fluentd \
  --namespace logging \
  --create-namespace \
  --values fluentd-values.yaml

6. Estratégias de Roteamento e Filtragem de Logs

Parsing de logs estruturados e não estruturados

Para logs JSON gerados por aplicações modernas, o parser nativo é suficiente. Para logs não estruturados ou multiline (como stack traces), é necessário configurar parsers específicos:

# Fluent Bit: parser para logs multiline (Java exceptions)
[MULTILINE_PARSER]
    name          java_exceptions
    type          regex
    flush_timeout 1000
    rules         |
        state      start     regex   /^(\d{4}-\d{2}-\d{2})/
        state      continue  regex   /^\s+/

Filtros para enriquecimento com metadados Kubernetes

O filtro kubernetes adiciona automaticamente informações como namespace, pod name, container name, labels e anotações. Isso permite rotear logs por namespace ou prioridade:

# Roteamento condicional no Fluentd
<match kubernetes.var.log.containers.**production**>
  @type elasticsearch
  host elasticsearch-prod
  port 9200
  index_name production-logs
</match>

<match kubernetes.var.log.containers.**debug**>
  @type s3
  s3_bucket debug-logs
  s3_region us-east-1
  path debug/
  store_as text
</match>

7. Boas Práticas e Troubleshooting

Gerenciamento de buffer e retenção

Para evitar perda de logs durante picos de tráfego ou falhas de rede, configure buffers adequados:

  • Fluent Bit: use mem_buf_limit para limitar memória e storage.path para buffer em disco
  • Fluentd: configure buffer_type file com buffer_path em disco persistente

Monitoramento da pipeline

Ambas as ferramentas expõem métricas via HTTP para Prometheus:

# Fluent Bit: habilitar monitoramento
[SERVICE]
    http_server    on
    http_listen    0.0.0.0
    http_port      2020

Problemas comuns

  • Alta latência de saída: aumente flush_interval ou ajuste workers para paralelismo
  • Vazamento de memória: verifique parsers multiline mal configurados que acumulam buffers
  • Logs duplicados: ajuste pos_file e verifique se múltiplos coletores estão lendo os mesmos arquivos

8. Conclusão e Recomendações Finais

A escolha entre Fluentd e Fluent Bit depende do cenário:

  • Escolha Fluentd quando precisar de pipelines complexos com múltiplos destinos, transformações avançadas (como roteamento condicional com base em conteúdo) ou integração com sistemas legados que exigem plugins específicos. É a opção certa para ambientes que já possuem infraestrutura robusta e podem alocar 100-200 MB de RAM por nó.

  • Escolha Fluent Bit para coleta leve e eficiente, especialmente em clusters grandes com milhares de pods, ambientes edge computing, sidecar containers ou quando o consumo de recursos é crítico. Sua simplicidade de configuração e desempenho superior o tornam a escolha padrão para novos projetos Kubernetes.

Uma tendência crescente é o uso do OpenTelemetry Collector como alternativa unificada, que combina coleta de logs, métricas e traces em um único agente. No entanto, para cenários exclusivamente de logs, Fluent Bit oferece a melhor relação entre simplicidade, performance e integração com o ecossistema Kubernetes.

Referências