Grafana Loki: централизованные логи без Elasticsearch
1
# Grafana Loki: централизованные логи без Elasticsearch
Если вы устали от тяжеловесного ELK stack, который съедает гигабайты RAM и требует постоянного внимания к шардам — пора познакомиться с Grafana Loki. Это система централизованного логирования, которая индексирует только метки, а не содержимое. Результат? В 5-10 раз меньше затрат на хранение и драматически упрощённая эксплуатация.
## Проблемы с ELK stack
Elasticsearch индексирует каждое слово в каждой строке лога. На практике это означает:
- **Раздутое хранилище**: 1 ГБ логов → 5-15 ГБ индексов на диске
- **Прожорливость по RAM**: минимум 16 ГБ на ноду для JVM heap
- **Операционная сложность**: управление шардами, lifecycle policies, capacity planning
- **Высокая стоимость**: для 100 ГБ логов в день ~$1000-3000/месяц
Для большинства команд это избыточно. Реальность: 90% запросов — "покажи логи этого сервиса за последний час", а не полнотекстовый поиск по всей истории.
## Архитектура Loki: distributor, ingester, querier
Loki построен как микросервисная система с чёткой ролевой моделью.
**Distributor** — точка входа для логов. Получает HTTP POST, валидирует, хеширует по меткам и распределяет между ingester'ами через consistent hashing. Stateless-компонент, легко масштабируется.
**Ingester** — сердце write path. Группирует логи в chunks (сжатые блоки) по меткам, держит в памяти, затем сбрасывает в object storage (S3, GCS). Репликация: distributor отправляет каждый поток на N ingester'ов (обычно 3), запись успешна при кворуме `floor(N/2) + 1`.
**Querier** выполняет LogQL-запросы. Опрашивает ingester'ы для свежих данных, затем читает chunks из object storage. Дедуплицирует данные по timestamp + labels + message.
**Query Frontend** разбивает большие запросы на подзапросы, кеширует результаты, управляет очередью.
Ключевое отличие: Loki не строит inverted index для содержимого. Индексируются только метки, логи хранятся как сжатые chunks. Экономия 10-20x на хранении.
## Интеграция с Promtail для сбора логов
Promtail — агент для сбора логов, заточенный под Loki. Автоматически обогащает логи метками из Kubernetes.
### Docker конфигурация
```yaml
server:
http_listen_port: 9080
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: docker_logs
docker_sd_configs:
- host: unix:///var/run/docker.sock
filters:
- name: label
values: ["logging=promtail"]
relabel_configs:
- source_labels: ['__meta_docker_container_name']
regex: '/(.*)'
target_label: 'container'
```
Promtail подключается к Docker socket, фильтрует контейнеры по label `logging=promtail`.
### Kubernetes DaemonSet
```yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: promtail
spec:
template:
spec:
containers:
- name: promtail
image: grafana/promtail:3.4.2
args:
- -config.file=/etc/promtail/config.yaml
volumeMounts:
- name: varlog
mountPath: /var/log
- name: containers
mountPath: /var/lib/docker/containers
readOnly: true
volumes:
- name: varlog
hostPath:
path: /var/log
- name: containers
hostPath:
path: /var/lib/docker/containers
```
DaemonSet разворачивает Promtail на каждой ноде. Агент читает логи из `/var/log/pods` и добавляет метки: `namespace`, `pod`, `container`.
## LogQL на практике: примеры запросов
LogQL — язык запросов Loki, похожий на PromQL.
**Базовая фильтрация:**
```logql
{namespace="production", app="api"}
```
**Grep по содержимому:**
```logql
{namespace="production"} |= "error" != "timeout"
```
**Парсинг JSON:**
```logql
{app="nginx"} | json | status_code >= 500
```
**Агрегация:**
```logql
sum(rate({namespace="production"} |= "error" [5m])) by (pod)
```
Считает rate ошибок за 5 минут, группирует по pod. Поддерживаются: `rate()`, `count_over_time()`, `sum()`, `avg()`.
## Сравнение затрат: Loki vs Elasticsearch
Реальные цифры для 100 ГБ логов/день, retention 30 дней:
| Параметр | Elasticsearch | Loki |
|----------|---------------|------|
| Хранилище | 6-9 ТБ | 1.5-3 ТБ |
| RAM | 48+ ГБ | 8 ГБ |
| CPU | 12+ ядер | 2-4 ядра |
| Хранение/месяц | $600-900 | $30-60 |
| Compute/месяц | $600-900 | $100-200 |
| **Итого** | **$1200-1800** | **$130-260** |
**Экономия: 5-10x**
Почему? Loki сжимает логи gzip/zstd (5-10x) и хранит в дешёвом S3 ($0.023/ГБ/месяц). Elasticsearch требует быстрые SSD ($0.10/ГБ/месяц) для индексов.
## Примеры настройки для Docker/Kubernetes
### Docker Compose
```yaml
version: '3.8'
services:
loki:
image: grafana/loki:3.4.2
ports:
- "3100:3100"
command: -config.file=/etc/loki/local-config.yaml
promtail:
image: grafana/promtail:3.4.2
volumes:
- /var/log:/var/log
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock
- ./promtail.yaml:/etc/promtail/config.yaml
command: -config.file=/etc/promtail/config.yaml
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_AUTH_ANONYMOUS_ENABLED=true
```
Запуск: `docker-compose up -d`. Grafana на `http://localhost:3000`.
### Kubernetes Helm
```bash
helm repo add grafana https://grafana.github.io/helm-charts
# Loki с S3
helm install loki grafana/loki \
--set loki.storage.type=s3 \
--set loki.storage.bucketNames.chunks=my-loki-chunks
# Promtail
helm install promtail grafana/promtail \
--set config.clients[0].url=http://loki:3100/loki/api/v1/push
```
### Loki конфигурация для S3
```yaml
auth_enabled: false
server:
http_listen_port: 3100
common:
storage:
s3:
endpoint: s3.amazonaws.com
bucketnames: my-loki-bucket
region: us-east-1
replication_factor: 3
schema_config:
configs:
- from: 2024-04-01
store: tsdb
object_store: s3
schema: v13
index:
prefix: loki_index_
period: 24h
limits_config:
retention_period: 720h # 30 дней
```
## Вывод
Loki — не замена Elasticsearch для всех сценариев. Если нужен полнотекстовый поиск, SIEM, сложная аналитика — ELK остаётся сильным выбором. Но для 80% команд, использующих логи для дебага в Kubernetes, Loki оптимален:
- **Экономия 5-10x** на инфраструктуре
- **Простота**: меньше компонентов, stateless querier'ы, object storage
- **Нативная интеграция** с Grafana и Prometheus
- **Kubernetes-native**: метки из pod labels автоматически
Начните с Loki, если у вас Grafana stack, ограниченный бюджет и команда <5 человек. Переходите на Elasticsearch, только если упрётесь в ограничения LogQL.