Zhvillimi i një shtojce për Grafana: një histori e goditjeve të mëdha

Pershendetje te gjitheve! Disa muaj më parë, ne nisëm në prodhim projektin tonë të ri me burim të hapur - shtojcën Grafana për monitorimin e kubernetes, të cilën e quajtëm DevOpsProdigy KubeGraf. Kodi burimor i shtojcës është i disponueshëm në depo publike në GitHub. Dhe në këtë artikull ne duam të ndajmë me ju historinë se si krijuam shtojcën, çfarë mjetesh përdorëm dhe çfarë grackash hasëm gjatë procesit të zhvillimit. Shkojme!

Pjesa 0 - hyrëse: si arritëm në këtë pikë?

Ideja për të shkruar shtojcën tonë për Grafan na erdhi krejt rastësisht. Kompania jonë ka monitoruar projekte në internet të niveleve të ndryshme të kompleksitetit për më shumë se 10 vjet. Gjatë kësaj kohe, ne kemi grumbulluar një sasi të madhe ekspertize, raste interesante dhe përvojë në përdorimin e sistemeve të ndryshme të monitorimit. Dhe në një moment ne pyetëm veten: "A ka një mjet magjik për monitorimin e Kubernetes, në mënyrë që, siç thonë ata, "vendosni dhe harroni atë"?". Standardi i industrisë për monitorimin e k8s, natyrisht, ka qenë prej kohësh Kombinimi Prometheus + Grafana. Dhe si zgjidhje të gatshme për këtë pirg, ekziston një grup i madh mjetesh të llojeve të ndryshme: prometheus-operator, një grup tabelash kubernetes-mixin, grafana-kubernetes-app.

Shtojca grafana-kubernetes-app dukej se ishte opsioni më interesant për ne, por nuk është mbështetur për më shumë se një vit dhe, për më tepër, nuk mund të funksionojë me versionet e reja të node-exporter dhe kube-state-metrics. Dhe në një moment vendosëm: "A nuk duhet të marrim vendimin tonë?"

Cilat ide vendosëm të zbatonim në shtojcën tonë:

  • vizualizimi i "hartës së aplikacionit": prezantim i përshtatshëm i aplikacioneve në grup, të grupuara sipas hapësirave të emrave, vendosjeve...;
  • vizualizimi i lidhjeve si "vendosja - shërbimi (+portet)".
  • vizualizimi i shpërndarjes së aplikacioneve të grupimeve nëpër nyjet e grupimeve.
  • mbledhja e metrikës dhe informacionit nga disa burime: Prometheus dhe serveri k8s api.
  • monitorimi i pjesës së infrastrukturës (përdorimi i kohës së CPU, memoria, nënsistemi i diskut, rrjeti) dhe logjika e aplikacionit - pods-at e statusit shëndetësor, numri i kopjeve të disponueshme, informacioni për kalimin e testeve të gjallërisë/gadishmërisë.

Pjesa 1: Çfarë është një "shtojcë Grafana"?

Nga pikëpamja teknike, shtojca për Grafana është një kontrollues këndor, i cili ruhet në drejtorinë e të dhënave Grafana (/var/grafana/plugins/ /dist/module.js) dhe mund të ngarkohet si një modul SystemJS. Gjithashtu në këtë direktori duhet të ketë një skedar plugin.json që përmban të gjitha informacionet meta në lidhje me shtojcën tuaj: emrin, versionin, llojin e shtojcës, lidhjet me depon/faqen/licencën, varësitë, etj.

Zhvillimi i një shtojce për Grafana: një histori e goditjeve të mëdha
modul.ts

Zhvillimi i një shtojce për Grafana: një histori e goditjeve të mëdha
plugin.json

Siç mund ta shihni në pamjen e ekranit, ne specifikuam plugin.type = app. Sepse shtojcat për Grafana mund të jenë të tre llojeve:

panel: lloji më i zakonshëm i shtojcave - është një panel për vizualizimin e çdo metrike, që përdoret për të ndërtuar panele të ndryshme.
Burim i të dhënave: lidhës i shtojcës me disa burime të dhënash (për shembull, Prometheus-datasource, ClickHouse-datasource, ElasticSearch-datasource).
app: Një shtesë që ju lejon të ndërtoni aplikacionin tuaj frontend brenda Grafana, të krijoni faqet tuaja html dhe të përdorni manualisht burimin e të dhënave për të vizualizuar të dhëna të ndryshme. Gjithashtu, shtojcat e llojeve të tjera (burimi i të dhënave, paneli) dhe panelet e ndryshme mund të përdoren si varësi.

Zhvillimi i një shtojce për Grafana: një histori e goditjeve të mëdha
Shembuj të varësive të shtojcave me tip=app.

Ju mund të përdorni JavaScript dhe TypeScript si gjuhë programimi (ne e zgjodhëm atë). Përgatitje për shtojcat hello-world të çdo lloji që mundeni gjeni lidhjen: kjo depo përmban një numër të madh paketash fillestare (madje ekziston një shembull eksperimental i një shtojce në React) me ndërtues të para-instaluar dhe të konfiguruar.

Pjesa 2: përgatitja e mjedisit lokal

Për të punuar në shtojcën, natyrisht na duhet një grup kubernetes me të gjitha mjetet e parainstaluara: prometheus, node-exporter, kube-state-metrics, grafana. Mjedisi duhet të konfigurohet shpejt, lehtë dhe natyrshëm dhe për të siguruar rifreskimin e nxehtë, direktoria e të dhënave Grafana duhet të montohet drejtpërdrejt nga makina e zhvilluesit.

Mënyra më e përshtatshme, sipas mendimit tonë, për të punuar në nivel lokal me kubernetes është minikube. Hapi tjetër është instalimi i kombinimit Prometheus + Grafana duke përdorur operatorin prometheus. NË Ky artikull Procesi i instalimit të operatorit prometheus në minikube është përshkruar në detaje. Për të aktivizuar qëndrueshmërinë, duhet të vendosni parametrin këmbëngulje: e vërtetë në skedarin charts/grafana/values.yaml, shtoni PV dhe PVC tuaj dhe specifikoni ato në parametrin persistence.existingClaim

Skripti ynë i fundit i nisjes së minikube duket si ky:

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 aktual

Modeli i objektit

Në përgatitje për zbatimin e shtojcës, 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 prej këtyre klasave trashëgon nga klasa e zakonshme BaseModel, e cila përshkruan konstruktorin, destruktorin, metodat për përditësimin dhe ndërrimin e dukshmërisë. Secila nga klasat përshkruan marrëdhëniet e ndërlidhura me entitete të tjera, për shembull, një listë pods për një entitet të tipit të vendosjes.

import {Pod} from "./pod";
import {Service} from "./service";
import {BaseModel} from './traits/baseModel';

export class Deployment extends BaseModel{
   pods: Array<Pod>;
   services: Array<Service>;

   constructor(data: any){
       super(data);
       this.pods = [];
       this.services = [];
   }
}

Me ndihmën e marrësve dhe vendosësve, ne mund të shfaqim ose vendosim metrikat e entitetit që na nevojiten në një formë të përshtatshme dhe të lexueshme. Për shembull, prodhimi i formatuar i nyjeve të ndara të CPU:

get cpuAllocatableFormatted(){
   let cpu = this.data.status.allocatable.cpu;
   if(cpu.indexOf('m') > -1){
       cpu = parseInt(cpu)/1000;
   }
   return cpu;
}

Faqet

Një listë e të gjitha faqeve tona të shtojcave përshkruhet fillimisht në pluing.json në seksionin e varësive:

Zhvillimi i një shtojce për Grafana: një histori e goditjeve të mëdha

Në bllokun për secilën faqe duhet të tregojmë EMRI FAQES (më pas do të shndërrohet në një slug me të cilin kjo faqe do të jetë e aksesueshme); emri i komponentit përgjegjës për funksionimin e kësaj faqeje (lista e komponentëve eksportohet në modul.ts); duke treguar rolin e përdoruesit për të cilin ofrohet puna me këtë faqe dhe cilësimet e navigimit për shiritin anësor.

