Zhvillimi i një plaku për Grafana: historia e goditjeve të ndjera

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

Zhvillimi i një plaku për Grafana: historia e goditjeve të ndjera
module.ts

Zhvillimi i një plaku për Grafana: historia e goditjeve të ndjera
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.

Zhvillimi i një plaku për Grafana: historia e goditjeve të ndjera
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Ă« gjenden nĂ« linkun: 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ë minikube. Hapi tjetër është të instalojmë setin Prometheus + Grafana përmes prometheus-operator. Në këto artikull ë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.L

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

Zhvillimi i një plaku për Grafana: historia e goditjeve të ndjera

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.

Zhvillimi i një plaku për Grafana: historia e goditjeve të ndjera

Zhvillimi i një plaku për Grafana: historia e goditjeve të ndjera

Zhvillimi i një plaku për Grafana: historia e goditjeve të ndjera

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

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

Zhvillimi i një plaku për Grafana: historia e goditjeve të ndjera

Zhvillimi i një plaku për Grafana: historia e goditjeve të ndjera

Zhvillimi i një plaku për Grafana: historia e goditjeve të ndjera

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

Zhvillimi i një plaku për Grafana: historia e goditjeve të ndjera

Zhvillimi i një plaku për Grafana: historia e goditjeve të ndjera

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

Pjesa 5: lëshohet

Zhvillimi i një plaku për Grafana: historia e goditjeve të ndjera

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

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

Zhvillimi i një plaku për Grafana: historia e goditjeve të ndjera

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:

Zhvillimi i një plaku për Grafana: historia e goditjeve të ndjera

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

Bli njĂ« hosting tĂ« besueshĂ«m pĂ«r faqet me mbrojtje DDoS, VPS VDS serverĂ« đŸ”„ Bli njĂ« hosting tĂ« besueshĂ«m pĂ«r faqet me mbrojtje DDoS, VPS VDS serverĂ« | ProHoster