Fluentd Fluentd

Envía logs de forma fiable: plugins de salida y buffering

Instala un plugin de salida, enruta distintas fuentes a distintos destinos y configura el buffering para que un backend caído no pierda datos.

12 min Intermedio

Recopilar y analizar logs es solo la mitad del pipeline; llevarlos a un lugar útil, de forma fiable, incluso cuando ese destino esté temporalmente inaccesible, es la otra mitad. Esta guía cubre cómo instalar un plugin de salida, enrutar varias fuentes a sus propios destinos y la configuración de buffering que realmente hace fiable la entrega en lugar de “mejor esfuerzo”.

Instalar un plugin de salida

Las salidas incorporadas de Fluentd cubren lo básico (file, stdout, forward a otra instancia de Fluentd), pero la mayoría de los destinos reales, Elasticsearch, almacenamiento en la nube, una plataforma de logs SaaS, vienen como plugins separados que instalas con fluent-gem, el wrapper de RubyGems gestionado por Fluentd:

sudo fluent-gem install fluent-plugin-elasticsearch

Usar fluent-gem en lugar de un gem install a secas importa: instala en el entorno de Ruby que Fluentd usa realmente, en lugar de en el Ruby que tenga el sistema por defecto, una fuente habitual de la confusión “instalé el plugin pero Fluentd sigue diciendo que falta”. Si ejecutas Fluentd como contenedor, instala el plugin como parte de la construcción de tu propia imagen basada en la oficial, en lugar de instalarlo a mano en un contenedor en ejecución, para que realmente esté presente la próxima vez que ese contenedor arranque.

Configurar la salida

Una vez instalado, un destino Elasticsearch es solo otro bloque <match>:

<match apache.access>
  @type elasticsearch
  host elasticsearch
  port 9200
  index_name fluentd-apache
</match>

Enrutar distintas fuentes a distintos destinos

Nada obliga a que todas las fuentes acaben en el mismo lugar. Varios bloques <match>, cada uno limitado a un tag distinto, envían datos distintos a destinos distintos dentro de la misma configuración:

<match apache.access>
  @type elasticsearch
  host elasticsearch
  port 9200
  index_name fluentd-apache
</match>

<match docker.**>
  @type elasticsearch
  host elasticsearch
  port 9200
  index_name fluentd-docker
</match>

<match app.**>
  @type forward
  <server>
    host aggregator.internal
    port 24224
  </server>
</match>

Los logs de aplicación van a un índice, los logs de contenedores a otro, y una tercera fuente se reenvía a una instancia de Fluentd completamente distinta para un procesamiento posterior, todo en el mismo pipeline. Así es también como una sola fuente puede enviarse a más de un destino a la vez: define dos bloques <match> separados que coincidan con el mismo tag (o usa una sección <copy>), ya que un único pipeline de Fluentd no está limitado a una salida por fuente.

Buffering: lo que realmente hace fiable la entrega

Por defecto, un plugin almacena en búfer en memoria antes de escribir en su destino, lo cual es rápido, pero significa que un fallo o reinicio de Fluentd pierde lo que aún no se había vaciado. Para cualquier caso en que perder datos de log en tránsito importe, configura en su lugar un file buffer explícito, de modo que las entradas en búfer se persistan en disco y sobrevivan a un reinicio:

<match apache.access>
  @type elasticsearch
  host elasticsearch
  port 9200
  index_name fluentd-apache

  <buffer>
    @type file
    path /var/log/fluent/buffer/apache
    flush_interval 5s
    retry_max_times 10
    retry_wait 5s
  </buffer>
</match>

Este es el comportamiento que la gente suele describir como “Fluentd no pierde datos si se reinicia”, pero conviene ser preciso: es cierto gracias a un file buffer configurado, no de forma automática. Con un buffer en memoria, un fallo a mitad de un vaciado sigue perdiendo lo que estaba en cola. Si la entrega fiable importa para un destino dado, configura el file buffer para él explícitamente en lugar de suponer que el valor predeterminado lo cubre.

Gestionar un destino que está caído temporalmente

La misma configuración de buffering es lo que gestiona con elegancia un backend caído. Si Elasticsearch (o el destino que sea) deja de ser accesible, las entradas se acumulan en el búfer en lugar de descartarse, y Fluentd reintenta la entrega según el calendario que definen retry_wait y retry_max_times, con los datos en búfer a salvo en disco mientras tanto si has configurado un file buffer. Cuando el destino vuelve a ser accesible, Fluentd se pone al día desde donde lo dejó. Esto es lo que hace que un breve corte de red o un reinicio del backend sea un no-evento en lugar de un hueco en tus logs.

Redactar y enriquecer antes de la salida final

Un <filter> sigue ejecutándose antes de la salida que coincide, esté donde esté entre la source y el match, de modo que los datos sensibles pueden eliminarse inmediatamente antes de llegar al destino:

<filter apache.access>
  @type record_transformer
  remove_keys remote_addr, user_agent
</filter>

record_transformer es el mismo plugin usado para enriquecer (consulta el ejemplo del hostname en la guía anterior); remove_keys es solo la otra dirección, eliminar campos en lugar de añadirlos. Es un lugar razonable para redactar cualquier cosa sensible, una dirección de correo, un token de sesión, una IP interna, antes de que salga de tu propia infraestructura hacia un destino de terceros, en lugar de confiar en que el destino lo gestione correctamente después.

Guías populares