Monitoring strong WWW - przesyłanie logów nginx do elasticsearcha
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.