Hi kollha! Ftit xhur ilu, nedejna l-proġett ta’ sors miftuħ il-ġdid tagħna fil-produzzjoni - il-plugin Grafana għall-monitoraġġ tal-kubernetes, li sejjaħna . Il-kodiċi tas-sors tal-plugin huwa disponibbli fuq . U f'dan l-artikolu rridu naqsmu miegħek l-istorja ta 'kif ħloqna l-plugin, liema għodod użajna u x'iżvantaġġi ltqajna magħhom matul il-proċess ta' żvilupp. Tlaqna!
Parti 0 - introduzzjoni: kif wasalna sa dan il-punt?
L-idea li niktbu l-plugin tagħna stess għal Grafan waslet lilna pjuttost b'inċident. Il-kumpanija tagħna ilha tissorvelja proġetti tal-web ta’ diversi livelli ta’ kumplessità għal aktar minn 10 snin. Matul dan iż-żmien, akkumulajna ammont kbir ta 'għarfien espert, każijiet interessanti, u esperjenza fl-użu ta' diversi sistemi ta 'monitoraġġ. U f'xi punt staqsejna lilna nfusna: "Hemm għodda maġika għall-monitoraġġ ta 'Kubernetes, sabiex, kif jgħidu, "issettjaha u tinsaha"?".. L-istandard tal-industrija għall-monitoraġġ tal-k8s, ovvjament, ilu żmien twil il- Prometheus + kombinazzjoni Grafana. U bħala soluzzjonijiet lesti għal dan il-munzell, hemm sett kbir ta 'diversi tipi ta' għodod: prometheus-operator, sett ta 'kubernetes-mixin dashboards, grafana-kubernetes-app.
Il-plugin grafana-kubernetes-app deher li kien l-aktar għażla interessanti għalina, iżda ma ġiex appoġġjat għal aktar minn sena u, barra minn hekk, ma jistax jaħdem ma 'verżjonijiet ġodda ta' node-exporter u kube-state-metrics. U f’xi punt iddeċidejna: “M’għandniex nieħdu d-deċiżjoni tagħna stess?”
Liema ideat iddeċidejna li nimplimentaw fil-plugin tagħna:
- viżwalizzazzjoni tal-"mappa tal-applikazzjoni": preżentazzjoni konvenjenti tal-applikazzjonijiet fil-cluster, miġbura minn namespaces, skjeramenti...;
- viżwalizzazzjoni ta' konnessjonijiet bħal "skjerament - servizz (+portijiet)".
- viżwalizzazzjoni tad-distribuzzjoni ta 'applikazzjonijiet cluster madwar cluster nodes.
- ġbir ta 'metriċi u informazzjoni minn diversi sorsi: Prometheus u k8s api server.
- monitoraġġ kemm tal-parti tal-infrastruttura (użu tal-ħin tas-CPU, memorja, subsistema tad-disk, netwerk) kif ukoll loġika tal-applikazzjoni - pods tal-istat tas-saħħa, numru ta 'repliki disponibbli, informazzjoni dwar il-passaġġ tat-testijiet tal-ħajja/prontezza.
Parti 1: X'inhu "Grafana plugin"?
Mil-lat tekniku, il-plugin għal Grafana huwa kontrollur angolari, li huwa maħżun fid-direttorju tad-dejta Grafana (/var/grafana/plugins/ /dist/module.js) u jista' jitgħabba bħala modulu SystemJS. F'dan id-direttorju wkoll għandu jkun hemm fajl plugin.json li jkun fih l-informazzjoni meta kollha dwar il-plugin tiegħek: isem, verżjoni, tip ta 'plugin, links għar-repożitorju/sit/liċenzja, dipendenzi, eċċ.

modulu.ts

plugin.json
Kif tistgħu taraw fil-screenshot, speċifikajna plugin.type = app. Minħabba li l-plugins għal Grafana jistgħu jkunu ta 'tliet tipi:
bord: l-aktar tip komuni ta 'plugin - huwa panel għall-viżwalizzazzjoni ta' kwalunkwe metrika, użata biex tibni diversi dashboards.
sors tad-data: konnettur tal-plugin għal xi sors tad-dejta (pereżempju, Prometheus-datasource, ClickHouse-datasource, ElasticSearch-datasource).
app: Plugin li jippermettilek tibni l-applikazzjoni frontend tiegħek stess ġewwa Grafana, toħloq il-paġni html tiegħek stess u taċċessa manwalment is-sors tad-dejta biex tara dejta varji. Ukoll, plugins ta 'tipi oħra (datasource, panel) u diversi dashboards jistgħu jintużaw bħala dipendenzi.

