Вопрос или проблема
Я пытаюсь настроить стек ELK (Kibana, Logstash и Elasticsearch) в Portainer, который должен получать логи от ПК по всему миру.
Я не уверен, как должна выглядеть правильная настройка, чтобы производительность для клиентов была хорошей.
Допустим, Portainer работает в Европе в контейнере Docker, и есть пользователи в Америке, Европе, Австралии и Азии.
Какой будет правильная настройка? Я предполагаю, что мне нужен сервер на каждом континенте в моем стеке, но как мне перенаправить логи на самый “быстрый” конечный пункт?
Будет здорово, если кто-нибудь сможет подсказать мне некоторые ключевые слова и статьи, где я могу найти решение, как может выглядеть эта настройка.
Прямо сейчас у меня есть стек ELK на моем локальном компьютере с Docker, и я отправляю UDP-сообщения (содержимое JSON) в мой стек. Частота этих сообщений может составлять несколько раз в секунду от клиента. В мире одновременно онлайн примерно 600-700 человек (возможно, больше в будущем).
Мой elasticsearch.yml
cluster.name: docker-cluster
network.host: 0.0.0.0
xpack.license.self_generated.type: trial
xpack.security.enabled: true
Вот мой docker-compose.yml
setup:
profiles:
- setup
build:
context: setup/
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
init: true
volumes:
- ./setup/entrypoint.sh:/entrypoint.sh:ro,Z
- ./setup/lib.sh:/lib.sh:ro,Z
- ./setup/roles:/roles:ro,Z
environment:
ELASTIC_PASSWORD: ${ELASTIC_PASSWORD:-}
LOGSTASH_INTERNAL_PASSWORD: ${LOGSTASH_INTERNAL_PASSWORD:-}
KIBANA_SYSTEM_PASSWORD: ${KIBANA_SYSTEM_PASSWORD:-}
METRICBEAT_INTERNAL_PASSWORD: ${METRICBEAT_INTERNAL_PASSWORD:-}
FILEBEAT_INTERNAL_PASSWORD: ${FILEBEAT_INTERNAL_PASSWORD:-}
HEARTBEAT_INTERNAL_PASSWORD: ${HEARTBEAT_INTERNAL_PASSWORD:-}
MONITORING_INTERNAL_PASSWORD: ${MONITORING_INTERNAL_PASSWORD:-}
BEATS_SYSTEM_PASSWORD: ${BEATS_SYSTEM_PASSWORD:-}
networks:
- elk
depends_on:
- elasticsearch
elasticsearch:
build:
context: elasticsearch/
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
volumes:
- ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro,Z
- elasticsearch:/usr/share/elasticsearch/data:Z
ports:
- 9200:9200
- 9300:9300
environment:
node.name: elasticsearch
ES_JAVA_OPTS: -Xms512m -Xmx512m
ELASTIC_PASSWORD: ${ELASTIC_PASSWORD:-}
discovery.type: single-node
networks:
- elk
restart: unless-stopped
logstash:
build:
context: logstash/
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
volumes:
- ./logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml:ro,Z
- ./logstash/pipeline:/usr/share/logstash/pipeline:ro,Z
ports:
- 5044:5044/udp
- 50000:50000/tcp
- 9600:9600
environment:
LS_JAVA_OPTS: -Xms256m -Xmx256m
LOGSTASH_INTERNAL_PASSWORD: ${LOGSTASH_INTERNAL_PASSWORD:-}
networks:
- elk
depends_on:
- elasticsearch
restart: unless-stopped
kibana:
build:
context: kibana/
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
volumes:
- ./kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml:ro,Z
ports:
- 5601:5601
environment:
KIBANA_SYSTEM_PASSWORD: ${KIBANA_SYSTEM_PASSWORD:-}
networks:
- elk
depends_on:
- elasticsearch
restart: unless-stopped
networks:
elk:
driver: bridge
volumes:
elasticsearch:
моя logstash.conf
input {
tcp {
port => 50000
}
udp {
port => 5044
codec => json
}
}
filter {
json {
source => "message"
target => "parsed_message"
skip_on_invalid_json => true
}
mutate {
rename => {
"[parsed_message][message]" => "message"
"[parsed_message][logLevel]" => "logLevel"
"[parsed_message][application]" => "application"
"[parsed_message][username]" => "username"
"[parsed_message][computer]" => "computer"
"[parsed_message][timestamp]" => "timestamp"
}
}
}
output {
elasticsearch {
#index => "logstash-%{+YYYY.MM.dd}"
#hosts => "elasticsearch:9200"
hosts => ["elasticsearch:9200"]
data_stream => "true"
data_stream_type => "logs"
data_stream_dataset => "logstash"
data_stream_namespace => "default"
user => "logstash_internal"
password => "${LOGSTASH_INTERNAL_PASSWORD}"
}
}
мой kibana.yml
xpack.fleet.agents.fleet_server.hosts: [ http://fleet-server:8220 ]
xpack.fleet.outputs:
- id: fleet-default-output
name: default
type: elasticsearch
hosts: [ http://elasticsearch:9200 ]
is_default: true
is_default_monitoring: true
xpack.fleet.packages:
- name: fleet_server
version: latest
- name: system
version: latest
- name: elastic_agent
version: latest
- name: docker
version: latest
- name: apm
version: latest
xpack.fleet.agentPolicies:
- name: Fleet Server Policy
id: fleet-server-policy
description: Static agent policy for Fleet Server
monitoring_enabled:
- logs
- metrics
package_policies:
- name: fleet_server-1
package:
name: fleet_server
- name: system-1
package:
name: system
- name: elastic_agent-1
package:
name: elastic_agent
- name: docker-1
package:
name: docker
- name: Agent Policy APM Server
id: agent-policy-apm-server
description: Static agent policy for the APM Server integration
monitoring_enabled:
- logs
- metrics
package_policies:
- name: system-1
package:
name: system
- name: elastic_agent-1
package:
name: elastic_agent
- name: apm-1
package:
name: apm
# Смотрите манифест пакета APM для списка возможных входов.
# https://github.com/elastic/apm-server/blob/v8.5.0/apmpackage/apm/manifest.yml#L41-L168
inputs:
- type: apm
vars:
- name: host
value: 0.0.0.0:8200
- name: url
value: http://apm-server:8200
Ответ или решение
Эффективная настройка ELK Stack с использованием Docker для многоуровневой UDP-логгирования
Введение
В современных распределённых системах необходимо обеспечить высокую надёжность и производительность обработки логов, особенно при наличии большого количества клиентов из разных регионов. Использование ELK Stack (Elasticsearch, Logstash и Kibana) в контейнерах Docker — это популярное решение для централизованного хранения и анализа логов. В данном руководстве будет описан оптимальный способ настройки ELK Stack для приёма UDP-сообщений от клиентов по всему миру, с учётом географического распределения пользователей.
Архитектура системы
1. Геобазирующие серверы
Для обеспечения высокой доступности и производительности рекомендуется разместить серверы ELK Stack в нескольких регионах, например, в Северной Америке, Европе, Австралии и Азии. Каждый из этих серверов будет получать логи локально от клиентов, что снижает задержку передачи данных.
Рекомендуемая архитектура:
- Серверы ELK в разных регионах: Разверните отдельные экземпляры ELK Stack на каждом сервере (например, AWS, GCP, Azure) в регионе, где находятся ваши клиенты.
- Забор логов через UDP: Настройте каждый Logstash для прослушивания UDP на соответствующих портах, обеспечивая поддержку JSON-кода.
2. Балансировка нагрузки
Для того чтобы направлять сообщения от клиентов к ближайшему серверу ELK, можно использовать механизмы маршрутизации:
- DNS Round Robin: Используйте DNS, чтобы настроить несколько A-записей, указывающих на IP-адреса всех серверов ELK, чтобы клиенты могли получать адреса в зависимости от их геолокации.
- Геораспределённые прокси: Внедрите прокси-сервера, которые будут перенаправлять UDP-сообщения на ближайший сервер ELK на основе географического расположения.
Пример конфигурации серверов
# docker-compose.yml для каждого сервера ELK
version: '3'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.5.0
environment:
- discovery.type=single-node
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- ELASTIC_PASSWORD=yourpassword
networks:
- elk
ports:
- "9200:9200"
- "9300:9300"
logstash:
image: docker.elastic.co/logstash/logstash:8.5.0
environment:
- "LOGSTASH_JAVA_OPTS=-Xms256m -Xmx256m"
- "LOGSTASH_PASSWORD=yourpassword"
networks:
- elk
ports:
- "5044:5044/udp"
kibana:
image: docker.elastic.co/kibana/kibana:8.5.0
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
- KIBANA_PASSWORD=yourpassword
networks:
- elk
ports:
- "5601:5601"
networks:
elk:
driver: bridge
Конфигурация Logstash
Настройте файл logstash.conf
для приёма UDP-сообщений и их отправки в Elasticsearch:
input {
udp {
port => 5044
codec => json
}
}
filter {
# Добавьте необходимые фильтры для трансформации логов
}
output {
elasticsearch {
hosts => ["http://elasticsearch:9200"]
index => "logs-%{+YYYY.MM.dd}"
user => "your_username"
password => "your_password"
}
}
3. Взаимодейственная настройка Kibana
Kibana будет использоваться для визуализации полученных логов. Убедитесь, что kibana.yml
настроен для работы с Elasticsearch:
elasticsearch.hosts: ["http://elasticsearch:9200"]
xpack.security.enabled: true
Заключение
Распределение серверов ELK Stack по нескольким регионам не только улучшит производительность системы, но и повлияет на стабильность приема данных от клиентов. Кроме того, правильное использование DNS и балансировщиков нагрузки поможет направить логирующие сообщения к ближайшим серверам, минимизируя задержки в связи.
Для дальнейшего изучения рекомендуется ознакомиться со следующими ресурсами:
С правильной настройкой ELK Stack, основанной на приведенных рекомендациях, вы сможете эффективно обрабатывать и визуализировать данные логов от пользователей всего мира.