Архитектура Loki, отличие от Elasticsearch, сбор и поиск логов
«Метрики говорят что происходит, логи — почему»
Prometheus отлично справляется с метриками, но не хранит логи.
Метрики — это числа во времени (CPU 75%, 100 запросов/сек). Логи — это текстовые записи о событиях («User 123 failed login at 14:32:01»).
Когда алерт сработал, вы смотрите на метрику и видите: «Error rate вырос до 10%». Но почему? Ответ в логах.
| Характеристика | Loki | Elasticsearch (ELK) |
|---|---|---|
| Индексация | Только метаданные (лейблы) | Полнотекстовая индексация всего контента |
| Хранение | Сжатые чанки в объектном хранилище | Индексы на диске |
| Запросы | LogQL (похож на PromQL) | Lucene query language |
| Ресурсы | Низкие требования | Требует много RAM и CPU |
| Use case | Агрегация логов, отладка | Полнотекстовый поиск, аналитика |
Loki проще и дешевле, потому что:
Когда Loki:
Когда Elasticsearch:
┌─────────────────────────────────────────────────────────────┐
│ Promtail / Agent │
│ (сбор логов с файлов, Docker, Kubernetes) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Loki │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Distributor │ │ Ingester │ │ Querier │ │
│ │ (приём) │ │ (чанки) │ │ (запросы) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Object Storage │ │
│ │ (S3, GCS, disk) │ │
│ └─────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌──────────┐
│ Grafana │
│ (запросы)│
└──────────┘
Компоненты:
Лог-линия — одна строка лога:
2026-03-18T14:30:00Z INFO User 123 logged in
Поток (Stream) — группа лог-линий с одинаковыми лейблами:
Stream: {app="api", env="production"}
└─ 2026-03-18T14:30:00Z INFO User 123 logged in
└─ 2026-03-18T14:30:01Z DEBUG Processing request
└─ 2026-03-18T14:30:02Z INFO Request completed
Лейблы — метаданные для фильтрации и агрегации.
Примеры лейблов:
app="api" — имя приложенияenv="production" — окружениеinstance="server1" — конкретный инстансlevel="error" — уровень логированияВажно: Loki индексирует только лейблы, не содержимое логов. Поэтому выбор лейблов критичен.
Хорошие лейблы:
app, env, instance, levelПлохие лейблы:
user_id, request_id (высокая кардинальность — миллионы значений)error_message)По аналогии с Prometheus:
LogQL похож на PromQL, но для логов.
{app="api", env="production"}Возвращает все логи с указанными лейблами.
# Логи содержащие "error"
{app="api"} |= "error"
# Логи НЕ содержащие "debug"
{app="api"} !~ "debug"
# Регулярное выражение
{app="api"} |~ "User \d+ logged in"
# Несколько фильтров
{app="api"} |= "error" |= "database"Операторы:
|= — содержит (case-sensitive)!= — не содержит=~ — совпадение с regex!~ — не совпадает с regex# Только ошибки
{app="api"} |= "level=error"
# Ошибки и предупреждения
{app="api"} |= "level=error" or |= "level=warn"LogQL поддерживает агрегации, похожие на PromQL:
# Количество лог-линий за период
count_over_time({app="api"}[5m])
# Количество ошибок за период
count_over_time({app="api"} |= "error"[1h])
# Первая строка лога
first_over_time({app="api"}[5m])
# Последняя строка лога
last_over_time({app="api"}[5m])# Логи в секунду
rate({app="api"}[5m])
# Ошибки в секунду
rate({app="api"} |= "error"[5m])Добавим Loki в наш docker-compose.
version: '3.8'
services:
prometheus:
# ... (без изменений)
grafana:
# ... (без изменений)
loki:
image: grafana/loki:2.9.0
container_name: loki
ports:
- "3100:3100"
volumes:
- ./loki/loki-config.yml:/etc/loki/local-config.yaml
- loki_data:/loki
command: -config.file=/etc/loki/local-config.yaml
restart: unless-stopped
promtail:
image: grafana/promtail:2.9.0
container_name: promtail
volumes:
- ./promtail/promtail-config.yml:/etc/promtail/config.yml
- /var/log:/var/log:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock
command: -config.file=/etc/promtail/config.yml
restart: unless-stopped
volumes:
prometheus_data:
grafana_data:
loki_data:loki/loki-config.yml)auth_enabled: false
server:
http_listen_port: 3100
grpc_listen_port: 9096
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
query_range:
results_cache:
cache:
embedded_cache:
enabled: true
max_size_mb: 100
schema_config:
configs:
- from: 2020-10-24
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
ruler:
alertmanager_url: http://localhost:9093
limits_config:
retention_period: 168h # Хранить логи 7 днейpromtail/promtail-config.yml)server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
# Логи Docker контейнеров
- job_name: containers
docker_sd_configs:
- host: unix:///var/run/docker.sock
refresh_interval: 5s
relabel_configs:
- source_labels: ['__meta_docker_container_name']
target_label: 'container'
- source_labels: ['__meta_docker_container_log_stream']
target_label: 'logstream'
- source_labels: ['__meta_docker_container_label_com_docker_compose_service']
target_label: 'service'
# Системные логи (если доступны)
- job_name: system
static_configs:
- targets:
- localhost
labels:
job: varlogs
__path__: /var/log/*logЧто делает Promtail:
После запуска стека:
docker compose up -dhttp://localhost:3000)http://loki:3100{container="prometheus"}Вы увидите:
Grafana предлагает интерактивные фильтры:
{container="api-app"}{container="api-app"} |= "ERROR"{container="api-app"} |= "ERROR" |~ "database.*connection"count_over_time({container="api-app"} |= "ERROR"[1h]){service="api"} |= "request"rate({container="api-app"}[5m])Показывает, сколько логов в секунду генерирует контейнер. Резкий скачок может указывать на проблему.
sum by (level) (count_over_time({app="api"} |= "level="[1h]))Показывает распределение логов по уровням (INFO, WARN, ERROR) за час.
Используйте JSON формат для логов:
{"timestamp":"2026-03-18T14:30:00Z","level":"INFO","message":"User logged in","user_id":123}Вместо:
2026-03-18T14:30:00Z INFO User 123 logged in
Преимущества:
Хорошо:
{app="api", env="production", level="error"}Плохо:
{user_id="12345", request_id="abc-123-xyz"} # Высокая кардинальность!Используйте стандартные уровни:
DEBUG — отладочная информацияINFO — нормальная работаWARN — предупрежденияERROR — ошибкиНастройте ротацию, чтобы логи не заполнили диск:
# В loki-config.yml
limits_config:
retention_period: 168h # 7 днейПричины:
Решение:
# Проверьте статус контейнеров
docker compose ps
# Посмотрите логи Promtail
docker logs promtail
# Проверьте подключение к Loki
curl http://localhost:3100/readyПричины:
Решение:
Причины:
Решение:
|=, !=, =~, !~.Теперь вы умеете собирать и искать логи. В следующей теме вы научитесь интегрировать Loki с Grafana для совместного анализа метрик и логов.
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.