PĂ«rshĂ«ndetje tĂ« gjithĂ«ve! Disa muaj mĂ« parĂ«, ne lançuam nĂ« prodhim projektin tonĂ« tĂ« ri open-source â njĂ« plugin pĂ«r Grafana pĂ«r monitorimin e Kubernetes, tĂ« cilin e quajtur . Kodi burimor i plugin-it Ă«shtĂ« i disponueshĂ«m nĂ« . NĂ« kĂ«tĂ« artikull, dĂ«shirojmĂ« tĂ« ndajmĂ« me ju historinĂ« e krijimit tĂ« plugin-it, cilat mjete kemi pĂ«rdorur dhe me cilat pengesa jemi pĂ«rballur gjatĂ« zhvillimit. Le tĂ« nisim!
Pjesa 0 â hyrje: si arritĂ«m deri kĂ«tu?
Ideja për të shkruar një plugin të vetin për Grafanën na lindi krejt rastësisht. Kompania jonë merret me monitorimin e projekteve web për më shumë se 10 vjet. Gjatë kësaj kohe, ne kemi akumuluar një bagazh të madh ekspertize, raste interesante dhe përvojë në përdorimin e sistemeve të ndryshme të monitorimit. Në një moment, na erdhi në mendje pyetja: "A ekziston ndonjë mjet magjik për monitorimin e Kubernetes, që mund të thuhet se 'e vendos dhe harron'?".. Standardi industrial për monitorimin e k8s, natyrisht, është prej kohësh kombinimi Prometheus + Grafana. Dhe për këtë stack, ekziston një gamë e gjerë zgjidhjesh të gatshme: prometheus-operator, një grup panelesh kubernetes-mixin, grafana-kubernetes-app.
Opsioni më interesant për ne duhej të ishte plugin grafana-kubernetes-app, por ai nuk mbështetet më për më shumë se një vit dhe, për më tepër, nuk punon me versionet e reja të node-exporter dhe kube-state-metrics. Në një moment, ne vendosëm: "Pse të mos krijojmë një zgjidhje tonën?"
Cilat ide vendosëm të realizojmë në pluginin tonë:
- visualizimi i "hartĂ«s sĂ« aplikacionit": njĂ« paraqitje e pĂ«rshtatshme e aplikacioneve nĂ« klaster, tĂ« grupuara sipas namespace-ve, deployment-eveâŠ;
- visualizimi i lidhjeve tĂ« tipit "deployment â service (+ports)".
- visualizimi i shpërndarjes së aplikacioneve të klasterit sipas nod-eve të klasterit.
- mbledhja e metrikeve dhe informacionit nga burime të ndryshme: Prometheus dhe k8s api server.
- monitorimi i pjesĂ«s infrastrukturore (pĂ«rdorimi i kohĂ«s sĂ« procesorit, memories, sistemit tĂ« diskut, rrjetit), si dhe logjikĂ«s sĂ« aplikacioneve â statusi i shĂ«ndetit tĂ« pod-eve, numri i replikave tĂ« disponueshme, informacion mbi kalimin e testeve tĂ« liveness/readyness.
Pjesa 1: ĂfarĂ« Ă«shtĂ« "plugin pĂ«r Grafana"?
Nga një perspektivë teknike, një plugin për Grafana është një kontrollor angular, i cili ruhet në drejtorinë e të dhënave të Grafanës (/var/grafana/plugins/<your_plugin_name>/dist/module.js) dhe mund të ngarkohet si një modul SystemJS. Gjithashtu, në këtë direktori duhet të ketë një skedar plugin.json, i cili përmban të gjithë metainformacionin mbi plugin-in tuaj: emri, versioni, tipi i plugin-it, lidhjet me depo/site/licencë, varësitë dhe kështu me radhë.

module.ts

