Sii Polska

SII UKRAINE

SII SWEDEN

  • Szkolenia
  • Kariera
Dołącz do nas Kontakt
Wstecz

Sii Polska

SII UKRAINE

SII SWEDEN

Wstecz
Wprowadzenie do FluentBit

Obecne systemy chmurowe zmagają się z coraz bardziej rosnącą ilością danych generowanych przez różnorodne serwisy. Skuteczne zarządzanie i analiza logów stają się kluczowymi aspektami utrzymania stabilności i efektywności systemów IT. W tym kontekście narzędzia do zbierania, przetwarzania i analizy danych zdecydowanie odgrywają istotną rolę. Jednym z nich jest Fluent Bit.

Fluent Bit pozwala na gromadzenie logów z różnych źródeł, ich przetwarzanie, filtrowanie oraz przesyłanie dalej do różnych miejsc docelowych. W niniejszym artykule zaprezentuję podstawowe funkcje Fluent Bita. Odczytam logi z przykładowego serwisu znajdującego się na klastrze kubernetesowym, przefiltruję logi w zależności od ich źródła pochodzenia i na koniec, prześlę je dalej do innych serwisów, aby tam mogły zostać poddane analizie.

Przygotowanie klastra

Aby pokazać podstawowe możliwości Fluent Bita, potrzebujemy lokalnego klastra kubernetesowego. Skorzystamy z Kinda. Do tego skomunikujemy się z klastrem za pomocą kubectl. Na koniec zainstalujemy Helma, aby w łatwy sposób dodać Fluent Bita do naszego klastra.

Instalacja Fluent Bita

Gdy nasz lokalny klaster jest gotowy do użytku, przy pomocy Helma instalujemy Fluent Bita:

helm repo add fluent https://fluent.github.io/helm-charts
helm upgrade --install fluent-bit fluent/fluent-bit --namespace default

Po uruchomieniu powyższych komend powinniśmy zobaczyć DaemonSeta, który uruchomi Poda z instancją FluentBita na każdym naszym Nodzie.

Generator logów

Aby sprawdzić, jak Fluent Bit przetwarza i przekazuje dalej logi, potrzebujemy serwisu, który te logi będzie dla nas produkował. Dodamy prosty serwer na naszym lokalnym klastrze:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: server
  labels:
    app: server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: server
  template:
    metadata:
      labels:
        app: server
    spec:
      containers:
        - name: server
          image: pjasiak/log-server:0.1.0
          ports:
            - containerPort: 8085
---
apiVersion: v1
kind: Service
metadata:
  name: server
spec:
  selector:
    app: server
  ports:
    - protocol: TCP
      port: 8085
      targetPort: 8085
kubectl apply -f server.yaml

Podstawowa konfiguracja

Konfiguracja Fluent Bita składa się z czterech podstawowych sekcji:

  • Service: definiuje globalne ustawienia instancji Fluent Bita.
  • Input: określa źródła logów.
  • Filter: definiuje reguły i operacje przetwarzania danych logów. To w tej sekcji można modyfikować lub filtrować strumień logów zgodnie z własnymi potrzebami zanim przekażemy je na wyjście.
  • Output: definiuje miejsca docelowe dla przefiltrowanych i/lub zmodyfikowanych logów. Obsługiwane typy miejsc docelowych to np. pliki, połączenia sieciowe (TCP, UDP, HTTP), systemy SIEM czy bazy danych.
Podstawowa konfiguracja Fluent Bita
Ryc. 1 Podstawowa konfiguracja Fluent Bita

Krok I.

Na początek skonfigurujemy Fluent Bita w celu weryfikacji poprawności odczytu logów z naszego przykładowego serwisu. Zastosujemy prostą konfigurację, która przekaże logi do standardowego wyjścia. Umożliwi to obserwację logów w Podzie Fluent Bita, zapewniając wgląd w ich zawartość i poprawność działania.

fluent-bit.conf: |
  [SERVICE]
    Flush         5
    Daemon        off
    Parsers_File  parsers.conf
    HTTP_Server   On
    HTTP_Listen   0.0.0.0
    HTTP_Port     2020

  [INPUT]
    Name              tail
    Tag               kube.default.server
    Path              /var/log/containers/server*.log
    Parser            cri
    DB                /var/log/flb_kube.db
    Mem_Buf_Limit     5MB
    Skip_Long_Lines   On
    Refresh_Interval  10

  [OUTPUT]
    Name  stdout
    Match kube.default.server
    Format json
    json_date_key false

parsers.conf: |
  [PARSER]
    Name        cri
    Format      regex

W sekcji SERVICE definiujemy globalne parametry Fluent Bita. Określamy tam interwał czasowy (Flush), który odpowiada za częstotliwość wysyłania logów na wyjście. Przykładowo, ustawienie flush: 1s spowoduje wysyłanie logów co sekundę.

Dodatkowo, w tej sekcji możemy włączyć oraz skonfigurować adres i port serwera, używany przez Kubernetes do sprawdzania, czy Fluent Bit jest aktywny i gotowy do obsługi żądań (Liveness i Readiness probe).

Rejestrujemy również parser, który poprawnie odczyta logi z kontenera.

W sekcji INPUT określamy między innymi typ i ścieżkę do pliku z logami. Ustawiamy też pole Tag, które razem z polem Match w innych sekcjach pozwala na łatwe filtrowanie logów.

W ostatniej sekcji OUTPUT również wskazujemy typ, a także format, w jakim logi będą przekazywane na wyjście. Konfiguracja naszego Fluent Bita znajduje się w Config Mapie, dlatego musimy ją zmodyfikować:

kubectl edit configmaps fluent-bit

i zresetować DameonSeta, aby nowa konfiguracja została dodana do Fluent Bita:

kubectl rollout restart daemonset fluent-bit

Gdy nowa konfiguracja zostanie wgrana, musimy przetestować, czy logi z naszego serwera pojawią się na standardowym wyjściu, czyli w logach Fluenta Bita.

kubectl logs -l app.kubernetes.io/name=fluent-bit -f

Przekierujmy port naszego serwera i wyślijmy zapytanie na nasz endpoint:

kubectl port-forward services/server 8085:8085
curl localhost:8085

Jeżeli wszystko działa poprawnie, powinniśmy zobaczyć logi przekierowane z naszego serwera.

Output

Fluent Bit oferuje szeroki wachlarz opcji OUTPUT, umożliwiając elastyczne przekazywanie przetworzonych danych. Dzięki temu, użytkownicy mogą dostosować miejsca docelowe do swoich konkretnych potrzeb integracyjnych i analitycznych. Użytkownicy mogą kierować logi do różnych systemów. Możliwa jest również konfiguracja wielu sekcji OUTPUT jednocześnie, co zapewnia pełną kontrolę nad dystrybucją logów.

W oficjalnej dokumentacji możemy znaleźć wiele przykładów integracji z różnymi serwisami. W naszym przykładzie chcemy skupić się na konfiguracji Fluent Bita, dlatego jako OUTPUT wykorzystamy nasz prosty server. Dodajmy kolejny Deployment z serwisem, który będzie odbierał przesłane logi:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: output
  labels:
    app: output
spec:
  replicas: 1
  selector:
    matchLabels:
      app: output
  template:
    metadata:
      labels:
        app: output
    spec:
      containers:
        - name: output
          image: pjasiak/log-server:0.1.0
          ports:
            - containerPort: 8085
---
apiVersion: v1
kind: Service
metadata:
  name: output
spec:
  selector:
    app: output
  ports:
    - protocol: TCP
      port: 8085
      targetPort: 8085
Output
Ryc. 2 Output

Musimy wskazać Fluent Bitowi, aby wysyłał logi do naszego nowo powstałego serwisu. W konfiguracji podmieniamy standardowy Output na serwer przetwarzający nasze logi pod adresem output.default.svc.cluster.local:

fluent-bit.conf: |
  [SERVICE]
    Flush         5
    Daemon        off
    Parsers_File  parsers.conf
    HTTP_Server  On
    HTTP_Listen  0.0.0.0
    HTTP_Port    2020

  [INPUT]
    Name              tail
    Tag               kube.default.server
    Path              /var/log/containers/server*.log
    Parser            cri
    DB                /var/log/flb_kube.db
    Mem_Buf_Limit     5MB
    Skip_Long_Lines   On
    Refresh_Interval  10

  [OUTPUT]
    Name  http
    Format json
    Match kube.default.server
    Host  output.default.svc.cluster.local
    Port  8085
    URI   /logs
    json_date_key false

Kiedy Fluent Bit uaktualni nową konfiguracje, logi z naszego serwera zaczną być przesyłane do serwisu „output”.

Przekierowywanie logów do różnych serwisów

Kolejnym krokiem będzie przekierowanie logów z różnych źródeł do różnych serwisów. W naszym prostym generatorze logów mamy dwa źródła logów:

  • wygenerowane przez zewnętrzną bibliotekę oznaczone jako „[GIN]”
  • oraz logi w postaci JSONa z takimi polami jak „time” czy „msg”.

Aby różne serwisy konsumowały różne rodzaje logów, potrzebujemy dodać osobny serwis, który wykorzysta dokładnie ten sam obraz naszej aplikacji:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: gin-output
  labels:
    app: gin-output
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gin-output
  template:
    metadata:
      labels:
        app: gin-output
    spec:
      containers:
        - name: gin-output
          image: pjasiak/log-server:0.1.0
          ports:
            - containerPort: 8085
---
apiVersion: v1
kind: Service
metadata:
  name: gin-output
spec:
  selector:
    app: gin-output
  ports:
    - protocol: TCP
      port: 8085
      targetPort: 8085
Przekierowywanie logów do różnych serwisów
Ryc. 3 Przekierowywanie logów do różnych serwisów

Musimy także zmodyfikować konfigurację naszego Fluent Bita:

fluent-bit.conf: |
  [SERVICE]
    Flush         5
    Daemon        off
    Parsers_File  parsers.conf
    HTTP_Server  On
    HTTP_Listen  0.0.0.0
    HTTP_Port    2020

  [INPUT]
    Name              tail
    Tag               kube.default.server
    Path              /var/log/containers/server*.log
    Parser            cri
    DB                /var/log/flb_kube.db
    Mem_Buf_Limit     5MB
    Skip_Long_Lines   On
    Refresh_Interval  10

  [FILTER]
    Name   rewrite_tag
    Match  kube.default.server
    RULE   $message \[GIN\]. $TAG.gin true

  [FILTER]
    Name    modify
    Match   kube.default.server.gin
    Remove stream
    Remove time
    Remove logtag

  [FILTER]
    Name    parser
    Match   kube.default.server
    Key_Name message
    Parser json

  [FILTER]
    Name    rewrite_tag
    Match kube.default.server
    RULE $msg . $TAG.json false

  [OUTPUT]
    Name  http
    Format json
    Match kube.default.server.json
    Host  output.default.svc.cluster.local
    Port  8085
    URI   /logs
    json_date_key false

  [OUTPUT]
    Name  http
    Format json
    Match kube.default.server.gin
    Host  gin-output.default.svc.cluster.local
    Port  8085
    URI   /logs
    json_date_key false

Po pierwsze, wprowadziliśmy kilka segmentów „Filter”, które poniżej pokrótce omówię:

  • pierwszy filtr sprawdza, czy w logu istnieje string [GIN] i jeżeli tak, to dodaje do takich logów przyrostek .gin ,
  • w następnym filtrze we wszystkich logach z nowo utworzonym tagiem z przyrostkiem .gin usuwamy zbędne pola w calach czysto kosmetycznych,
  • kolejny filtr parser wyciąga z jsona pole message i przekształca je ze stringa na json,
  • w ostatnim filtrze sprawdzamy, czy nasz json posiada pole msg (co sugeruje, że nie został wygenerowany przez zewnętrzną bibliotekę) i jeżeli tak, dodajemy do takich tagów przyrostek .json,

W naszym pierwszym segmencie OUTPUT musimy teraz zmienić pole Match, tak aby zajmował się on tylko logami z tagiem kube.default.server.json.

Na koniec dodaliśmy drugi segment OUTPUT, w którym to logi z etykietą kube.default.server.gin zostaną przekierowane na inny adres docelowy: gin-output.default.svc.cluster.local

Po wygenerowaniu kolejnego loga, możemy prześledzić nasze serwisy końcowe. Każdy z nich powinien otrzymać różny rodzaj logów w zależności od ich rodzajów.

oferta pracy

Podsumowanie

Powyższy artykuł prezentuje jedynie szczyptę możliwości Fluent Bita. Narzędzie to zachwyca szybkością i wydajnością. Dokładna dokumentacja i intuicyjny interfejs ułatwiają konfigurację, a mnogość wbudowanych opcji zapewnia szybką integrację z różnymi systemami dostępnymi na rynku.

***

Jeżeli interesują Cię inne narzędzia wykorzystywane w barnży IT, zajrzyj koniecznie również do pozostałych artykułów naszych ekspertów.

5/5
Ocena
5/5
Avatar

O autorze

Piotr Jasiak

Programista z 13-letnim doświadczeniem, od 6 lat związany z językiem Golang. Pasjonat rozwiązań chmurowych. Fan Kubernetes i narzędzi CNCF. Doświadczenie zdobywał w różnych firmach – od małych start-upów po duże korporacje. Prywatnie fan science-fiction, pieszych wędrówek i capoeiry

Wszystkie artykuły autora

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Może Cię również zainteresować

ZAPISZ SIĘ I BĄDŹ NA BIEŻĄCO

Newsletter blogowy

Dołącz do nas

Sprawdź oferty pracy

Pokaż wyniki
Dołącz do nas Kontakt

This content is available only in one language version.
You will be redirected to home page.

Are you sure you want to leave this page?