DEV Community

Samoilenko Yuri for RNDSOFT

Posted on • Originally published at blog.rnds.pro on

Централизованное логирование

В данной статье мы рассмотрим вопрос централизованного логирования с использованием filebeat (гребаный спойлер) и graylog. В какой-то момент мы заметили, что машин в нашей инфраструктуре стало достаточно много, и чтобы посмотреть логи, приходилось иногда заходить на несколько машин и мучительно искать по множеству контейнеров, в этот момент мы поняли, что дальше жить так нельзя.

Постановка задачи стояла следующим образом:

  1. Чем собирать логи
  2. Где хранить
  3. Нужно не потерять логи при недоступности центрального хранилища логов

Ранее мы уже пробовали централизованно собирать логи vector (https://vector.dev/), но нам хотелось иметь удобный веб-интерфейс для просмотра. А vector веб-интерфейса не имеет. В качестве веб-интерфейса, а заодно и местом централизованного хранения, мы выбрали graylog, фактически сейчас единственное open source решение, которое имеет обширный функционал и удобство использования. На момент написания статьи vector “из коробки” не умеет отправлять в gelf формате в graylog, но в одном из issues на github один энтузиаст смог сконфигурировать vector нужным образом (https://github.com/vectordotdev/vector/issues/4868#issuecomment-782740639). В общем vector в качестве решения для сбора логов отбросили.

Прежде чем отвечать на вопрос “Чем собирать”, нужно немного сказать про инфраструктуру: в инфраструктуре у нас все приложения запускаются в docker контейнерах, машин на момент написания у нас уже 16, а самих контейнеров около 60, контейнеры в свою очередь находятся под управлением nomad. Также важным моментом является то, что несколько машин в нашей инфраструктуре являются прерываемыми, они один раз в сутки перезапускаются. С инфраструктурой разобрались, теперь нужно определяться, чем собирать. Сперва наш взгляд упал на fluentd, fluentbit, т.к. они умели отправлять в gelf формате. В процессе настройки fluentd почему-то не слал больше 30 сообщений, разобраться, почему, нам так и не удалось, при использовании fluentbit в какой-то момент использования docker logging driver gelf и настройки fluentbit c output gelf выяснилось, что при недоступности fluentbit в момент рестарта контейнеров (на прерываемых машинах контейнеры один раз в сутки перезапускаются) они не запустятся и становятся неработоспособными. Мы поняли, что чем проще - тем лучше, и решили, что нужно собирать из файлов. В свою очередь настроили fluentbit для сбора из файлов, но fluentbit почему-то тоже доставлял не все логи, аналогично с fluentd определить, почему так происходит, не удалось. И в итоге мы остановились на filebeat в качестве сборщика логов (https://www.elastic.co/guide/en/beats/filebeat/current/how-filebeat-works.html), а graylog в качестве хранилища логов.

Еще один важный момент, который нужно учесть, это то, что graylog находится в другой инфраструктуре, т.е. прямой сетевой связности между graylog сервером и машинами, на которых запущен filebeat, нет. Т.о. мы связали это все через гейт, на котором у нас находится traefik (смотри диаграмму ниже). Теперь перейдем к настройке. Graylog мы запустили на отдельной машине в обычном docker-compose.yml файле.

Graylog docker-compose.yml

version: "2.3"

services:

 es01:
   image: elasticsearch:7.10.1
   restart: unless-stopped
   network_mode: host
   ulimits:
     memlock:
       soft: -1
       hard: -1
     nofile:
       soft: 65536
       hard: 65536
   environment:
       - "ES_JAVA_OPTS=-Xms5g -Xmx5g"
       - ELASTIC_PASSWORD=test
       - discovery.type=single-node
       - cluster.max_shards_per_node=20000
       - search.max_open_scroll_context=9000
   volumes:
     - /etc/localtime:/etc/localtime:ro
     - /graylog/data/es01:/usr/share/elasticsearch/data
   labels:
     - "SERVICE_CHECK_HTTP=/_cluster/health"
     - "SERVICE_CHECK_INTERVAL=40s"
     - "SERVICE_CHECK_TIMEOUT=3s"
     - "SERVICE_CHECK_DEREGISTER_AFTER=10m"

 mongodb:
   image: mongo:4.2
   restart: unless-stopped
   network_mode: host
   volumes:
     - /graylog/data/mongo:/data/db

 graylog:
   image: graylog/graylog:4.3.3
   restart: unless-stopped
   depends_on:
     - mongodb
     - es01
   network_mode: host
   volumes:
     - /graylog/data/graylog:/usr/share/graylog/data
   environment:
     - GRAYLOG_PASSWORD_SECRET=test
     - GRAYLOG_ROOT_PASSWORD_SHA2=shashasha
     - GRAYLOG_HTTP_EXTERNAL_URI=http://192.168.2.2:9000/
   entrypoint: /usr/bin/tini -- wait-for-it 172.22.202.104:9200 -- /docker-entrypoint.sh
   labels:
     - "SERVICE_TAGS=hostname=graylog,traefik.enable=true,\
        traefik.http.routers.graylog.rule=Host(`graylog.dev`),\
        traefik.http.routers.graylog.entrypoints=websecure,\
        traefik.http.routers.graylog.tls=true"
     - SERVICE_NAME=graylog
     - SERVICE_CHECK_DEREGISTER_AFTER=10m
     - SERVICE_9000_NAME=graylog
     - SERVICE_9000_CHECK_TCP=true
     - SERVICE_9000_CHECK_INTERVAL=40s
     - SERVICE_9000_CHECK_TIMEOUT=5s
     - SERVICE_9000_CHECK_DEREGISTER_AFTER=10m

Enter fullscreen mode Exit fullscreen mode

Перейдем к конфигурации filebeat

Конфиг filebeat.yml у нас простейший

filebeat.inputs:
- type: container
  paths:
    - /var/lib/docker/containers/*/*.log
  processors:
    - add_docker_metadata:
        match_source_index: 4 
output.logstash:
   hosts: 
     - graylog_host:graylog_port

Enter fullscreen mode Exit fullscreen mode

Тут все просто, мы просто отправляем все логи всех контейнеров на хост graylog, в свою очередь graylog_host - это у нас хост с traefik, а в конфигурации traefik уже указан сам graylog, т.к. с гейта есть прямая сетевая связность с graylog.

Т.к. у нас nomad, то filebeat мы деплоим тоже в nomad, далее конфигурация filebeat job для деплоя его в nomad. Единственное, что здесь стоит отметить, так это то, что в env параметры GRAYLOG_HOST, GRAYLOG_PORT мы передаем ip адрес и порт на traefik. Также стоит обратить внимание, что тип job у нас system, что запускает filebeat на всех машинах. Также мы монтируем в контейнер filebeat каталог /filebeat/registry, для сохранения registry файла. Это необходимо для того, чтобы при отказе output filebeat отслеживал последние изменения, чтобы после того, как output вернется в рабочее состояние, доставить туда логи. Более подробно про registry файл можно почитать в документации filebeat https://www.elastic.co/guide/en/beats/filebeat/current/how-filebeat-works.html#_how_does_filebeat_keep_the_state_of_files

job "filebeat" {
 datacenters = ["a", "b", "c"]
 namespace = "default"
 update {
   max_parallel = 1
   auto_revert = true
   auto_promote = false
   canary = 0
 }
 type = "system"
 group "logging" {
   restart {
     mode = "delay"
     attempts = 2
     interval = "1m"
     delay = "30s"
   }
   task "filebeat" {
     driver = "docker"
     kill_timeout = "30s"
     leader = true
     user = "root"
     env {
       SERVICE_IGNORE = "true"
       GRAYLOG_HOST = "GRAYLOG_HOST"
       GRAYLOG_PORT = "GRAYLOG_PORT"
     }
     config {
       auth {
         username = "test"
         password = "test"
       }
       image = "docker.registry/filebeat:7.10.1"
       force_pull = true
       volumes = [
         "/var/lib/docker/containers:/var/lib/docker/containers:ro",
         "/var/run/docker.sock:/var/run/docker.sock:ro",
         "/filebeat/registry:/filebeat/registry:rw"
       ]
     }
     service {
       name = "filebeat"
       tags = ["filebeat", "logging", "hostname=${attr.unique.hostname}"]
       check_restart {
         grace = "1m"
         ignore_warnings = false
       }
     }
     logs {
       max_files = 3
       max_file_size = 10
     }
     resources {
       memory = 100
       memory_max = 150
     }
   }
 }
}
Enter fullscreen mode Exit fullscreen mode

Теперь перейдем к конфигурации traefik, здесь лишь фрагмент конфига traefik.yml, мы добавляем еще один entrypoint для graylog.

…………
entryPoints:
 web:
   address: ":80"
   forwardedHeaders:
     insecure: true

 websecure:
   address: ":443"
   http:
     middlewares:
       - sslheader@file
       - trimwww@file

 graylog:
   address: ":11111"
…………
Enter fullscreen mode Exit fullscreen mode

Также не забываем сконфигурировать порт для работы с graylog в конфиге job nomad для traefik, ниже указан фрагмент traefik job.

job "traefik" {
 datacenters = ["a", "b", "c"]

…………………

 type = "system"

 group "traefik" {
   network {
     mode = "host"

     port "http" {
       static = 80
       to = 80
       host_network = "private"
     }

     port "public" {
               static = 443
               to = 443
       host_network = "public"
     }

     port "ui" {
               to = 8080
       host_network = "private"
     }

     port "graylog" {
       static = 11111
       to = "11111"
       host_network = "private"
     }

   }

   task "traefik" {
     driver = "docker"
     kill_timeout = "30s"
     leader = true

………………

     config {
       image = "traefik:v2.8.7"
       force_pull = true
       ports = ["http", "public", "ui",
        "graylog"
       ]
…………………

}

Enter fullscreen mode Exit fullscreen mode

Так выглядят entrypoints в веб-интерфейсе traefik.

Конфигурация роутера для graylog осуществляется в tcp router, вот как это выглядит в веб-интерфейсе traefik:

Также нужно сконфигурировать сервис (в терминологии traefik), куда мы будем отправлять логи в graylog, именно в конфигурации сервиса в traefik указывается сам ip и порт graylog сервера.

В веб-интерфейсе graylog вот так конфигурируется input (в терминологии graylog), т.е. входная точка, которая будет принимать логи на стороне graylog. Тут видно, что тип input у нас Beats.

Вот так выглядит сам веб-интерфейс graylog, где мы уже ищем конкретные логи:

Вот так достаточно просто (конечно после нескольких десятков часов исследований) настраивается централизованный сбор логов. Мы пойдем посмотрим, что у нас там в логах, а вы пока stay tuned.

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs