Configuración de los registros de Amazon ECS para conseguir un alto rendimiento - Amazon Elastic Container Service

Configuración de los registros de Amazon ECS para conseguir un alto rendimiento

Para escenarios de alto rendimiento de registros, recomendamos utilizar el controlador de registro awsfirelens con Firelens y Fluent Bit. Fluent Bit es un procesador de registro ligero que es eficiente con los recursos y puede gestionar millones de registros. Sin embargo, para lograr un rendimiento óptimo a escala es necesario ajustar su configuración.

En esta sección se describen las técnicas de optimización de Fluent Bit avanzadas para gestionar un alto rendimiento de los registros y, al mismo tiempo, mantener la estabilidad del sistema y garantizar que no se pierdan datos.

Para obtener información acerca de cómo utilizar archivos de configuración personalizados con FireLens, consulte Uso de un archivo de configuración personalizado. Para ver más ejemplos, consulte Ejemplos de FireLens en Amazon ECS en GitHub.

nota

Algunas opciones de configuración de esta sección, como workers y threaded, requieren AWS para la versión 3 o posterior de Fluent Bit. Para obtener información sobre las versiones disponibles, consulte Versiones de AWS para Fluent Bit.

Utilizar el almacenamiento en búfer del sistema de archivos

De forma predeterminada, Fluent Bit almacena en búfer todos los datos de la memoria. Cuando los datos se ingieren más rápido de lo que pueden transferirse a las salidas, el búfer se llena. Una vez lleno, el complemento de entrada se detiene hasta que hay espacio disponible en el búfer, lo que puede provocar una contrapresión y ralentizar la aplicación.

Para escenarios de alto rendimiento, recomendamos utilizar el almacenamiento en búfer del sistema de archivos. Para obtener más información sobre cómo Fluent Bit gestiona el almacenamiento en búfer y el almacenamiento, consulte Almacenamiento en búfer y almacenamiento en la documentación de Fluent Bit.

El uso del almacenamiento en búfer del sistema de archivos proporciona los siguientes beneficios:

  • Mayor capacidad de búfer: el espacio en disco suele ser más abundante que la memoria.

  • Persistencia: los datos almacenados en búfer sobreviven a los reinicios de Fluent Bit.

  • Degradación gradual: durante los errores de salida, los datos se acumulan en el disco en lugar de agotar la memoria.

Para activar el almacenamiento en búfer del sistema de archivos, proporciona un archivo de configuración personalizado de Fluent Bit. A continuación se muestra un ejemplo de configuración recomendada:

[SERVICE] # Flush logs every 1 second Flush 1 # Wait 120 seconds during shutdown to flush remaining logs Grace 120 # Directory for filesystem buffering storage.path /var/log/flb-storage/ # Limit chunks stored 'up' in memory (reduce for memory-constrained environments) storage.max_chunks_up 32 # Flush backlog chunks to destinations during shutdown (prevents log loss) storage.backlog.flush_on_shutdown On [INPUT] Name forward unix_path /var/run/fluent.sock # Run input in separate thread to prevent blocking threaded true # Enable filesystem buffering for persistence storage.type filesystem [OUTPUT] Name cloudwatch_logs Match * region us-west-2 log_group_name /aws/ecs/my-app log_stream_name $(ecs_task_id) # Use multiple workers for parallel processing workers 2 # Retry failed flushes up to 15 times retry_limit 15 # Maximum disk space for buffered data for this output storage.total_limit_size 10G

Parámetros principales de configuración:

storage.path

El directorio donde Fluent Bit almacena los fragmentos almacenados en búfer en el disco.

storage.backlog.flush_on_shutdown

Cuando está activado, Fluent Bit intenta vaciar todos los fragmentos del sistema de archivos pendientes y llevarlos a sus destinos durante el apagado. Esto ayuda a garantizar la entrega de los datos antes de que Fluent Bit se detenga, pero puede aumentar el tiempo de apagado.

storage.max_chunks_up

