Kas yra Grafana Loki ir kodėl tai svarbu?
Kai tavo Kubernetes klasteris auga kaip ant mielių, o podų skaičius peršoka šimtą ar net tūkstantį, pradedi suprasti, kad tradiciniai būdai žiūrėti į logus tiesiog nebefunkcionuoja. Nebegali tiesiog SSH’intis į serverį ir vykdyti `tail -f` – tai būtų kaip bandyti išgerti vandenyną per šiaudelį.
Čia ir ateina į pagalbą Grafana Loki. Tai horizontaliai masteliuojama log agregacijos sistema, kurią sukūrė Grafana Labs komanda. Jei jau naudoji Prometheus metrikoms rinkti, Loki tau pasirodys labai pažįstamas – jis naudoja tą pačią PromQL užklausų kalbą (tik šiek tiek pritaikytą logams) ir puikiai integruojasi su Grafana vizualizacijos įrankiu.
Skirtingai nei Elasticsearch ar kiti tradiciniai log agregacijos sprendimai, Loki neindeksuoja viso log turinio. Vietoj to, jis indeksuoja tik metaduomenis (labels) ir saugo neapdorotus log įrašus. Tai reiškia žymiai mažesnes infrastruktūros išlaidas ir greitesnį deployment’ą. Nereikia laukti, kol sistema suindeksuos terabaitus tekstų – tiesiog pradedi rašyti ir skaityti logus.
Loki architektūra ir pagrindiniai komponentai
Loki susideda iš kelių pagrindinių komponentų, kurie dirba kartu kaip gerai suderinta mašina. Pirmiausia yra Promtail – tai agent’as, kuris veikia kiekviename Kubernetes node’e kaip DaemonSet ir renka logus iš visų podų. Promtail žino, kaip skaityti Kubernetes metaduomenis ir automatiškai prideda juos kaip labels prie surinktų logų.
Pats Loki serveris yra atsakingas už log įrašų priėmimą, saugojimą ir užklausų apdorojimą. Jis gali veikti monolitiniu režimu (viskas viename procese) arba mikroservisų architektūra, kur kiekvienas komponentas – distributor, ingester, querier – veikia atskirai. Pradedantiesiems rekomenduoju monolitinį režimą, o kai klasteris išauga, galima pereiti prie mikroservisų.
Trečias svarbus elementas – saugykla. Loki palaiko įvairias backend sistemas: nuo paprasto failų sistemos saugojimo iki S3, GCS ar Azure Blob Storage. Produkcijoje tikrai norėsi naudoti objektų saugyklą – tai pigiau ir patikimiau nei lokalūs diskai.
Diegimas Kubernetes klasteryje per Helm
Greičiausias būdas įdiegti Loki Kubernetes’e – naudoti oficialų Helm chart’ą. Pirma, pridėk Grafana Helm repository:
„`bash
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
„`
Dabar sukurk `values.yaml` failą su savo konfigūracija. Štai bazinė konfigūracija, kuri veiks daugumai atvejų:
„`yaml
loki:
auth_enabled: false
commonConfig:
replication_factor: 1
storage:
type: ‘filesystem’
singleBinary:
replicas: 1
persistence:
enabled: true
size: 10Gi
monitoring:
selfMonitoring:
enabled: false
lokiCanary:
enabled: false
test:
enabled: false
„`
Šita konfigūracija įdiegs Loki single binary režimu su 10GB persistent volume. Produkcijoje tikrai norėsi padidinti replication_factor iki 3 ir naudoti objektų saugyklą, bet testavimui tai puikiai veiks.
Įdiegimas paprastas:
„`bash
helm install loki grafana/loki -n logging –create-namespace -f values.yaml
„`
Promtail konfigūravimas ir log rinkimas
Dabar reikia įdiegti Promtail, kad jis rinktų logus iš visų podų. Promtail chart’as paprastai ateina atskirai:
„`bash
helm install promtail grafana/promtail -n logging
„`
Promtail automatiškai sukonfigūruotas dirbti su Loki, bet gali norėti pritaikyti, kokie labels pridedami prie logų. Štai pavyzdys, kaip galima enrichinti logus papildoma informacija:
„`yaml
config:
clients:
– url: http://loki:3100/loki/api/v1/push
snippets:
pipelineStages:
– docker: {}
– labeldrop:
– filename
– labels:
namespace:
pod:
container:
app:
„`
Viena iš galingiausių Promtail funkcijų – galimybė parsinti logus ir ištraukti papildomus labels. Pavyzdžiui, jei tavo aplikacija logina JSON formatu, gali naudoti `json` pipeline stage:
„`yaml
– json:
expressions:
level: level
user_id: user.id
– labels:
level:
user_id:
„`
Dabar galėsi filtruoti logus pagal log level’į ar user ID tiesiog naudodamas labels, o ne ieškodamas tekste – tai DAUG greitesnis būdas.
LogQL: kaip rašyti efektyvias užklausas
LogQL sintaksė iš pradžių gali atrodyti keista, bet kai įpranti, tampa labai galinga. Bazinė užklausa atrodo taip:
„`
{namespace=”production”, app=”api”}
„`
Tai grąžins visus logus iš production namespace, kur app label yra „api”. Bet tikrasis malonumas prasideda, kai pradedi naudoti filtrus:
„`
{namespace=”production”, app=”api”} |= „error” != „timeout”
„`
Šita užklausa suranda visus logus, kuriuose yra žodis „error”, bet nėra žodžio „timeout”. Operatoriai `|=` (contains) ir `!=` (does not contain) yra tavo geriausi draugai.
Dar galingesnė funkcija – regex filtrai:
„`
{app=”api”} |~ „status=[45][0-9]{2}”
„`
Tai suranda visus 4xx ir 5xx HTTP status kodus. Galima ir neigti regex su `!~`.
Kai reikia agreguoti duomenis, naudok metric queries. Pavyzdžiui, norint pamatyti error rate per laiko tarpą:
„`
sum(rate({app=”api”} |= „error” [5m])) by (pod)
„`
Tai parodys, kiek error’ų per sekundę generuoja kiekvienas pod’as per paskutines 5 minutes. Labai naudinga debugging’ui, kai vienas pod’as elgiasi kitaip nei kiti.
Integracijos su Grafana ir alerting
Loki ir Grafana kartu dirba kaip sviestas ir duona. Pridėti Loki kaip data source Grafanoje paprasta – eik į Configuration → Data Sources → Add data source → Loki. URL paprastai bus `http://loki.logging:3100` jei naudoji tą patį namespace.
Sukurti dashboard’ą logams yra šiek tiek kitaip nei metrikoms. Vietoj graph panel’ių, dažniausiai naudosi Logs panel, kuris rodo logus lentelės formatu. Bet galima ir vizualizuoti log metrics – pavyzdžiui, sukurti graph, rodantį error rate per laiką.
Štai praktiškas pavyzdys, kaip sukurti alert’ą, kuris praneša, kai error rate viršija ribą:
„`
sum(rate({namespace=”production”} |= „error” [5m])) > 10
„`
Jei per 5 minutes error’ų rate’as viršija 10 per sekundę, gausi alert’ą. Grafana Alerting palaiko įvairius notification channel’us – Slack, PagerDuty, email ir t.t.
Vienas cool trick’as – galima naudoti template variables dashboard’uose. Pavyzdžiui, sukurti dropdown su visais namespace’ais:
„`
label_values(namespace)
„`
Tada užklausose naudoti `{namespace=”$namespace”}` ir galėsi lengvai switch’inti tarp skirtingų namespace’ų.
Performance optimizacija ir best practices
Loki yra greitas, bet tik jei naudoji jį teisingai. Pirmoji ir svarbiausia taisyklė – nenaudok per daug unikalių label kombinacijų. Kiekviena unikali label kombinacija sukuria naują stream’ą, o per daug stream’ų gali užmušti performance’ą.
Pavyzdžiui, NIEKADA nedaryk šito:
„`yaml
– labels:
user_id: # BAD! Gali būti tūkstančiai ar milijonai user_id
request_id: # BAD! Kiekvienas request’as unikalus
„`
Vietoj to, tokią informaciją laikyk log turinyje ir ieškoki naudodamas filtrus. Labels turėtų būti tik high-cardinality metadata – namespace, pod name, container name, app name, environment.
Kitas svarbus dalykas – retention policy. Nereikia saugoti visų logų amžinai. Sukonfigūruok retention pagal savo poreikius:
„`yaml
limits_config:
retention_period: 744h # 31 diena
„`
Jei naudoji objektų saugyklą, galima sukonfigūruoti lifecycle policies, kad senesni logai būtų perkeliami į pigesnį storage tier’ą.
Dar vienas performance tip’as – naudok chunk caching. Loki gali cache’inti chunks memory’je ar Redis’e, kas labai pagreitina užklausas:
„`yaml
chunk_store_config:
chunk_cache_config:
memcached:
batch_size: 256
parallelism: 10
memcached_client:
host: memcached.logging:11211
„`
Troubleshooting ir dažniausios problemos
Viena dažniausių problemų – Promtail neranda podų arba nerenka logų. Pirmiausia patikrink, ar Promtail pod’ai veikia visuose node’uose:
„`bash
kubectl get pods -n logging -l app.kubernetes.io/name=promtail -o wide
„`
Jei trūksta pod’ų, gali būti node selector ar taint’ų problemos. Patikrink DaemonSet konfigūraciją.
Kita dažna problema – „too many outstanding requests” error. Tai reiškia, kad Loki negali suspėti apdoroti visų incoming log’ų. Sprendimas – padidinti ingester’ių skaičių arba optimizuoti log volume:
„`yaml
ingester:
max_chunk_age: 2h
chunk_idle_period: 30m
chunk_block_size: 262144
„`
Jei matai „stream limit exceeded” error’us, tai reiškia, kad per daug unikalių label kombinacijų. Reikia peržiūrėti Promtail konfigūraciją ir sumažinti label cardinality.
Kartais Loki query’ai būna lėti. Pirmas dalykas – patikrink, ar naudoji label filtrus PRIEŠ text search:
„`
# GOOD – pirmiausia filtruoja pagal labels
{namespace=”prod”, app=”api”} |= „error”
# BAD – ieško per visus logus
{} |= „error” | namespace=”prod”
„`
Labels filtrai naudoja index’ą ir yra DAUG greitesni nei text search.
Kai viskas veikia kartu: realaus pasaulio scenarijai
Praktikoje Loki tampa neįkainojamu įrankiu debugging’ui ir monitoring’ui. Vienas iš mano mėgstamiausių use case’ų – distributed tracing su logais. Jei tavo aplikacija prideda trace_id prie kiekvieno log įrašo, gali lengvai sekti visą request’o kelionę per mikroservisus:
„`
{namespace=”production”} |= „trace_id=abc123″
„`
Tai parodys visus logus iš visų servisų, susijusius su tuo konkrečiu request’u. Pridėk Split view Grafanoje ir galėsi matyti skirtingų servisų logus greta vienas kito – debugging’as tampa DAUG paprastesnis.
Kitas praktiškas pavyzdys – capacity planning. Naudodamas log metrics, gali analizuoti, kokie endpoint’ai generuoja daugiausiai trafiko:
„`
sum by (endpoint) (rate({app=”api”} | json | __error__=”” [1h]))
„`
Arba sekti, kaip greitai auga duomenų bazės užklausų skaičius:
„`
sum(rate({app=”api”} |= „database query” [5m]))
„`
Tokia informacija padeda numatyti, kada reikės scale’inti infrastruktūrą.
Dar vienas cool use case – security monitoring. Gali sukurti alert’us, kurie praneša apie suspicious activity:
„`
sum(rate({namespace=”production”} |~ „failed login|unauthorized|403|401” [5m])) > 5
„`
Jei per 5 minutes matai daugiau nei 5 authentication failure’ų per sekundę, gali būti brute force ataka.
Loki taip pat puikiai veikia su GitOps workflow. Galima saugoti visas Loki ir Promtail konfigūracijas Git’e ir deploy’inti per ArgoCD ar Flux. Tai užtikrina, kad visi environment’ai turi consistent log collection setup’ą ir galima lengvai track’inti configuration changes.
Galiausiai, kai tavo Loki setup’as subręsta, pradedi jį naudoti ne tik debugging’ui, bet ir business analytics. Pavyzdžiui, tracking’ui, kokie features naudojami dažniausiai, arba analizuoti user behavior patterns. Logai tampa ne tik troubleshooting įrankiu, bet ir vertingu duomenų šaltiniu.
Svarbiausia pamoka, kurią išmokau naudodamas Loki – pradėk paprastai. Įdiek basic setup’ą, paeksperimentuok su užklausomis, sukurk kelis dashboard’us. Kai suprasi, kaip viskas veikia, galėsi optimize’inti ir scale’inti. Nebandyk iš karto deploy’inti super complex multi-tenant setup’o su visais bells and whistles – greičiausiai tik sukomplikuosi sau gyvenimą. Loki grožis yra jo paprastume, tai ir išnaudok.
