PĂ«rshĂ«ndetje tĂ« gjithĂ«ve! Disa muaj mĂ« parĂ« ne lançuam nĂ« prodhim projektin tonĂ« tĂ« ri open-source â plugin-in Grafana pĂ«r monitorimin e Kubernetes, tĂ« cilin e quajtĂ«m . Kodi burimor i plugin-it Ă«shtĂ« nĂ« dispozicion nĂ« . NĂ« kĂ«tĂ« artikull ne duam tĂ« ndajmĂ« me ju historinĂ« e mĂ«nyrĂ«s se si e krijuam plugin-in, cilat mjete pĂ«rdorĂ«m dhe me cilat vĂ«shtirĂ«si u pĂ«rballĂ«m gjatĂ« zhvillimit. Le tĂ« fillojmĂ«!
Pjesa 0 â hyrje: si e arritĂ«m deri kĂ«tu?
Ideja për të shkruar plugin-in tonë për Grafanën 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 fituar një bagazh të madh ekspertize, rastesh interesante, dhe përvojash në përdorimin e sistemeve të ndryshme të monitorimit. Ndërsa një moment ne na erdhi në mendje pyetja: "A ekziston ndonjë mjet magjik për monitorimin e Kubernetes-it, që, siç thuhet, 'e vendos dhe harro'"? Standardi industrial për monitorimin e k8s, natyrisht, është bashkimi Prometheus + Grafana. Dhe për zgjidhjet e gatshme për këtë stack ekziston një grup i madh mjetesh të ndryshme: prometheus-operator, grup dashboard-esh kubernetes-mixin, aplikacioni grafana-kubernetes.
Opsioni më interesant për ne dukej të ishte plugin-i grafana-kubernetes-app, por ai nuk është mbështetur për më shumë se një vit dhe, përveç kësaj, nuk punon me versionet e reja të node-exporter dhe kube-state-metrics. Ndërsa një moment vendosëm: "A nuk do ta bënim ne zgjidhjen tonë?"
Cilat ide vendosëm të realizojmë në plugin-in tonë:
- vizualizimi i 'hartĂ«s sĂ« aplikacionit': pĂ«rfaqĂ«sim i pĂ«rshtatshĂ«m i aplikacioneve nĂ« kluster, tĂ« grupuara sipas namespace-ve, deployment-eveâŠ;
- vizualizimi i lidhjeve tĂ« tipit 'deployment â shĂ«rbim (+ports)'.
- vizualizimi i shpërndarjes së aplikacioneve të klusterit sipas nod-eve të klusterit.
- mbledhja e metrikave dhe informacionit nga disa burime: Prometheus dhe serveri i API të k8s.
- monitorimi i pjesĂ«s infrastrukturore (pĂ«rdorimi i kohĂ«s sĂ« procesorit, memories, sistemit disk, 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 këndvështrimi teknik, një plugin për Grafana është një kontrollues angular që ruhet në direktorinë data të Grafanës (/var/grafana/plugins/<your_plugin_name>/dist/module.js) dhe mund të ngarkohet si një modul SystemJS. Gjithashtu, në këtë direktor duhet të jetë një skedar plugin.json, që përmban të gjitha metainformacionet për plugin-in tuaj: emri, versioni, tipi i plugin-it, lidhjet me depot/sitë/licencë, varësitë dhe kështu me radhë.

module.ts

plugin.json
Siç shihet në foto, ne kemi caktuar plugin.type = app. Sepse plugin-et për Grafana mund të jenë të tre llojeve:
paneli: tipi mĂ« i zakonshĂ«m i plugin-eve â pĂ«rfaqĂ«son njĂ« panel pĂ«r vizualizimin e disa metrikave, pĂ«rdoret pĂ«r ndĂ«rtimin e disa dashboard-eve tĂ« ndryshme.
datasource: plugin-connector në një burim të dhënash (për shembull, Prometheus-datasource, ClickHouse-datasource, ElasticSearch-datasource).
app: plugin që ju lejon të ndërtoni aplikacionin tuaj të frontend-it brenda Grafana, të krijoni faqet tuaja html dhe të bëni kërkesa manuale në datasource për vizualizimin e disa të dhënave të ndryshme. Gjithashtu, si varësi mund të përdoren plugin-e të lloje të tjera (datasource, panel) dhe dashboard-e të ndryshme.

Shembulli i varësive të plugin-it me type = app.
Si gjuhĂ« programimi mund tĂ« pĂ«rdoret si JavaScript, ashtu edhe TypeScript (ne e kemi zgjedhur atĂ«). Skellet pĂ«r plugin-e hello-world tĂ« çdo lloji mund tĂ« : nĂ« kĂ«tĂ« depo paraqitet njĂ« numĂ«r i madh starter-packâash (madje ka edhe njĂ« shembull eksperimental plugin-i nĂ« React) me ndĂ«rtues tĂ« parainstaluar dhe tĂ« konfiguruar.
Pjesa 2: përgatitja e mjedisit lokal
PĂ«r tĂ« punuar nĂ« plugin, natyrisht, na nevojitet njĂ« grup kubernetes me tĂ« gjitha mjete tĂ« parainstaluara: prometheus, node-exporter, kube-state-metrics, grafana. Mjedisi duhet tĂ« konfigurohet shpejt, lehtĂ«sisht dhe pa probleme, dhe pĂ«r tĂ« siguruar hot-reload, ĐŽĐžŃĐ”ĐșŃoria e tĂ« dhĂ«nave tĂ« Grafana duhet tĂ« montohet pĂ«rmes kompjuterit tĂ« zhvilluesit.
Më i rehatshmi, sipas mendimit tonë, është . Hapi tjetër është të instalohet lidhja Prometheus + Grafana me anë të prometheus-operator. Në përshkruhet në detaje procesi i instalimit të prometheus-operator në minikube. Për të aktivizuar persistencën, duhet të vendosni parametrin persistence: true në skedarin charts/grafana/values.yaml, shtoni PV dhe PVC tuaj të vetëdijshëm dhe tregoni ato në parametrin persistence.existingClaim
Skema përfundimtare e nisjes së 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 implementimin e plugin-it, ne vendosëm të përshkruajmë të gjitha entitetet bazë të Kubernetes me të cilat do të punojmë në formën e klasave TypeScript: pod, deployment, daemonset, statefulset, job, cronjob, service, node, namespace. Secila nga këto klasa trashëgon nga klasa e përbashkët BaseModel, e cila përshkruan konstruktorin, destruktorin dhe metodat për përditësimin dhe ndryshimin e dukshmërisë. Në secilën nga klasat përshkruhen marrëdhëniet e ngulitura me entitete të tjera, për shembull, lista e pod-eve për 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 anĂ« tĂ« getterâave dhe setterâave, ne mund tĂ« nxjerrim ose vendosim metrikat e nevojshme tĂ« entiteteve nĂ« njĂ« format tĂ« pĂ«rshtatshĂ«m dhe tĂ« lexueshĂ«m. PĂ«r shembull, output-i i formatizuar i 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 në seksionin e varësive:

Në bllokun për secilën faqe, ne duhet të specifikojmë EMRIN E FAQES (ky do të konvertohet më pas në slug, me të cilin do të jetë e accesueshme kjo faqe); emrin e komponentit, i cili është përgjegjës për funksionimin e kësaj faqe (lista e komponentëve eksporton në module.ts); përcaktimin e rolit të përdoruesit, për të cilin është e aksesuar puna me këtë faqe dhe konfigurimet e navigimit për panelin anësor.
Në komponentin që është përgjegjës për funksionimin e faqes, ne duhet të vendosim templateUrl, duke kaluar aty rrugën deri në skedarin html me markup. Brenda kontrolluesit, përmes injeksionit të varësive, ne mund të kemi qasje në 2 shërbime të rëndësishme të angular:
- backendSrv â shĂ«rbimi qĂ« siguron ndĂ«rveprimin me serverin api tĂ« Grafana;
- datasourceSrv â shĂ«rbimi qĂ« siguron ndĂ«rveprimin lokal me tĂ« gjitha datasource-t qĂ« janĂ« instaluar nĂ« Grafana tuaj (pĂ«r shembull, metoda .getAll() â kthen njĂ« listĂ« tĂ« tĂ« gjitha datasource-ve tĂ« instaluara; .get() â kthen objektin-instancĂ«n e njĂ« datasource-i tĂ« caktuar.



Pjesa 4: datasource
Sipas Grafana, një burim të dhënash është i njëjtë si çdo plugin tjetër: ai ka hyrjen e tij module.js, ka një skedë me metainformata plugin.json. Kur zhvillojmë një plugin me tipin = app, mund të interaktojmë me burime ekzistuese të dhënash (p.sh. prometheus-datasource) si dhe me të tuat, të cilat mund t'i mbajmë direkt në direktorinë e plugin-it (dist/datasource/*) ose t'i installojmë si varësi. Në rastin tonë, burimi i të dhënave vjen së bashku me kodin e plugin-it. Gjithashtu, është e domosdoshme që të kemi një model config.html dhe kontrolluesin ConfigCtrl, të cilat do të përdoren për faqen e konfigurimit të instancës së burimit të të dhënave dhe kontrolluesin e Burimit të të Dhënave, në të cilin implementohet logjika e funksionimit të burimit të dhënave.
Në plugin-in KubeGraf, nga pikëpamja e ndërfaqes së përdoruesit, burimi i të dhënave përfaqëson një instancë të klasterit kubernetes, në të cilin janë implementuar funksionalitetet e mëposhtme (kodin burimor e ka në dispozicion ):
- marrja e tĂ« dhĂ«nave nga api-server i k8s (marrja e listĂ«s sĂ« namespace-ve, deploymenteveâŠ)
- proksimi i kërkesave për burimin e të dhënave prometheus (i zgjedhur në konfigurimet e plugin-it për çdo klaster specifik) dhe formatimi i përgjigjeve për përdorimin e të dhënave si në faqet statike ashtu edhe në panelët e kontrollit.
- përditësimi i të dhënave në faqet statike të plugin-it (me një kohë të caktuar refresh rate).
- përpunimi i kërkesave për formimin e listës së templates 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: "Burimi i të dhënave është OK", title: "Sukses"};
}else{
return {status: "error", message: "Burimi i të dhënave nuk është OK", title: "Gabim"};
}
}, error => {
return {status: "error", message: "Burimi i të dhënave nuk është OK", title: "Gabim"};
})
}NjĂ« moment interesant, sipas mendimit tonĂ«, Ă«shtĂ« implementimi i mekanizmit tĂ« autentifikimit dhe autorizimit pĂ«r datasource. Zakonisht, nga kutia, pĂ«r konfigurimin e aksesit nĂ« burimin e fundit tĂ« tĂ« dhĂ«nave, mund tĂ« pĂ«rdorim komponentin e integruar tĂ« Grafana â datasourceHttpSettings. Me kĂ«tĂ« komponent mund tĂ« konfigurojmĂ« qasjen nĂ« burimin e tĂ« dhĂ«nave http, duke specifikuar url dhe parametrat bazĂ« tĂ« autentifikimit/ autorizimit: emri i pĂ«rdoruesit - fjalĂ«kalimi, ose client-cert/client-key. PĂ«r tĂ« realizuar mundĂ«sinĂ« e konfigurimit tĂ« qasjes me tokenin bearer (standard de facto pĂ«r k8s), duhej tĂ« bĂ«hej pak "kimistrie".
Për zgjidhjen e kësaj çështjeje mund të përdorim mekanizmin e integruar të Grafana "Plugin Routes" (më shumë në ). Në cilësimet e datasource-it tonë mund të shpallim një grup rregullash rruge, të cilat do të përpunohen nga serveri proxy i grafana. Për shembull, për çdo endpoint të veçantë ekziston mundësia e vendosjes së kokave ose url me mundësinë e templating, 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ë shkruar). Në shembullin tonë, kërkesat si /__proxy/api/v1/namespaces do të proksohen në url si
/api/v1/namespaces me vendosjen e kokës Authorization: Bearer.