El número de fragmentos que permanecen en la memoria. El valor predeterminado es de 128 fragmentos, que pueden consumir más de 500 MB de memoria, ya que cada bloque puede utilizar entre 4 y 5 MB. En entornos con limitaciones de memoria, reduzca este valor. Por ejemplo, si tiene 50 MB disponibles para almacenar en búfer, configúrelo entre 8 y 10 fragmentos.

storage.type filesystem

Active el almacenamiento en el sistema de archivos para el complemento de entrada. A pesar del nombre, Fluent Bit utiliza mmap para asignar fragmentos tanto en la memoria como en el disco, lo que proporciona persistencia sin sacrificar el rendimiento.

threaded true

Ejecuta la entrada en su propio hilo, separado del bucle de eventos principal de Fluent Bit. Esto evita que las entradas lentas bloqueen toda la canalización.

Optimizar configuración de salida

Los problemas de red, las interrupciones del servicio y la limitación del destino pueden impedir que se entreguen los registros. La configuración de salida adecuada garantiza la resiliencia sin pérdida de datos.

Cuando se produce un error al vaciar la salida, Fluent Bit puede volver a intentar la operación. Los clústeres de la región pueden obtener los siguientes beneficios.

retry_limit

El número máximo de reintentos antes de eliminar registros. El valor predeterminado es 1. Para los entornos de producción, recomendamos 15 o más, lo que cubre varios minutos de interrupción con un retraso exponencial.

scheduler.base

El mínimo de segundos entre reintentos. Recomendamos 10 segundos.

scheduler.cap

El máximo de segundos entre reintentos cuando se utiliza un retroceso exponencial. Recomendamos 60 segundos.

workers

El número de hilos para el procesamiento de salida en paralelo. Varios trabajos permiten vaciados concurrentes, lo que mejora el rendimiento al procesar muchos fragmentos.

El parámetro Grace de la sección [SERVICE] establece el tiempo de espera de Fluent Bit durante el apagado para vaciar los datos almacenados en el búfer. El período de Grace debe coordinarse con el valor de stopTimeout del contenedor. Asegúrese de que el valor stopTimeout supere el período Grace para permitir que Fluent Bit complete la descarga antes de recibir SIGKILL. Por ejemplo, si el valor de Grace es de 120 segundos, establezca el de stopTimeout en 150 segundos.

El siguiente ejemplo muestra una configuración de Fluent Bit completa con todos los ajustes recomendados para escenarios de alto rendimiento:

[SERVICE] # Flush logs every 1 second Flush 1 # Wait 120 seconds during shutdown to flush remaining logs Grace 120 # Directory for filesystem buffering storage.path /var/log/flb-storage/ # Limit chunks stored 'up' in memory (reduce for memory-constrained environments) storage.max_chunks_up 32 # Flush backlog chunks to destinations during shutdown (prevents log loss) storage.backlog.flush_on_shutdown On # Minimum seconds between retries scheduler.base 10 # Maximum seconds between retries (exponential backoff cap) scheduler.cap 60 [INPUT] Name forward unix_path /var/run/fluent.sock # Run input in separate thread to prevent blocking threaded true # Enable filesystem buffering for persistence storage.type filesystem [OUTPUT] Name cloudwatch_logs Match * region us-west-2 log_group_name /aws/ecs/my-app log_stream_name $(ecs_task_id) # Use multiple workers for parallel processing workers 2 # Retry failed flushes up to 15 times retry_limit 15 # Maximum disk space for buffered data for this output storage.total_limit_size 10G

Utilice el registro multidestino para garantizar la fiabilidad

El envío de registros a varios destinos elimina los puntos únicos de error. Por ejemplo, si Registros de CloudWatch sufre una interrupción, los registros seguirán llegando a Amazon S3.

El registro multidestino ofrece los siguientes beneficios. El complemento de salida de Amazon S3 también admite opciones de compresión como los formatos .gzip y Parquet, lo que puede reducir los costos de almacenamiento. Para obtener más información, consulte Compresión de S3 en la documentación de Fluent Bit.

El registro multidestino puede ofrecer los siguientes beneficios:

  • Redundancia: si un destino falla, los registros siguen llegando al otro.

  • Recuperación: reconstruya las brechas en un sistema respecto al otro.

  • Durabilidad: archive registros en Amazon S3 para la retención a largo plazo.

  • Optimización de costos: guarde los registros recientes en un servicio de consultas rápido como Registros de CloudWatch con una retención más corta y, al mismo tiempo, archive todos los registros en un almacenamiento de Amazon S3 de menor costo para conservarlos a largo plazo.

La siguiente configuración de Fluent Bit envía registros tanto a Registros de CloudWatch como a Amazon S3:

[OUTPUT] Name cloudwatch_logs Match * region us-west-2 log_group_name /aws/ecs/my-app log_stream_name $(ecs_task_id) workers 2 retry_limit 15 [OUTPUT] Name s3 Match * bucket my-logs-bucket region us-west-2 total_file_size 100M s3_key_format /fluent-bit-logs/$(ecs_task_id)/%Y%m%d/%H/%M/$UUID upload_timeout 10m # Maximum disk space for buffered data for this output storage.total_limit_size 5G

Ambas salidas utilizan el mismo patrón de Match *, por lo que todos los registros se envían a ambos destinos de forma independiente. Durante una interrupción en un destino, los registros siguen fluyendo hacia el otro, mientras que las descargas fallidas se acumulan en el búfer del sistema de archivos para volver a intentarlo más adelante.

Utilice el registro basado en archivos con el complemento de entrada trasera

Para escenarios de alto rendimiento en los que la pérdida de registros es un problema fundamental, puede utilizar un enfoque alternativo: haga que la aplicación escriba los registros en los archivos del disco y configure Fluent Bit para leerlos mediante el complemento de entrada tail. Este enfoque evita por completo la capa del controlador de registro de Docker.

El registro basado en archivos con el complemento de entrada trasera proporciona los siguientes beneficios:

  • Seguimiento del desplazamiento: el complemento de entrada trasera puede almacenar los desplazamientos de los archivos en un archivo de base de datos (mediante la opción DB), lo que proporciona durabilidad tras los reinicios de Fluent Bit. Esto ayuda a evitar la pérdida de registros al reiniciar el contenedor.

  • Almacenamiento en búfer a nivel de entrada: puede configurar los límites del búfer de memoria directamente en el complemento de entrada mediante Mem_Buf_Limit, lo que proporciona un control más detallado del uso de la memoria.

  • Evita la sobrecarga de Docker: los registros pasan directamente de un archivo a Fluent Bit, sin pasar por los búferes de registro de Docker.

Para utilizar este enfoque, la aplicación debe escribir los registros en los archivos en lugar de hacerlo stdout. Tanto el contenedor de aplicaciones como el contenedor de Fluent Bit montan un volumen compartido donde se almacenan los archivos de registro.

El siguiente ejemplo muestra una configuración de entrada secundaria con las mejores prácticas:

[INPUT] Name tail # File path or glob pattern to tail Path /var/log/app.log # Database file for storing file offsets (enables resuming after restart) DB /var/log/flb_tail.db # when true, controls that only fluent-bit will access the database (improves performance) DB.locking true # Skip long lines instead of skipping the entire file Skip_Long_Lines On # How often (in seconds) to check for new files matching the glob pattern Refresh_Interval 10 # Extra seconds to monitor a file after rotation to account for pending flush Rotate_Wait 30 # Maximum size of the buffer for a single line Buffer_Max_Size 10MB # Initial allocation size for reading file data Buffer_Chunk_Size 1MB # Maximum memory buffer size (tail pauses when full) Mem_Buf_Limit 75MB

Cuando utilice el complemento de entrada trasera, tenga en cuenta lo siguiente:

  • Implemente la rotación de registros en los registros de sus aplicaciones para evitar que se agote el disco. Supervise las métricas de volumen subyacentes para medir el rendimiento.

  • Considere configuraciones como Ignore_Older, Read_from_Head y analizadores multilínea según el formato de registro.

Para obtener más información, consulte Entrada trasera en la documentación de Fluent Bit. Si desea conocer las prácticas recomendadas, consulte la sección Configuración de entrada trasera con las prácticas recomendadas en la guía de solución de problemas de AWS para Fluent Bit.

