Kas tas Fluent Bit ir kodėl turėtum apie jį žinoti
Jei kada nors bandei susigaudyti, kas vyksta tavo aplikacijoje production aplinkoje, kai viskas griūva, tikrai žinai, kad logai yra tavo geriausias draugas. Bet kai tuos logus reikia rinkti iš dešimčių ar šimtų konteinerių, serverių ar mikroservisų, prasideda tikras galvos skausmas. Čia ir ateina į pagalbą Fluent Bit – kompaktiškas, greitas ir efektyvus log procesorius, kuris tapo neatsiejama daugelio modernių infrastruktūrų dalimi.
Fluent Bit yra atvirojo kodo duomenų rinkimo ir log’inimo įrankis, sukurtas būti lengvu ir našiu. Jis gimė kaip Cloud Native Computing Foundation (CNCF) projektas ir yra glaudžiai susijęs su Fluentd – jo „vyresniuoju broliu”. Tačiau skirtingai nuo Fluentd, Fluent Bit sukurtas būti kur kas mažesnis ir efektyvesnis resursų atžvilgiu, kas jį daro idealų sprendimą edge computing, embedded sistemoms ir konteinerizuotoms aplinkoms.
Pagrindinė Fluent Bit užduotis – rinkti duomenis iš įvairių šaltinių (logų failai, metrikos, sistemų įvykiai), juos apdoroti, filtruoti ir persiųsti į pasirinktas paskirties vietas. Tai gali būti Elasticsearch, InfluxDB, Kafka, S3 ar bet kuri kita populiari duomenų saugykla ar analizės platforma.
Architektūra ir veikimo principai
Fluent Bit architektūra yra paremta pipeline principu, kuris susideda iš kelių pagrindinių komponentų: Input, Parser, Filter, Buffer ir Output. Kiekvienas iš šių komponentų atlieka specifinę funkciją duomenų apdorojimo grandinėje.
Input pluginai yra atsakingi už duomenų rinkimą iš įvairių šaltinių. Tai gali būti failų skaitymas (tail), sistemų metrikų rinkimas, Docker ar Kubernetes logai, TCP/UDP srautai ir daug kitų variantų. Vienas iš didžiausių Fluent Bit privalumų – milžiniškas palaikomų input šaltinių skaičius.
Parser komponentas leidžia struktūrizuoti nestruktūrizuotus duomenis. Pavyzdžiui, jei tavo aplikacija generuoja JSON formato logus, parseris gali juos išskaidyti į atskirus laukus, kuriuos vėliau galėsi filtruoti ar transformuoti. Palaikomi įvairūs formatai: JSON, regex, LTSV ir kiti.
Filtrai – čia prasideda tikroji magija. Filtrai leidžia modifikuoti, praturtinti ar išmesti duomenis prieš juos siunčiant toliau. Gali pridėti papildomus laukus (pavyzdžiui, hostname ar environment), pakeisti reikšmes, išfiltruoti nereikalingus įrašus pagal tam tikras sąlygas ar net transformuoti duomenų struktūrą.
Output pluginai užtikrina, kad tavo duomenys pasiektų galutinę paskirties vietą. Fluent Bit palaiko dešimtis output variantų – nuo tradicinių failų ir duomenų bazių iki modernių cloud sprendimų ir streaming platformų.
Praktinis konfigūracijos pavyzdys
Teorija teorija, bet pažiūrėkime, kaip tai atrodo praktikoje. Štai paprastas bet funkcionalus Fluent Bit konfigūracijos pavyzdys, kuris renka Docker konteinerių logus ir siunčia juos į Elasticsearch:
[SERVICE]
Flush 5
Daemon Off
Log_Level info
[INPUT]
Name tail
Path /var/lib/docker/containers/*/*.log
Parser docker
Tag docker.*
Refresh_Interval 5
[FILTER]
Name kubernetes
Match docker.*
Kube_URL https://kubernetes.default.svc:443
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
[FILTER]
Name modify
Match docker.*
Add environment production
Add cluster main-cluster
[OUTPUT]
Name es
Match *
Host elasticsearch.logging.svc.cluster.local
Port 9200
Index fluent-bit
Type _doc
Logstash_Format On
Šioje konfigūracijoje matome visą pipeline’ą: skaitome Docker logus, praturtinome juos Kubernetes metadata, pridedame papildomus laukus ir siunčiame į Elasticsearch su Logstash formato indeksavimu. Paprasta, bet galinga.
Kubernetes integracija ir DaemonSet deployment
Kubernetes aplinkoje Fluent Bit dažniausiai deployjamas kaip DaemonSet – tai reiškia, kad vienas Fluent Bit pod’as veikia kiekviename cluster node’e. Toks deployment modelis užtikrina, kad visi konteinerių logai būtų renkami nepriklausomai nuo to, kuriame node’e jie veikia.
Štai kaip atrodo bazinis Fluent Bit DaemonSet manifest’as:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluent-bit
namespace: logging
spec:
selector:
matchLabels:
app: fluent-bit
template:
metadata:
labels:
app: fluent-bit
spec:
serviceAccountName: fluent-bit
containers:
- name: fluent-bit
image: fluent/fluent-bit:2.1
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
- name: fluent-bit-config
mountPath: /fluent-bit/etc/
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- name: fluent-bit-config
configMap:
name: fluent-bit-config
Svarbu suprasti, kad Fluent Bit reikia prieigos prie host sistemos direktorijų, kur saugomi konteinerių logai. Todėl naudojame hostPath volumes, kurie suteikia prieigą prie /var/log ir /var/lib/docker/containers.
Dar vienas svarbus aspektas – RBAC (Role-Based Access Control) konfigūracija. Fluent Bit reikia teisių skaityti Kubernetes API, kad galėtų praturtinti logus metadata apie pod’us, namespace’us ir kitus Kubernetes objektus:
apiVersion: v1 kind: ServiceAccount metadata: name: fluent-bit namespace: logging --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: fluent-bit-read rules: - apiGroups: [""] resources: - namespaces - pods verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: fluent-bit-read roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: fluent-bit-read subjects: - kind: ServiceAccount name: fluent-bit namespace: logging
Performance tuning ir resursų optimizavimas
Vienas iš pagrindinių Fluent Bit privalumų – jo efektyvumas. Tačiau netinkamai sukonfigūravus, net ir šis lengvasvoris įrankis gali tapti resursų rijiku. Štai keletas praktinių patarimų, kaip išspausti maksimalų našumą:
Buffer konfigūracija yra kritiškai svarbi. Fluent Bit naudoja memory ir filesystem bufferius duomenims laikyti prieš juos siunčiant į output. Jei tavo output paskirties vieta lėta ar laikinai nepasiekiama, bufferiai užpildys atmintį. Rekomenduoju naudoti filesystem bufferius production aplinkoje:
[SERVICE]
storage.path /var/log/flb-storage/
storage.sync normal
storage.checksum off
storage.max_chunks_up 128
Flush intervalas nusako, kaip dažnai duomenys siunčiami į output. Mažesnis intervalas reiškia mažesnį latency, bet didesnį network overhead. Paprastai 5-10 sekundžių yra geras balansas:
[SERVICE]
Flush 5
Mem_Buf_Limit parametras input lygyje riboja, kiek atminties gali naudoti konkretus input plugin’as. Tai apsaugo nuo situacijų, kai vienas input „suėda” visą atmintį:
[INPUT]
Name tail
Path /var/log/*.log
Mem_Buf_Limit 5MB
Workers – nuo Fluent Bit 1.9 versijos galima konfigūruoti output workers skaičių, kas leidžia paralelizuoti duomenų siuntimą:
[OUTPUT]
Name es
Match *
Host elasticsearch
Workers 2
Praktikoje pastebėjau, kad Kubernetes aplinkoje Fluent Bit pod’ui pakanka 100-200Mi atminties ir 100-200m CPU limito normaliam darbui. Žinoma, tai priklauso nuo log’ų kiekio ir apdorojimo sudėtingumo.
Multiline logų apdorojimas
Viena iš dažniausių problemų, su kuriomis susiduriama renkant logus – multiline įrašai. Java stack trace’ai, Python exception’ai ar bet kokie kiti logai, kurie tęsiasi per kelias eilutes, gali tapti tikru košmaru, jei jų tinkamai neapdorosi.
Fluent Bit turi puikų multiline parser’į, kuris leidžia sujungti kelias eilutes į vieną log įrašą. Štai pavyzdys, kaip apdoroti Java stack trace’us:
[MULTILINE_PARSER]
name java_multiline
type regex
flush_timeout 1000
rule "start_state" "/^\d{4}-\d{2}-\d{2}/" "cont"
rule "cont" "/^(?!\d{4}-\d{2}-\d{2})/" "cont"
[INPUT]
Name tail
Path /var/log/app.log
multiline.parser java_multiline
Šis parser’is naudoja regex taisykles nustatyti, kur prasideda naujas log įrašas (pagal datą formato pradžioje) ir tęsia rinkti eilutes, kol nepasirodo kitas įrašas su data.
Alternatyvus būdas – naudoti multiline filter’į, kuris veikia po duomenų surinkimo:
[FILTER]
Name multiline
Match *
multiline.key_content log
multiline.parser java_multiline
Svarbu suprasti skirtumą: multiline input lygyje apdoroja duomenis jų rinkimo metu, o filter’is – jau surinktus duomenis. Input lygio apdorojimas paprastai efektyvesnis, bet filter’is suteikia daugiau lankstumo.
Troubleshooting ir debugging patarimai
Net ir su geriausiai sukonfigūruotu Fluent Bit, kartais kažkas nepavyksta. Štai keletas patikrintų būdų, kaip diagnozuoti problemas:
Log level kėlimas – pirmasis žingsnis visada turėtų būti debug režimo įjungimas:
[SERVICE]
Log_Level debug
Tai išspausdins daug daugiau informacijos apie tai, kas vyksta Fluent Bit viduje. Tik nepamirškite grąžinti į info ar warn production’e, nes debug logai gali būti labai verbose.
HTTP server įjungimas leidžia gauti realtime metrikas ir health check endpoint’ą:
[SERVICE]
HTTP_Server On
HTTP_Listen 0.0.0.0
HTTP_Port 2020
Tada galite pasiekti http://localhost:2020/api/v1/metrics ir pamatyti detalizuotas metrikas apie kiekvieną plugin’ą – kiek įrašų apdorota, kiek klaidų įvyko, buffer’ių būsena ir t.t.
Stdout output testavimui – kai neveikia output į Elasticsearch ar kitą sistemą, laikinai pridėkite stdout output’ą, kad pamatytumėte, ar duomenys iš viso pasiekia output stage’ą:
[OUTPUT]
Name stdout
Match *
Format json_lines
Tag matching tikrinimas – dažna klaida yra neteisingi tag’ai ar match pattern’ai. Įsitikinkite, kad jūsų filter’iai ir output’ai tikrai atitinka input tag’us. Galite naudoti wildcard’us: Match kube.* atitiks visus tag’us, prasidedančius „kube.”.
Dar vienas naudingas triukas – naudoti rewrite_tag filter’į, kad geriau kontroliuotumėte duomenų srautą:
[FILTER]
Name rewrite_tag
Match kube.*
Rule $kubernetes['namespace_name'] ^production$ production.logs false
Rule $kubernetes['namespace_name'] ^staging$ staging.logs false
Tai leidžia perrašyti tag’us pagal tam tikras sąlygas ir nukreipti skirtingus duomenis į skirtingus output’us.
Alternatyvos ir kada rinktis Fluent Bit
Būtų nesąžininga nekalbėti apie alternatyvas. Log’ų rinkimo ir apdorojimo srityje yra nemažai konkurentų: Fluentd, Logstash, Filebeat, Vector ir kiti. Kiekvienas turi savo nišą ir privalumus.
Fluentd vs Fluent Bit – tai dažniausias palyginimas. Fluentd yra brandus, funkcionalus ir turi didžiulę plugin’ų ekosistemą. Tačiau jis parašytas Ruby ir naudoja daugiau resursų. Fluent Bit parašytas C kalba, yra kur kas lengvesnis (apie 450KB binary) ir efektyvesnis. Tipinis use case’as: naudoti Fluent Bit edge’e (Kubernetes node’uose, IoT įrenginiuose) duomenų rinkimui ir pradiniam apdorojimui, o Fluentd – centralizuotam apdorojimui ir agregavimui.
Filebeat – Elastic stack dalis, puikiai integruojasi su Elasticsearch. Jei jau naudojate ELK stack’ą ir jums nereikia siųsti duomenų į kitas sistemas, Filebeat gali būti paprastesnis pasirinkimas. Tačiau Fluent Bit yra vendor-neutral ir lankstesnis.
Vector – naujesnis žaidėjas, parašytas Rust kalba. Turi įspūdingą našumą ir modernią architektūrą. Tačiau ekosistema dar ne tokia brandi kaip Fluent Bit, ir community mažesnė.
Logstash – galingas, bet sunkus. Jei jums reikia sudėtingo duomenų transformavimo ir praturtinimo, Logstash gali būti geras pasirinkimas. Bet Kubernetes aplinkoje jis dažniausiai per daug „turtingas” paprastam log’ų rinkimui.
Fluent Bit yra idealus pasirinkimas, kai:
– Dirbate su Kubernetes ar konteinerizuota aplinka
– Svarbu efektyvus resursų naudojimas
– Reikia siųsti duomenis į kelias skirtingas sistemas
– Norite CNCF palaikomo, aktyviai vystomo projekto
– Reikia edge computing ar embedded sistemų palaikymo
Ką reikia žinoti prieš pradedant gamyboje
Prieš deployjant Fluent Bit production aplinkoje, yra keletas dalykų, kuriuos būtina apgalvoti ir sukonfigūruoti.
High availability – nors Fluent Bit kaip DaemonSet jau yra distributed, reikia pagalvoti apie output pasiekiamumą. Jei jūsų Elasticsearch ar kita paskirties sistema nukrenta, kas nutinka su log’ais? Filesystem buffer’iai padeda, bet jie turi limitus. Apsvarstykite multi-output konfigūraciją arba intermediate queue (pvz., Kafka) naudojimą.
Security – logai dažnai turi sensitive informacijos. Įsitikinkite, kad:
– Naudojate TLS komunikacijai su output sistemomis
– Filtruojate sensitive duomenis (slaptažodžius, token’us) prieš siunčiant
– Tinkamai sukonfigūravote RBAC Kubernetes’e
– Apsvarstote log’ų encryption at rest
Štai pavyzdys, kaip išfiltruoti sensitive laukus:
[FILTER]
Name modify
Match *
Remove password
Remove token
Remove api_key
Monitoring – Fluent Bit pats turi būti monitorinamas. Eksportuokite jo metrikas į Prometheus:
[INPUT]
Name prometheus_scrape
Host 127.0.0.1
Port 2020
Scrape_interval 30s
Stebėkite tokius dalykus kaip:
– Buffer’ių užpildymas
– Output retry rate
– Dropped records
– Memory ir CPU naudojimas
Version management – Fluent Bit aktyviai vystomas, naujos versijos išleidžiamos reguliariai. Turėkite aiškų upgrade procesą ir testuokite naujus release’us staging aplinkoje prieš keliant į production. Breaking changes pasitaiko, nors ir retai.
Costs – nors Fluent Bit pats nemokamas, duomenų saugojimas ir perdavimas gali kainuoti. Apskaičiuokite, kiek log’ų generuojate per dieną ir kiek tai kainuos jūsų pasirinktoje storage platformoje. Kartais verta investuoti į agresyvesnį filtravimą ar sampling’ą, kad sumažintumėte kiekį.
Retention policy – neužmirškite sukonfigūruoti, kiek laiko saugoti logus. Elasticsearch index’ai gali greitai išpūsti diskus. Naudokite ILM (Index Lifecycle Management) ar panašius mechanizmus automatiniam senų log’ų valymui.
Realūs scenarijai ir best practices iš praktikos
Per kelerius metus dirbant su Fluent Bit įvairiuose projektuose, susiformavo keletas patikrintų pattern’ų ir best practices, kurie veikia realybėje, ne tik teorijoje.
Namespace segregacija – jei turite multi-tenant Kubernetes cluster’į, būtinai atskiriate log’us pagal namespace’us jau Fluent Bit lygyje:
[FILTER]
Name kubernetes
Match kube.*
[FILTER]
Name rewrite_tag
Match kube.*
Rule $kubernetes['namespace_name'] ^prod-(.*)$ prod.$TAG true
Rule $kubernetes['namespace_name'] ^dev-(.*)$ dev.$TAG true
[OUTPUT]
Name es
Match prod.*
Host prod-elasticsearch
Index prod-logs
[OUTPUT]
Name es
Match dev.*
Host dev-elasticsearch
Index dev-logs
Taip užtikrinate, kad production ir development logai nepasimišo ir gali turėti skirtingas retention policies.
Structured logging enforcement – skatinkite development komandas naudoti structured logging (JSON). Tai labai palengvina log’ų analizę. Fluent Bit gali padėti konvertuoti plain text logus į JSON, bet geriau, kad aplikacijos iš karto generuotų struktūrizuotus logus.
Centralizuotas konfigūracijos valdymas – naudokite ConfigMap’us Kubernetes’e ir version control’ę juos Git’e. Tai leidžia track’inti konfigūracijos pakeitimus ir greitai rollback’inti, jei kas negerai:
kubectl create configmap fluent-bit-config \ --from-file=fluent-bit.conf \ --from-file=parsers.conf \ -n logging
Gradual rollout – kai keičiate Fluent Bit konfigūraciją ar versiją, nedarykite to visame cluster’yje iš karto. Naudokite node selector’ius ar taints/tolerations, kad pirmiausia išbandytumėte pokyčius mažoje node’ų grupėje:
spec:
template:
spec:
nodeSelector:
fluent-bit-version: v2
Log sampling – jei turite labai verbose aplikacijų (pvz., debug logai production’e), apsvarstykite sampling’ą. Galite naudoti grep filter’į su regex, kad išlaikytumėte tik tam tikrą procentą log’ų:
[FILTER]
Name grep
Match kube.*
Regex log ^(?!.*debug).*$
Arba dar geriau – naudokite throttle filter’į, kuris leidžia kontroliuoti log’ų rate per laiko vienetą:
[FILTER]
Name throttle
Match kube.*
Rate 1000
Window 60
Interval 1m
Tai leis praėjti maksimaliai 1000 log įrašų per minutę iš kiekvieno šaltinio.
Disaster recovery – turėkite backup planą. Jei viskas sugenda ir prarandate logus, kas nutinka? Apsvarstykite dual-write strategiją – siųskite logus į dvi skirtingas sistemas arba bent jau į S3 kaip backup:
[OUTPUT]
Name es
Match *
Host primary-elasticsearch
[OUTPUT]
Name s3
Match *
bucket backup-logs
region eu-west-1
store_dir /tmp/fluent-bit/s3
total_file_size 100M
upload_timeout 10m
Praktikoje pastebėjau, kad organizacijos, kurios rimtai traktuoja logging infrastruktūrą, turi atskirą komandą ar bent dedicated žmogų, kuris už tai atsakingas. Logging nėra „set and forget” dalykas – tai gyvybiškai svarbi infrastruktūros dalis, kuri reikalauja nuolatinio dėmesio ir optimizavimo.
Dar vienas insight’as – investuokite į mokymą. Įsitikinkite, kad jūsų development ir operations komandos supranta, kaip veikia logging pipeline’as, kaip rašyti efektyvias queries, kaip debug’inti problemas naudojant logus. Geriausia logging infrastruktūra pasaulyje nenaudinga, jei niekas nemoka ja naudotis.
Galiausiai, nepamirškite, kad Fluent Bit yra tik įrankis. Jis neišspręs problemų, kurios kyla iš blogai suprojektuotos aplikacijos ar chaotiško logging’o. Prieš optimizuojant log’ų rinkimą, įsitikinkite, kad pačios aplikacijos generuoja prasmingas, struktūrizuotas ir tinkamo lygio logus. Kartais geriau investuoti laiką į aplikacijos logging strategijos pagerinimą nei bandyti išspręsti viską Fluent Bit konfigūracija.