Në komponentin përgjegjës për funksionimin e faqes, duhet të vendosim templateUrl, duke kaluar atje shtegun e skedarit html me shënim. Brenda kontrolluesit, nëpërmjet injektimit të varësisë, ne mund të aksesojmë deri në 2 shërbime të rëndësishme këndore:

  • backendSrv - një shërbim që ofron ndërveprim me serverin API Grafana;
  • datasourceSrv - një shërbim që ofron ndërveprim lokal me të gjitha burimet e të dhënave të instaluara në Grafana-n tuaj (për shembull, metoda .getAll() - kthen një listë të të gjitha burimeve të instaluara të të dhënave; .get( ) - kthen një objekt shembulli të një burimi specifik të dhënash.

Zhvillimi i një shtojce për Grafana: një histori e goditjeve të mëdha

Zhvillimi i një shtojce për Grafana: një histori e goditjeve të mëdha

Zhvillimi i një shtojce për Grafana: një histori e goditjeve të mëdha

Pjesa 4: Burimi i të dhënave

Nga këndvështrimi i Grafana-s, burimi i të dhënave është saktësisht i njëjti shtojcë si të gjithë të tjerët: ka modulin e vet të pikës hyrëse.js, ka një skedar me informacion meta plugin.json. Kur zhvillojmë një shtojcë me tip = aplikacion, ne mund të ndërveprojmë si me burimet ekzistuese të të dhënave (për shembull, prometheus-burimi i të dhënave) ashtu edhe me tonat, të cilat mund t'i ruajmë drejtpërdrejt në direktorinë e shtojcave (dist/burimi i të dhënave/*) ose ta instalojmë si një varësi. Në rastin tonë, burimi i të dhënave vjen me kodin e shtojcës. Është gjithashtu e nevojshme të keni një shabllon config.html dhe një kontrollues ConfigCtrl, i cili do të përdoret për faqen e konfigurimit të shembullit të burimit të të dhënave dhe kontrolluesin e burimit të të dhënave, i cili zbaton logjikën e burimit tuaj të të dhënave.

Në shtojcën KubeGraf, nga pikëpamja e ndërfaqes së përdoruesit, burimi i të dhënave është një shembull i një grupi kubernetes që zbaton aftësitë e mëposhtme (kodi burimor është i disponueshëm по ссылке):

  • mbledhja e të dhënave nga serveri api k8s (duke marrë një listë të hapësirave të emrave, vendosjet...)
  • proksimi i kërkesave për burimin e të dhënave prometheus (i cili zgjidhet në cilësimet e shtojcave për çdo grup specifik) dhe formatimi i përgjigjeve për të përdorur të dhënat si në faqet statike ashtu edhe në panele kontrolli.
  • përditësimi i të dhënave në faqet statike të shtojcave (me një normë të caktuar rifreskimi).
  • përpunimi i pyetjeve për të gjeneruar një fletë shabllon në grafana-dashboards (metoda metriFindQuery())

Zhvillimi i një shtojce për Grafana: një histori e goditjeve të mëdha

Zhvillimi i një shtojce për Grafana: një histori e goditjeve të mëdha

Zhvillimi i një shtojce për Grafana: një histori e goditjeve të mëdha

  • testi i lidhjes me grupin përfundimtar të 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ë pikë më vete interesante, për mendimin tonë, është zbatimi i një mekanizmi vërtetimi dhe autorizimi për burimin e të dhënave. Në mënyrë tipike, jashtë kutisë, ne mund të përdorim komponentin e integruar Grafana datasourceHttpSettings për të konfiguruar aksesin në burimin përfundimtar të të dhënave. Duke përdorur këtë komponent, ne mund të konfigurojmë qasjen në burimin e të dhënave http duke specifikuar url-në dhe cilësimet bazë të vërtetimit/autorizimit: login-password, ose client-cert/client-key. Për të zbatuar aftësinë për të konfiguruar aksesin duke përdorur një token bartës (standardi de fakto për k8s), na u desh të bënim një ndryshim të vogël.

Për të zgjidhur këtë problem, mund të përdorni mekanizmin e integruar Grafana "Plugin Routes" (më shumë detaje në faqja zyrtare e dokumentacionit). Në cilësimet e burimit tonë të të dhënave, ne mund të deklarojmë një sërë rregullash të rrugëtimit që do të përpunohen nga serveri proxy grafana. Për shembull, për çdo pikë përfundimtare individuale është e mundur të vendosni tituj ose url me mundësinë e shabllonit, të dhënat për të cilat mund të merren nga fushat jsonData dhe safeJsonData (për ruajtjen e fjalëkalimeve ose shenjave në formë të koduar). Në shembullin tonë, pyetjet si /__proxy/api/v1/namespaces do të përafrohet me url-në e formularit
/api/v8/namespaces me autorizimin: titulli i bartësit.

Zhvillimi i një shtojce për Grafana: një histori e goditjeve të mëdha

Zhvillimi i një shtojce për Grafana: një histori e goditjeve të mëdha

Natyrisht, për të punuar me serverin api k8s na duhet një përdorues me qasje vetëm për lexim, manifeste për krijimin e të cilave mund t'i gjeni edhe në kodi burim i shtojcës.

Pjesa 5: lirimi

Zhvillimi i një shtojce për Grafana: një histori e goditjeve të mëdha

Pasi të keni shkruar shtojcën tuaj Grafana, natyrisht do të dëshironi ta bëni atë të disponueshme për publikun. Në Grafana kjo është një bibliotekë e shtojcave të disponueshme këtu grafana.com/grafana/plugins

Në mënyrë që shtojca juaj të jetë e disponueshme në dyqanin zyrtar, duhet të bëni një PR këtë depoduke shtuar përmbajtje si kjo në skedarin repo.json:

Zhvillimi i një shtojce për Grafana: një histori e goditjeve të mëdha

ku versioni është versioni i shtojcës suaj, url-ja është një lidhje për në depo dhe commit është hash-i i commit-it për të cilin do të jetë i disponueshëm një version specifik i shtojcës.

Dhe në dalje do të shihni një foto të mrekullueshme si:

Zhvillimi i një shtojce për Grafana: një histori e goditjeve të mëdha

Të dhënat për të do të merren automatikisht nga skedari juaj Readme.md, Changelog.md dhe plugin.json me përshkrimin e shtojcës.

Pjesa 6: në vend të përfundimeve

Ne nuk ndaluam së zhvilluari shtojcën tonë pas lëshimit. Dhe tani ne po punojmë në monitorimin e saktë të përdorimit të burimeve të nyjeve të grupimeve, duke prezantuar veçori të reja për të përmirësuar UX, dhe gjithashtu grumbullojmë një sasi të madhe reagimesh të marra pas instalimit të shtojcës si nga klientët tanë ashtu edhe nga njerëzit në GitHub (nëse largoheni problemi juaj ose kërkesa juaj tërheqëse, do të jem shumë i lumtur :)

Shpresojmë që ky artikull t'ju ndihmojë të kuptoni një mjet kaq të mrekullueshëm si Grafana dhe, ndoshta, të shkruani shtojcën tuaj.

Faleminderit!)

Burimi: www.habr.com

Shto një koment