Produto

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. Using Kibana to analyze access logs

.

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.

.