plugin.json
Siç shihet në screenshot, ne kemi specifikuar plugin.type = app. Sepse plugins për Grafana mund të jenë të tre llojeve:
panel: lloji mĂ« i zakonshĂ«m i plugjeve â paraqet njĂ« panel pĂ«r vizualizimin e disa metrikave, pĂ«rdoret pĂ«r ndĂ«rtimin e dashboard-eve tĂ« ndryshme.
burimi i të dhënave: plugin-connector për një burim të dhënash (p.sh., Prometheus-datasource, ClickHouse-datasource, ElasticSearch-datasource).
app: plugin që ju lejon të ndërtoni aplikacionin tuaj frontend brenda Grafana, të krijoni faqet tuaja HTML dhe të bëni thirrje manuale në burimin e të dhënave për vizualizimin e të dhënave të ndryshme. Gjithashtu, si varësi mund të përdoren plugj të llojeve të tjera (datasource, panel) dhe dashboard-e të ndryshme.

Shembulli i varësive të plugin me llojin = app.
Si gjuhĂ« programuese mund tĂ« pĂ«rdorni si JavaScript ashtu edhe TypeScript (ne kemi zgjedhur kĂ«tĂ« tĂ« fundit). Shabllonat pĂ«r plugin-et hello-world tĂ« çdo lloji mund tĂ« : nĂ« kĂ«tĂ« depo paraqiten njĂ« numĂ«r i madh starter-packâesh (ka edhe njĂ« shembull eksperimental tĂ« plugin-it nĂ« React) me ndĂ«rtues tĂ« paracaktuar dhe tĂ« konfiguruar.
Pjesa 2: përgatitja e ambientit lokal
Natyrisht, për të punuar me plugin, do na nevojitet një klaster kubernetes me të gjitha mjetet e parainstaluara: prometheus, node-exporter, kube-state-metrics, grafana. Mjedisi duhet të konfigurohet shpejt, lehtë dhe pa ndihmë, dhe për të siguruar hot-reload, direktoria e të dhënave të Grafana duhet të montohet drejtpërdrejt nga makina e zhvilluesit.
Mënyra më e përshtatshme për ne për të punuar lokal me kubernetes është . Hapi tjetër është të instalojmë setin Prometheus + Grafana përmes prometheus-operator. Në është përshkruar në detaje procesi i instalimit të prometheus-operator në minikube. Për të përfshirë këndvështrimin e qëndrueshmërisë, duhet të vendosni parametrin persistence: true në skedarin charts/grafana/values.yaml, të shtoni PV dhe PVC tuaj dhe t'i regjistroni ata në parametrin persistence.existingClaim.
Skripti përfundimtar për nisjen e minikube duket kështu:
minikube start --kubernetes-version=v1.13.4 --memory=4096 --bootstrapper=kubeadm --extra-config=scheduler.address=0.0.0.0 --extra-config=controller-manager.address=0.0.0.0
minikube mount
/home/sergeisporyshev/Projects/Grafana:/var/grafana --gid=472 --uid=472 --9p-version=9p2000.LPjesa 3: zhvillimi i drejtpërdrejtë
Modeli i objektit
Si pĂ«rgatitje pĂ«r zbatimin e plugin-it, ne vendosĂ«m tĂ« pĂ«rshkruajmĂ« tĂ« gjitha entitetet bazĂ« tĂ« Kubernetes me tĂ« cilat do tĂ« punojmĂ« si klasat TypeScript: pod, deployment, daemonset, statefulset, job, cronjob, service, node, namespace. Ădo njĂ« nga kĂ«to klasa trashĂ«gon nga klasa e pĂ«rbashkĂ«t BaseModel, nĂ« tĂ« cilĂ«n pĂ«rshkruhen konstruktorĂ«t, destruktorĂ«t, metodat pĂ«r azhurnimin dhe kalimin e dukshmĂ«risĂ«. NĂ« secilĂ«n nga kĂ«to klasa pĂ«rshkruhen marrĂ«dhĂ«niet e ngjashme me entitete tĂ« tjera, pĂ«r shembull, lista e pod-Ă«ve nĂ« entitetin e tipit deployment.
import {Pod} from "./pod";
import {Service} from "./service";
import {BaseModel} from './traits/baseModel';
export class Deployment extends BaseModel{
pods: Array;
services: Array;
constructor(data: any){
super(data);
this.pods = [];
this.services = [];
}
}Me ndihmën e getter-ëve dhe setter-ëve, mund të nxjerrim ose vendosim metrikat që na nevojiten në një format të përshtatshëm dhe lexueshëm. Për shembull, shpërndarja e formatizuar e allocatable cpu të nodës:
get cpuAllocatableFormatted(){
let cpu = this.data.status.allocatable.cpu;
if(cpu.indexOf('m') > -1){
cpu = parseInt(cpu)/1000;
}
return cpu;
}Faqet
Lista e të gjitha faqeve të plugin-it tonë përshkruhet fillimisht në pluing.json tonë në seksionin e varësive:

Në bllokun për çdo faqe, duhet të specifikojmë TITULLIN E FAQES (i cili më pas do të konvertohet në slug, me të cilin kjo faqe do të jetë e aksesueshme); titulli i komponentit që është përgjegjës për funksionimin e kësaj faqe (lista e komponentëve eksportohet në module.ts); përcaktimi i rolit të përdoruesit për të cilin është e mundur puna me këtë faqe dhe konfigurimi i navigimit për panelin anësor.
Në komponentin që merret me faqen, duhet të vendosim templateUrl, duke kaluar aty rrugën për skedarin html me përbërjen. Brenda kontrolluesit, përmes injektimit të varësive, mund të qasemi në dy shërbime të rëndësishme angular:
- backendSrv â shĂ«rbimi qĂ« siguron ndĂ«rveprimin me api-serverin e GrafanĂ«s;
- datasourceSrv â shĂ«rbimi qĂ« siguron ndĂ«rveprimin lokal me tĂ« gjitha burimet e tĂ« dhĂ«nave qĂ« janĂ« instaluar nĂ« GrafanĂ«n tuaj (pĂ«r shembull, metoda .getAll() â kthen listĂ«n e tĂ« gjitha burimeve tĂ« dhĂ«nave tĂ« instaluara; .get() â kthen objekt-instancĂ«n e burimit tĂ« dhĂ«nave specifik.



Pjesa 4: burimi i të dhënave
Sipas Grafana, burimi i dhënash është një plugin si të tjerët: ka pikën e tij të hyrjes module.js dhe një skedar me të dhëna meta plugin.json. Gjatë zhvillimit të një plugin me tipin = app, mund të bashkëveprojmë si me burimet e dhënash ekzistuese (p.sh., prometheus-datasource), ashtu edhe me ato që krijojmë vetë, të cilat mund t'i ruajmë direkt në direktorinë e plugin-it (dist/datasource/*) ose t'i instalojmë si varësi. Në rastin tonë, burimi i dhënash jepet së bashku me kodin e plugin-it. Gjithashtu, është e domosdoshme të ketë një model config.html dhe një kontrollues ConfigCtrl, të cilat do të përdoren për faqen e konfigurimit të instancës së burimit të dhënash dhe kontrolluesit të Dhenash, ku implementohet logjika e funksionimit të burimit tuaj të dhënash.
Në plugin-in KubeGraf, nga pikëpamja e ndërfaqes së përdoruesit, burimi i dhënash paraqet një instancë të klasterit kubernetes, i cili implementon kapacitetet e mëposhtme (kod burimor), ):
- marrjen e tĂ« dhĂ«nave nga api-server-i k8s (marrja e listĂ«s sĂ« namespace-ve, deploymentsâŠ)
- proksionimi i pyetjeve në prometheus-datasource (i cila zgjidhet në cilësimet e pluginit për çdo klaster të caktuar) dhe formatimi i përgjigjeve për përdorim në të dhëna si në faqet statike ashtu edhe në tabelat e kontrollit.
- aktualizimi i të dhënave në faqet statike të pluginëve (me një refresh rate të caktuar).
- trajtim i pyetjeve për formimin e listës së template në grafana-dashboards (metoda .metriFindQuery())



