Logowanie w Kubernetes: jak zbierać, przechowywać, analizować i przetwarzać logi

Omówimy podstawy logowania w Docker i Kubernetes, a następnie zaprezentujemy dwa narzędzia, które można śmiało stosować w produkcji: Grafana Loki i stos EFK (Elasticsearch + Fluent Bit + Kibana).

Materiał artykułu — podsumowanie z otwartej lekcji szkoły „Słörm”. Jeśli jest chęć i tym bardziej konieczność produkcyjna, można przejść pełne szkolenie — zapisz się na kurs dotyczący monitorowania i logowania infrastruktury w Kubernetes.

Logowanie w Kubernetes: jak zbierać, przechowywać, analizować i przetwarzać logi

Logowanie w Dockerze

Na poziomie Kubernetes aplikacje uruchamiane są w podach, ale na niższym poziomie zwykle działają w Dockerze. Dlatego trzeba skonfigurować logowanie w taki sposób, aby zbierać logi z kontenerów. Kontenery uruchamia Docker — oznacza to, że należy zrozumieć, jak logowanie działa na poziomie Dockera.

Mam nadzieję, że każdy czytelnik wie: logi aplikacji należy pisać do stdout/stderr, a nie do wewnątrz kontenera. Logi agreguje Docker Daemon, a on pracuje tylko z tymi logami, które są wysyłane do stdout/stderr. Poza tym zapisywanie logów wewnątrz kontenera rodzi problemy: kontener puchnie od rosnącego logu (ponieważ prawdopodobnie nie ma w kontenerze żadnego Logrotate), a Docker Daemon nie ma pojęcia o tym logu.

Docker ma kilka sterowników logów lub wtyczek do zbierania logów kontenerów. W bezpłatnej wersji Docker Community Edition (CE) jest mniej sterowników logów niż w komercyjnej wersji Docker Enterprise Edition (EE).

Logowanie w Kubernetes: jak zbierać, przechowywać, analizować i przetwarzać logi

Docker EE nie używałem w praktyce: w Southbridge staramy się trzymać rozwiązań typu Open Source, a klienci nie potrzebują wielu dodatkowych możliwości, które oferuje Docker EE.

Sterowniki logów w Docker CE:

local — zapisywanie logów w wewnętrznych plikach Docker Daemon;
json-file — tworzenie logu json w folderze każdego kontenera;
journald — wysyłanie logów do journald.

Ustawienia logowania w Dockerze znajdują się w pliku daemon.json.

W polu “log-driver” wskazuje się wtyczkę, a w polu “log-opts” — jej ustawienia. W powyższym przykładzie wskazana jest wtyczka “json-file”, ograniczenie rozmiaru logu wynosi “max-size”: “10m”; ograniczenie liczby plików (ustawienia rotacji) wynosi “max-file”: “3”; a także wartości, które będą dołączane do logów.

Logowanie w Kubernetes: jak zbierać, przechowywać, analizować i przetwarzać logi

Niektóre ustawienia sterownika logów można skonfigurować za pomocą narzędzia wiersza poleceń. To wygodne, jeśli trzeba uruchomić osobny kontener z innym sterownikiem logów.

Oto jak wygląda schemat logowania w Dockerze:

Logowanie w Kubernetes: jak zbierać, przechowywać, analizować i przetwarzać logi

Jak działa schemat: log-driver, na przykład json-file, tworzy pliki. Zbieracze logów (Rsyslog, Fluentd, Logagent i inne) zbierają te pliki i przesyłają je do przechowywania w Elastic, Sematext lub innych magazynach.

Cechy logowania w Kubernetes

Uproszczony schemat logowania w Kubernetes wygląda tak: jest pod, w którym uruchomiono kontener, kontener wysyła logi do stdout/stderr. Następnie Docker tworzy plik i zapisuje logi, które mogą być rotowane.

Logowanie w Kubernetes: jak zbierać, przechowywać, analizować i przetwarzać logi

Przyjrzyjmy się cechom logowania w Kubernetes.

Zachowywanie logów między wdrożeniami. To jest warunek konieczny do prawidłowej konfiguracji logowania. Jeśli nie zachowasz logów między wdrożeniami, to przy wprowadzeniu nowej wersji aplikacji logi z poprzedniej będą nadpisywane, a ponowne uruchomienie kontenera również grozi utratą logów. Kubernetes ma flagę —previous, która pozwala zobaczyć logi aplikacji przed ostatnim ponownym uruchomieniem Pod, ale nie dalej.

Agregowanie logów ze wszystkich instancji. Jeśli mikroserwisy są hostowane w chmurze, to za kontrolę systemu odpowiada dostawca chmurowy. Jeśli mikroserwisy działają na własnym sprzęcie, to oprócz logów z kontenerów należy zbierać również logi systemowe.

Dawniej nie było wygodnych narzędzi do zbierania logów zarówno z systemu, jak i z mikroserwisów. Zazwyczaj jedno narzędzie zbierało logi systemowe (na przykład Rsyslog), a drugie — logi z Dockera (na przykład journal-bit z konfiguracją log-drivera Dockera na journald). Próbowano używać journal-bit — zbierać logi zarówno z kontenerów (w log-driverze Dockera wskazać, że logi mają być zapisywane w journald), jak i z systemu (w CentOS 7 już istnieje systemd i journald). Rozwiązanie działa, ale nie jest idealne. Jeśli logów jest dużo, journal-bit zaczyna lagować, a wiadomości są tracone.

Eksperymenty trwały — i znaleziono inny sposób. W CentOS 7 główne logi systemowe (messages, audit, secure) są duplikowane w var-log w postaci plików. W Dockerze również można skonfigurować zapis logów do plików json. W związku z tym te pliki z CentOS 7 i Dockera można zbierać razem.

Z czasem stało się popularne rozwiązanie ELK Stack. To kombinacja kilku narzędzi: Elasticsearch, Logstash i Kibana.

Elasticsearch przechowuje logi z kontenerów, Logstash zbiera logi z instancji, Kibana pozwala przetwarzać otrzymane logi, tworzyć na ich podstawie wykresy. Przez pewien czas aktywnie używano ELK Stack, ale moim zdaniem jego czas mija. Później opowiem, dlaczego.

Dodawanie metadanych. Pody, aplikacje, kontenery mogą być uruchamiane wszędzie. Co więcej, jedna aplikacja może mieć wiele instancji. Logi są zapisane w jednym formacie, a my musimy zrozumieć, która to dokładnie replika, który Pod je zapisuje i w jakim namespace się znajduje. Dlatego logom należy dodawać metadane.

Parsowanie logów. Zabawne, ale koszty utrzymania systemu logowania i monitorowania mogą przewyższyć wydatki na główną aplikację. Kiedy dostajecie dziesiątki i setki tysięcy logów na sekundę, wydaje się to być logiczne, ale trzeba znać granice. Jednym ze sposobów znalezienia tej granicy jest parsowanie logów.

Zazwyczaj nie ma potrzeby zbierać i przechowywać wszystkich logów, trzeba wysyłać do przechowania tylko część – na przykład logi o statusie „warning” lub „error”. Jeśli mówimy o logach nginx lub kontrolerów ingress, to można przechowywać tylko te, których status różni się od 200. Jednak to nie jest uniwersalna rada: jeśli budujecie w jakiś sposób analitykę na podstawie logów Nginx, to zdecydowanie warto je zbierać.

Nie zaleca się bezmyślnego filtrowania logów, ponieważ przefiltrowanych danych może brakować do normalnej analizy. Z drugiej strony, być może analitykę warto prowadzić nie na poziomie logowania, a na poziomie zbierania metryk. Wtedy nie trzeba będzie przechowywać setek tysięcy linii z kodem 200. Jednym z podejść jest uzyskiwanie informacji o ruchu i błędach z metryk kontrolerów ingress.

Ogólnie, trzeba tutaj dobrze pomyśleć: co chcecie przechowywać i jak długo, ponieważ w przeciwnym razie pojawi się sytuacja, w której system logowania zajmie więcej zasobów niż główny projekt.

Jak dotąd nie ma standardowego rozwiązania dla logowania. W przeciwieństwie do monitorowania, gdzie istnieje jedno najbardziej rozpowszechnione rozwiązanie Prometheus, w logowaniu nie ma standardu.

W ramach tej lekcji rozważymy dwa narzędzia: jedno popularne, a drugie — zdobywające popularność. Oprócz nich są też inne, ale w tym artykule ich nie omówimy.

Biorąc pod uwagę wszystkie powyższe aspekty, logowanie w Kubernetes można teraz przedstawić na takiej schemacie:

Logowanie w Kubernetes: jak zbierać, przechowywać, analizować i przetwarzać logi