Natyrisht, për të punuar me serverin api të k8s, na nevojitet një përdorues me akses vetëm për lexim, manifestet për krijimin e të cilit mund t'i gjeni gjithashtu në .
Pjesa 5: lansohet

Pasi të shkruani plugin-in tuaj për Grafana, natyrisht do të dëshironit ta publikoni atë në mënyrë të hapur. Në Grafana ka një bibliotekë plugins që ë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 kjo:

ku version â Ă«shtĂ« versioni i plugin-it tuaj, url â lidhja pĂ«r depo, dhe commit â hash i commit-it, me tĂ« cilin do tĂ« jetĂ« e aksesueshme versioni specifike e plugin-it.
Dhe në fund do të shihni një pamje të mrekullueshme si kjo:

Të dhënat për të do të dihen automatikisht nga Readme.md, Changelog.md dhe skedari plugin.json që përshkruan plugin-in.
Pjesa 6: në vend të përfundimeve
Ne e kemi ndaluar zhvillimin e plugin-it tonĂ« pas lançimit. Aktualisht po punojmĂ« pĂ«r monitorimin e saktĂ« tĂ« pĂ«rdorimit tĂ« burimeve tĂ« nyjave tĂ« klasterit, implementimin e veçorive tĂ« reja pĂ«r tĂ« pĂ«rmirĂ«suar pĂ«rvojĂ«n e pĂ«rdoruesit, si dhe po shqyrtojmĂ« njĂ« sasi tĂ« madhe tĂ« reagimeve qĂ« kemi marrĂ« pas instalimeve tĂ« plugin-it nga klientĂ«t tanĂ«, si dhe nga çështjet e raportuara nĂ« GitHub (nĂ«se lini njĂ« çështje ose njĂ« kĂ«rkesĂ« tĂ«rheqjeje, do tĂ« isha shumĂ« i lumtur đ ).
Shpresojmë që ky artikull t'ju ndihmojë të kuptoni një mjet kaq të mrekullueshëm si Grafana dhe, ndoshta, të shkruani plugin-in tuaj të vet.
Faleminderit!)
Burimi: habr.com
