Настройка Logrotate для файлов Fluentd. Необходимо?
У меня есть следующий fluent.conf
<source>
type forward
</source>
<source>
type monitor_agent
port 24220
</source>
# Listen DRb for debug
<source>
type debug_agent
port 24230
</source>
<source>
type tail
path /var/data/www/apps/app/logs/*.log
pos_file /tmp/fluent.nginx.pos
format syslog
tag app.nginx-access
# Regex fields
format /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*) "(?<referer>[^\"]*)" "(?<agent>[^\"]*)"$/
# Date and time format
time_format %d/%b/%Y:%H:%M:%S %z
</source>
<match app.**>
type copy
<store>
type file
path /var/log/fluent/app
</store>
</match>
Нужно ли использовать Logrotate @ /var/log/fluent/app/*
или Fluent справится с этим сам?
2 ответа
Плагин Fluentd out_file автоматически разбивает выходные файлы по дням, поэтому вам не нужно использовать logrotate.
Если вы хотите разделить с разной степенью детализации, измените параметр "time_slice_format" (по умолчанию это%Y%m%d).
Однако это означает, что для выходного файла нет текущего канонического имени. Для этого вы можете использовать параметр "symlink_path" с "file_type file". Это не особенность out_file как таковой, но любой буферизованный вывод.
Как указал @kiyoto-tamura,
fluentd
может разбивать выходные файлы по дням, и это поведение по умолчанию.
И, как указывает @vaab,
fluentd
не может удалить старые файлы. Следовательно, очевидным решением было бы отключить разделение
fluentd
и разреши
logrotate
для обработки разбиения на разделы с отслеживанием количества файлов.
Однако это может создать ненужную сложность, особенно в простых случаях: нужно будет установить, настроить и контролировать дополнительную службу, которая
logrotate
.
Более того, получить аналог
logrotate
в Windows (если вам не удобно устанавливать
cygwin
или используя
0.0.0.x
версии в производстве).
Итак, другое возможное решение было бы позволить
fluentd
для разделения выходных файлов по дням как обычно, но периодически удаляйте старые файлы.
В UNIX-подобных системах это несложно и может быть достигнуто путем написания однострочного сценария оболочки, вызывающего
find
и планируя это через
cron
.
Та же логика применима к среде Windows. Например, можно написать сценарий PowerShell и запланировать его через системный планировщик задач ( см. "Суть" для удобства чтения).
Следующий листинг определяет такой сценарий как пример:
# delete-old-service-logs.ps1
[CmdletBinding()]
param(
[Parameter(Position=0, Mandatory=$true)]
[ValidateScript({
if( -Not ($_ | Test-Path) ){
throw "Specified logs dir path does not exist (path='$_')"
}
if(-Not ($_ | Test-Path -PathType Container) ){
throw "Specified logs dir path does not point to a directory (path='$_')"
}
return $true
})]
[string]$LogsDirPath,
[Parameter(Position=1)]
[int]$LogsFileMaxN = 31,
[Parameter(Position=2)]
[ValidateNotNullOrEmpty()]
[string]$LogsFileNamePattern = "service.????-??-??.log"
)
[string[]]$FileNamesToRemove = Get-ChildItem -Path $LogsDirPath -Filter $LogsFileNamePattern |
Sort-Object -Property CreationTime -Descending |
Select-Object -Skip $LogsFileMaxN |
Select -ExpandProperty "Name"
$Shell = new-object -comobject "Shell.Application"
$LogsDir = $Shell.Namespace($LogsDirPath)
Foreach ($FileName in $FileNamesToRemove)
{
$Item = $LogsDir.ParseName($FileName)
$Item.InvokeVerb("delete")
}
Логика довольно проста:
- Идите по пути к директории с журналами.
- Возьмите максимальное количество файлов, которые нужно оставить.
- Возьмите шаблон файла для поиска в журналах.
- Найдите все файлы в каталоге журналов, выполните обратную сортировку по дате создания и возьмите имена старых файлов.
- Удалите старые файлы, если они есть.
Пример вызова:
./delete-old-service-logs.ps1 "path/to/logs/dir"
или же:
./delete-old-service-logs.ps1 -LogsDirPath "path/to/logs/dir"
Поскольку создание запланированной задачи в Windows через графический интерфейс может быть проблемой, можно создать сценарий, который автоматизирует это:
# create-task_delete-old-service-logs.ps1
[CmdletBinding()]
param(
[Parameter(Position=0, Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$LogsDirPath,
[Parameter(Position=1)]
[int]$LogsFileMaxN = 31,
[Parameter(Position=2)]
[ValidateNotNullOrEmpty()]
[string]$LogsFileNamePattern = "service.????-??-??.log",
[Parameter(Position=3)]
[ValidateNotNullOrEmpty()]
[string]$TaskScriptFilePath = "delete-old-service-logs.ps1",
[Parameter(Position=4)]
[ValidateNotNullOrEmpty()]
[string]$TaskName = "SERVICE NAME - Delete Old Logs",
[Parameter(Position=5)]
[ValidateNotNullOrEmpty()]
[string]$TaskDescription = "Delete old logs of SERVICE NAME aggregated via Fluentd",
[Parameter(Position=6)]
[ValidateNotNullOrEmpty()]
[string]$TaskTriggerTime = "5:00:00 AM"
)
try {
$LogsDirPath = Resolve-Path -Path $LogsDirPath
}
catch {
throw "Specified logs dir path does not exist (path='$LogsDirPath')"
}
if(-Not ($LogsDirPath | Test-Path -PathType Container) ){
throw "Specified logs dir path does not point to a directory (path='$LogsDirPath')"
}
try {
$TaskScriptFilePath = Resolve-Path -Path $TaskScriptFilePath
}
catch {
throw "Specified task script file path does not exist (path='$TaskScriptFilePath')"
}
if( -Not ($TaskScriptFilePath | Test-Path -PathType Leaf) ){
throw "Specified task script file path is not a file (path='$TaskScriptFilePath')"
}
$TaskAction = New-ScheduledTaskAction -Execute "C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe" `
-Argument "-NoProfile -WindowStyle Hidden -command ""$TaskScriptFilePath -LogsDirPath ""$LogsDirPath"" -LogsFileMaxN $LogsFileMaxN -LogsFileNamePattern ""$LogsFileNamePattern"""""
$TaskTrigger = New-ScheduledTaskTrigger -Daily -At $TaskTriggerTime
Register-ScheduledTask -TaskName $TaskName -Description $TaskDescription -Action $TaskAction -Trigger $TaskTrigger
Фактическая логика происходит в последних 3 строках, где создаются и регистрируются действие, триггер и задача. В целом рабочий процесс выглядит следующим образом:
- Возьмите параметры для
delete-old-service-logs.ps1
. - Выберите путь к
delete-old-service-logs.ps1
сценарий. - Возьмите название задачи, описание и время запуска скрипта.
- Попробуйте разрешить и проверить пути.
- Создайте действие для вызова PowerShell с аргументами для запуска
delete-old-service-logs.ps1
. - Создайте ежедневный триггер.
- Зарегистрируйте задачу.
Пример вызова, если оба сценария находятся в одном каталоге:
./create-task_delete-old-service-logs.ps1 "path/to/logs/dir"
Или же:
./create-task_delete-old-service-logs.ps1 -LogsDirPath "path/to/logs/dir" -TaskScriptFilePath "path/to/delete-old-service-logs.ps1"
К сожалению если out_file
плагин в настоящее время может разбить файлы журнала по времени (вещь logrotate
может сделать также), это не удаление N старых файлов (которые logrotate
реализует).
Итак, используя logrotate
кажется, все еще необходимо, если вам нужно контролировать количество и размер сохраняемых журналов (источник: https://github.com/fluent/fluentd/issues/2111).
На этом этапе вы можете отключить fluentd
функция разделения файлов, связанная со временем, и обязательно используйте append true
позволить logrotate
сделать это полную работу. Обратите внимание, что нет необходимости postrotate
приятности в logrotate
конф как fluentd
повторно открывать файл при каждой очистке буфера... и это приветствуется fluentd
,
fluentd
останется полезным для фильтров / копирования потоков журналов, разделения файлов по тегам и буферизации.