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.
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
-
Por qué el logging centralizado: el problema que resuelve Fluentd Qué sale mal cuando los logs viven en decenas de archivos y formatos, y cómo lo arregla el pipeline recopilar-transformar-enviar de Fluentd. -
Fundamentos de configuración de Fluentd: source, filter, match y tags Las directivas con las que se construye toda configuración de Fluentd, cómo las conectan los tags y cómo validar una configuración antes de ejecutarla. -
Recopila logs desde archivos, HTTP y contenedores Configura las tres fuentes de entrada más comunes: un archivo en disco, un endpoint HTTP y todos los contenedores de un host Docker.