Pozostają logi kontenera, rotacja, ale pojawia się agent zbierający, który zbiera logi i wysyła je do przechowania (na schemacie — do Logging Backend). Agent działa na każdej nodzie i zazwyczaj jest uruchamiany w Kubernetes.

Teraz przyjrzymy się narzędziom do logowania.

Grafana Loki

Grafana Loki pojawił się niedawno, ale już stał się dość znany. Jego zalety: łatwa instalacja, niewielkie zużycie zasobów, nie wymaga instalacji Elasticsearch, ponieważ przechowuje dane w TSDB (baza danych szeregów czasowych). W poprzednim artykule pisałem, że tego typu baza przechowuje dane Prometheus i to jedna z licznych podobieństw obu produktów. Deweloperzy twierdzą nawet, że Loki to „Prometheus dla świata logowania”.

Małe odskoczenie do TSDB dla tych, którzy nie czytali poprzedni artykuł: TSDB doskonale radzi sobie z przechowywaniem dużej ilości danych, szeregów czasowych, ale nie jest przeznaczona do długoterminowego przechowywania. Jeśli z jakiegoś powodu musisz przechowywać logi dłużej niż dwa tygodnie, lepiej skonfigurować ich transfer do innej bazy danych.

Kolejną zaletą Loki jest to, że do wizualizacji danych używa Grafany. Bardzo wygodne: w Grafanie oglądamy dane dotyczące monitorowania, a tam, podłączając Loki, oglądamy logi. Na podstawie logów można tworzyć wykresy.

Architektura Loki wygląda mniej więcej tak:

Logowanie w Kubernetes: jak zbierać, przechowywać, analizować i przetwarzać logi

Za pomocą DaemonSet na wszystkich serwerach klastra uruchamiany jest agent — Promtail lub Fluent Bit. Agent zbiera logi. Loki je pobiera i przechowuje w TSDB. Do logów od razu dodawane są metadane, co jest wygodne: można filtrować według Pods, namespaces, nazw kontenerów, a nawet etykiet.

Instrukcja instalacji Loki

Loki działa w znanym interfejsie Grafany. Loki ma nawet własny język zapytań, nazywa się LogQL — z nazwy i składni przypomina PromQL w Prometheus. W interfejsie Loki są podpowiedzi dotyczące zapytań, dlatego nie trzeba ich znać na pamięć.

Dokumentacja do języka LogQL

Logowanie w Kubernetes: jak zbierać, przechowywać, analizować i przetwarzać logi
Loki w interfejsie Grafany

Używając filtrów, w Loki można znaleźć kody ("400", "404" i inne); przeglądać logi z całego węzła; filtrować wszystkie logi zawierające słowo „error”. Jeśli klikniesz na log, rozwinie się karta z całymi informacjami o zdarzeniu.

W Loki jest wystarczająco dużo narzędzi, które pozwalają wydobywać potrzebne logi, chociaż szczerze mówiąc, technicznie mogło by ich być więcej. Obecnie Loki aktywnie się rozwija i zyskuje na popularności.

Elastic + Fluent Bit + Kibana (Stos EFK)

Stos EFK to bardziej klasyczne, a jednocześnie nie mniej popularne narzędzie do logowania.

Na początku artykułu wspomniano o ELK (Elasticsearch + Logstash + Kibana), ale ten stos się zestarzał z powodu niewystarczającej wydajności i jednocześnie dużego zużycia zasobów przez Logstash. Zamiast niego zaczęto używać bardziej lekkiego i wydajnego Fluentd, a po pewnym czasie do pomocy dołączył Fluent Bit — jeszcze bardziej lekki i jeszcze bardziej wydajny agent zbierający.

Jeśli wierzyć deweloperom, to Fluent Bit jest ponad 100 razy bardziej wydajny niż Fluentd: „tam, gdzie Fluentd zużywa 20 MB RAM, Fluent Bit będzie zużywał 150 kB” — to dosłowny cytat z dokumentacji. Patrząc na to, Fluent Bit zaczęto częściej stosować.

Fluent Bit ma mniej możliwości niż Fluentd, ale zaspokaja podstawowe potrzeby, więc głównie korzystamy z Fluent Bit.

Schemat działania stosu EFK: agenta zbiera logi z wszystkich podów (zazwyczaj jest to DaemonSet uruchomiony na wszystkich serwerach klastra) i przesyła do magazynu (Elasticsearch, PostgreSQL lub Kafka). Kibana łączy się z magazynem i pobiera stamtąd wszystkie potrzebne informacje.

Logowanie w Kubernetes: jak zbierać, przechowywać, analizować i przetwarzać logi

Kibana prezentuje informacje w wygodnym interfejsie internetowym. Są wykresy, filtry i wiele więcej.

Logowanie w Kubernetes: jak zbierać, przechowywać, analizować i przetwarzać logi

Z logów można tworzyć całe pulpitowe tablice.

Logowanie w Kubernetes: jak zbierać, przechowywać, analizować i przetwarzać logi

Możliwości Fluent Bit

Ponieważ o Fluent Bit z reguły słyszało się mniej niż o Logstash, przyjrzyjmy się mu bliżej. Fluent Bit można logicznie podzielić na 6 modułów, a do niektórych modułów można dodać wtyczki, które rozszerzają możliwości Fluent Bit.

Logowanie w Kubernetes: jak zbierać, przechowywać, analizować i przetwarzać logi

Moduł Input zbiera logi z plików, usług systemd, a nawet z gniazd tcp (należy tylko wskazać punkt końcowy, a Fluent Bit zacznie tam ściągać). Te możliwości są wystarczające, aby zbierać logi zarówno z systemu, jak i z kontenerów.

W produkcji najczęściej używamy wtyczek tail (można go skierować na folder z logami) i systemd (można mu powiedzieć, z jakich usług zbierać logi).

Moduł Parser przyjmuje logi w jednolitym formacie. Domyślnie logi Nginx są reprezentowane jako ciąg. Za pomocą wtyczki można przekształcić ten ciąg w JSON: określić pola i ich wartości. Z JSON-em znacznie łatwiej się pracuje niż z logiem w postaci ciągu, ponieważ oferuje bardziej elastyczne możliwości sortowania.

Moduł Filter. Na tym poziomie odrzucane są niepotrzebne logi. Na przykład do przechowywania wysyłane są tylko logi ze znakiem „warning” lub z określonymi etykietami. Wybrane logi trafiają do bufora.

Moduł Buffer. Fluent Bit ma dwa rodzaje buforów: bufor pamięci i bufor na dysku. Bufor to tymczasowe miejsce przechowywania logów, potrzebne w przypadku błędów lub awarii. Każdy chce oszczędzać pamięć RAM, dlatego zwykle wybiera się bufor dyskowy. Należy jednak pamiętać, że przed zapisaniem na dysku logi są i tak ładowane do pamięci.

Moduł Routing/Output zawiera zasady i adresy wysyłania logów. Jak już wspomniano, logi można wysyłać do Elasticsearch, PostgreSQL lub na przykład do Kafka.

Ciekawe, że z Fluent Bit logi można wysyłać do Fluentd. Ponieważ pierwszy jest lżejszy i mniej funkcjonalny, można przez niego zbierać logi i wysyłać je do Fluentd, a następnie tam, za pomocą dodatkowych wtyczek, je przetwarzać i wysyłać do magazynów.

Jeśli planujesz korzystać z Elasticsearch...

Na koniec dwa wskazówki dla tych, którzy planują używać Elasticsearch jako magazynu logów w produkcji.

  1. Skonfiguruj powiadomienia za pomocą ElastAlert. Ten program wyodrębnia z ogólnego strumienia logów istotne wiadomości i tworzy powiadomienia do e-maila lub innego kanału. Niestety, niedawno pojawiła się smutna wiadomość, że projekt może wkrótce przestać istnieć.
  2. Rotuj logi za pomocą aplikacji Curator lub korzystając z API Elasticsearch. Sam Elastic obecnie podejmuje znaczące kroki w zarządzaniu cyklem życia indeksów bez stosowania zewnętrznych narzędzi. Generalnie nie ma sensu przechowywać logów przez długi czas: trudno wyobrazić sobie, aby jakikolwiek log był przydatny po dwóch tygodniach — jeśli jest naprawdę krytyczny, na pewno zostanie przetworzony w tym czasie. W ostateczności stare logi można zarchiwizować i przesłać gdzie indziej na długoterminowe przechowywanie. Słyszałem o szczególnych logach, które według przepisów prawa muszą być przechowywane przez 5 lat. Osobiście z takim się nie spotkałem, ale nie potrafiłbym porównać takich informacji z zwykłymi logami, a być może nawet przechowywałbym je oddzielnie.

Ciąg dalszy nastąpi…

Autor: Marcel Ibraev, certyfikowany administrator Kubernetes, inżynier praktykujący w firmie Southbridge, prelegent i twórca kursów Slurm.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster