Monitoring strong WWW - przesyłanie logów nginx do elasticsearcha

22/04/2017Administracja

Jak w bardzo łatwy sposób można przesłać access logi  serwera NGINX do elasticsearch w celu uzyskania naprawdę dobrego monitoringu. 

NGINX

Jest to jeden z najpopularniejszych serwerów HTTP. Nastawiony na szybkość w przetwarzaniu requestów zapewnia także loadbalancing i cachowanie. Jako jedyną jego wadę widzę to, że jego konfiguracja jest trochę trudniejsza niż np. Apacha, ale moim zdaniem daje za to dużo więcej możliwości.

Elasticsearch

To narzędzie do przeprowadzania wyszukiwań pełnotekstowych. Oprócz zastosowania do analizy tekstów czy wyszukiwania obiektów, z powodzeniem można zastosować je do analizy czy monitoringu. W połączeniu z Kibaną pozwala w prosty i szybki sposób stworzyć wizualizacje danych. 

Tyle tytułem wstępu. Przejdźmy do konfiguracji komponentów.

Konfiguracja NGINX

Koncepcja polega na tym, że NGINX będzie zapisywał log w postaci JSON-a, które póżniej za pomocą rsysloga zostaną przesłane do elasticsearcha.

Konfiguracja NGINX

Tu mamy bardzo prosto. Wystarczy, że w pliku /etc/nginx/nginx.config w sekcji http dodamy nowy log_formater w którym skleimy JSONa z interesujących nas wartości. Opcja escape powoduje, że NGINX będzie eskejpował wartości do formatu JSONa(znaki UTF-8 itp), ta opcja dostępna jest w NGINX od wersji 1.12.0

Przykładowy bardzo podstawowy log_formater może wyglądać tak:

  log_format json escape=json '{'
            '"time":"$time_iso8601",'
            '"cfclIp":"$http_cf_connecting_ip",'
            '"clGA":"$cookie__ga",'
            '"clIp":"$remote_addr",'
            '"clPort":"$remote_port",'
            '"clUser":"$remote_user"'
'}';

Teraz wystarczy użyć przygotowanego przez nas formatera w dowolnym serwerze.

    access_log /var/log/nginx/json-logs.access.log json;

Reload nginx i mam już plik który chcemy przesłać do elasticsearcha

Elasticsearcha

Instalacja

Instalacja polega na ściągnięciu 2 debów ze strony elastic.co. Oprócz elasticsearcha instalujemy także kibane, jest to front, który w przystępny sposób wyświetla dane z elasticsearch. Sposób instalacji został przedstawiony poniżej. Drobna uwaga - elasticsearch do działania wymaga Javy w wersji 8.

wget https://artifacts.elastic.co/downloads/kibana/kibana-5.3.0-amd64.deb
dpkg -i kibana-5.3.0-amd64.deb
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.3.0.deb
dpkg -i elasticsearch-5.3.0.deb

Jeśli wszystko przebiegnie bez zarzutu to pod adresem http://localhost:9200 powinniśmy mieć dostępnego elasticsearch, a pod http://localhost:5601 kibane.

Konfiguracja

Zanim zaczniemy wysyłać dane do elastisearcha warto go na nie przygotować. Opłaca się stworzyć template dla indeksu na jakim ma działać Elasticsearch. W takim ideksie możemy ustawić parametry dla indeksu oraz, co jest moim zdaniem najważniejsze, zdefiniować typy dla pól. Do dodania templatu dla indeksu można użyć narzędzia Dev Tool z Kibany. Podajemy w nim to, co poniżej

PUT _templates/access-logs
{
  "template": "access-logs-*",
  "settings": {
    "number_of_shards": 1
  },
  "mappings": {
      "access-log": {
        "properties": {
          "cfclIp": {
            "type": "ip"
          },
          "clUser": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "clGA": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
        
          "clIp": {
            "type": "ip"
          },
          "clPort": {
            "type": "integer"
          }
         }
     }
   }
}

Od teraz indeksy, które można dopasować do wyrażenia access-logs-* będą miały własności zdefiniowane przez ten template. Należy pamietać, że template działa tylko dla nowo tworzonych indeksów. Tworzenie indeksów w taki sposób pozwali nam zarządzać retencją danych. Będziemy mogli utworzyć sobie indeksy z logami z danego dnia, a nie jeden ogromny. Dzięki czemu jeśli będzie nam brakowało zasobów możemy usuwać indeksy starsze niż X dni

Konfiguracja rsyslog

Rsyslog posiada wiele możliwości przesyłania logów do różny usług w tym także do elasticsearch. W tym przypadku należy doinstalować moduł omelastisearch dla dystrybucji debiano podobnych wystarczy wykonać polecenie

sudo apt-get install rsyslog-elasticsearch

Można się zastanowić czy rozwiązanie w którym nginx musi pisać logi do pliku, a pózniej rsyslog je czytać nie jest dodanie dodatkowego narzutu, ale takie podejście ma duży plus. Rsyslog potrafi zapisać miejsce, gdzie zakończył czytanie pliku, dzięki czemu nie tracimy i też nie duplikujemy danych. Konfiguracja, której użyłem znajduje się poniżej. Dodałem do niej komentarze objaśniające ważniejsze elementy.


module(load="omelasticsearch")
module(load="imfile")

input(type="imfile"
    File="/var/log/nginx/json-logs.access.log"
    Tag="nginx-json"
    Ruleset="nginx-json"
    PersistStateInterval="100"
    stateFile="nginx-json"
)
# template dla indexu
template(name="access-logs-index"
  type="list") {
    constant(value="access-logs-")
    property(name="timereported" dateFormat="rfc3339" position.from="1" position.to="4")
    constant(value=".")
    property(name="timereported" dateFormat="rfc3339" position.from="6" position.to="7")
    constant(value=".")
    property(name="timereported" dateFormat="rfc3339" position.from="9" position.to="10")
}

template(name="lines" type="string"
    string="%msg%"
)

ruleset(name="nginx-json") {
    action(
        type="omelasticsearch"
        server="elasticsearch-server"
        searchIndex="access-logs-index" # template z nazwą indeksu
        searchType="access-log"
        template="lines" # template z JSONem wejściowym
        dynSearchIndex="on" # włączenie dynamicznego indeksu
        bulkmode="on" # wysyłanie danych w batchu
        errorFile="/var/log/rsyslog-error.log"
        # dodatkowa konifguracja dla rsysloga żeby niezgubic danych
        queue.workerThreads="2"
        action.resumeRetryCount="-1"
        queue.spoolDirectory="/var/spool/rsyslog"
        queue.filename="nginx-json_log"
        queue.saveonshutdown="on"
        queue.type="LinkedList"
        queue.size="10000"
    )
}

 

Demo time

 

Od teraz jak ktoś wejdzie na naszą stronę w kibanie powinniśmy zobaczyć kolejne wpisy z access logów.

Można też utworzyć dashbordy, które w sposób graficzny przedstawi nasze dane.

 


Powiązane posty