- testimi i lidhjes me klasterin përfundimtar k8s.
testDatasource(){
let url = '/api/v1/namespaces';
let _url = this.url;
if(this.accessViaToken)
_url += '/__proxy';
_url += url;
return this.backendSrv.datasourceRequest({
url: _url,
method: "GET",
headers: {"Content-Type": 'application/json'}
})
.then(response => {
if (response.status === 200) {
return {status: "success", message: "Data source is OK", title: "Success"};
}else{
return {status: "error", message: "Data source is not OK", title: "Error"};
}
}, error => {
return {status: "error", message: "Data source is not OK", title: "Error"};
})
}NjĂ« moment interesant, sipas mendimit tonĂ«, Ă«shtĂ« implementimi i mekanizmit tĂ« autentikimit dhe autorizimit pĂ«r datasource. Si rregull, nga kutia pĂ«r konfigurimin e aksesit nĂ« burimin e fundit tĂ« tĂ« dhĂ«nave, ne mund tĂ« pĂ«rdorim komponentin e integruar tĂ« Grafana â datasourceHttpSettings. Me kĂ«tĂ« komponent, mund tĂ« konfigurojmĂ« aksesin nĂ« burimin http tĂ« tĂ« dhĂ«nave duke treguar url-nĂ« dhe parametrat themelorĂ« tĂ« autentikimit/autorizimit: emrin e pĂ«rdoruesit â fjalĂ«kalimin, ose client-cert/client-key. PĂ«r tĂ« implementuar mundĂ«sinĂ« e konfigurimit tĂ« aksesit me anĂ« tĂ« bearer-token (standard de facto pĂ«r k8s), duhej tĂ« bĂ«heshin disa ndryshime.
Për të zgjidhur këtë detyrë, mund të përdorim mekanizmin e integruar të Grafana "Plugin Routes" (lexoni më shumë në ). Në konfigurimet e datasource tonë, mund të shpallim një grup rregullash për routing, të cilat do të trajtohen nga serveri proxy i grafana. Për shembull, për çdo endpoint të veçantë, ekziston mundësia për të vendosur headers ose url me mundësinë e template-izimit, të dhënat për të cilat mund të merren nga fushat jsonData dhe secureJsonData (për ruajtjen e fjalëkalimeve ose tokeneve në formë të enkriptuar). Në shembullin tonë, kërkesat e tipit /__proxy/api/v1/namespaces do të proksohen në url përkatës
/api/v1/namespaces me caktimin e titullit Authorization: Bearer.


Natyrisht, për të punuar me api-serverin k8s, na nevojitet një përdorues me qasje readonly, manifestet për krijimin e të cilit mund t'i gjeni gjithashtu në .
Pjesa 5: lëshohet

Pasi të shkruani plugin-in tuaj për Grafana, natyrisht do të dëshironi ta publikoni atë për akses të hapur. Në Grafana ka një bibliotekë plugin-esh, e cila është e aksesueshme në lidhjen
Për ta bërë plugin-in tuaj të aksesueshëm në dyqanin zyrtar, duhet të bëni PR në , duke shtuar në skedarin repo.json përmbajtjen si:

ku version është versioni i plugin-it tuaj, url është lidhja në depo, dhe commit është hash i commit-it, sipas të cilit do të jetë e aksesueshme versioni specifike i plugin-it.
Dhe do të shihni një imazh të shkëlqyer si:

Të dhënat për të do të grumbullohen automatikisht nga Readme.md juaj, Changelog.md dhe skedari plugin.json me përshkrimin e plugin-it.
Pjesa 6: përfundimet
Ne kemi vazhduar zhvillimin e pluginit tonĂ« pas lançimit. Tani po punojmĂ« pĂ«r monitorimin e saktĂ« tĂ« pĂ«rdorimit tĂ« burimeve tĂ« nodit tĂ« klasterit, pĂ«r implementimin e karakteristikave tĂ« reja pĂ«r pĂ«rmirĂ«simin e pĂ«rvojĂ«s sĂ« pĂ«rdoruesit, si dhe pĂ«r tĂ« trajtuar njĂ« numĂ«r tĂ« madh feedback-u qĂ« kemi marrĂ« pas instalimeve tĂ« pluginit nga klientĂ«t tanĂ« dhe nga probleme tĂ« ngritura nĂ« GitHub (nĂ«se lini njĂ« problem ose njĂ« kĂ«rkesĂ« pĂ«r tĂ«rheqje, do tĂ« jem shumĂ« i lumtur đ ).
Shpresojmë që ky artikull t'ju ndihmojë të kuptoni një mjet të mrekullueshëm si Grafana dhe, ndoshta, të shkruani pluginin tuaj të vet.
Faleminderit!)
Burimi: habr.com
