Zhvillimi i një plugin-i për Grafana: historia e mësimeve të marra

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 DevOpsProdigy KubeGraf. Kodi burimor i plugin-it Ă«shtĂ« nĂ« dispozicion nĂ« repo publik nĂ« GitHub. 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ë.

Zhvillimi i një plugin-i për Grafana: historia e mësimeve të marra
module.ts

Zhvillimi i një plugin-i për Grafana: historia e mësimeve të marra
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.

Zhvillimi i një plugin-i për Grafana: historia e mësimeve të marra
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Ă« gjĂ«nden nĂ« lidhje: 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ë minikube. Hapi tjetër është të instalohet lidhja Prometheus + Grafana me anë të prometheus-operator. Në këtë artikull 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.L

Pjesa 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:

Zhvillimi i një plugin-i për Grafana: historia e mësimeve të marra

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.

Zhvillimi i një plugin-i për Grafana: historia e mësimeve të marra

Zhvillimi i një plugin-i për Grafana: historia e mësimeve të marra

Zhvillimi i një plugin-i për Grafana: historia e mësimeve të marra

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 në lidhje):

  • 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())

Zhvillimi i një plugin-i për Grafana: historia e mësimeve të marra

Zhvillimi i një plugin-i për Grafana: historia e mësimeve të marra

Zhvillimi i një plugin-i për Grafana: historia e mësimeve të marra

  • 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ë faqen zyrtare të dokumentacionit). 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.

Zhvillimi i një plugin-i për Grafana: historia e mësimeve të marra

Zhvillimi i një plugin-i për Grafana: historia e mësimeve të marra

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ë kodin burimor të plugin-it.

Pjesa 5: lansohet

Zhvillimi i një plugin-i për Grafana: historia e mësimeve të marra

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 grafana.com/grafana/plugins

Për ta bërë plugin-in tuaj të aksesueshëm në dyqanin zyrtar, duhet të bëni PR në këtë depo, duke shtuar në skedarin repo.json përmbajtjen si kjo:

Zhvillimi i një plugin-i për Grafana: historia e mësimeve të marra

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:

Zhvillimi i një plugin-i për Grafana: historia e mësimeve të marra

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

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster