Современные информационные системы генерируют большое количество отладочной информации, которую желательно хранить какое-то время. Я расскажу, как установить и настроить Grafana Loki - комплексную систему для сбора и хранения логов. Это современное, эффективное и технически развитое решение, которые покрывает большинство потребностей из этой технической области.
Научиться настраивать MikroTik с нуля или систематизировать уже имеющиеся знания можно на углубленном онлайн-курcе по администрированию MikroTik. Автор курcа – сертифицированный тренер MikroTik Дмитрий Скоромнов. Более 40 лабораторных работ по которым дается обратная связь. В три раза больше информации, чем в MTCNA.
Реклама ИП Скоромнов Д.А. ИНН 331403723315
Введение
Grafana Loki - это в первую очередь сервис по сбору, анализу и хранению логов. Непосредственно служба для обработки и хранения называется Loki, а Grafana в данном случае - название компании, которое совпадает с изначальным их продуктом - панелью для визуализации метрик. В итоге у нас получается сервис для приёма и хранения логов - Loki и панель визуализации - Grafana.
Я не буду тратить своё и ваше время на описание продукта, так как это легко сделает любой ИИ и скорее всего не ошибётся. Сфокусируюсь на конкретных примерах настроек, которые я проверю и изложу, чтобы вы могли взять, повторить и быть уверенным в том, что это решение работает. Тут на ИИ пока не всегда можно положиться, так как он предложенные варианты выдумывает, но не проверяет. Пока не проверяет. Думаю, со временем будет.
Все компоненты системы, кроме сборщиков логов на хостах, я буду запускать в контейнерах Docker. Это необязательное условие, но считаю, что так проще и удобнее в большинстве случаев. Если вам это не подходит, то нет особых проблем запускать всё вручную, скачивая бинарники или готовые пакеты. Основное время на запуск итоговой системы уходит на отладку конфигураций, а не саму установку служб.
Для установки Docker на сервер я предпочитаю использовать вот такую простую команду. Привожу просто для справки, возможно кто-то не знает. Способов установить Docker много.
# curl https://get.docker.com | bash -
Все дальнейшие настройки будут проходить на системе Debian. Принципиальной разницы между разными дистрибутивами не будет. Конфигурация везде плюс-минус одинаковая.
Установка Loki
Выполним установку Loki с помощью Docker Compose. Я возьму стандартную конфигурацию с хранением логов в локальной директории сервера. Это наиболее простой способ хранения логов, который доступен всем и везде. Достаточно выделить виртуальной машине дополнительное место для логов или отдельный диск, раздел.
Создаём директорию для конфигурации Loki и в ней файл compose.yaml:
# mkdir ~/loki && cd ~/loki && touch compose.yaml
services:
loki:
container_name: loki
image: docker.io/grafana/loki:3.6
command: "-config.file=/etc/loki/config.yaml"
ports:
- "3100:3100"
volumes:
- ./config/config.yaml:/etc/loki/config.yaml:ro
- /mnt/loki:/loki:rw
restart: unless-stopped
На что тут обратить внимание:
- loki:3.6 - актуальная версия loki на момент написания статьи, уточнить версию можно в репозитории
- config.yaml - файл конфигурации самого Loki, настроим далее
- /mnt/loki - раздел, где будут храниться логи, не забудьте его создать с правильными правами для доступа из контейнера
# mkdir /mnt/loki # chown -R 10001:10001 /mnt/loki # chmod 755 /mnt/loki
Раздел для хранения логов у меня вынесен в /mnt/loki и подключается через механизм Bind Mount. Это удобнее для запуска в проде, так как можно легко вынести хранение на отдельный раздел и диск со своими настройками и файловой системой. Но это неудобно с точки зрения переносимости конфигурации на другой хост. Надо не забывать указывать актуальную директорию. Если вы используете Loki для запуска в тестовой среде или для очень маленького проекта, то удобнее использовать Volumes. Примерно так:
services:
loki:
container_name: loki
image: docker.io/grafana/loki:3.6
command: "-config.file=/etc/loki/config.yaml"
ports:
- "3100:3100"
volumes:
- ./config/config.yaml:/etc/loki/config.yaml:ro
- data_loki:/loki:rw
restart: unless-stopped
volumes:
data_loki:
driver: local
Как запускать вам, решайте у себя по месту. Создадим конфигурацию для Loki:
# mkdir ~/loki/config && cd ~/loki/config && touch config.yaml
---
auth_enabled: false
server:
http_listen_port: 3100
common:
instance_addr: 127.0.0.1
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
schema_config:
configs:
- from: 2020-10-24
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
compactor:
working_directory: /loki/compactor
retention_enabled: true
delete_request_store: filesystem
compaction_interval: 10m
retention_delete_delay: 2h
retention_delete_worker_count: 150
limits_config:
retention_period: 720h
ingestion_rate_mb: 4
ingestion_burst_size_mb: 6
max_streams_per_user: 10000
max_line_size: 256000
ruler:
alertmanager_url: http://localhost:9093
Здесь обращаем внимание на следующие параметры:
- auth_enabled: false - аутентификация на уровне Loki отключена, если она будет нужна, то можно настроить доступ через reverse-proxy и сделать аутентификацию на ней
- replication_factor: 1 - каждый чанк логов хранится в единственном числе, что логично для установки в единственном экземпляре с локальных хранением
- from: 2020-10-24 - формат схемы хранения, не знаю, что конкретно обозначает эта дата, но в документации по умолчанию используется эта схема
- prefix: index_ и period: 24h - данные хранятся в индексах с указанным префиксом, а индексы создаются раз в сутки, при очистке старых данных удаление происходит суточными индексами
- retention_period: 720h - хранения логов 720 часов = 30 дней
- ingestion_rate_mb: 4 и ingestion_burst_size_mb: 6 - максимальная скорость приёма логов 4 МБ/с на пользователя с разрешённым всплеском до 6 МБ/с
- max_line_size: 256000 - максимальный размер одной строки лога ~256 КБ
Отмечу, что в одно и то же хранилище могут писать несколько экземпляров Loki. Префиксы индексов нужны в том числе для того, чтобы различать логи от разных экземпляров.
Compose файл готов, конфигурация тоже. Можно запускать Loki. Для этого будучи в директории с файлом compose.yaml выполните:
# docker compose up -d
После запуска сразу же проверим, отвечает ли сервис на настроенном порту:
# curl http://192.168.137.29:3100 404 page not found
В данном случае ответ 404 подходит, так как даёт его сервис Loki в контейнере, а значит он как минимум запущен и отвечает на запросы. Мы отправили неверный запрос, поэтому и ответ 404.
На этом установка и настройка базовой конфигурации Loki завершена. Двигаемся дальше.
Установка Grafana
Для взаимодействия с логами в Loki нам понадобится установить веб панель Grafana. Никаких особых требований к настройке нет, поэтому запустим с базовой минимальной конфигурацией. Её можно было бы запустить в одном compose файле с Loki, но я для удобство запускаю по отдельности, потому что есть высокая вероятность, что запущены они будут на разных серверах, так как Grafana чаще всего связана ещё и с мониторингом. Архитектурно нет никакого смысла запускать её вместе с Loki. Но на небольших или тестовых проектах их можно объединить.
Создаём compose.yaml для Grafana:
# mkdir ~/grafana && cd ~/grafana && touch compose.yaml
services:
grafana:
image: docker.io/grafana/grafana-oss:12.3.2
container_name: grafana
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
restart: unless-stopped
volumes:
grafana-data:
driver: local
Запускаем:
# docker compose up -d
Идём в браузере в веб интерфейс на порт 3000. Учётная запись по умолчанию в Grafana - admin / admin.
Первым делом нам нужно будет добавить источник данных в виде нашего Loki. Для этого идём в раздел Connections ⇨ Data sources ⇨ Add data source. Выбираем Loki. Указываем url, остальное можно не трогать. В моём случае это http://192.168.137.29:3100/. Мотаем страничку в самый низ и нажимаем Save & Test. Ошибок быть не должно.
Grafana тоже установили и настроили в связке с Loki. Можно передавать логи в хранилище.
Настройка Alloy для текстовых логов Linux и Journald
Актуальным и рекомендуемым Графаной на момент написания статьи способом передачи различной информации в Loki является их же агент Alloy, который нужно установить на конечный сервер, с которого надо забирать данные. Это могут быть не только логи, но и метрики мониторинга, трейсы и некоторые другие вещи. В рамках данной статьи я рассмотрю вариант только с логами.
Настроим Alloy для отправки системных логов Linux в Loki. Покажу сразу в одном примере и отправку традиционных текстовых логов от syslog, которые хранятся в /var/log, и журналов journald, компонента логирования systemd.
Логи могут собираться не только с хостов, где установлен Docker, поэтому в своём примере выполню установку из пакета, собранного под все популярные системы Linux. Если у вас нет блокировки доступа к официальному репозиторию Grafana, то можете подключить его к своей системе Debian/Ubuntu:
# mkdir -p /etc/apt/keyrings # wget -O /etc/apt/keyrings/grafana.asc https://apt.grafana.com/gpg-full.key # chmod 644 /etc/apt/keyrings/grafana.asc # echo "deb [signed-by=/etc/apt/keyrings/grafana.asc] https://apt.grafana.com stable main" > /etc/apt/sources.list.d/grafana.list
Установку под другие системы или другим способом можно посмотреть в официальной документации. Там всё подробно расписано.
Если же вы из России, то доступ к репозиторию скорее всего будет заблокирован, но можно воспользоваться любым зеркалом. Например, от Яндекса:
# echo "deb [trusted=yes] https://mirror.yandex.ru/mirrors/packages.grafana.com/oss/deb/ stable main" > /etc/apt/sources.list.d/grafana.list
Устанавливаем Alloy:
# apt update # apt install alloy
Для сбора системных логов из /var/log и journald настройте следующую конфигурацию в файле /etc/alloy/config.alloy:
// SECTION: TARGETS
loki.write "default" {
endpoint {
url = "http://192.168.137.30:3100/loki/api/v1/push"
}
external_labels = {}
}
// !SECTION
// SECTION: SYSTEM LOGS & JOURNAL
loki.source.journal "journal" {
max_age = "24h0m0s"
relabel_rules = discovery.relabel.journal.rules
forward_to = [loki.write.default.receiver]
labels = {component = string.format("%s-journal", constants.hostname)}
path = "/var/log/journal"
}
local.file_match "system" {
path_targets = [{
__address__ = "localhost",
__path__ = "/var/log/{syslog,messages,*.log}",
instance = constants.hostname,
job = string.format("%s-logs", constants.hostname),
}]
}
discovery.relabel "journal" {
targets = []
rule {
source_labels = ["__journal__systemd_unit"]
target_label = "unit"
}
rule {
source_labels = ["__journal__boot_id"]
target_label = "boot_id"
}
rule {
source_labels = ["__journal__transport"]
target_label = "transport"
}
rule {
source_labels = ["__journal_priority_keyword"]
target_label = "level"
}
}
loki.source.file "system" {
targets = local.file_match.system.targets
forward_to = [loki.write.default.receiver]
}
// !SECTION
Здесь вам возможно нужно будет изменить следующие параметры:
- url = "http://192.168.137.30:3100/loki/api/v1/push" - адрес сервера Loki
- __path__ = "/var/log/{syslog,messages,*.log}" - перечисление логов, которые будут отправляться, в данном случае файлы syslog и messages, плюс все файлы с окончанием .log
- labels = {component = string.format("%s-journal", constants.hostname)} - назначение метки в виде hostname-journal, то есть имя хоста и через тире добавление journal
- job = string.format("%s-logs", constants.hostname) - метка job с именем хоста и приставкой logs, чтобы удобно было отличать от логов journald
Остальные параметры можно не трогать. Перезапускаем Alloy с новой конфигурацией и добавляем в автозагрузку:
# systemctl restart alloy # systemctl enable alloy
Переходим в веб интерфейс Grafana, в раздел Drilldown ⇨ Logs. Так как это наш первый сборщик логов, то там мы увидим 2 наборов логов под названием debian13-logs и debian13-journal.
В данном случае debian13 - имя сервера. На этом сервере одновременно записываются логи и в /var/logs, и в journald.
Выбрав в разделе Service в выпадающем списке один из источников логов, можно детально изучить их, используя выборки по различным меткам. Например, по имени файла с логом.
Настройка Promtail для сбора логов
Для полноты картины покажу, как сбор этих же логов из /var/log и journald можно настроить с помощью более старого и легковесного продукта Promtail, который в настоящее время объявлен устаревшим и не развивается, но до сих пор продолжает нормально работать в качестве сборщика логов.
Подключаем репозиторий Grafana, как показано в предыдущем разделе и устанавливаем Promtail:
# apt install promtail
Формируем для него конфигурационный файл /etc/promtail/config.yml:
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://192.168.137.29:3100/loki/api/v1/push
scrape_configs:
- job_name: logs
static_configs:
- targets:
- localhost
labels:
host: ${HOSTNAME}
job: ${HOSTNAME}-logs
__path__: '/var/log/{syslog,*.log}'
- job_name: journal
journal:
max_age: 24h
labels:
host: ${HOSTNAME}
job: ${HOSTNAME}-journal
relabel_configs:
- source_labels: ['__journal__systemd_unit']
target_label: 'unit'
- source_labels: ['__journal__hostname']
target_label: 'journal_host'
- source_labels: ["__journal__boot_id"]
target_label: 'boot_id'
- source_labels: ["__journal_priority_keyword"]
target_label: 'level'
- source_labels: ["__journal__transport"]
target_label: 'transport'
Я в конфигурации использую переменную окружения ${HOSTNAME}, с помощью которой передаю имя сервера в метки. По умолчанию promtail не читает переменные окружения. Чтобы это исправить, надо явно в юнит systemd передать эту переменную и указать для promtail использование внешних переменных. Для этого есть отдельный параметр запуска -config.expand-env=true. Добавляем его. Для этого правим юнит systemd:
# systemctl edit promtail
Добавляем туда строки:
[Service] Environment=HOSTNAME=%H ExecStart= ExecStart=/usr/bin/promtail -config.file /etc/promtail/config.yml -config.expand-env=true
Перечитываем конфигурацию systemd:
# systemctl daemon-reload
Добавляем пользователя promtail, от которого работает сборщик логов, в группу adm, чтобы он имел к ним доступ:
# usermod -aG adm promtail # usermod -aG systemd-journal promtail
Перезапускаем promtail:
# systemctl restart promtail
У вас не должно быть ошибок. Если ошибки есть и служба promtail не запускается, смотрите системный лог. Там будут видны ошибки. Я в процессе настройки и отладки этой конфигурации сначала получал ошибки на неправильное форматирование yaml файла:
promtail[17820]: Unable to parse config: /etc/promtail/config.yml: yaml: line 27: did not find expected key.
Исправил это. А потом получил ошибку на отсутствие доступа к лог-файлам:
promtail[17820]: Unable to parse config: /etc/promtail/config.yml: yaml: line 27: did not find expected key.
После того, как выдал права, системные логи Linux отправились от Promtail в Loki. Теперь у меня там логи от Debian 13, отправленные через Alloy, и от Ubuntu 24, отправленные через Promtail.
Отлично. Базовую настройку Loki и отправку туда системных логов Linux мы настроили, используя при этом разные программы - Alloy и Promtail. Переходим к отправке в Loki других видов логов.
Сбор логов Docker
Отправить в Loki логи Docker можно разными способами. Например, это можно сделать в том числе с помощью Promtail или Alloy, про которые я написал выше. В этом разделе я покажу самый простой и быстрой способ - с помощью Docker Driver. Устанавливаем его:
# docker plugin install grafana/loki-docker-driver:3.6.0-amd64 --alias loki --grant-all-permissions
Проверяем, что он установился:
# docker plugin ls
Далее у нас есть 2 пути:
- Можно глобально на хосте для службы Docker указать отправку логов в Loki для всех контейнеров.
- Для каждого отдельного контейнера при создании указать, куда отправлять его логи.
Мне лично видится более удобным второй способ, так как он позволяет гибко управлять отправкой логов в каждом конкретном случае. Для этого достаточно в настройках compose.yaml добавить секцию с logging и указать там параметры для драйвера loki. Выглядит примерно так:
services: grafana: image: docker.io/grafana/grafana-oss:12.3.2 container_name: grafana logging: driver: loki options: loki-url: "http://192.168.137.29:3100/loki/api/v1/push" loki-retries: 2 loki-max-backoff: 800ms loki-timeout: 1s keep-file: "true" mode: "non-blocking" ports: - "3000:3000" volumes: - grafana-data:/var/lib/grafana restart: unless-stopped volumes: grafana-data: driver: local
Здесь мы для Docker контейнера с Grafana указали, что логи необходимо отправлять на наш сервер Loki. Дополнительные параметры указаны для того, чтобы не было блокировки запуска контейнера, если сервер с логами будет недоступен. Подробное описание параметров можно посмотреть в документации, не буду на этом останавливаться.
Если контейнеры у вас уже созданы без настроек логирования, то для их добавления контейнеры придётся пересоздать.
Для отправки логов от всех контейнеров Docker конкретного хоста в Loki, добавьте в файл конфигурации /etc/docker/daemon.json параметры:
{
"debug": true,
"log-driver": "loki",
"log-opts": {
"loki-url": "http://192.168.137.29:3100//loki/api/v1/push",
"loki-batch-size": "400"
}
}
После этого службу Docker надо перезапустить. Если файла daemon.json по указанному пути нет, то просто создайте его.
Сбор логов Windows в Loki
Настроим сбор стандартных журналов Windows в Loki. Для этого я буду использовать всё тот же Alloy. Для Windows проще всего скачать установщик из официального репозитория. Нужен будет файл alloy-installer-windows-amd64.exe.
Alloy установится как служба с автоматическим запуском.
Файл конфигурации config.alloy располагается в директории C:\Program Files\GrafanaLabs\Alloy\. В нём нужно явно указать все журналы, которые вы хотите собирать. Ниже привожу пример со сбором стандартных журналов System, Application и Security.
logging {
level = "info"
}
// SECTION: TARGETS
loki.write "default" {
endpoint {
url = "http://192.168.137.30:3100/loki/api/v1/push"
}
external_labels = {}
}
// !SECTION
// SECTION: WINLOGS
loki.source.windowsevent "system" {
eventlog_name = "System"
use_incoming_timestamp = true
bookmark_path = "C:/ProgramData/GrafanaLabs/alloy/system.xml"
labels = {
instance = constants.hostname,
job = string.format("%s-system", constants.hostname),
}
forward_to = [loki.write.default.receiver]
}
loki.source.windowsevent "application" {
eventlog_name = "Application"
use_incoming_timestamp = true
bookmark_path = "C:/ProgramData/GrafanaLabs/alloy/application.xml"
labels = {
instance = constants.hostname,
job = string.format("%s-application", constants.hostname),
}
forward_to = [loki.write.default.receiver]
}
loki.source.windowsevent "security" {
eventlog_name = "Security"
use_incoming_timestamp = true
bookmark_path = "C:/ProgramData/GrafanaLabs/alloy/security.xml"
labels = {
instance = constants.hostname,
job = string.format("%s-security", constants.hostname),
}
forward_to = [loki.write.default.receiver]
}
// !SECTION
Особое внимание, как обычно, стоит уделить меткам. Когда логов много, нужно иметь возможность быстро находить то, что вам нужно. Я здесь каждому логу добавил две метки:
- instance = "имя сервера", например WIN-VN3PJCM08OH.
- job = "имя сервера"-"имя журнала", то есть WIN-VN3PJCM08OH-system.
Достаточно изменить файл config.alloy и перезапустить службу. Windows логи отправятся в Loki. Отлаживать конфигурацию Alloy неудобно. Если что-то не так, то служба просто не будет запускаться, выдавая в системный лог неинформативную ошибку. ИИшки тут мне несильно помогли, так как они то и давали конфигурацию, которая не запускалась. Пришлось вручную разобраться и сделать нормальную работающую версию.
В общем плане настройка сбора логов из Windows в Loki проста. По сути их нужно только отправить, а дальше Loki сам всё распарсит и выделит стандартные поля event_id, channel, level, security_userId, timeCreated и т.д. По ним можно будет делать выборку.
Нам по умолчанию становятся доступны все фильтры, что и в стандартной оснастке для просмотра логов в системе Windows.
Приём Syslog логов
У Loki нет прямого приёмника для syslog. Нужно будет воспользоваться промежуточным агентом для приёма и отправки логов. Тут есть несколько вариантов:
- Grafana Alloy
- Promtail
- Vector, Fluent Bit или любой другой похожий сторонний софт
- Сбор логов в текстовый файл с помощью rsyslog и отправка в Loki, как я показывал ранее.
В целом, все эти способы имеют право на жизнь. Выбирать стоит в зависимости от вашей инфраструктуры. Проще всего конфигурация будет у Promtail, но так как он уже объявлен deprecated, я покажу пример с Alloy и Vector. Собирать логи буду с Mikrotik, а сборщики установлю на один из хостов с Linux. Можно взять тот же сервер, где работает Loki. Разницы нет, выбирайте, как вам удобнее.
Про установку Alloy я уже рассказывал ранее, так что не буду на этом останавливаться. Рисуем ему следущую конфигурацию:
loki.write "default" {
endpoint {
url = "http://192.168.137.30:3100/loki/api/v1/push"
}
external_labels = {}
}
loki.source.syslog "syslog_in" {
listener {
address = "0.0.0.0:1514"
protocol = "udp"
labels = { job = "syslog" }
}
forward_to = [loki.process.syslog_process.receiver]
}
loki.process "syslog_process" {
stage.labels {
values = {
remote_ip = "__syslog_connection_ip_address",
hostname = "__syslog_message_hostname",
app = "__syslog_message_app_name",
}
}
forward_to = [loki.write.default.receiver]
}
По умолчанию Alloy умеет парсить логи формата RFC5424. А Mikrotik и некоторые другие сетевые устройства используют более старый формат RFC3164. Если у вас такое устройство, то нужно будет добавить в конфигурацию пару дополнительных параметров в раздел loki.source.syslog и заодно я сразу отдельную метку Mikrotik добавил, так как эта конфигурация для него:
loki.source.syslog "syslog_in" {
listener {
address = "0.0.0.0:1514"
protocol = "udp"
syslog_format = "rfc3164"
rfc3164_default_to_current_year = true
labels = { job = "syslog", device = "Mikrotik"}
}
forward_to = [loki.process.syslog_process.receiver]
}
Остальное можно не менять, но нужно понимать, что автоматическое назначение меток для формата RFC3164 работать не будет, так как Alloy его не распарсит.
Перезапускаем Alloy и идём настраивать Mikrotik на отправку своих логов.
# systemctl restart alloy
Переходим в раздел System ⇨ Logging ⇨ Actions и добавляем новое действие. Я назвал его Loki, указал адрес и порт сервера, где установлен Alloy, в качестве Remote Log Format выбрал BSD Syslog. После этого в разделе Rules добавил новое правило для логов System действие - Loki.
Всё, в Микротике больше ничего делать не надо. Можно идти в Loki и смотреть новые логи. Если их там нет, то посмотрите системный лог на сервере с Alloy. Но по умолчанию в syslog или journald пишет. Если есть ошибки, вы их там увидите.
В Loki логи от Микротика выглядят примерно так:
Содержимое логов присутствует, но работать с ними не удобно, так как нет метаданных об отправителе, имени устройства и т.д. Если в один приёмник будут отправлять логи разные устройства, всё это превратится в общую портянку, где трудно будет найти что-то конкретное. Эту проблему можно решить средствами Alloy, например, добавив в обработку парсинг с помощью regex, но это хлопотно и трудоёмко. Я покажу решение гораздо проще и универсальнее, где всё это будет выполняться автоматически.
Для приёма и отправки логов формата syslog воспользуемся программой Vector. Ставим её в систему из пакетов:
# bash -c "$(curl -L https://setup.vector.dev)" # apt install vector
Первая команда использует скрипт для подключения репозиториев. Вы можете использовать любой способ установки. В документации разработчиков их представлено много. Рисуем конфигурацию для Vector в файле /etc/vector/vector.yaml:
sources:
syslog_udp:
type: syslog
address: 0.0.0.0:2514
mode: udp
sinks:
syslog_to_loki:
type: loki
inputs:
- syslog_udp
compression: none
encoding:
codec: json
endpoint: http://192.168.137.30:3100
healthcheck: false
buffer:
type: disk
max_size: 1073741824 # 1GB
labels:
job: syslog
Она универсальная и подойдёт для логов любого формата. Перезапускаем Vector и добавляем в автозапуск:
# systemctl restart vector # systemctl enable vector
Не забудьте на Mikrotik поменять порт с 1514, который настроен в Alloy на 2514, как в конфигурации Vector. Смотрим на те же самые логи в Loki, но отправленные вектором.
У нас все основные поля распарсены. Мы можем по ним делать выборку, настраивать удобное представление логов. Например, вот так.
Я отфильтровал записи по конкретному устройству и настроил отображение в логе имени устройства, его IP, название приложения и сам текст сообщения. Такое представление удобнее и нагляднее того, что предлагает Alloy. Это благодаря тому, что Vector автоматически парсит любой формат syslog и сразу трансформирует его в json. А с json в Loki автоматически работают любые группировки и поиск.
Сбор логов веб сервера Nginx и Angie в Loki
Рассмотри ещё один практический пример. Соберём логи веб сервера и сделаем для них дашборд. В качестве веб сервера возьмём наиболее популярные Nginx/Angie. В данном примере их настройка будет идентична. Для того, чтобы показать не готовое решение, а научить вас самих собирать дашборды, я вначале возьму генератор логов веб сервера и покажу на его примере. А потом адаптируем настройки логов реального веб сервера под получившийся пример.
В качестве генератора логов я возьму простую утилиту flog. Она может создавать логи веб сервера в наиболее популярных форматах, с заданной интенсивностью и максимальным размером. Для отладки хранилища логов отличное и простое решение.
# wget https://github.com/mingrammer/flog/releases/download/v0.4.4/flog_0.4.4_linux_amd64.tar.gz # tar -xzf flog_0.4.4_linux_amd64.tar.gz flog # mv flog /usr/local/bin/
Теперь сгенерируем логи в формате json. Для Loki удобнее всего генерировать логи именно в этом формате, так как он существенно упрощает дальнейший парсинг. Фактически он будет происходить автоматически. Можно разово сделать лог файл размером 10 мегабайт:
# flog -t log -f json -o /var/log/nginx/access.log -b 10485760
Это не очень удобно для нашей задачи, так как время всех событий в логе будет идентичное. Удобнее запустить непрерывную генерацию с заданным интервалом. В данном случае - 300 мс.
# flog -t log -f json -o /var/log/nginx/access.log -b 10485760 -d 300ms -w
Можно в одном терминале запустить генерации и оставить. А в другом работать с настройкой. Формат логов будет вот такой:
{"host":"208.71.182.144", "user-identifier":"gutmann7885", "datetime":"13/Apr/2026:10:57:27 +0300", "method": "HEAD", "request": "/recontextualize", "protocol":"HTTP/1.0", "status":302, "bytes":5054, "referer": "https://www.humanefficient.io/e-markets/brand/killer/e-commerce"}
По получаемым данным этот формат соответствует типу логов apache_combined. Но из-за того, что у нас выбран формат json, названия полей могут различаться в зависимости от настроек, которые можно указывать вручную. Я имею ввиду названия полей host, datetime, request и т.д.
Для данного формата лога имеет смысл сразу же назначить метки некоторым полям, по которым потом можно будет делать группировки. Это ускорит данную процедуру и уменьшит потребление ресурсов на неё. Рисуем конфигурацию для alloy, которая будет передавать логи в Loki.
loki.write "default" {
endpoint {
url = "http://192.168.137.30:3100/loki/api/v1/push"
}
external_labels = {}
}
local.file_match "web_logs" {
path_targets = [
{
__path__ = "/var/log/nginx/access.log",
instance = constants.hostname,
job = "nginx",
service = "web",
},
{
__path__ = "/var/log/angie/access.log",
instance = constants.hostname,
job = "angie",
service = "web",
},
]
}
loki.source.file "web_logs" {
targets = local.file_match.web_logs.targets
forward_to = [loki.process.nginx_pipeline.receiver]
}
loki.process "nginx_pipeline" {
forward_to = [loki.write.default.receiver]
stage.json {
expressions = {
request = "request",
status = "status",
method = "method",
host = "host",
}
}
stage.labels {
values = {
request = "",
status = "",
method = "",
host = "",
}
}
}
Мне приходится работать с обоими веб серверами, поэтому сразу оба добавил в конфигурацию. Если вам какой-то не нужен, просто удалите строки с ним. Я добавил метки на следующие поля:
- request - url запроса, например /deploy/innovative
- status - код ответа, например, 200, 404, 502 и т.д.
- method - метод запроса, например, GET, PUT и т.д.
- host - IP адрес клиента, отправившего запрос
Смотрим на эти логи в Grafana:
Видим настроенные индексированные поля. Они нужны будут для дашборда. Без них некоторые выборки будут очень ресурсоёмки. Переходим к созданию своего дашборда.
Создание дашбордов для логов
Изначально я ожидал увидеть готовые дашборды для логов веб сервера Nginx. Но я их не нашёл. Пришлось разбираться самому с нуля и делать свой. Для этого сразу же привлёк на помощь ИИ. Они сильно упрощают решение однотипных задач. А рисование дашборда таковой и является. Другое дело, что сразу получить готовое работающее решение у меня не получилось. Пришлось потом дорабатывать и изменять то, что нагенерилили ИИ.
У меня получилась в итоге вот такая панель:
Добавил в неё тот набор визуализаций, что мне показались полезными для быстрого анализа состояния веб сервера в плане запросов к нему. Тут отображены следующие значения:
- Количество запросов в секунду (RPC)
- Исходящий трафик веб сервера (bytes/sec)
- Количество 400-х и 500-х ошибок
- Коды ответа веб сервера
- Типы запроса к веб серверу
- ТОП 20 IP клиентов с запросами к веб севреру
- ТОП 20 урлов, к которым выполнялись запросы
Последние 2 метрики в зависимости от объёма логов, временного интервала и настройки max_query_series в Loki могут то работать, то нет. Они очень затратны по ресурсам, так как на лету выполняют вычисления по всему объёму логов. Если вам они сильно не нужны, то лучше отключить. Но иногда они бывают полезны, поэтому я оставил. На небольших временных интервалах должны работать.
В целом, ничего сложного в построении дашбордов нет. Нужен опыт, так как очень много всевозможных настроек и преобразований в визуализации. Когда первый раз разбираешься, приходится долго пробовать те или иные настройки, сортировки, замены полей для удобства и т.д.
Сами запросы на выборку данных выглядят интуитивно. Например, смотрим график с RPS. Запрос там такой:
sum(rate({job="$job"} [1m]))
Меняя запрос и параметры отображения, можно тут же в режиме реального времени следить за изменениями. Для отображения статусов запросов, используется такое выражение:
sum by (status) (rate({job="$job"} [1m]))
Ну и так далее. Отдельные запросы вам без проблем напишет ИИ и всё разъяснит. Можно очень быстро во всём разобраться. Нюансы будут возникать с нагрузкой и хранением. Там уже нужно будет разбираться с labels, structured_metadata и т.д. В общем случае для простых визуализаций это не потребуется.
Вот исходный код настроенного мной дашборда для этой статьи:
{
"__inputs": [
{
"name": "DS_LOKI",
"label": "loki",
"description": "",
"type": "datasource",
"pluginId": "loki",
"pluginName": "Loki"
}
],
"__elements": {},
"__requires": [
{
"type": "panel",
"id": "bargauge",
"name": "Bar gauge",
"version": ""
},
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "12.3.1"
},
{
"type": "datasource",
"id": "loki",
"name": "Loki",
"version": "12.3.1"
},
{
"type": "panel",
"id": "piechart",
"name": "Pie chart",
"version": ""
},
{
"type": "panel",
"id": "table",
"name": "Table",
"version": ""
},
{
"type": "panel",
"id": "timeseries",
"name": "Time series",
"version": ""
}
],
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"links": [],
"panels": [
{
"datasource": {
"type": "loki",
"uid": "${DS_LOKI}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"barWidthFactor": 0.6,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"showValues": false,
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"displayName": "Число запросов в сек (среднее)",
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": 0
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 11,
"x": 0,
"y": 0
},
"id": 1,
"options": {
"legend": {
"calcs": [
"mean"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"hideZeros": false,
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "12.3.1",
"targets": [
{
"direction": "backward",
"editorMode": "code",
"expr": "sum(rate({job=\"$job\"} [1m]))",
"queryType": "range",
"refId": "A",
"datasource": {
"type": "loki",
"uid": "${DS_LOKI}"
}
}
],
"title": "Requests per second (RPS)",
"type": "timeseries"
},
{
"datasource": {
"type": "loki",
"uid": "${DS_LOKI}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"barWidthFactor": 0.6,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"showValues": false,
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": 0
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 13,
"x": 11,
"y": 0
},
"id": 7,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": false
},
"tooltip": {
"hideZeros": false,
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "12.3.1",
"targets": [
{
"direction": "backward",
"editorMode": "code",
"expr": "sum(rate({job=\"$job\"} | json | unwrap bytes [1m]))",
"queryType": "range",
"refId": "A",
"datasource": {
"type": "loki",
"uid": "${DS_LOKI}"
}
}
],
"title": "Traffic (bytes/sec)",
"type": "timeseries"
},
{
"datasource": {
"type": "loki",
"uid": "${DS_LOKI}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "RPS",
"axisPlacement": "auto",
"barAlignment": 0,
"barWidthFactor": 0.6,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"showValues": false,
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": 0
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 8,
"x": 0,
"y": 8
},
"id": 5,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": false
},
"tooltip": {
"hideZeros": false,
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "12.3.1",
"targets": [
{
"direction": "backward",
"editorMode": "code",
"expr": "sum(rate({job=\"$job\"} | status >= 400 and status < 500 [1m]))", "queryType": "range", "refId": "A", "datasource": { "type": "loki", "uid": "${DS_LOKI}" } } ], "title": "4xx Errors", "type": "timeseries" }, { "datasource": { "type": "loki", "uid": "${DS_LOKI}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "RPS", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "showValues": false, "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": 0 }, { "color": "red", "value": 80 } ] } }, "overrides": [] }, "gridPos": { "h": 7, "w": 8, "x": 8, "y": 8 }, "id": 6, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": false }, "tooltip": { "hideZeros": false, "hoverProximity": -1, "mode": "single", "sort": "none" } }, "pluginVersion": "12.3.1", "targets": [ { "direction": "backward", "editorMode": "code", "expr": "sum(rate({job=\"$job\"} | status >= 500 [1m]))",
"queryType": "range",
"refId": "A",
"datasource": {
"type": "loki",
"uid": "${DS_LOKI}"
}
}
],
"title": "5xx Errors",
"type": "timeseries"
},
{
"datasource": {
"type": "loki",
"uid": "${DS_LOKI}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "RPS",
"axisPlacement": "auto",
"barAlignment": 0,
"barWidthFactor": 0.6,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"showValues": false,
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": 0
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 8,
"x": 16,
"y": 8
},
"id": 2,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"hideZeros": false,
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "12.3.1",
"targets": [
{
"direction": "backward",
"editorMode": "code",
"expr": "sum by (status) (rate({job=\"$job\"} [1m]))",
"queryType": "range",
"refId": "A",
"datasource": {
"type": "loki",
"uid": "${DS_LOKI}"
}
}
],
"title": "HTTP Status Codes",
"type": "timeseries"
},
{
"datasource": {
"type": "loki",
"uid": "${DS_LOKI}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
}
},
"mappings": []
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 8,
"x": 0,
"y": 15
},
"id": 8,
"options": {
"legend": {
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"pieType": "pie",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"sort": "desc",
"tooltip": {
"hideZeros": false,
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "12.3.1",
"targets": [
{
"direction": "backward",
"editorMode": "code",
"expr": "sum by (method) (count_over_time({job=\"$job\"} [$__range]))",
"queryType": "range",
"refId": "A",
"datasource": {
"type": "loki",
"uid": "${DS_LOKI}"
}
}
],
"title": "HTTP Methods",
"type": "piechart"
},
{
"datasource": {
"type": "loki",
"uid": "${DS_LOKI}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": 0
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "host"
},
"properties": []
},
{
"matcher": {
"id": "byName",
"options": "Число запросов"
},
"properties": []
}
]
},
"gridPos": {
"h": 9,
"w": 8,
"x": 8,
"y": 15
},
"id": 9,
"options": {
"displayMode": "gradient",
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": false
},
"maxVizHeight": 300,
"minVizHeight": 16,
"minVizWidth": 8,
"namePlacement": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": true
},
"showUnfilled": true,
"sizing": "auto",
"valueMode": "color"
},
"pluginVersion": "12.3.1",
"targets": [
{
"direction": "backward",
"editorMode": "code",
"expr": "topk(20,\r\n sum by (host) (\r\n count_over_time({job=\"$job\"}[$__range])\r\n )\r\n)",
"queryType": "instant",
"refId": "A",
"datasource": {
"type": "loki",
"uid": "${DS_LOKI}"
}
}
],
"title": "Top Client IPs",
"transformations": [
{
"id": "sortBy",
"options": {
"fields": {},
"sort": [
{
"desc": true,
"field": "Value #A"
}
]
}
}
],
"type": "bargauge"
},
{
"datasource": {
"type": "loki",
"uid": "${DS_LOKI}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {
"align": "auto",
"cellOptions": {
"type": "auto"
},
"footer": {
"reducers": [
"sum"
]
},
"inspect": false
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": 0
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "URL"
},
"properties": []
},
{
"matcher": {
"id": "byName",
"options": "Число запросов"
},
"properties": []
}
]
},
"gridPos": {
"h": 9,
"w": 8,
"x": 16,
"y": 15
},
"id": 3,
"options": {
"cellHeight": "sm",
"enablePagination": true,
"showHeader": true,
"sortBy": [
{
"desc": true,
"displayName": "Число запросов"
}
]
},
"pluginVersion": "12.3.1",
"targets": [
{
"direction": "backward",
"editorMode": "code",
"expr": "topk(20,\r\n sum by (request) (\r\n count_over_time({job=\"$job\"}[$__range])\r\n )\r\n)",
"queryType": "instant",
"refId": "A",
"datasource": {
"type": "loki",
"uid": "${DS_LOKI}"
}
}
],
"title": "Top URLs",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {
"Time": true
},
"includeByName": {},
"indexByName": {},
"renameByName": {
"Time": "",
"Value #A": "Число запросов",
"request": "URL"
}
}
},
{
"id": "sortBy",
"options": {
"fields": {},
"sort": [
{
"desc": true,
"field": "Число запросов"
}
]
}
}
],
"type": "table"
}
],
"preload": false,
"refresh": "",
"schemaVersion": 42,
"tags": [],
"templating": {
"list": [
{
"current": {},
"definition": "",
"name": "job",
"options": [],
"query": {
"label": "job",
"refId": "LokiVariableQueryEditor-VariableQuery",
"stream": "",
"type": 1
},
"refresh": 1,
"regex": "",
"type": "query"
}
]
},
"time": {
"from": "now-5m",
"to": "now"
},
"timepicker": {},
"timezone": "browser",
"title": "Nginx Logs (Loki)",
"uid": "1d2b765b-d840-4b33-98c1-667fddd56b37",
"version": 31,
"weekStart": "",
"id": null
}
Для добавления его к себе в Grafana при создании дашборда выберите пункт Import и вставьте json дашборда в соответствующее поле.
Свяжите его со своим Datasource с Loki и пользуйтесь.
Для того, чтобы этот дашборд заработал с реальными логами веб сервера, их необходимо привести к такому же виду. Вот как это выглядит в конфигурации Nginx/Angie:
http {
...................
log_format json escape=json
'{'
'"host":"$remote_addr",'
'"user-identifier":"$remote_user",'
'"datetime":"$time_local",'
'"method":"$request_method",'
'"request":"$request_uri",'
'"protocol":"$server_protocol",'
'"status":"$status",'
'"bytes":"$request_length",'
'"referrer":"$http_referer",'
'"user_agent":"$http_user_agent"'
'}';
...............
}
Данный код нужно добавить в блок http в основной конфигурации веб сервера. И потом выбрать этот формат в настройках общего логирования или конкретного виртуального хоста.
access_log /var/log/nginx/access.log json;
Данный формат можно вести параллельно с обычным, если вы хотите себе оставить возможность привычным способом просматривать логи. То есть можно сделать примерно вот так:
access_log /var/log/nginx/access.log main; access_log /var/log/nginx/access.json.log json;
Веб сервер будет одновременно писать два лог файла в разных форматах.
Очистка данных в Loki
Удалять логи вручную из Loki - муторное занятие и в общем случае его не рекомендуется делать. Оно затратно по ресурсам, происходит не сразу, а помещается в очередь на удаление. На нагруженном сервере эта процедура может растянуться во времени.
Для ручного удаления необходимо будет воспользоваться специальным методом API. Вот пример, как это может выглядеть:
# curl -X POST -G "http://localhost:3100/loki/api/v1/delete" --data-urlencode "start=2026-04-12T00:00:00Z" --data-urlencode "end=2026-04-13T20:00:00Z" --data-urlencode "query={job=\"nginx\"}"
Этот запрос удаляет все логи с меткой job=nginx в заданном интервале времени. Его указание обязательно. Не перепутайте часовые пояса при вставлении интервалов. Чтобы сделать более узкую выборку, запрос можно сформировать в разделе Explore и проверить то, что вы хотите удалить.
Другого способа частичного ручного удаления логов в Loki нет.
Заключение
Я разобрал все основные моменты в настройке Loki, чтобы начать собирать в него разнородные логи со всей инфраструктуры:
- Системные логи Linux и Windows
- Логи Docker контейнеров
- Логи веб сервера Nginx или Angie
- Логи сетевых устройств
На удивление, когда изучал его, потратил больше времени по сравнению с ELK. Во многом это из-за того, что в ELK больше возможностей, и я ожидал их же увидеть в Loki, но их нет. Объясняется это тем, что Loki - более легковесное хранилище, структура хранения которого отличается от ELK. Из-за этого работать с данными надо аккуратнее, особенно при построении запросов в дашбордах.
На углубленном курсе "Архитектура современных компьютерных сетей" вы с нуля научитесь работать с Wireshark и «под микроскопом» изучите работу сетевых протоколов. На протяжении курса надо будет выполнить более пятидесяти лабораторных работ в Wireshark.
Реклама ИП Скоромнов Д.А. ИНН 331403723315
Server Admin Авторский блог системного администратора























