Alexey Lizunov, gerente da área do centro de competências de canais de atendimento remoto da diretoria de tecnologias da informação da MKB

Como alternativa ao stack ELK (ElasticSearch, Logstash, Kibana), estamos realizando pesquisas sobre o uso do banco de dados ClickHouse como armazenamento de dados para logs.
Neste artigo, gostaríamos de compartilhar nossa experiência com o uso do banco de dados ClickHouse e os resultados preliminares após a implementação piloto. É importante notar desde o início que os resultados foram impressionantes.

A seguir, descreveremos com mais detalhes como nosso sistema está configurado e de quais componentes ele é composto. Mas agora gostaríamos de falar um pouco sobre este banco de dados em geral e por que ele merece sua atenção. O banco de dados ClickHouse é um banco de dados analítico em coluna de alta performance desenvolvido pela Yandex. É utilizado nos serviços da Yandex, sendo originalmente o armazenamento principal de dados para o Yandex.Metrica. O sistema é open-source e gratuito. Do ponto de vista do desenvolvedor, sempre me interessei por como isso é implementado, pois lidam com volumes de dados fantastamente grandes. E a interface do usuário do Metrica é muito flexível e rápida. Na primeira vez que conheci este banco de dados, a impressão foi: “Finalmente! Feito ‘para as pessoas’! Desde o processo de instalação até o envio de consultas.”
Este banco de dados tem um limiar de entrada muito baixo. Mesmo um desenvolvedor de média habilidade pode instalar este banco de dados em alguns minutos e começar a usá-lo. Tudo funciona perfeitamente. Mesmo pessoas que não estão familiarizadas com Linux podem gerenciar a instalação e realizar operações simples de forma rápida. Se antes, quando se falava em Big Data, Hadoop, Google BigTable, HDFS, a imagem que um desenvolvedor comum tinha era de que se tratava de terabytes e petabytes, e que as configurações e desenvolvimento dessas sistemas eram feitas por super-humanos, agora com o surgimento do banco de dados ClickHouse temos uma ferramenta simples e compreensível que nos permite resolver um conjunto de tarefas que antes era inacessível. Basta uma máquina bastante comum e cinco minutos para a instalação. Ou seja, temos um banco de dados como o MySql, mas apenas para armazenar bilhões de registros! Uma espécie de super-arquivador com linguagem SQL. É como se as pessoas recebessem armas de alienígenas.
Sobre nosso sistema de coleta de logs
Para coletar informações, utilizam-se arquivos de log do IIS em formato padrão (atualmente também estamos fazendo a análise dos logs de aplicativos, mas o objetivo principal nesta fase de teste é a coleta dos logs do IIS).
Não conseguimos abandonar completamente a pilha ELK devido a várias razões, e continuamos utilizando os componentes LogStash e Filebeat, que se mostraram eficazes e funcionam de maneira bastante confiável e previsível.
O esquema geral de logging é apresentado na figura abaixo:

Uma característica da gravação de dados no banco de dados ClickHouse é a inserção rara (uma vez por segundo) de registros em grandes lotes. Essa, aparentemente, é a parte mais "problemática" que se enfrenta na primeira experiência com o banco de dados ClickHouse: o esquema é um pouco mais complexo.
Aqui, o plugin para LogStash que insere dados diretamente no ClickHouse ajudou bastante. Este componente é implantado no mesmo servidor que o banco de dados. Na verdade, isso não é recomendado, mas, do ponto de vista prático, para não criar servidores separados, enquanto está implantado no mesmo servidor. Não observamos falhas nem conflitos de recursos com o banco de dados. Além disso, é necessário notar que o plugin possui um mecanismo de repetição em caso de erros. Em caso de falhas, o plugin grava no disco um lote de dados que não pôde ser inserido (o formato do arquivo é conveniente: após a correção, é fácil inserir o lote corrigido com a ajuda do clickhouse-client).
A lista completa de softwares utilizados no esquema é apresentada na tabela:
Lista de softwares utilizados
Nome
Descrição
Link para o distribuidor
NGINX
Reverse-proxy para limitar o acesso por portas e organizar a autenticação
Atualmente não é utilizado no esquema
FileBeat
Transmissão de logs de arquivos.
(distribuidor para Windows 64bit).
LogStash
Coletor de logs.
Utilizado para coletar logs do FileBeat e também para coletar logs da fila RabbitMQ (para os servidores que estão na DMZ).
Logstash-output-clickhouse
Plugin Logstash para transmissão de logs para o banco de dados ClickHouse em lotes
/usr/share/logstash/bin/logstash-plugin install logstash-output-clickhouse
/usr/share/logstash/bin/logstash-plugin install logstash-filter-prune
/usr/share/logstash/bin/logstash-plugin install logstash-filter-multiline
ClickHouse
Armazenamento de logs
Nota. Desde agosto de 2018, apareceram no repositório do Yandex assemblagens "normais" .rpm para RHEL, então pode-se tentar usá-las. No momento da instalação, utilizamos pacotes construídos pela Altinity.
Grafana
Visualização de logs. Configuração de dashboards
Redhat & CentOS (64 Bit) – versão mais recente
Fonte de dados ClickHouse para Grafana 4.6+
Plugin para Grafana com a fonte de dados ClickHouse
LogStash
Roteador de logs do FileBeat para a fila RabbitMQ.
Nota. Infelizmente, o FileBeat não possui saída direta para o RabbitMQ, portanto, é necessário um elo intermediário na forma do Logstash.
RabbitMQ
Fila de mensagens. Este é um buffer de entradas de logs na DMZ.
Erlang Runtime (Necessário para RabbitMQ)
Ambiente de execução Erlang. Requerido para operação do RabbitMQ.
A configuração do servidor com o banco de dados ClickHouse é apresentada na tabela a seguir:
Nome
O valor
Nota
Configuração
HDD: 40GB
RAM: 8GB
Processador: Core 2 2Ghz
É necessário observar as dicas para operação do banco de dados ClickHouse ()
Software de sistema geral
SO: Red Hat Enterprise Linux Server (Maipo)
JRE (Java 8)
Como pode ser visto, é uma estação de trabalho comum.
A estrutura da tabela para armazenar logs é a seguinte:
log_web.sql
CREATE TABLE log_web (
logdate Date,
logdatetime DateTime CODEC(Delta, LZ4HC),
fld_log_file_name LowCardinality( String ),
fld_server_name LowCardinality( String ),
fld_app_name LowCardinality( String ),
fld_app_module LowCardinality( String ),
fld_website_name LowCardinality( String ),
serverIP LowCardinality( String ),
method LowCardinality( String ),
uriStem String,
uriQuery String,
port UInt32,
username LowCardinality( String ),
clientIP String,
clientRealIP String,
userAgent String,
referer String,
response String,
subresponse String,
win32response String,
timetaken UInt64
, uriQuery__utm_medium String
, uriQuery__utm_source String
, uriQuery__utm_campaign String
, uriQuery__utm_term String
, uriQuery__utm_content String
, uriQuery__yclid String
, uriQuery__region String
) Engine = MergeTree()
PARTITION BY toYYYYMM(logdate)
ORDER BY (fld_app_name, fld_app_module, logdatetime)
SETTINGS index_granularity = 8192;Usamos os valores padrão para particionamento (por meses) e granularidade do índice. Todos os campos correspondem praticamente às entradas do log do IIS para o registro de solicitações HTTP. Ressaltamos campos separados para armazenamento de rótulos UTM (eles são analisados na fase de inserção na tabela a partir do campo da string de consulta).
Além disso, a tabela contém vários campos de sistema para armazenar informações sobre sistemas, componentes e servidores. A descrição desses campos pode ser encontrada na tabela abaixo. Em uma única tabela, armazenamos logs de vários sistemas.
Nome
Descrição
Exemplo
fld_app_name
Nome do aplicativo/sistema
Valores permitidos:
- site1.domain.com Site externo 1
- site2.domain.com Site externo 2
- internal-site1.domain.local Site interno 1
site1.domain.com
fld_app_module
Módulo do sistema
Valores permitidos:
- web — Site
- svc — Serviço web do site
- intgr — Serviço web de integração
- bo — Admin (BackOffice)
web
fld_website_name
Nome do site no IIS
Em um único servidor, podem ser implementados vários sistemas, ou mesmo várias instâncias de um único módulo do sistema.
web-main
fld_server_name
Nome do servidor
web1.domain.com
fld_log_file_name
Caminho para o arquivo de log no servidor
C:inetpublogsLogFiles
W3SVC1u_ex190711.log
Isso permite criar gráficos de forma eficaz no Grafana. Por exemplo, visualizar as consultas do frontend de um sistema específico. Isso é semelhante a um contador de site no Yandex.Metrica.
Aqui estão algumas estatísticas sobre o uso do banco de dados nos últimos dois meses.
Número de registros divididos por sistemas e seus componentes
SELECT
fld_app_name,
fld_app_module,
count(fld_app_name) AS rows_count
FROM log_web
GROUP BY
fld_app_name,
fld_app_module
WITH TOTALS
ORDER BY
fld_app_name ASC,
rows_count DESC
┌─fld_app_name─────┬─fld_app_module─┬─rows_count─┐
│ site1.domain.ru │ web │ 131441 │
│ site2.domain.ru │ web │ 1751081 │
│ site3.domain.ru │ web │ 106887543 │
│ site3.domain.ru │ svc │ 44908603 │
│ site3.domain.ru │ intgr │ 9813911 │
│ site4.domain.ru │ web │ 772095 │
│ site5.domain.ru │ web │ 17037221 │
│ site5.domain.ru │ intgr │ 838559 │
│ site5.domain.ru │ bo │ 7404 │
│ site6.domain.ru │ web │ 595877 │
│ site7.domain.ru │ web │ 27778858 │
└──────────────────┴────────────────┴────────────┘
Totals:
┌─fld_app_name─┬─fld_app_module─┬─rows_count─┐
│ │ │ 210522593 │
└──────────────┴────────────────┴────────────┘
11 rows in set. Elapsed: 4.874 sec. Processed 210.52 million rows, 421.67 MB (43.19 million rows/s., 86.51 MB/s.)Tamanho dos dados em disco
SELECT
formatReadableSize(sum(data_uncompressed_bytes)) AS uncompressed,
formatReadableSize(sum(data_compressed_bytes)) AS compressed,
sum(rows) AS total_rows
FROM system.parts
WHERE table = 'log_web'
┌─uncompressed─┬─compressed─┬─total_rows─┐
│ 54.50 GiB │ 4.86 GiB │ 211427094 │
└──────────────┴────────────┴────────────┘
1 rows in set. Elapsed: 0.035 sec.Grau de compressão dos dados nas colunas
SELECIONE
nome,
formatReadableSize(data_uncompressed_bytes) AS não_comprimido,
formatReadableSize(data_compressed_bytes) AS comprimido,
data_uncompressed_bytes / data_compressed_bytes AS taxa_de_compressão
FROM system.columns
WHERE table = 'log_web'
┌─nome────────────────────┬─não_comprimido─┬─comprimido─┬─────taxa_de_compressão────┐
│ logdate │ 401.53 MiB │ 1.80 MiB │ 223.16665968777315 │
│ logdatetime │ 803.06 MiB │ 35.91 MiB │ 22.363966401202305 │
│ fld_log_file_name │ 220.66 MiB │ 2.60 MiB │ 84.99905736932571 │
│ fld_server_name │ 201.54 MiB │ 50.63 MiB │ 3.980924816977078 │
│ fld_app_name │ 201.17 MiB │ 969.17 KiB │ 212.55518183686877 │
│ fld_app_module │ 201.17 MiB │ 968.60 KiB │ 212.67805817411906 │
│ fld_website_name │ 201.54 MiB │ 1.24 MiB │ 162.7204926761546 │
│ serverIP │ 201.54 MiB │ 50.25 MiB │ 4.010824061219731 │
│ method │ 201.53 MiB │ 43.64 MiB │ 4.617721053304486 │
│ uriStem │ 5.13 GiB │ 832.51 MiB │ 6.311522291936919 │
│ uriQuery │ 2.58 GiB │ 501.06 MiB │ 5.269731450124478 │
│ port │ 803.06 MiB │ 3.98 MiB │ 201.91673864241824 │
│ username │ 318.08 MiB │ 26.93 MiB │ 11.812513794583598 │
│ clientIP │ 2.35 GiB │ 82.59 MiB │ 29.132328640073343 │
│ clientRealIP │ 2.49 GiB │ 465.05 MiB │ 5.478382297052563 │
│ userAgent │ 18.34 GiB │ 764.08 MiB │ 24.57905114484208 │
│ referer │ 14.71 GiB │ 1.37 GiB │ 10.736792723669906 │
│ response │ 803.06 MiB │ 83.81 MiB │ 9.582334090987247 │
│ subresponse │ 399.87 MiB │ 1.83 MiB │ 218.4831068635027 │
│ win32response │ 407.86 MiB │ 7.41 MiB │ 55.050315514606815 │
│ timetaken │ 1.57 GiB │ 402.06 MiB │ 3.9947395692010637 │
│ uriQuery__utm_medium │ 208.17 MiB │ 12.29 MiB │ 16.936148912472955 │
│ uriQuery__utm_source │ 215.18 MiB │ 13.00 MiB │ 16.548367623199912 │
│ uriQuery__utm_campaign │ 381.46 MiB │ 37.94 MiB │ 10.055156353418509 │
│ uriQuery__utm_term │ 231.82 MiB │ 10.78 MiB │ 21.502540454070672 │
│ uriQuery__utm_content │ 441.34 MiB │ 87.60 MiB │ 5.038260760449327 │
│ uriQuery__yclid │ 216.88 MiB │ 16.58 MiB │ 13.07721335008116 │
│ uriQuery__region │ 204.35 MiB │ 9.49 MiB │ 21.52661903446796 │
└────────────────────────┴─────────────────┴────────────┴──────────────────────────┘
28 linhas no conjunto. Tempo decorrido: 0.005 seg.Descrição dos componentes utilizados
FileBeat. Transmissão de logs de arquivos
Este componente monitora alterações em arquivos de log no disco e transmite as informações para o LogStash. É instalado em todos os servidores onde os arquivos de log são gerados (geralmente, IIS). Funciona no modo tail (ou seja, transmite apenas os registros adicionados ao arquivo). Mas também pode ser configurado para transmitir arquivos inteiros. Isso é conveniente quando é necessário carregar dados dos meses anteriores. Basta colocar o arquivo de log na pasta e ele será lido completamente.
Quando o serviço for interrompido, os dados param de ser enviados para o armazenamento.
Um exemplo de configuração é o seguinte:
filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- C:/inetpub/logs/LogFiles/W3SVC1/*.log
exclude_files: ['.gz$','.zip$']
tail_files: true
ignore_older: 24h
fields:
fld_server_name: "site1.domain.ru"
fld_app_name: "site1.domain.ru"
fld_app_module: "web"
fld_website_name: "web-main"
- type: log
enabled: true
paths:
- C:/inetpub/logs/LogFiles/__Import/access_log-*
exclude_files: ['.gz$','.zip$']
tail_files: false
fields:
fld_server_name: "site2.domain.ru"
fld_app_name: "site2.domain.ru"
fld_app_module: "web"
fld_website_name: "web-main"
fld_logformat: "logformat__apache"
filebeat.config.modules:
path: ${path.config}/modules.d/*.yml
reload.enabled: false
reload.period: 2s
output.logstash:
hosts: ["log.domain.com:5044"]
ssl.enabled: true
ssl.certificate_authorities: ["C:/filebeat/certs/ca.pem", "C:/filebeat/certs/ca-issuing.pem"]
ssl.certificate: "C:/filebeat/certs/site1.domain.ru.cer"
ssl.key: "C:/filebeat/certs/site1.domain.ru.key"
#================================ Processors =====================================
processors:
- add_host_metadata: ~
- add_cloud_metadata: ~LogStash. Coletor de logs
Este componente é projetado para receber registros de log do FileBeat (ou através da fila RabbitMQ), fazer a análise e inserir em lote no banco de dados ClickHouse.
Para inserção no ClickHouse, é utilizado o plugin Logstash-output-clickhouse. O Logstash possui um mecanismo de retry para requisições, mas durante uma parada programada, é melhor interromper o próprio serviço. Durante a parada, as mensagens se acumularão na fila RabbitMQ, portanto, se a interrupção for por um longo período, é melhor parar os Filebeats nos servidores. Na configuração onde o RabbitMQ não é utilizado (na rede local, o Filebeat envia logs diretamente para o Logstash), os Filebeats funcionam de forma aceitável e segura, portanto, para eles, a indisponibilidade da saída não resulta em consequências.
Um exemplo de configuração é o seguinte:
log_web__filebeat_clickhouse.conf
input {
beats {
port => 5044
type => 'iis'
ssl => true
ssl_certificate_authorities => ["/etc/logstash/certs/ca.cer", "/etc/logstash/certs/ca-issuing.cer"]
ssl_certificate => "/etc/logstash/certs/server.cer"
ssl_key => "/etc/logstash/certs/server-pkcs8.key"
ssl_verify_mode => "peer"
add_field => {
"fld_server_name" => "%{[fields][fld_server_name]}"
"fld_app_name" => "%{[fields][fld_app_name]}"
"fld_app_module" => "%{[fields][fld_app_module]}"
"fld_website_name" => "%{[fields][fld_website_name]}"
"fld_log_file_name" => "%{source}"
"fld_logformat" => "%{[fields][fld_logformat]}"
}
}
rabbitmq {
host => "queue.domain.com"
port => 5671
user => "q-reader"
password => "password"
queue => "web_log"
heartbeat => 30
durable => true
ssl => true
#ssl_certificate_path => "/etc/logstash/certs/server.p12"
#ssl_certificate_password => "password"
add_field => {
"fld_server_name" => "%{[fields][fld_server_name]}"
"fld_app_name" => "%{[fields][fld_app_name]}"
"fld_app_module" => "%{[fields][fld_app_module]}"
"fld_website_name" => "%{[fields][fld_website_name]}"
"fld_log_file_name" => "%{source}"
"fld_logformat" => "%{[fields][fld_logformat]}"
}
}
}
filter {
if [message] =~ "^#" {
drop {}
}
if [fld_logformat] == "logformat__iis_with_xrealip" {
grok {
match => ["message", "%{TIMESTAMP_ISO8601:log_timestamp} %{IP:serverIP} %{WORD:method} %{NOTSPACE:uriStem} %{NOTSPACE:uriQuery} %{NUMBER:port} %{NOTSPACE:username} %{IPORHOST:clientIP} %{NOTSPACE:userAgent} %{NOTSPACE:referer} %{NUMBER:response} %{NUMBER:subresponse} %{NUMBER:win32response} %{NUMBER:timetaken} %{NOTSPACE:xrealIP} %{NOTSPACE:xforwarderfor}"]
}
} else {
grok {
match => ["message", "%{TIMESTAMP_ISO8601:log_timestamp} %{IP:serverIP} %{WORD:method} %{NOTSPACE:uriStem} %{NOTSPACE:uriQuery} %{NUMBER:port} %{NOTSPACE:username} %{IPORHOST:clientIP} %{NOTSPACE:userAgent} %{NOTSPACE:referer} %{NUMBER:response} %{NUMBER:subresponse} %{NUMBER:win32response} %{NUMBER:timetaken}"]
}
}
date {
match => [ "log_timestamp", "YYYY-MM-dd HH:mm:ss" ]
timezone => "Etc/UTC"
remove_field => [ "log_timestamp", "@timestamp" ]
target => [ "log_timestamp2" ]
}
ruby {
code => "tstamp = event.get('log_timestamp2').to_i
event.set('logdatetime', Time.at(tstamp).strftime('%Y-%m-%d %H:%M:%S'))
event.set('logdate', Time.at(tstamp).strftime('%Y-%m-%d'))"
}
if [bytesSent] {
ruby {
code => "event['kilobytesSent'] = event['bytesSent'].to_i / 1024.0"
}
}
if [bytesReceived] {
ruby {
code => "event['kilobytesReceived'] = event['bytesReceived'].to_i / 1024.0"
}
}
ruby {
code => "event.set('clientRealIP', event.get('clientIP'))"
}
if [xrealIP] {
ruby {
code => "event.set('clientRealIP', event.get('xrealIP'))"
}
}
if [xforwarderfor] {
ruby {
code => "event.set('clientRealIP', event.get('xforwarderfor'))"
}
}
mutate {
convert => ["bytesSent", "integer"]
convert => ["bytesReceived", "integer"]
convert => ["timetaken", "integer"]
convert => ["port", "integer"]
add_field => {
"clientHostname" => "%{clientIP}"
}
}
useragent {
source => "useragent"
prefix => "browser"
}
kv {
source => "uriQuery"
prefix => "uriQuery__"
allow_duplicate_values => false
field_split => "&"
include_keys => [ "utm_medium", "utm_source", "utm_campaign", "utm_term", "utm_content", "yclid", "region" ]
}
mutate {
join => { "uriQuery__utm_source" => "," }
join => { "uriQuery__utm_medium" => "," }
join => { "uriQuery__utm_campaign" => "," }
join => { "uriQuery__utm_term" => "," }
join => { "uriQuery__utm_content" => "," }
join => { "uriQuery__yclid" => "," }
join => { "uriQuery__region" => "," }
}
}
output {
#stdout {codec => rubydebug}
clickhouse {
headers => ["Authorization", "Basic abcdsfks..."]
http_hosts => ["http://127.0.0.1:8123"]
save_dir => "/etc/logstash/tmp"
table => "log_web"
request_tolerance => 1
flush_size => 10000
idle_flush_time => 1
mutations => {
"fld_log_file_name" => "fld_log_file_name"
"fld_server_name" => "fld_server_name"
"fld_app_name" => "fld_app_name"
"fld_app_module" => "fld_app_module"
"fld_website_name" => "fld_website_name"
"logdatetime" => "logdatetime"
"logdate" => "logdate"
"serverIP" => "serverIP"
"method" => "method"
"uriStem" => "uriStem"
"uriQuery" => "uriQuery"
"port" => "port"
"username" => "username"
"clientIP" => "clientIP"
"clientRealIP" => "clientRealIP"
"userAgent" => "userAgent"
"referer" => "referer"
"response" => "response"
"subresponse" => "subresponse"
"win32response" => "win32response"
"timetaken" => "timetaken"
"uriQuery__utm_medium" => "uriQuery__utm_medium"
"uriQuery__utm_source" => "uriQuery__utm_source"
"uriQuery__utm_campaign" => "uriQuery__utm_campaign"
"uriQuery__utm_term" => "uriQuery__utm_term"
"uriQuery__utm_content" => "uriQuery__utm_content"
"uriQuery__yclid" => "uriQuery__yclid"
"uriQuery__region" => "uriQuery__region"
}
}
}pipelines.yml
# This file is where you define your pipelines. You can define multiple.
# For more information on multiple pipelines, see the documentation:
# https://www.elastic.co/guide/en/logstash/current/multiple-pipelines.html
- pipeline.id: log_web__filebeat_clickhouse
path.config: "/etc/logstash/log_web__filebeat_clickhouse.conf"ClickHouse. Armazenamento de logs
Os logs de todos os sistemas são armazenados em uma única tabela (veja no início do artigo). Ela se destina a armazenar informações sobre as solicitações: todos os parâmetros são semelhantes para diferentes formatos, como logs do IIS, logs do Apache e Nginx. Para logs de aplicações, onde são registrados, por exemplo, erros, mensagens informativas e avisos, haverá uma tabela separada, com a estrutura adequada (atualmente em fase de projeto).
Ao projetar a tabela, é muito importante definir a chave primária (com a qual os dados serão ordenados ao serem armazenados). Isso afeta o grau de compressão dos dados e a velocidade das consultas. No nosso exemplo, a chave é
ORDER BY (fld_app_name, fld_app_module, logdatetime)
Ou seja, pelo nome do sistema, nome do componente do sistema e data do evento. Inicialmente, a data do evento estava em primeiro lugar. Após movê-la para o último lugar, as consultas passaram a funcionar aproximadamente duas vezes mais rápido. Alterar a chave primária exigirá a recriação da tabela e o reenviado dos dados para que o ClickHouse reorganize os dados no disco. Esta é uma operação intensa, portanto, é desejável planejar cuidadosamente o que deve estar incluído na chave de ordenação.
Também é necessário observar que, nas versões mais recentes, apareceu o tipo de dado LowCardinality. Ao usá-lo, há uma redução acentuada no tamanho dos dados comprimidos para aqueles campos que possuem baixa cardinalidade (poucas opções).
Atualmente, está sendo utilizada a versão 19.6, e planejamos tentar atualizar para a última versão. Nelas surgiram funcionalidades incríveis, como Granularidade Adaptativa, índices de Omissão e o codec DoubleDelta, por exemplo.
Por padrão, ao instalar, o nível de registro na configuração está definido como trace. Os logs são rotacionados e arquivados, mas se expandem até um gigabyte. Se não houver necessidade, pode-se definir o nível como warning, reduzindo consideravelmente o tamanho do log. A configuração do logging é definida no arquivo config.xml:
<!-- Níveis possíveis: https://github.com/pocoproject/poco/blob/develop/Foundation/include/Poco/Logger.h#L105 -->
<level>warning</level>Alguns comandos úteis
Como os pacotes de instalação originais são construídos com base no Debian, para outras versões do Linux, é necessário usar pacotes criados pela Altinity.
Aqui está o link com instruções e links para o repositório deles: https://www.altinity.com/blog/2017/12/18/logstash-with-clickhouse
sudo yum search clickhouse-server
sudo yum install clickhouse-server.noarch
1. verificar o status
sudo systemctl status clickhouse-server
2. parar o servidor
sudo systemctl stop clickhouse-server
3. iniciar o servidor
sudo systemctl start clickhouse-server
Iniciar para executar consultas em modo multilinha (executar após o sinal ";")
clickhouse-client --multiline
clickhouse-client --multiline --host 127.0.0.1 --password pa55w0rd
clickhouse-client --multiline --host 127.0.0.1 --port 9440 --secure --user default --password pa55w0rd
O plugin ClickHouse para Logstash, em caso de erro em uma linha, salva todo o lote no arquivo /tmp/log_web_failed.json
Você pode corrigir manualmente este arquivo e tentar carregá-lo no banco de dados manualmente:
clickhouse-client --host 127.0.0.1 --password password --query="INSERT INTO log_web FORMAT JSONEachRow" < /tmp/log_web_failed__fixed.json
sudo mv /etc/logstash/tmp/log_web_failed.json /etc/logstash/tmp/log_web_failed__fixed.json
sudo chown user_dev /etc/logstash/tmp/log_web_failed__fixed.json
sudo clickhouse-client --host 127.0.0.1 --password password --query="INSERT INTO log_web FORMAT JSONEachRow" < /etc/logstash/tmp/log_web_failed__fixed.json
sudo mv /etc/logstash/tmp/log_web_failed__fixed.json /etc/logstash/tmp/log_web_failed__fixed_.json
sair do terminal
quit;
## Configurando o TLS
https://www.altinity.com/blog/2019/3/5/clickhouse-networking-part-2
openssl s_client -connect log.domain.com:9440 < /dev/nullLogStash. O roteador de logs do FileBeat para a fila RabbitMQ
Este componente é usado para roteamento de logs que chegam do FileBeat para a fila RabbitMQ. Aqui estão dois pontos:
- Infelizmente, o FileBeat não possui um plugin de saída para gravação diretamente no RabbitMQ. E tal funcionalidade, segundo as questões no GitHub deles, não está planejada. Há um plugin para Kafka, mas por razões específicas não podemos usá-lo.
- Há requisitos para coleta de logs na DMZ. De acordo com esses requisitos, os logs devem primeiro ser armazenados em uma fila e, em seguida, o LogStash lê registros da fila externamente.
Portanto, para o caso de servidores localizados na DMZ, é necessário utilizar um esquema um pouco mais complexo. Um exemplo de configuração é o seguinte:
iis_w3c_logs__filebeat_rabbitmq.conf
input {
beats {
port => 5044
type => 'iis'
ssl => true
ssl_certificate_authorities => ["/etc/pki/tls/certs/app/ca.pem", "/etc/pki/tls/certs/app/ca-issuing.pem"]
ssl_certificate => "/etc/pki/tls/certs/app/queue.domain.com.cer"
ssl_key => "/etc/pki/tls/certs/app/queue.domain.com-pkcs8.key"
ssl_verify_mode => "peer"
}
}
output {
#stdout {codec => rubydebug}
rabbitmq {
host => "127.0.0.1"
port => 5672
exchange => "monitor.direct"
exchange_type => "direct"
key => "%{[fields][fld_app_name]}"
user => "q-writer"
password => "password"
ssl => false
}
}RabbitMQ. Fila de mensagens
Este componente é utilizado para bufferizar registros de logs na DMZ. A gravação é realizada através da combinação Filebeat → LogStash. A leitura é feita externamente à DMZ via LogStash. Ao operar através do RabbitMQ, cerca de 4 mil mensagens são processadas por segundo.
O roteamento das mensagens é configurado pelo nome do sistema, ou seja, com base nas configurações do FileBeat. Todas as mensagens vão para uma única fila. Se, por algum motivo, o serviço de filas for interrompido, isso não resultará na perda de mensagens: os FileBeats receberão erros de conexão e suspenderão temporariamente o envio. O LogStash, que lê da fila, também receberá erros de rede e aguardará a restauração da conexão. Os dados, claro, pararão de ser gravados no banco de dados.
As seguintes instruções são usadas para criar e configurar as filas:
sudo /usr/local/bin/rabbitmqadmin/rabbitmqadmin declare exchange --vhost=/ name=monitor.direct type=direct sudo /usr/local/bin/rabbitmqadmin/rabbitmqadmin declare queue --vhost=/ name=web_log durable=true
sudo /usr/local/bin/rabbitmqadmin/rabbitmqadmin --vhost="/" declare binding source="monitor.direct" destination_type="queue" destination="web_log" routing_key="site1.domain.ru"
sudo /usr/local/bin/rabbitmqadmin/rabbitmqadmin --vhost="/" declare binding source="monitor.direct" destination_type="queue" destination="web_log" routing_key="site2.domain.ru"Grafana. Painéis
Este componente é utilizado para visualizar dados de monitoramento. Para isso, é necessário instalar o plugin ClickHouse datasource for Grafana 4.6+. Tivemos que ajustá-lo um pouco para aumentar a eficiência do processamento de filtros SQL no painel.
Por exemplo, utilizamos variáveis e, se não estiverem definidas no campo do filtro, gostaríamos que ele não gerasse uma condição no WHERE do tipo ( uriStem = » AND uriStem != » ). Nesse caso, o ClickHouse lerá a coluna uriStem. No geral, experimentamos várias opções e, no final, ajustamos o plugin (macro $valueIfEmpty) para que, em caso de valor vazio, retornasse 1, sem mencionar a própria coluna.
E agora é possível usar uma consulta como esta para o gráfico
$columns(response, count(*) c) from $table where $adhoc
and $valueIfEmpty($fld_app_name, 1, fld_app_name = '$fld_app_name')
and $valueIfEmpty($fld_app_module, 1, fld_app_module = '$fld_app_module') and $valueIfEmpty($fld_server_name, 1, fld_server_name = '$fld_server_name') and $valueIfEmpty($uriStem, 1, uriStem like '%$uriStem%')
and $valueIfEmpty($clientRealIP, 1, clientRealIP = '$clientRealIP')que é convertido para este SQL (note que os campos vazios uriStem foram transformados em apenas 1)
SELECT
t,
groupArray((response, c)) AS groupArr
FROM (
SELECT
(intDiv(toUInt32(logdatetime), 60) * 60) * 1000 AS t, response,
count(*) AS c FROM default.log_web
WHERE (logdate >= toDate(1565061982)) AND (logdatetime >= toDateTime(1565061982)) AND 1 AND (fld_app_name = 'site1.domain.ru') AND (fld_app_module = 'web') AND 1 AND 1 AND 1
GROUP BY
t, response
ORDER BY
t ASC,
response ASC
)
GROUP BY t ORDER BY t ASCConclusão
O surgimento do banco de dados ClickHouse foi um evento marcante no mercado. Era difícil imaginar que, de forma absolutamente gratuita, nós teríamos em mãos uma poderosa e prática ferramenta para trabalhar com grandes volumes de dados. Sem dúvida, à medida que as necessidades aumentam (por exemplo, sharding e replicação em vários servidores), o esquema se tornará mais complexo. Mas pelas primeiras impressões, trabalhar com este banco de dados é muito agradável. É evidente que o produto foi feito "para as pessoas".
Comparado ao ElasticSearch, os custos de armazenamento e processamento de logs, segundo estimativas preliminares, são reduzidos de cinco a dez vezes. Em outras palavras, se para o atual volume de dados precisaríamos configurar um cluster de várias máquinas, ao usar o ClickHouse, um único servidor de baixo desempenho é suficiente. Sim, claro, o ElasticSearch também possui mecanismos de compressão de dados em disco e outras funcionalidades que permitem reduzir significativamente o consumo de recursos, mas em comparação com o ClickHouse, isso exigirá maiores gastos.
Sem quaisquer otimizações especiais da nossa parte, com as configurações padrão, o carregamento de dados e as consultas ao banco de dados funcionam com uma velocidade impressionante. Por enquanto, temos um volume moderado de dados (cerca de 200 milhões de registros), mas o servidor é fraco. Este ferramenta podemos usar futuramente para outros objetivos, não apenas para armazenamento de logs. Por exemplo, para análise holística, na área de segurança e aprendizado de máquina.
No final, um pouco sobre os prós e contras.
Desvantagens
- Carregamento de registros em grandes lotes. Isso, por um lado, é um recurso, mas é necessário utilizar componentes adicionais para bufferizar os registros. Essa tarefa nem sempre é simples, mas é solucionável. E gostaríamos de simplificar o esquema.
- Algumas funcionalidades exóticas ou novos recursos frequentemente falham em novas versões. Isso gera preocupações, diminuindo o desejo de atualizar para a nova versão. Por exemplo, o mecanismo de tabelas Kafka – um recurso muito útil que permite ler eventos diretamente do Kafka, sem a necessidade de implementar consumidores. Mas, com base na quantidade de problemas no GitHub, ainda estamos cautelosos em usar esse mecanismo em produção. No entanto, se não fizermos mudanças bruscas e utilizarmos a funcionalidade principal, ele opera de forma estável.
Prós
- Não trava.
- Baixa barreira de entrada.
- Código aberto.
- Gratuito.
- Escalabilidade adequada (sharding/reduplicação "fora da caixa").
- Está listado no registro de software russo recomendado pelo Ministério das Comunicações.
- A presença de suporte oficial do Yandex.
Fonte: habr.com
