Logstash no OpenShift
ATUALIZAÇÃO: este artigo se refere à nossa oferta hospedada do Elasticsearch com um nome mais antigo: Found. Observe que o Found agora é conhecido como Elastic Cloud.
Comece a analisar seus logs no OpenShift. Embora o OpenShift permita acompanhar os logs de seus aplicativos, a trindade Elasticsearch/Logstash/Kibana oferece uma cadeia de ferramentas muito flexível e poderosa para visualizar e analisar esses logs. Este artigo explica como criar um cartucho do Logstash no OpenShift. O cartucho alimenta seus logs no Elasticsearch, onde você pode usar o mecanismo de visualização do Kibana para acompanhar tendências, detectar anomalias e inspecionar incidentes em seu ambiente.
Introdução
OpenShift é a iniciativa PaaS da RedHat, com uma oferta pública e uma versão empresarial que permite que você leve a abordagem de plataforma como serviço, cada vez mais popular, para seus próprios data centers e sua nuvem privada.
.Logstash é uma ferramenta para gerenciar eventos e logs. O Logstash combinado com Elasticsearch e Kibana oferece uma cadeia de ferramentas muito poderosa para buscar, analisar e visualizar seus logs. Essa trindade é popularmente chamada de ELK-stack.
.Embora o OpenShift permita facilmente cauda os logs de todas as suas apps, o cauda não é tão poderoso quanto a ELK-stack. No entanto, por design, aspectos específicos da aplicação, como o logging, são deixados para o que o OpenShift chama de cartridges. Um cartridge fornece uma funcionalidade muito específica, e você os mistura nos gears das aplicações que implanta. Um gear é um container com um determinado propósito, e sua aplicação pode ser composta por múltiplos gears.
.Neste artigo, criaremos um Logstash-cartridge simples, que você pode facilmente integrar à sua aplicação para obter insights sobre seus logs.
.Premissas e objetivos
O Logstash tem muitas saídas, entre elas Elasticsearch, Graphite e S3, para citar algumas. O Elasticsearch é uma das saídas mais utilizadas. Configuraremos nossos Logstashes para enviar logs para o Elasticsearch, mas a abordagem pode ser facilmente generalizada para outras saídas também. Você pode até enviar para um Logstash upstream, para distinguir entre o envio de log e o processamento de log.
.Se você precisar de um cluster Elasticsearch hospedado, experimente o Found.
.Pressupomos alguma familiaridade com o OpenShift. Se você não tiver experiência com o OpenShift, confira o guia de introdução.
.O objetivo é ter um cartucho que você possa adicionar à sua aplicação e, em seguida, observar os logs aparecerem em um cluster do Elasticsearch. Depois, você pode usar o Kibana para visualizar e analisar seus logs, inspecionar incidentes, acompanhar tendências e detectar anomalias em seu ambiente.
.Configuração e Logs do OpenShift
Os cartridges são normalmente personalizados com configurações específicas da aplicação (como credenciais de banco de dados) por meio de variáveis de ambiente. Uma dessas variáveis, $OPENSHIFT_LOG_DIR, indica onde um cartridge deve salvar o log.
.Os Cartridges podem executar qualquer coisa, portanto não há um formato de logging padrão, ou mesmo um formato de carimbo de data/hora padrão. Este é um problema universal para logging e é algo que o Logstash lida muito bem. O Logstash tem muitas entradas e filtros diferentes. No exemplo a seguir, configuraremos o Logstash com entradas file, alguns filtros para processar logs do Apache, carimbos de data/hora e IPs, finalmente gerando a saída dos logs para o Elasticsearch. O Logstash pode fazer muito mais, e sua documentação é boa.
.Os formatos de log são altamente específicos da aplicação, portanto, você precisará configurar o processamento do Logstash de acordo. Para ter um exemplo real, veremos uma aplicação Python simples que produz logs de acesso:
.# Crie uma aplicação. Qualquer coisa que produza logs. Com este app, teremos um servidor Web em execução que produz logs de acesso, que é tudo o que precisamos. $ rhc app create my-app python-2.6 Opções de aplicação ------------------- Domínio: espaço de nome Cartuchos: python-2.6 Tamanho da engrenagem: padrão Redimensionamento: não Criando aplicativo 'my-app' ... concluído [ ... ] Seu aplicativo 'my-app' já está disponível. URL: http://my-app-namespace.rhcloud.com/ [ ... ] # Configure variáveis de ambiente, como hostname do cluster e opções de autenticação $ rhc set-env --app my-app --env "OPENSHIFT_LOGSTASH_ES_HOST=dabadeee123-us-east-1.foundcluster.com" Definição de variável(is) de ambiente... concluída $ rhc set-env --app my-app --env "OPENSHIFT_LOGSTASH_ES_USER=readwrite" Definição de variável(is) de ambiente... concluída $ rhc set-env --app my-app --env "OPENSHIFT_LOGSTASH_ES_PASSWORD=secret" Definição de variável(is) de ambiente... concluída # Por fim, adicione o cartucho. $ rhc cartridge add -a my-app https://cartreflect-claytondev.rhcloud.com/github/foundit/openshift-logstash-cartridge O cartridge 'https://cartreflect-claytondev.rhcloud.com/github/foundit/openshift-logstash-cartridge' será baixado e instalado Adicionando https://cartreflect-claytondev.rhcloud.com/github/foundit/openshift-logstash-cartridge para o aplicativo 'my-app' ... concluído found-logstash-1.4.1 (Logstash 1.4.1) ------------------------------------- De: https://cartreflect-claytondev.rhcloud.com/github/foundit/openshift-logstash-cartridge Gears: Localizado com python-2.6
Após algum tempo, os logs devem começar a aparecer no cluster do Elasticsearch configurado. Se você visitar sua aplicação Web, logs de acesso semelhantes aos seguintes deverão aparecer em python.log:
.1.2.3.4 - - [10/Jun/2014:10:31:17 -0400] "GET / HTTP/1.1" 200 39617 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36"
Eles serão então capturados pelo Logstash e indexados no Elasticsearch desta forma:
.{
"_type": "logs",
"_source": {
"tags": ["app-name", "gear-name", "namespace"],
"@timestamp": "2014-06-10T14:31:18.907Z",
"host": "ex-std-node7.prod.rhcloud.com",
"path": "/var/lib/openshift/530001200012cd3502000122/app-root/logs/python.log",
"message": "1.2.3.4 - - [10/Jun/2014:10:31:17 -0400] \"GET / HTTP/1.1\" 200 39617 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36\"",
"@version": "1"
},
"_index": "logstash-2014.06.10",
"_id": "dCfV_YUjSwOlISJWQMafaw"
}
Embora este seja um bom começo, as informações mais interessantes estão agrupadas na string 1.2.3.4 - - [10/Jun/2014:10:31:17 -0400] "GET / HTTP/1.1\" 200 39617 \"-\" \"Mozilla/5.0 [...]".
.Esta string segue o formato Apache Combined, e o Logstash tem um padrão predefinido para correspondê-la. Geralmente, se você estiver usando algum software bem conhecido, é provável que encontre padrões do Logstash para ele. Dê uma olhada no diretório patterns do Logstash. O recurso Discoverdo Grok Debugger também pode ser útil. Se você colar a mensagem de log acima nele, ele terá %{COMBINEDAPACHELOG} como saída. Na próxima seção, veremos como usá-lo.
.Personalizando o Cartridge
O cartridge base, disponível no GitHub (foundit/openshift-logstash-cartridge), tem uma configuração muito simples que produz o log acima.
.Para configurar o Logstash para processar corretamente o log e extrair os dados, precisamos alterar um pouco a configuração. Primeiro, diremos que o arquivo python.logé do tipo apache e, em seguida, garantiremos que filtremos adequadamente quaisquer logs do tipo apache posteriormente.
.Queremos que a seção de entrada e filtro da configuração do Logstash seja semelhante ao seguinte. Veja o logstash.conf.erb completo em GitHub. Ologstash.conf.erb é o modelo usado para gerar o arquivo de configuração do Logstash, interpolando variáveis de ambiente como URLs e informações de autenticação.
.entrada {
# Tudo o que for registrado, exceto python.log
arquivo {
path => "<%= ENV['OPENSHIFT_LOG_DIR'] %>*.log"
# Adicione alguns openshift-metadata para fins de filtragem.
tags => ["<%= ENV['OPENSHIFT_APP_NAME'] %>", "<%= ENV['OPENSHIFT_GEAR_NAME'] %>", "<%= ENV['OPENSHIFT_NAMESPACE'] %>"]
exclude => "python.log"
}
# Sabemos que o python.log contém logs de acesso do Apache.
arquivo {
path => "<%= ENV['OPENSHIFT_LOG_DIR'] %>python.log"
tags => ["<%= ENV['OPENSHIFT_APP_NAME'] %>", "<%= ENV['OPENSHIFT_GEAR_NAME'] %>", "<%= ENV['OPENSHIFT_NAMESPACE'] %>"]
type => "apache"
}
}
filter {
if [type] == "apache" {
# Isso extrairá os diferentes metadados na mensagem de log, como registro de data/hora, IP, método etc.
Grok {
match => ["message", "%{COMBINEDAPACHELOG}"]
}
# Converter o formato de hora em algo adequado.
data {
match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
}
# Anotar log com informações geográficas aproximadas.
geoip {
source => "clientip"
}
}
}
Com essa configuração, o Logstash produzirá documentos como o seguinte:
.{
"_type": "apache",
"_source": {
"ident": "-",
"tags": ["app-name", "gearname", "espaço de nome"],
"type": "apache",
"@timestamp": "2014-06-10T15:19:31.000Z",
"request": "/",
"auth": "-",
"resposta": "200",
"referrer": "\"-\"",
"bytes": "39617",
"host": "ex-std-node7.prod.rhcloud.com",
"verb": "GET",
"agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) [...]",
"timestamp": "10/Jun/2014:11:19:31 -0400",
"path": "/var/lib/openshift/539709b8e0b8cd3502000122/app-root/logs/python.log",
"message": "1.2.3.4 - - [10/Jun/2014:11:19:31 -0400] \"GET / HTTP/1.1\" 200 39617 [...]",
"@version": "1",
"clientip": "1.2.3.4",
"httpversion": "1.1",
"geoip": {
"region_name": "16",
"ip": "1.2.3.4",
"continent_code": "EU",
"country_name": "Norway",
"city_name": "Trondheim",
"timezone": "Europe/Oslo",
"longitude": 10,416699999999992,
"country_code3": "NOR",
"country_code2": "NO",
"location": [
10,416699999999992,
63,41669999999999
],
"latitude": 63,41669999999999,
"real_region_name": "Sor-Trondelag"
}
},
"_index": "logstash-2014.06.10",
"_id": "Z1N65K5-QTOwZ9z3jPgEUw"
}
Podemos fazer muito mais com este documento. Podemos dividir os logs de acesso com base na origem do usuário, no que ele visita, encontrar facilmente solicitações problemáticas e assim por diante. A figura abaixo mostra um exemplo de um dashboard do Kibana que usa os dados acima.
Para personalizar o cartridge, basta fazer um fork do repositório e editar o conf/logstash.conf.erb com a configuração do Logstash desejada.
.Em seguida, personalize a URL ao adicionar seu cartridge, ou seja, altere foundit/openshift-logstash-cartridge para your-organization/repository-name.
.$ rhc cartridge add -a my-app https://cartreflect-claytondev.rhcloud.com/github/your-organization/your-repo
Por padrão, será usada a branch master. Você também pode passar a opção ` ?commit=branch-or-commit-idna URL, por exemplo: https://cartreflect-claytondev.rhcloud.com/github/foundit/openshift-logstash-cartridge?commit=python-sample?commit=python-sample`.
.Para obter mais informações sobre a personalização de cartridges e o uso de cartridges que não estão disponíveis publicamente, consulte o guia do OpenShift sobre como os cartridges são baixados.
.Mapeamentos compatíveis com logs
Como vimos, o Logstash cuida do envio de logs para o Elasticsearch. Ainda precisamos dizer ao Elasticsearch como tratar esses logs. Precisamos configurar os mapeamentos para os índices resultantes. (Veja também: Uma introdução ao mapeamento do Elasticsearch e Um fluxo de trabalho de exploração de dados para mapeamentos)
.Normalmente, o Logstash enviará logs para o índice logstash-YYYY-MM-DD, onde YYYY-MM-DD é a data do log. Isso permite que você limite as buscas a intervalos de datas específicos e arquive ou exclua logs antigos.
.Para configurar nosso mapeamento de log, precisamos definir um modelo de índice, que define o mapeamento para todos os índices cujo nome corresponda a logstash-*.
.O seguinte é um mapeamento apropriado para os logs produzidos acima. Os campos de string não são analisados por padrão, exceto pelo campo message, a geoip-location é configurada para ser do tipo geo_point, clientip como um ip, etc.
.{
"template": "logstash-*",
"settings": {
"index.refresh_interval": "5s"
},
"mappings": {
"_default_": {
"_all": {
"enabled": true
},
"dynamic_templates": [
{
"string_fields": {
"match": "*",
"match_mapping_type": "string",
"mapeamento": {
"type": "string",
"index": "not_analyzed"
}
}
}
],
"properties": {
"geoip": {
"properties": {
"location": {
"type": "geo_point"
}
}
},
"clientip": {
"type": "ip"
},
"bytes": {
"type": "long"
},
"message" : {
"type": "string",
"index": "analyzed",
"omit_norms": true
}
}
}
}
}
Para aplicar o modelo, envie uma solicitação PUTpara /_template/logstash com o corpo JSON:
.$ curl https://user:pass@cluster-id.foundcluster.com:9243/_template/logstash -XPUT -d @index-template.json
{"acknowledged":true}
Em seguida, o Elasticsearch usará as configurações e os mapeamentos especificados no modelo de índice sempre que criar um novo logstash-index.
.Resumo
Agora temos um cartridge que pode servir como base para cartridges do Logstash personalizados com uma configuração mais específica para a aplicação. Colocar seus logs em um cluster do Elasticsearch para buscas e analítica incríveis agora é apenas uma questão de adicionar um cartridge do OpenStack.
.