Iniciar sesión directamente en FireLens

Cuando se especifica el controlador de registros awsfirelens en una definición de tarea, el agente de contenedor de Amazon ECS introduce las siguientes variables de entorno en el contenedor:

FLUENT_HOST

La dirección IP que está asignada al contenedor FireLens.

nota

Si utiliza EC2 con el modo de red bridge, la variable de entorno FLUENT_HOST del contenedor de aplicaciones puede dejar de ser precisa tras reiniciar el contenedor del router de registro de FireLens (el contenedor con el objeto firelensConfiguration en su definición de contenedor). Esto se debe a que FLUENT_HOST es una dirección IP dinámica y puede cambiar tras un reinicio. El registro directo desde el contenedor de la aplicación en la dirección IP FLUENT_HOST puede empezar a fallar después de que la dirección cambie. Para obtener más información acerca de cómo reiniciar contenedores individuales, consulte Reinicio de contenedores individuales en tareas de Amazon ECS con políticas de reinicio de contenedores.

FLUENT_PORT

El puerto en el que se está escuchando el protocolo Fluent Forward.

Puede utilizar estas variables de entorno para enviar registros directamente al enrutador de registro de Fluent Bit desde el código de su aplicación mediante el protocolo Fluent Forward, en lugar de escribir en stdout. Este enfoque evita la capa de controladores de registro de Docker, lo que proporciona las siguientes ventajas:

  • Menor latencia: los registros se transfieren directamente a Fluent Bit sin pasar por la infraestructura de registro de Docker.

  • Registro estructurado: envíe datos de registro estructurados de forma nativa sin sobrecargas de codificación JSON.

  • Mejor control: su aplicación puede implementar su propia lógica de almacenamiento en búfer y gestión de errores.

Las siguientes bibliotecas de registradores de Fluent son compatibles con el protocolo Fluent Forward y se pueden utilizar para enviar los registros directamente a Fluent Bit:

Configurar el límite de búfer de Docker

Al crear una definición de tareas, puede indicar el número de líneas de registro que se almacenan en búfer en la memoria mediante la especificación del valor en log-driver-buffer-limit. Esto controla el búfer entre Docker y Fluent Bit. Para obtener más información, consulte Controladores de registro Fluentd en la documentación de Docker.

Utilice esta opción cuando haya un alto rendimiento, ya que Docker podría quedarse sin memoria de búfer y descartar mensajes de búfer para poder agregar nuevos mensajes.

Tenga en cuenta lo siguiente cuando utilice esta opción:

  • Esta opción se admite en el tipo de EC2 y de Fargate con la versión de la plataforma 1.4.0 o posterior.

  • La opción solo es válida cuando logDriver se establece en awsfirelens.

  • El límite de búfer predeterminado es de 1048576 líneas de registro.

  • El límite del búfer debe ser igual o mayor que 0 y menor que las líneas de registro 536870912.

  • La cantidad máxima de memoria utilizada para este búfer es el producto del tamaño de cada línea de registro y el tamaño del búfer. Por ejemplo, si las líneas de registro de la aplicación tienen un promedio de 2 KiB, un límite de búfer de 4096 utilizaría como máximo 8 MiB. La cantidad total de memoria asignada a nivel de tarea debe ser superior a la cantidad de memoria asignada a todos los contenedores, además del búfer de memoria del controlador de registro.

La siguiente definición de tarea muestra cómo configurar log-driver-buffer-limit:

{ "containerDefinitions": [ { "name": "my_service_log_router", "image": "public.ecr.aws/aws-observability/aws-for-fluent-bit:3", "cpu": 0, "memoryReservation": 51, "essential": true, "firelensConfiguration": { "type": "fluentbit" } }, { "essential": true, "image": "public.ecr.aws/docker/library/httpd:latest", "name": "app", "logConfiguration": { "logDriver": "awsfirelens", "options": { "Name": "firehose", "region": "us-west-2", "delivery_stream": "my-stream", "log-driver-buffer-limit": "52428800" } }, "dependsOn": [ { "containerName": "my_service_log_router", "condition": "START" } ], "memoryReservation": 100 } ] }