Kaixo guztioi! Duela hilabete batzuk, gure kode irekiko proiektu berria abiarazi genuen produkziora: kubernetes monitorizatzeko Grafana plugina, deitu genuena.
0. zatia - sarrera: nola iritsi gara honaino?
Grafanerako gure plugina idazteko ideia ustekabean etorri zitzaigun. Gure enpresak 10 urte baino gehiago daramatza konplexutasun maila ezberdineko web proiektuen jarraipena egiten. Denbora horretan, espezializazio, kasu interesgarri eta esperientzia ugari pilatu ditugu hainbat monitorizazio sistema erabiltzen. Eta noizbait galdetu genion geure buruari: βBa al dago Kubernetes monitorizatzeko tresna magikorik, esaten den bezala, βezarri eta ahaztuβ?β. Prometheus + Grafana konbinazioa. Eta pila honetarako prest dauden soluzio gisa, hainbat tresna motako multzo handi bat dago: prometheus-operator, kubernetes-mixin panelen multzoa, grafana-kubernetes-app.
grafana-kubernetes-app plugina aukerarik interesgarriena iruditu zitzaigun, baina urtebete baino gehiago ez da onartzen eta, gainera, ezin du funtzionatu node-exporter eta kube-state-metrics bertsio berriekin. Eta noizbait erabaki genuen: "Ez al genuke gure erabakia hartu behar?"
Zer ideia erabaki genuen gure pluginean ezartzea:
- βaplikazioen mapaβ bistaratzea: klusterreko aplikazioen aurkezpen erosoa, izen-espazioen, inplementazioen... multzokatuta;
- "hedapena - zerbitzua (+portuak)" bezalako konexioen bistaratzea.
- kluster-aplikazioen banaketaren bistaratzea kluster-nodoen artean.
- metrika eta informazio bilketa hainbat iturritatik: Prometheus eta k8s api zerbitzaria.
- Azpiegitura zatiaren (PUZaren denboraren erabilera, memoria, disko azpisistema, sarea) eta aplikazioaren logikaren jarraipena - osasun-egoeraren podak, erabilgarri dauden erreplika kopurua, bizitasun/presttasun probak gainditzeari buruzko informazioa.
1. zatia: Zer da "Grafana plugina"?
Ikuspuntu teknikotik, Grafanarako plugina kontrolagailu angeluarra da, Grafana datuen direktorioan gordetzen dena (/var/grafana/plugins/ /dist/module.js) eta SystemJS modulu gisa kargatu daiteke. Direktorio honetan ere plugin.json fitxategi bat egon beharko litzateke zure pluginari buruzko meta-informazio guztia duena: izena, bertsioa, plugin mota, biltegira/gune/lizentziarako estekak, menpekotasunak eta abar.
modulua.ts
plugin.json
Pantaila-argazkian ikus dezakezun bezala, plugin.type = app zehaztu dugu. Grafanarako pluginak hiru motatakoak izan daitezkeelako:
panel: plugin mota ohikoena - edozein metrika ikusteko panel bat da, hainbat aginte-panel eraikitzeko erabiltzen dena.
datu-iturria: plugin-a datu-iturburu batzuetarako (adibidez, Prometheus-datasource, ClickHouse-datasource, ElasticSearch-datasource).
aplikazioa: Grafana barruan zure frontend aplikazioa eraikitzeko, zure html orriak sortu eta datu-iturburura eskuz sartzeko aukera ematen dizun hainbat datu ikusteko. Gainera, beste mota bateko pluginak (datu iturria, panela) eta hainbat aginte-panel erabil daitezke mendekotasun gisa.
Plugin-mendekotasunen adibidea type=app-rekin.
JavaScript eta TypeScript erabil ditzakezu programazio-lengoaia gisa (guk aukeratu dugu). Ahal duzun edozein motatako hello-world pluginetarako prestaketak
2. zatia: tokiko ingurunea prestatzea
Plugin-a lantzeko, kubernetes kluster bat behar dugu aurrez instalatutako tresna guztiak dituena: prometheus, node-exporter, kube-state-metrics, grafana. Ingurunea azkar, erraz eta modu naturalean konfiguratu behar da, eta beroa birkargatzeko, Grafana datu-direktorioa garatzailearen makinatik zuzenean muntatu behar da.
Gure ustez, kubernetesekin lokalean lan egiteko modurik erosoena da
Gure azken minikube abiarazteko gidoia hauxe da:
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
3. zatia: benetako garapena
Objektu eredua
Plugin-a ezartzeko prestatzeko, TypeScript klaseetan lan egingo ditugun oinarrizko Kubernetes-eko entitate guztiak deskribatzea erabaki dugu: pod, inplementazioa, daemonset, statefulset, job, cronjob, service, node, namespace. Klase horietako bakoitzak BaseModel klase arruntetik heredatzen du, zeinak eraikitzailea, suntsitzailea, eguneratzeko eta ikusgarritasuna aldatzeko metodoak deskribatzen dituena. Klase bakoitzak beste entitate batzuekin habiatutako harremanak deskribatzen ditu, adibidez, inplementazio motako entitate baten pods zerrenda bat.
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 = [];
}
}
Getters eta setter-en laguntzaz, behar ditugun entitate-neurriak forma eroso eta irakurgarri batean bistaratu edo ezarri ditzakegu. Adibidez, eslei daitezkeen CPU-nodoen irteera formatua:
get cpuAllocatableFormatted(){
let cpu = this.data.status.allocatable.cpu;
if(cpu.indexOf('m') > -1){
cpu = parseInt(cpu)/1000;
}
return cpu;
}
artikuluak
Gure plugin orri guztien zerrenda hasiera batean gure pluing.json-en deskribatzen da mendekotasunen atalean:
Orrialde bakoitzeko blokean ORRI IZENA adierazi behar dugu (orrialde hau atzitzeko moduko slug bihurtuko da gero); orrialde honen funtzionamenduaz arduratzen den osagaiaren izena (osagaien zerrenda module.ts-era esportatzen da); orrialde honekin lan egiteko erabilgarri dagoen erabiltzaile-rola eta alboko barrarako nabigazio-ezarpenak adieraziz.
Orriaren funtzionamenduaz arduratzen den osagaian, templateUrl ezarri behar dugu, hor html fitxategirako bidea markatuz pasatuz. Kontrolagailuaren barruan, mendekotasun-injekzio bidez, 2 zerbitzu angelu garrantzitsuetara sar gaitezke:
- backendSrv - Grafana API zerbitzariarekin elkarrekintza eskaintzen duen zerbitzua;
- datasourceSrv - zure Grafanan instalatutako datu-iturburu guztiekin tokiko elkarrekintza eskaintzen duen zerbitzua (adibidez, .getAll() metodoa - instalatutako datu-iturburu guztien zerrenda itzultzen du; .get() ) - datu-iturburu zehatz baten instantzia-objektua itzultzen du.
4. zatia: datu-iturria
Grafanaren ikuspuntutik, datu-iturburua beste guztien plugin bera da: bere sarrera-puntua module.js dauka, meta informazioa plugin.json duen fitxategi bat dago. Type = app-a duen plugin bat garatzean, lehendik dauden datu-iturburuekin (adibidez, prometheus-datasource) eta gurearekin elkarreragin dezakegu, zuzenean pluginen direktorioan (dist/datasource/*) gorde ditzakegu edo mendekotasun gisa instalatu. Gure kasuan, datu-iturburua plugin-kodearekin dator. Era berean, beharrezkoa da config.html txantiloia eta ConfigCtrl kontroladore bat edukitzea, datu-iturburuaren instantzia konfiguratzeko orrialderako eta Datu-iturburuaren kontrolatzailea, zure datu-iturburuaren logika inplementatzen duena.
KubeGraf pluginean, erabiltzailearen interfazearen ikuspuntutik, datu-iturburua kubernetes kluster baten instantzia bat da, honako gaitasun hauek ezartzen dituena (iturburu-kodea eskuragarri dago
- k8s api-zerbitzariaren datuak biltzea (izen-espazioen zerrenda, inplementazioak...)
- Proxy-eskaerak prometheus-datasource-ra (plugin-ezarpenetan hautatzen dena kluster zehatz bakoitzeko) eta formateatzeko erantzunak datuak erabiltzeko orri estatikoetan zein aginte-paneletan.
- plugin-orrialde estatikoetako datuak eguneratzea (ezarritako freskatze-tasa batekin).
- grafana-dashboardetan txantiloi-orri bat sortzeko kontsultak prozesatzea (metriFindQuery() metodoa)
- konexio proba azken k8s klusterrarekin.
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"};
})
}
Aparteko puntu interesgarri bat, gure ustez, datu-iturbururako autentifikazio- eta baimen-mekanismo bat ezartzea da. Normalean, kutxatik kanpo, integratutako Grafana osagaiaren datu-iturburuaHttpSettings erabil dezakegu azken datu-iturbururako sarbidea konfiguratzeko. Osagai hau erabiliz, http datu-iturbururako sarbidea konfiguratu dezakegu url eta oinarrizko autentifikazio/baimen ezarpenak zehaztuz: login-password edo client-cert/client-key. Eramaile-token bat erabiliz sarbidea konfiguratzeko gaitasuna ezartzeko (k8s-en de facto estandarra), doikuntza txiki bat egin behar izan dugu.
Arazo hau konpontzeko, Grafana integratutako "Plugin Ibilbideak" mekanismoa erabil dezakezu (xehetasun gehiago hemen
/api/v8/namespaces Authorization: Bearer goiburuarekin.
Jakina, k8s api zerbitzariarekin lan egiteko, irakurtzeko soilik sarbidea duen erabiltzaile bat behar dugu, sortzeko manifestuak, hemen ere aurki ditzakezunak.
5. zatia: kaleratzea
Zure Grafana plugina idatzi ondoren, publikoki eskuragarri jarri nahi izango duzu. Grafanan hau hemen eskuragarri dagoen pluginen liburutegia da
Zure plugina denda ofizialean eskuragarri egon dadin, PR bat egin behar duzu
non bertsioa zure pluginaren bertsioa den, url biltegirako esteka bat da, eta commit pluginaren bertsio zehatz bat erabilgarri egongo den konpromezuaren hash-a da.
Eta irteeran irudi zoragarri bat ikusiko duzu:
Haren datuak automatikoki jasoko dira zure Readme.md, Changelog.md eta plugin.json fitxategitik plugin deskribapenarekin.
6. zatia: ondorioen ordez
Askatu ondoren ez genuen gure plugina garatzeari utzi. Eta orain kluster-nodoen baliabideen erabilera zuzen kontrolatzen ari gara, UX hobetzeko eginbide berriak sartuz eta plugina instalatu ondoren jasotako iritzi ugari jasotzen ere bai gure bezeroek bai GitHub-eko jendearengandik (irten baduzu. zure arazoa edo tira eskaera, oso pozik egongo naiz :)
Espero dugu artikulu honek Grafana bezalako tresna zoragarri bat ulertzen lagunduko dizula eta, agian, zure plugina idazten.
Eskerrik asko!)
Iturria: www.habr.com