Eżempju tad-dipendenzi tal-plugin b'tip=app.
Tista 'tuża kemm JavaScript kif ukoll TypeScript bħala lingwa ta' programmar (għażilna). Tħejjijiet għal plugins hello-world ta 'kull tip li tista' : dan ir-repożitorju fih numru kbir ta 'starter-packs (saħansitra hemm eżempju sperimentali ta' plugin f'React) b'bennejja installati minn qabel u kkonfigurati.
Parti 2: it-tħejjija tal-ambjent lokali
Biex naħdmu fuq il-plugin, naturalment għandna bżonn kubernetes cluster bl-għodod kollha installati minn qabel: prometheus, node-exporter, kube-state-metrics, grafana. L-ambjent għandu jiġi stabbilit malajr, faċilment u b'mod naturali, u biex jiġi żgurat hot-reload, id-direttorju tad-dejta Grafana għandu jiġi mmuntat direttament mill-magna tal-iżviluppatur.
L-aktar mod konvenjenti, fl-opinjoni tagħna, biex taħdem lokalment ma 'kubernetes huwa . Il-pass li jmiss huwa li tinstalla l-kombinazzjoni Prometheus + Grafana billi tuża prometheus-operator. IN Il-proċess ta 'installazzjoni ta' prometheus-operator fuq minikube huwa deskritt fid-dettall. Biex tippermetti l-persistenza, trid issettja l-parametru persistenza: vera fil-fajl charts/grafana/values.yaml, żid il-PV u l-PVC tiegħek stess u speċifikahom fil-parametru persistentence.existingClaim
L-iskript tat-tnedija tal-minikube finali tagħna jidher bħal dan:
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.LParti 3: żvilupp attwali
Mudell ta' Għan
Bi tħejjija għall-implimentazzjoni tal-plugin, iddeċidejna li niddeskrivu l-entitajiet bażiċi kollha ta 'Kubernetes li se naħdmu magħhom fil-forma ta' klassijiet TypeScript: pod, deployment, daemonset, statefulset, job, cronjob, service, node, namespace. Kull waħda minn dawn il-klassijiet tirret mill-klassi BaseModel komuni, li tiddeskrivi l-kostruttur, id-distruttur, il-metodi għall-aġġornament u l-bidla tal-viżibilità. Kull waħda mill-klassijiet tiddeskrivi relazzjonijiet nested ma' entitajiet oħra, pereżempju, lista ta 'miżwed għal entità ta' tip skjerament.
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 = [];
}
}Bl-għajnuna ta 'getters u setters, nistgħu nuru jew nissettjaw il-metriċi tal-entità li għandna bżonn f'forma konvenjenti u li tinqara. Pereżempju, output ifformattjat ta' nodi CPU allokabbli:
get cpuAllocatableFormatted(){
let cpu = this.data.status.allocatable.cpu;
if(cpu.indexOf('m') > -1){
cpu = parseInt(cpu)/1000;
}
return cpu;
}paġni
Lista tal-paġni kollha tal-plugins tagħna hija inizjalment deskritta fil-pluing.json tagħna fit-taqsima tad-dipendenzi:

Fil-blokk għal kull paġna rridu nindikaw l-ISEM TAL-PAĠNA (imbagħad tiġi kkonvertita fi slug li biha din il-paġna tkun aċċessibbli); l-isem tal-komponent responsabbli għat-tħaddim ta 'din il-paġna (il-lista tal-komponenti hija esportata lejn module.ts); li jindika r-rwol tal-utent li għalih ix-xogħol ma 'din il-paġna huwa disponibbli u s-settings tan-navigazzjoni għall-sidebar.
Fil-komponent responsabbli għall-operat tal-paġna, irridu nissettjaw templateUrl, u ngħaddu hemm it-triq għall-fajl html b'markup. Ġewwa l-kontrollur, permezz ta 'injezzjoni ta' dipendenza, nistgħu naċċessaw sa 2 servizzi angolari importanti:
- backendSrv - servizz li jipprovdi interazzjoni mas-server tal-API Grafana;
- datasourceSrv - servizz li jipprovdi interazzjoni lokali mas-sorsi tad-data kollha installati fil-Grafana tiegħek (per eżempju, il-metodu .getAll() - jirritorna lista tas-sorsi tad-data kollha installati; .get() ) - jirritorna oġġett ta 'istanza ta' datasource speċifika.



Parti 4: sors tad-dejta
Mill-perspettiva ta' Grafana, id-datasource huwa eżattament l-istess plugin bħall-oħrajn kollha: għandu l-punt tad-dħul tiegħu module.js, hemm fajl b'meta informazzjoni plugin.json. Meta niżviluppaw plugin b'tip = app, nistgħu jinteraġixxu kemm ma 'sorsi tad-data eżistenti (per eżempju, prometheus-datasource) kif ukoll tagħna stess, li nistgħu naħżnu direttament fid-direttorju tal-plugin (dist/datasource/*) jew ninstallaw bħala dipendenza. Fil-każ tagħna, is-sors tad-data jiġi mal-kodiċi tal-plugin. Huwa wkoll meħtieġ li jkollok mudell config.html u kontrollur ConfigCtrl, li se jintużaw għall-paġna tal-konfigurazzjoni tal-istanza tad-datasource u l-kontrollur tad-Datasource, li jimplimenta l-loġika tad-datasource tiegħek.
Fil-plugin KubeGraf, mil-lat tal-interface tal-utent, is-sors tad-dejta huwa eżempju ta’ cluster kubernetes li jimplimenta l-kapaċitajiet li ġejjin (il-kodiċi tas-sors huwa disponibbli ):
- ġbir ta' data mis-server api k8s (kiseb lista ta' namespaces, skjeramenti...)
- proxy talbiet lil prometheus-datasource (li jintgħażel fis-settings tal-plugin għal kull cluster speċifiku) u tweġibiet ifformattjar biex tuża d-dejta kemm f'paġni statiċi kif ukoll f'dashboards.
- aġġornament tad-dejta fuq paġni tal-plugin statiċi (b'rata ta' aġġornament stabbilita).
- l-ipproċessar ta' mistoqsijiet biex jiġġenera folja mudell f'grafana-dashboards (metodu metriFindQuery())



- test ta 'konnessjoni mal-cluster finali 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"};
})
}Punt interessanti separat, fl-opinjoni tagħna, huwa l-implimentazzjoni ta 'mekkaniżmu ta' awtentikazzjoni u awtorizzazzjoni għas-sors tad-data. Tipikament, barra mill-kaxxa, nistgħu nużaw il-komponent Grafana integrat datasourceHttpSettings biex jiġi kkonfigurat l-aċċess għas-sors finali tad-dejta. Billi nużaw dan il-komponent, nistgħu kkonfiguraw l-aċċess għas-sors tad-dejta http billi nispeċifikaw l-url u s-settings bażiċi ta 'awtentikazzjoni/awtorizzazzjoni: login-password, jew client-cert/client-key. Sabiex timplimenta l-abbiltà li tikkonfigura l-aċċess bl-użu ta 'bearer token (l-istandard de facto għal k8s), kellna nagħmlu ftit tweaking.
Biex issolvi din il-problema, tista’ tuża l-mekkaniżmu integrat ta’ Grafana “Rotot tal-Plugin” (aktar dettalji fuq ). Fis-settings tas-sors tad-data tagħna, nistgħu niddikjaraw sett ta 'regoli ta' routing li se jiġu pproċessati mis-server proxy grafana. Pereżempju, għal kull endpoint individwali huwa possibbli li jiġu stabbiliti headers jew urls bil-possibbiltà ta 'templating, li d-dejta tagħhom tista' tittieħed mill-oqsma jsonData u secureJsonData (għall-ħażna ta' passwords jew tokens f'forma kriptata). Fl-eżempju tagħna, mistoqsijiet bħal /__proxy/api/v1/namespaces se jiġi prokurat għall-url tal-formola
/api/v8/namespaces bl-Awtorizzazzjoni: Header Bearer.


Naturalment, biex naħdmu mas-server k8s api għandna bżonn utent b'aċċess għall-qari biss, manifesti għall-ħolqien li tista' ssib ukoll f' .
Parti 5: rilaxx

Ladarba tkun ktibt il-plugin Grafana tiegħek, naturalment tkun trid tagħmilha disponibbli pubblikament. Fi Grafana din hija librerija ta' plugins disponibbli hawn
Sabiex il-plugin tiegħek ikun disponibbli fuq il-maħżen uffiċjali, trid tagħmel PR in billi żżid kontenut bħal dan fil-fajl repo.json:

fejn il-verżjoni hija l-verżjoni tal-plugin tiegħek, l-url hija link għar-repożitorju, u l-commit hija l-hash tal-commit li għalih tkun disponibbli verżjoni speċifika tal-plugin.
U fl-output se tara stampa mill-isbaħ bħal:

Id-dejta għaliha tinqabad awtomatikament minn Readme.md, Changelog.md u l-fajl plugin.json tiegħek bid-deskrizzjoni tal-plugin.
Parti 6: minflok konklużjonijiet
Aħna ma waqfitx niżviluppaw il-plugin tagħna wara r-rilaxx. U issa qed naħdmu biex nissorveljaw b'mod korrett l-użu tar-riżorsi tan-nodi tal-clusters, nintroduċu karatteristiċi ġodda biex intejbu l-UX, u wkoll nirbħu ammont kbir ta' feedback li waslu wara l-installazzjoni tal-plugin kemm mill-klijenti tagħna kif ukoll minn nies fuq GitHub (jekk titlaq il-kwistjoni tiegħek jew it-talba tal-ġibda, inkun kuntent ħafna :)
Nittamaw li dan l-artikolu jgħinek tifhem għodda mill-isbaħ bħal Grafana u, forsi, tikteb il-plugin tiegħek.
Grazzi!)
Sors: www.habr.com
