▍ELK Stack¶
Настройка централизованного логирования в Docker с применением ELK Stack¶
Название стека представляет собой аббревиатуру первых букв трех открытых проектов, разрабатываемых и поддерживаемых компанией Elastic: Elasticsearch, Logstash, Kibana
Этот набор компонентов обеспечивает удобное централизованное логирование (ведение журналов) с разных серверов. ELK stack позволяет надежно и безопасно получать данные из любого источника во всех форматах и работать с этими данными: осуществлять поиск по ним, анализировать и визуализировать их в режиме real-time (NRT).
Основными его элементами являются: Elasticsearch (search engine – для хранения и быстрого поиска структурированных данных), Logstash (collector – для приема в различном формате данных, их фильтрации и преобразования, и последующей отправки в различные базы данных) и Kibana (инструмент для визуализации).
Настройка Elasticsearch¶
version: '3.3'
services:
elasticsearch:
image: elasticsearch:8.4.3
restart: always
container_name: elasticsearch
ports:
- "9200:9200"
environment:
- discovery.type=single-node
- ELASTIC_PASSWORD=passwd123
- xpack.license.self_generated.type=basic
- path.data=/usr/share/elasticsearch/data
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
volumes:
- /srv/docker/data/elasticsearch:/usr/share/elasticsearch/data
Генерируем токен:
$ docker exec -ti elasticsearch bash
[email protected]:~$ bin/elasticsearch-create-enrollment-token -s kibana
WARNING: Owner of file [/usr/share/elasticsearch/config/users] used to be [root], but now is [elasticsearch]
WARNING: Owner of file [/usr/share/elasticsearch/config/users_roles] used to be [root], but now is [elasticsearch]
eyJ2ZXIiOiI4LjQuMyIsImFkciI6WyIxNzIuMTguMC4yOjkyMDAiXSwiZmdyIjoiY2U4NDI4ODcyM2Q3NmU2OGY3NDUxNTkyMDExOWMyY2Y1YzA2YjQ3MWE1NTgxNTZiNTE2OTdmNjA4OTFmMDBmMiIsImtleSI6ImxVYnMxWU1CcWhLT05uZ3AtdGg0Om16VFF3dVpLU1Z5Q1Rqa245Uk0zcGcifQ==
Настройка Kibana¶
version: '3.3'
services:
kibana:
image: kibana:8.4.3
restart: always
container_name: kibana
ports:
- "5601:5601"
depends_on:
- elasticsearch
environment:
- ELASTICSEARCH_URL=https://elasticsearch:9200
- SERVER_NAME=kibana
- PATH_DATA=/usr/share/kibana/data
volumes:
- /srv/docker/conf/kibana:/usr/share/kibana/data
Запускаем:
Запустим вывод лога кибаны, там будет указан пин код, который потребуется позже ввести в дашборде:
$ docker logs -f kibana
[2022-10-14T09:58:31.932+00:00][INFO ][node] Kibana process configured with roles: [background_tasks, ui]
[2022-10-14T09:58:44.796+00:00][INFO ][http.server.Preboot] http server running at http://0.0.0.0:5601
[2022-10-14T09:58:44.851+00:00][INFO ][plugins-system.preboot] Setting up [1] plugins: [interactiveSetup]
[2022-10-14T09:58:44.854+00:00][INFO ][preboot] "interactiveSetup" plugin is holding setup: Validating Elasticsearch connection configuration…
[2022-10-14T09:58:44.900+00:00][INFO ][root] Holding setup until preboot stage is completed.
i Kibana has not been configured.
Go to http://0.0.0.0:5601/?code=029224 to get started.
Your verification code is: 029 224
Заходим в сам дашбор кибаны и вводим сгенерированный ранее токен:
Указываем пин код:
Вводим логин elastic и пароль, указанный ранее, в переменной ELASTIC_PASSWORD:
и попадаем в сам дашборд:
Настройка Logstash¶
version: '3.3'
services:
logstash:
image: logstash:8.4.3
container_name: logstash
restart: always
ports:
- "5044:5044"
environment:
- NODE_NAME=logstash
- xpack.monitoring.enabled=false
volumes:
- /srv/docker/conf/logstash/pipeline:/usr/share/logstash/pipeline
links:
- elasticsearch
depends_on:
- elasticsearch
Добавим пайплайн для nginx логов:
# Sample Logstash configuration for creating a simple
# Beats -> Logstash -> Elasticsearch pipeline.
input {
beats {
port => 5044
}
}
filter{
if "nginx-access" in [tags] {
grok {
match => {
'message' => '%{DATA:[nginx][access][referrer]} %{IPORHOST:[nginx][access][remote_ip]} (?:%{IPORHOST:[nginx][access][x_forwarded_for]}|-) \[%{HTTPDATE:timestamp_nginx_access}\] %{NUMBER:[nginx][access][response_code]} (?:%{IPO>
}
remove_field => 'message'
}
useragent {
source => "[nginx][access][agent]"
target => "[nginx][access][user_agent]"
remove_field => "[nginx][access][agent]"
}
geoip {
source => "[nginx][access][remote_ip]"
target => "[nginx][access][geoip]"
}
mutate {
add_field => { "[fileset][name]" => "access" }
}
}
}
output {
if "nginx-access" in [tags] {
stdout { codec => rubydebug }
elasticsearch {
hosts => ["https://elasticsearch:9200"]
index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}"
ssl => true
ssl_certificate_verification => false
user => 'elastic'
password => 'passwd123'
}
}
}
Зададим формат лога в конфиге nginx.conf:
log_format main '"$host" $http_x_forwarded_for $remote_addr [$time_local] $status $upstream_addr $upstream_response_time $msec $request_time '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent"';
access_log /var/log/nginx/access.log main;
Настройка Filebeat¶
version: '3.3'
services:
filebeat:
image: docker.elastic.co/beats/filebeat:8.4.3
container_name: filebeat
entrypoint: "filebeat -e -strict.perms=false"
volumes:
- /srv/docker/conf/filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml
- /var/log/docker/nginx:/var/log/nginx
Конфиг Filebeat:
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/nginx/*.log
tags: ["nginx-access"]
output.logstash:
enabled: true
hosts: ["logstash:5044"]
setup.kibana:
host: "http://kibana:5601"
username: "elastic"
password: "passwd123"
Запускаем оставшиеся контейнеры:
Снова открывает дашборд с кибаной, переходим в раздел Discover -> Create data view и указываем данные как на скриншоте:
В случае если необходимо прикрутить уведомления, например, по почте по какому-либо тексту в логах, то доустановим ElastAlert 2
Настройка ElastAlert 2¶
version: '3.3'
services:
elastalert:
image: jertel/elastalert2
restart: always
container_name: elastalert
depends_on:
- elasticsearch
volumes:
- /srv/docker/conf/elastalert/elastalert.yaml:/opt/elastalert/config.yaml
- /srv/docker/conf/elastalert/smtp_auth_file.yml/opt/elastalert/smtp_auth_file.yml
- /srv/docker/conf/elastalert/rules:/opt/elastalert/rules
Конфиг ElastAlert 2:
rules_folder: /opt/elastalert/rules
run_every:
seconds: 10
buffer_time:
minutes: 15
es_host: elasticsearch
es_port: 9200
use_ssl: true
verify_certs: false
es_username: elastic
es_password: passwd123
writeback_index: elastalert_status
alert_time_limit:
days: 2
Отправка уведомлений в нашем случае будет происходить через SMTP подключение, в smtp_auth_file.yml укажем логин и пароль от ящика:
user: "[email protected]"
password: "пароль от ящика"
name: "rule"
type: "any"
index: "filebeat-*"
is_enabled: true
realert:
minutes: 0
terms_size: 50
timestamp_field: "@timestamp"
timestamp_type: "iso"
use_strftime_index: false
alert_subject: "Error"
alert_text: "Error code:"
alert_text_args:
- "message"
filter:
- query:
query_string:
query: 'message: "ERROR 400" OR message: "ERROR 401" OR message: "ERROR 403"'
alert:
- "email"
from_addr: [email protected]
smtp_host: smtp.mail.ru
smtp_port: 465
smtp_ssl: true
smtp_auth_file: /opt/elastalert/smtp_auth_file.yml
email:
- "[email protected]"
где "ERROR 400", "ERROR 401", "ERROR 403" тексты ошибок, которые будут искаться в логах и при их обнаружении отправляться сообщение на почту.