Предыдущий пост серии – Grafana Labs: Loki – сбор и просмотр логов.
Задача на сейчас – попробовать собрать распределённую систему:
- Grafana будет работать на одном хосте
- Loki – на втором
- Promtail – на третьем
Суть идеи такова:
- имеется рабочее окружение, скажем Dev, включает в себя 2 хоста
- имеется окружение мониторинга – хост с Grafana/Prometheus/etc
На хостах Dev-окружения – запустим promtail
, которые будут пушить собранные логи в Loki, а Grafana будет ходить к этому серверу с Loki, и получать данные от неё.
В общем картина должна получиться такая (рисовалось в https://cloudcraft.co):
Только S3 и DynamoDB – в следующий раз.
Вроде должно заработать, пробуем.
Запускаем три сервера:
И к ним привязываем три домена для удобства:
11 | promtail.setevoy.org.ua | ||
12 | loki.setevoy.org.ua | ||
13 | grafana.setevoy.org.ua |
Содержание
Promtail
Начнём с хоста с promtail
.
Тут мы хотим собирать логи nginx
, и затем пушить их на хост с Loki.
Создаём файл promtail-conf.yml
:
server: http_listen_port: 9080 grpc_listen_port: 0 positions: filename: /tmp/positions.yaml client: url: http://loki.setevoy.org.ua:3100/api/prom/push scrape_configs: - job_name: system entry_parser: raw static_configs: - targets: - localhost labels: job: varlogs __path__: /var/log/*log - job_name: nginx entry_parser: raw static_configs: - targets: - localhost labels: job: nginx __path__: /var/log/nginx/*log
Создаём для него Compose файл promtail-compose.yml
:
version: "3" services: promtail: image: grafana/promtail:master volumes: - /home/admin/promtail-conf.yml:/etc/promtail/docker-config.yaml - /var/log:/var/log command: -config.file=/etc/promtail/docker-config.yaml
Запускаем:
[simterm]
root@ip-172-31-32-175:/home/admin# docker-compose -f promtail-compose.yml up -d
[/simterm]
Проверяем:
[simterm]
root@ip-172-31-32-175:/home/admin# curl -s localhost:9080/metrics | head -5 # HELP go_gc_duration_seconds A summary of the GC invocation durations. # TYPE go_gc_duration_seconds summary go_gc_duration_seconds{quantile="0.0"} 3.6174e-05 go_gc_duration_seconds{quantile="0.25"} 3.6174e-05 go_gc_duration_seconds{quantile="0.5"} 4.6829e-05
[/simterm]
Loki
Переходим к хосту с Loki.
Созаём конфиг loki-conf.yml
:
auth_enabled: false server: http_listen_port: 3100 ingester: lifecycler: address: 0.0.0.0 ring: store: inmemory replication_factor: 1 chunk_idle_period: 15m schema_config: configs: - from: 0 store: boltdb object_store: filesystem schema: v9 index: prefix: index_ period: 168h storage_config: boltdb: directory: /tmp/loki/index filesystem: directory: /tmp/loki/chunks limits_config: enforce_metric_name: false
В address: 0.0.0.0 указываем прослушивать все доступные интерфейсы.
Создаём Compose-файл loki-compose.yml
:
version: "3" services: loki: image: grafana/loki:master volumes: - /home/admin/loki-conf.yml:/etc/loki/local-config.yaml ports: - "3100:3100" command: -config.file=/etc/loki/local-config.yaml
Запускаем:
[simterm]
root@ip-172-31-38-97:/home/admin# docker-compose -f loki-compose.yml up -d Starting admin_loki_1 ... done
[/simterm]
Проверяем:
[simterm]
root@ip-172-31-38-97:/home/admin# curl -s localhost:3100/metrics | head -5 # HELP cortex_cache_corrupt_chunks_total Total count of corrupt chunks found in cache. # TYPE cortex_cache_corrupt_chunks_total counter cortex_cache_corrupt_chunks_total 0.0 # HELP cortex_chunk_store_chunks_per_query Distribution of #chunks per query. # TYPE cortex_chunk_store_chunks_per_query histogram
[/simterm]
Работает, доступен.
Пробуем подключиться с promtail-хоста:
[simterm]
root@ip-172-31-32-175:/home/admin# curl -s loki.setevoy.org.ua:3100/metrics | head -5 # HELP cortex_cache_corrupt_chunks_total Total count of corrupt chunks found in cache. # TYPE cortex_cache_corrupt_chunks_total counter cortex_cache_corrupt_chunks_total 0.0 # HELP cortex_chunk_store_chunks_per_query Distribution of #chunks per query. # TYPE cortex_chunk_store_chunks_per_query histogram
[/simterm]
Работает, доступен.
Grafana
Создаём Compose-файл grafana-compose.yml
:
version: "3" services: grafana: image: grafana/grafana:master ports: - "3000:3000"
Запускаем:
[simterm]
root@ip-172-31-43-174:/opt/loki# docker-compose -f grafana-compose.yml up -d
[/simterm]
Проверяем UI – http://grafana.setevoy.org.ua:3000:
Настраиваем data source Loki:
Так…
И где логи?
nginx группы нет…
Проверяем логи promtail
-а:
[simterm]
root@ip-172-31-32-175:/home/admin# docker logs -f admin_promtail_1 ... l=error ts=2019-02-07T12:13:23.938327315Z caller=client.go:129 msg="error sending batch" error="Post http://loki.setevoy.org.ua:3100/api/prom/push: dial tcp 52.16.65.121:3100: connect: connection refused" level=error ts=2019-02-07T12:13:24.946257437Z caller=client.go:129 msg="error sending batch" error="Post http://loki.setevoy.org.ua:3100/api/prom/push: dial tcp 52.16.65.121:3100: connect: connection refused"
[/simterm]
И почему?
Перезапускаем promtail
:
[simterm]
root@ip-172-31-32-175:/home/admin# docker-compose -f promtail-compose.yml restart
[/simterm]
И всё появилось:
Теги
Это всё хорошо, но планируется, то хостов будет пачка, а значит – надо добавить возможность выбора логов по тегам.
Запускаем ещё один сервер с promtail
, аналогичный первому.
Повторяем настройку аналогично первому – создаём файл promtail2-conf.yml
:
server: http_listen_port: 9080 grpc_listen_port: 0 positions: filename: /tmp/positions.yaml client: url: http://loki.setevoy.org.ua:3100/api/prom/push scrape_configs: - job_name: system entry_parser: raw static_configs: - targets: - localhost labels: job: varlogs __path__: /var/log/*log - job_name: nginx entry_parser: raw static_configs: - targets: - localhost labels: job: nginx host: promtail2 __path__: /var/log/nginx/*log
Он идентичен конфигу первого сервера, но тут мы добавили новый тег – host: promtail2.
Аналогично – добавляем его на первом хсоте, как host: promtail1:
... labels: job: nginx host: promtail1 __path__: /var/log/nginx/*log ...
Сначала думал добавить в global
секцию через external_labels
, как в Prometheus:
global: scrape_interval: 15s external_labels: monitor: 'monitoring-production' ...
Но global
нет:
Creating admin_promtail_1 … done
Attaching to admin_promtail_1
promtail_1 | level=error ts=2019-02-07T13:32:36.436335841Z caller=main.go:36 msg=”error loading config” filename=/etc/promtail/docker-config.yaml err=”yaml: unmarshal errors:\n line 1: field global not found in type api.Config”
Т.к. документация пока толком не описывает доступные варианты – смотрим в исходники>>>:
... type Config struct { ServerConfig server.Config `yaml:"server,omitempty"` ClientConfig client.Config `yaml:"client,omitempty"` PositionsConfig positions.Config `yaml:"positions,omitempty"` ScrapeConfig []ScrapeConfig `yaml:"scrape_configs,omitempty"` } ... type ScrapeConfig struct { JobName string `yaml:"job_name,omitempty"` EntryParser EntryParser `yaml:"entry_parser"` RelabelConfigs []*relabel.Config `yaml:"relabel_configs,omitempty"` ServiceDiscoveryConfig sd_config.ServiceDiscoveryConfig `yaml:",inline"` } ...
Тут есть две структуры, которые описывают допустимые в конфигурации поля – общие, и для scrape_configs
.
Создаём Compose на хосте promtail2:
version: "3" services: promtail: image: grafana/promtail:master volumes: - /home/admin/promtail2-conf.yml:/etc/promtail/docker-config.yaml - /var/log:/var/log command: -config.file=/etc/promtail/docker-config.yaml ports: - "9080:9080"
Тоже аналогичен файлу с первого хоста, только в контейнер мапим файл /home/admin/promtail2-conf.yml
, а не /home/admin/promtail-conf.yml
.
На первом хосте – перезапускаем контейнер:
[simterm]
root@ip-172-31-32-175:/home/admin# docker-compose -f promtail-compose.yml restart
[/simterm]
На втором – просто запускаем:
[simterm]
root@ip-172-31-44-176:/home/admin# docker-compose -f promtail-compose.yml up -d
[/simterm]
И в логах ошибка error=”watcher.Add: no such file or directory”:
promtail_1 | level=info ts=2019-02-07T13:55:05.004415129Z caller=filetargetmanager.go:165 msg=”Adding target” key=”{job=\”varlogs\”}”
promtail_1 | level=info ts=2019-02-07T13:55:05.004815207Z caller=filetargetmanager.go:165 msg=”Adding target” key=”{job=\”nginx\”}”
promtail_1 | level=error ts=2019-02-07T13:55:05.004981321Z caller=filetargetmanager.go:168 msg=”Failed to create target” key=”{job=\”nginx\”}” error=”watcher.Add: no such file or directory”
А на первом всё хорошо:
level=info ts=2019-02-07T13:43:52.153207236Z caller=filetargetmanager.go:165 msg=”Adding target” key=”{job=\”varlogs\”}”
level=info ts=2019-02-07T13:43:52.153657621Z caller=filetargetmanager.go:165 msg=”Adding target” key=”{host=\”promtail1\”, job=\”nginx\”}”
2019/02/07 13:43:52 Seeked /var/log/alternatives.log – &{Offset:19515 Whence:0}
WTF?
А сам nginx
я установил?
[simterm]
root@ip-172-31-44-176:/home/admin# dpkg -l | grep nginx
[/simterm]
Нет.
А зачем?…)
[simterm]
root@ip-172-31-44-176:/home/admin# ls -l /var/log/nginx ls: cannot access '/var/log/nginx': No such file or directory
[/simterm]
Собственно – теперь понятна причина сообщения “No such file or directory“.
Устанавливаем NGINX, перезапускаем promtail
:
[simterm]
root@ip-172-31-44-176:/home/admin# apt -y install nginx
Проверяем лог:
[/simterm]
promtail_1 | level=info ts=2019-02-07T13:59:54.422710535Z caller=filetargetmanager.go:165 msg=”Adding target” key=”{job=\”varlogs\”}”
promtail_1 | level=info ts=2019-02-07T13:59:54.423260616Z caller=filetargetmanager.go:165 msg=”Adding target” key=”{host=\”promtail2\”, job=\”nginx\”}”
…
promtail_1 | level=info ts=2019-02-07T13:59:54.426593486Z caller=filetarget.go:269 msg=”start tailing file” path=/var/log/nginx/access.log
promtail_1 | level=info ts=2019-02-07T13:59:54.426667134Z caller=filetarget.go:269 msg=”start tailing file” path=/var/log/nginx/error.log
Гуд.
Переходим в Grafana:
Отлично – теги появились.
Фильтры запросов
Последним – быстрый пример выборки по логам.
“Документация” – тут>>>.
Сделаем запрос с “левого” хоста, что бы в логах было что искать:
[simterm]
16:24:39 [setevoy@venti ~] $ curl http://54.194.13.55/someuri
[/simterm]
Теперь ищем данные с тегом job == nginx и host == promtail2:
Или добавим фильтр по IP 77.120.103.20:
Или с регулярным выражением:
{job="nginx", host="promtail2"} 77.120.[\d\.]
Или с условием “IP по маске 77.120.[\d\.], либо если в запросе есть слово someuri“:
{job="nginx", host="promtail2"} (77.120.[\d\.]|someuri)
В целом на этом всё.
Завтра попробую подключить DynamoDB для хранения индексов и S3 для хранения данных, и можно пробовать разворачивать систему на Staging.