Зачем нужно логирование
ELK Stack
▸Архитектура
▸Docker Compose
1version: '3.8'2services:3 elasticsearch:4 image: docker.elastic.co/elasticsearch/elasticsearch:8.11.05 environment:6 - discovery.type=single-node7 - xpack.security.enabled=false8 ports:9 - "9200:9200"10 volumes:11 - es_data:/usr/share/elasticsearch/data1213 logstash:14 image: docker.elastic.co/logstash/logstash:8.11.015 volumes:16 - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf17 depends_on:18 - elasticsearch1920 kibana:21 image: docker.elastic.co/kibana/kibana:8.11.022 ports:23 - "5601:5601"24 depends_on:25 - elasticsearch2627volumes:28 es_data:
▸Logstash конфигурация
1# logstash.conf2input {3 beats {4 port => 50445 }67 tcp {8 port => 50009 codec => json10 }11}1213filter {14 if [type] == "nginx" {15 grok {16 match => { "message" => "%{COMBINEDAPACHELOG}" }17 }18 date {19 match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]20 }21 }2223 mutate {24 remove_field => ["timestamp"]25 }26}2728output {29 elasticsearch {30 hosts => ["elasticsearch:9200"]31 index => "%{[@metadata][beat]}-%{+YYYY.MM.dd}"32 }33}
Grafana Loki
▸Архитектура
Loki — это легковесная система логирования, хранящая только индексы (без полного текста логов).
▸Docker Compose
1version: '3.8'2services:3 loki:4 image: grafana/loki:2.9.05 ports:6 - "3100:3100"7 volumes:8 - ./loki-config.yml:/etc/loki/local-config.yaml910 promtail:11 image: grafana/promtail:2.9.012 volumes:13 - /var/log:/var/log14 - ./promtail-config.yml:/etc/promtail/config.yml1516 grafana:17 image: grafana/grafana:10.2.018 ports:19 - "3000:3000"20 environment:21 - GF_SECURITY_ADMIN_PASSWORD=admin
▸Promtail конфигурация
1# promtail-config.yml2server:3 http_listen_port: 908045positions:6 filename: /tmp/positions.yaml78clients:9 - url: http://loki:3100/loki/api/v1/push1011scrape_configs:12 - job_name: system13 static_configs:14 - targets:15 - localhost16 labels:17 job: system18 __path__: /var/log/*.log1920 - job_name: nginx21 static_configs:22 - targets:23 - localhost24 labels:25 job: nginx26 __path__: /var/log/nginx/access.log27 pipeline_stages:28 - regex:29 expression: '^(?P<ip>\S+) .* "(?P<method>\S+) (?P<path>\S+) .* (?P<status>\d+)'30 - labels:31 method:32 status:
Запросы в Loki (LogQL)
1# Поиск по job2{job="nginx"}34# Поиск по тексту5{job="nginx"} |= "error"67# Регулярное выражение8{job="nginx"} |~ "status=5[0-9]{2}"910# Метрики11rate({job="nginx"} |= "error" [5m])1213# Агрегация14sum(rate({job="nginx"} | json [5m])) by (status)
Структурированные логи
▸JSON формат (Node.js)
1const pino = require('pino');2const logger = pino({3 level: 'info',4 formatters: {5 level: (label) => ({ level: label }),6 },7 timestamp: pino.stdTimeFunctions.isoTime,8});910logger.info({ userId: 123, action: 'login' }, 'User logged in');
Заключение
ELK Stack предоставляет полный стек для логирования, Loki — легковесную альтернативу. Структурированные логи и правильная настройка сбора упрощают поиск и анализ проблем в продакшн.