Skip to content

Instantly share code, notes, and snippets.

@isaqueprofeta
Created April 24, 2022 18:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save isaqueprofeta/1cdab13bb23b8a16245046bd31952c78 to your computer and use it in GitHub Desktop.
Save isaqueprofeta/1cdab13bb23b8a16245046bd31952c78 to your computer and use it in GitHub Desktop.
Laboratório de eventos real-time do Zabbix para OpenSearch usando Logstash

Laboratório de eventos real-time do Zabbix para OpenSearch usando Logstash

TL;DR: O ingestão e atualizaçao dos dados foi feita com sucesso, a PoC terminou no ponto onde o Logstash para o OpenSearch não se mostrou interessante do ponto de vista de não ter recursos (que em pesquisa existem plugins do logstash para a versão proprietária do ElasticSearch) para calcular em novos campos no processo de atualização o tempo de duração dos eventos para facilitar o desenvolvimento de dashboards de apresentação de dados. Concluindo-se assim que seria mais interessante um python no lugar do logstash para executar funções de "update by query".

Composição

  • Logstash para processamento dos dados vindos de triggers do real-time export do Zabbix
  • OpenSearch para armazenamento e pesquisa
  • OpenSearch Dashboards para analise de dados e dashboard

Testes

  • Usado o projeto zabbix-lab

  • Copiados todos os arquivos deste gist para um "diretório 'zabbix-opensearch' vizinho" do zabbix-lab para usar a pasta "../zabbix-opensearch/data" compartilhada na montagem do volumes dos containeres docker

  • Adicionados 3 variáveis "environments" no service zabbix-server do arquivo docker-compose.yml ficando assim:

    environment:
      - DB_SERVER_PORT=5432
      - DB_SERVER_HOST=postgresql
      - POSTGRES_DB=zabbix
      - POSTGRES_USER=zabbix
      - POSTGRES_PASSWORD=zabbix
      - ENABLE_TIMESCALEDB=true
      - ZBX_STARTREPORTWRITERS=2
      - ZBX_WEBSERVICEURL=http://zabbix-reports:10053/report
      - ZBX_EXPORT=/var/lib/zabbix/export/
      - ZBX_EXPORTFILESIZE=1G
      - ZBX_EXPORTTYPE=events
    
  • Adicionado o volume para os arquivos ndjson do real-time exporter no service zabbix-server do arquivo docker-compose.yml ficando assim (caso não seja feito o merge dos docker-compose.yml, corrigir aqui o caminho para os dados de real-time export):

    volumes:
    - ./zabbix/usr/lib/zabbix/externalscripts:/usr/lib/zabbix/externalscripts:ro
    - ../zabbix-opensearch/data:/var/lib/zabbix/export
    
  • Após iniciados os testes:

    • Foi configurado um item de Zabbix Trapper numérico simples
    • Foi configurada uma trigger de baseado no item de teste Trapper para alertar em last(/Zabbix server/Zabbix test)>10 e recuperar em last(/Zabbix server/Zabbix test)<10
    • Testes executados com um comando de zabbix_sender, quando o "-o" for maior que 10 gera a trigger e quando menor que 10 normaliza a trigger:
      /usr/bin/zabbix_sender --zabbix-server zabbix-server --host "Zabbix server" -k zabbixtest -o 8
      
  • Abrindo o http://opensearch-dashboards:5601 e logando com as credenciais padrão admin:admin é possível adicionar o index-pattern "zabbix-triggers" com o @timestamp como campo de linha de tempo, e no discover verificar a adição do evento na geração do problem e a atualização do evento na geração do recover.

  • O ingestão e atualizaçao dos dados foi feita com sucesso, a PoC terminou no ponto onde o Logstash para o OpenSearch não se mostrou interessante do ponto de vista de não ter recursos (que em pesquisa existem plugins do logstash para a versão proprietária do ElasticSearch) para calcular em novos campos no processo de atualização o tempo de duração dos eventos para facilitar o desenvolvimento de dashboards de apresentação de dados. Concluindo-se assim que seria mais interessante um python no lugar do logstash para executar funções de "update by query".

Configuração

  • Alterar no arquivo o caminho para o diretório com os arquivos de real-time export do Zabbix ou apontar/montar o local indicado:
    • Padrão:

      ZABBIX_FILE_PATH=./data
      
    • Alteração:

      ZABBIX_FILE_PATH=/ALTERAR_O_PATH/AQUI
      

Instalação

  • Iniciar o ambiente opensearch no docker:

    docker-compose up -d

Acesso aos dados

Mapeamento de dados

Evento de problema

  • Mapeamentos definidos

    • clock => time_start
    • clock => @timestamp
    • eventid => eventid_problem
    • eventid => _id
    • severity => severity
    • name => trigger_name
    • [hosts][host] => hostname
    • [hosts][name] => hostdisplayname
    • groups => groups
    • tags => tags
    • ns => REMOVIDO
  • Log Zabbix

    {
      "clock": 1650474058,
      "ns": 391767948,
      "value": 1,
      "eventid": 36,
      "name": "High swap space usage (less than 50% free)",
      "severity": 2,
      "hosts": [{
          "host": "Zabbix server",
          "name": "Zabbix server"
      }],
      "groups": [
          "Zabbix servers"
      ],
      "tags": [
          { "tag": "scope", "value": "capacity" },
          { "tag": "component", "value": "storage" }
      ]
    }

Evento de problema

  • Mapeamentos definidos

    • clock => time_finish
    • eventid => eventid_recovery
    • p_eventid => eventid_problem
    • ns => REMOVIDO
  • Log Zabbix

    {
      "clock":1650409264,
      "ns":146613192,
      "value":0,
      "eventid":34,
      "p_eventid":33
    }
version: '3'
volumes:
opensearch-node1_data:
opensearch-node2_data:
services:
opensearch-node1:
restart: unless-stopped
image: opensearchproject/opensearch:latest
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
environment:
- cluster.name=opensearch-cluster
- node.name=opensearch-node1
- discovery.seed_hosts=opensearch-node1,opensearch-node2
- cluster.initial_master_nodes=opensearch-node1,opensearch-node2
- bootstrap.memory_lock=true
- "OPENSEARCH_JAVA_OPTS=-Xms2g -Xmx2g"
volumes:
- opensearch-node1_data:/usr/share/opensearch/data
ports:
- 9200:9200
- 9600:9600
expose:
- "9200"
opensearch-node2:
image: opensearchproject/opensearch:latest
environment:
- cluster.name=opensearch-cluster
- node.name=opensearch-node2
- discovery.seed_hosts=opensearch-node1,opensearch-node2
- cluster.initial_master_nodes=opensearch-node1,opensearch-node2
- bootstrap.memory_lock=true
- "OPENSEARCH_JAVA_OPTS=-Xms2g -Xmx2g"
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
volumes:
- opensearch-node2_data:/usr/share/opensearch/data
opensearch-dashboards:
restart: unless-stopped
image: opensearchproject/opensearch-dashboards:latest
environment:
OPENSEARCH_HOSTS: '["https://opensearch-node1:9200","https://opensearch-node2:9200"]'
ports:
- 5601:5601
expose:
- "5601"
depends_on:
- opensearch-node1
- opensearch-node2
logstash:
restart: unless-stopped
image: opensearchproject/logstash-oss-with-opensearch-output-plugin:latest
volumes:
- ./index-mappings.json:/zabbix-template/index-mappings.json:ro
- ./triggers-ingest.yml:/usr/share/logstash/pipeline/triggers-ingest.yml:ro
- ./data:/data/
depends_on:
- opensearch-node1
- opensearch-node2
dns-hoster:
restart: unless-stopped
image: dvdarias/docker-hoster
volumes:
- /var/run/docker.sock:/tmp/docker.sock
- /etc/hosts:/tmp/hosts
{
"settings": {
"index": {
"number_of_shards": 1,
"number_of_replicas": 0
}
},
"mappings": {
"properties": {
"@timestamp": {
"type": "date"
},
"@version": {
"type": "keyword"
},
"value": {
"type": "short"
},
"time_start": {
"type": "date"
},
"time_finish": {
"type": "date"
},
"eventid_problem": {
"type": "integer"
},
"eventid_recovery": {
"type": "integer"
},
"severity": {
"type": "short"
},
"trigger_name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"hostname": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"hostdisplay": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"groups": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"tags": {
"properties": {
"tag": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"value": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
}
}
}
input {
file {
path => ["/data/problems-*.ndjson"]
start_position => "beginning"
sincedb_path => "/dev/null"
}
}
filter {
mutate {
replace => [ "message", "%{message}" ]
gsub => [ 'message','\n','']
}
if [message] =~ /^{.*}$/ {
json {
source => message
}
}
if [value] == 1 {
date {
match => [ "clock", "UNIX" ]
target => "@timestamp"
timezone => "America/Sao_Paulo"
}
date {
match => [ "clock", "UNIX" ]
target => "time_start"
timezone => "America/Sao_Paulo"
}
date {
match => [ "clock", "UNIX" ]
target => "time_finish"
timezone => "America/Sao_Paulo"
}
mutate {
rename => {
"name" => "trigger_name"
"[hosts][host]" => "hostname"
"[hosts][name]" => "hostdisplayname"
"eventid" => "eventid_problem"
}
remove_field => [
"clock"
]
}
} else if [value] == 0 {
date {
match => [ "clock", "UNIX" ]
target => "time_finish"
timezone => "America/Sao_Paulo"
}
mutate {
rename => {
"p_eventid" => "eventid_problem"
}
remove_field => [
"clock"
]
}
}
}
output {
if [value] == 1 {
opensearch {
hosts => ["https://opensearch-node1:9200"]
index => "zabbix-triggers"
user => "admin"
password => "admin"
ssl => true
ssl_certificate_verification => false
document_id => "%{eventid_problem}"
template => "/zabbix-template/index-mappings.json"
}
} else if [value] == 0 {
opensearch {
hosts => ["https://opensearch-node1:9200"]
index => "zabbix-triggers"
user => "admin"
password => "admin"
ssl => true
ssl_certificate_verification => false
document_id => "%{eventid_problem}"
template => "/zabbix-template/index-mappings.json"
action => "update"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment