Moien alleguer! Virun e puer MĂ©int hu mir eisen neien Open-Source Projet an d'Produktioun lancĂ©iert - de Grafana Plugin fir d'Iwwerwaachung vu Kuberneten, dee mir genannt hunn . De Plugin Quellcode ass verfĂŒgbar op . An an dĂ«sem Artikel wĂ«lle mir mat Iech d'Geschicht deelen wĂ©i mir de Plugin erstallt hunn, wĂ©i eng Tools mir benotzt hunn a wĂ©i eng Falen mir am EntwĂ©cklungsprozess begĂ©int hunn. A lass!
Deel 0 - Aféierung: Wéi si mir op dëse Punkt komm?
D'Iddi fir eisen eegene Plugin fir Grafan ze schreiwen ass bei eis zimmlech zoufÀlleg komm. Eis Firma iwwerwaacht Webprojete vu verschiddene Komplexitéitsniveauen fir méi wéi 10 Joer. WÀrend dëser ZÀit hu mir eng grouss Quantitéit un Expertise gesammelt, interessant FÀll an Erfarung beim Gebrauch vu verschiddene Iwwerwaachungssystemer. An iergendwann hu mir eis gefrot: "Gëtt et e magescht Instrument fir d'Iwwerwaachung vu Kubernetes, sou datt, wéi se soen, "set et a vergiess et"? Prometheus + Grafana Kombinatioun. A wéi fÀerdeg Léisunge fir dëse Stack gëtt et e grousse Set vu verschiddenen Tools: Prometheus-Operateur, eng Rei vu kubernetes-mixin Dashboards, Grafana-kubernetes-App.
De Grafana-kubernetes-App Plugin schéngt déi interessantst Optioun fir eis ze sinn, awer et ass net méi wéi engem Joer ënnerstëtzt ginn an och kann net mat neie Versioune vun Node-Exporter a Kube-State-Metriken funktionnéieren. An iergendwann hu mir décidéiert: "Sollte mir net eis eegen Entscheedung treffen?"
Wéi eng Iddien hu mir decidéiert an eisem Plugin ëmzesetzen:
- Visualiséierung vun der "Applikatiounskaart": praktesch Presentatioun vun Uwendungen am Cluster, gruppéiert no Nummraim, Deployment ...;
- Visualiséierung vu Verbindunge wéi "Deployment - Service (+Ports)".
- Visualiséierung vun der Verdeelung vu Clusterapplikatiounen iwwer Clusternoden.
- Sammlung vu Metriken an Informatioun aus verschiddene Quellen: Prometheus an k8s API Server.
- Iwwerwaachung vu bĂ©iden Infrastrukturen Deel (Notzung vun der CPU ZĂ€it, ErĂ«nnerung, Disk Subsystem, Netzwierk) an Uwendungslogik - Gesondheetsstatus Pods, Zuel vun verfĂŒgbare Repliken, Informatioun iwwer d'Liewer / Bereetschaftstester.
Deel 1: Wat ass e "Grafana Plugin"?
Aus technescher Siicht ass de Plugin fir Grafana e WĂ©nkelkontroller, deen am Grafana Datenverzeichnis (/var/grafana/plugins/ /dist/module.js) a kann als SystemJS Modul geluede ginn. Och an dĂ«sem Verzeechnes sollt et eng plugin.json Datei sinn, dĂ©i all Meta-Informatioun iwwer Ăre Plugin enthĂ€lt: Numm, Versioun, Plugin-Typ, Linken op de Repository/Site/Lizenz, OfhĂ€ngegkeeten, a sou weider.

module.ts

plugin.json
Wéi Dir am Screenshot gesitt, hu mir plugin.type = app spezifizéiert. Well Plugins fir Grafana kënnen vun drÀi Aarte sinn:
Kompletéiert: déi allgemeng Aart vu Plugin - et ass e Panel fir all Metrik ze visualiséieren, benotzt fir verschidde Dashboards ze bauen.
Datenquell: Plugin Connector op eng Datenquell (zum Beispill Prometheus-Datenquelle, ClickHouse-Datenquelle, ElasticSearch-Datenquelle).
App: E Plugin deen Iech erlaabt Ăr eege Frontend-Applikatioun bannent Grafana ze bauen, Ăr eege HTML SĂ€iten ze kreĂ©ieren an manuell op d'Datequelle ze kommen fir verschidden DonnĂ©eĂ«n ze visualisĂ©ieren. Och Plugins vun aneren Typen (Datenquelle, Panel) a verschidde Dashboards kĂ«nnen als OfhĂ€ngegkeet benotzt ginn.

Beispill Plugin OfhÀngegkeeten mat Typ = App.
Dir kënnt souwuel JavaScript wéi och TypeScript als Programméierungssprooch benotzen (mir hunn et gewielt). Virbereedunge fir Hallo-Welt Plugins vun all Typ Dir kënnt : Dëse Repository enthÀlt eng grouss Zuel vu Starter-PÀck (et gëtt souguer en experimentellt Beispill vun engem Plugin am React) mat virinstalléierten a konfiguréierte Builder.
Deel 2: Virbereedung vun der lokaler Ămwelt
Fir um Plugin ze schaffen, brauche mir natierlech e Kubernetes-Cluster mat all de virinstallĂ©ierten Tools: Prometheus, Node-Exporter, Kube-State-Metrics, Grafana. D'Ămfeld soll sĂ©ier, einfach an natierlech ageriicht ginn, a fir Hot-Reload ze garantĂ©ieren, sollt de Grafana Dateverzeichnis direkt vun der Maschinn vum EntwĂ©ckler montĂ©iert ginn.
DĂ©i bequemste ManĂ©ier, eiser Meenung no, fir lokal mat kubernetes ze schaffen ass . De nĂ€chste SchrĂ«tt ass d'Prometheus + Grafana Kombinatioun mat Prometheus-Operator z'installĂ©ieren. IN De Prozess vun der Installatioun vum Prometheus-Bedreiwer op Minikube gĂ«tt am Detail beschriwwen. Fir Persistenz z'aktivĂ©ieren, musst Dir de Parameter setzen Persistenz: wouer an den Charts/grafana/values.yaml Datei, fĂŒĂŒgt Ăren eegene PV a PVC derbĂ€i a spezifizĂ©iert se am Persistence.existingClaim Parameter
Eis lescht Minikube Startskript gesÀit esou aus:
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.LDeel 3: tatsÀchlech Entwécklung
Objektmodell
Als Virbereedung fir d'Ămsetzung vum Plugin hu mir beschloss all Basis Kubernetes EntitĂ©iten ze beschreiwen, mat deenen mir a Form vun TypeScript Klassen schaffen: Pod, Deployment, Daemonset, Statefulset, Job, Cronjob, Service, Node, Nummraum. All eenzel vun dĂ«se Klassen ierft aus der gemeinsamer BaseModel Klass, dĂ©i beschreift de constructor, destructor, Methode fir AktualisĂ©ierung opgetrueden an Wiessel VisibilitĂ©it. Jiddereng vun de Klassen beschreift nested Relatiounen mat aneren EntitĂ©ite, Zum Beispill, eng LĂ«scht vun pods fir eng EntitĂ©it vun Typ Deployment.
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 = [];
}
}Mat der Hëllef vu Getters a Setzer kënne mir d'Entitéitsmetriken weisen oder setzen déi mir brauchen an enger praktescher a liesbarer Form. Zum Beispill, formatéiert Ausgang vun allocatable CPU Noden:
get cpuAllocatableFormatted(){
let cpu = this.data.status.allocatable.cpu;
if(cpu.indexOf('m') > -1){
cpu = parseInt(cpu)/1000;
}
return cpu;
}SĂ€iten
Eng Lëscht vun all eise Plugin SÀiten gëtt ufanks an eisem pluing.json an der OfhÀngegkeetssektioun beschriwwen:

Am Block fir all SĂ€it musse mir de PAGE NAME uginn (en gĂ«tt dann an e Slug Ă«mgewandelt, duerch deen dĂ«s SĂ€it zougĂ€nglech ass); den Numm vun der Komponent verantwortlech fir d'Operatioun vun dĂ«ser SĂ€it (d'LĂ«scht vun de Komponenten gĂ«tt op module.ts exportĂ©iert); dĂ©i d'Benotzerroll uginn fir dĂ©i d'Aarbecht mat dĂ«ser SĂ€it verfĂŒgbar ass an d'Navigatiounsastellunge fir d'Sidebar.
An der Komponent verantwortlech fir d'Operatioun vun der SÀit, musse mir TemplateUrl setzen, de Wee an d'HTML-Datei mat Markup laanschtgoen. Bannen am Controller, duerch OfhÀngegkeetsinjektioun, kënne mir bis zu 2 wichteg Wénkelservicer zougrÀifen:
- backendSrv - e Service deen Interaktioun mam Grafana API Server ubitt;
- datasourceSrv - e Service deen lokal Interaktioun mat all Datenquellen ubitt, dĂ©i an Ărem Grafana installĂ©iert sinn (zum Beispill d'.getAll() Method - gĂ«tt eng LĂ«scht vun all installĂ©ierten Datequellen zrĂ©ck; .get( ) - gĂ«tt en Instanzobjekt vun enger spezifescher Datenquell zrĂ©ck.



Deel 4: Daten Quell
Vun Grafana Siicht, Datasource genee dĂ©i selwecht Plugin wĂ©i all dĂ©i aner: et huet seng eege EntrĂ©en Punkt module.js, et gĂ«tt e Fichier mat Meta Informatiounen plugin.json. Wann Dir e Plugin mat Typ = App entwĂ©ckelen, kĂ«nne mir souwuel mat existĂ©ierende Datequellen interagĂ©ieren (zum Beispill, prometheus-datasource) an eis eegen, dĂ©i mir direkt am Plugin-Verzeichnis spĂ€icheren (dist/datasource/*) oder als OfhĂ€ngegkeet installĂ©ieren. An eisem Fall kĂ«nnt d'Datenquelle mam Plugin Code. Et ass och noutwendeg eng config.html Schabloun an e ConfigCtrl Controller ze hunn, dĂ©i fir d'Datenquell Instanz KonfiguratiounssĂ€it an den Datasource Controller benotzt gĂ«tt, deen d'Logik vun Ărer Datequell implementĂ©iert.
Am KubeGraf Plugin, aus der User-Interface Siicht, ass d'Datenquell eng Instanz vun engem kubernetes-Cluster deen dĂ©i folgend FĂ€egkeeten implementĂ©iert (Quellcode ass verfĂŒgbar ):
- sammelen Daten vum k8s api-Server (kréien eng Lëscht vun Nummraim, Deployment ...)
- Proxying Ufroe fir prometheus-Datenquelle (dĂ©i an de Plugin-Astellunge fir all spezifesche Cluster ausgewielt gĂ«tt) an d'FormatĂ©ierung vun Ăntwerte fir Daten souwuel op statesche SĂ€iten an an Dashboards ze benotzen.
- d'Aktualiséierung vun Daten op statesche Plugin SÀiten (mat engem festgeluegten Erfrëschungsrate).
- Veraarbechtung vun Ufroen fir e Schablounblat a Grafana-Dashboards ze generéieren (metriFindQuery () Method)



- Verbindung Test mat der Finale k8s StÀrekoup.
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"};
})
}En separaten interessante Punkt, eiser Meenung no, ass d'Ămsetzung vun engem Authentifikatiouns- an Autorisatiounsmechanismus fir d'Datequelle. Typesch, aus der KĂ«scht, kĂ«nne mir dĂ©i agebaute Grafana Komponent DatasourceHttpSettings benotzen fir den Zougang zu der definitiver Datequell ze konfigurĂ©ieren. Mat dĂ«ser Komponente kĂ«nne mir den Zougang zu der http Datenquell konfigurĂ©ieren andeems Dir d'URL an d'Basis Authentifikatioun / Autorisatioun Astellunge spezifizĂ©iert: Login-Passwuert oder Client-cert/client-key. Fir d'FĂ€egkeet ze realisĂ©ieren den Zougang mat engem Bearer Token ze konfigurĂ©ieren (de de facto Standard fir k8s), hu mir e bĂ«ssen Tweaking misse maachen.
Fir dëse Problem ze léisen, kënnt Dir den agebaute Grafana "Plugin Routes" Mechanismus benotzen (méi Detailer op ). An den Astellunge vun eiser Datessource kënne mir eng Rei vu Routingregelen deklaréieren, déi vum Grafana Proxy Server veraarbecht ginn. Zum Beispill, fir all eenzel Endpunkt ass et méiglech Header oder URLen mat der Méiglechkeet vun Template ze setzen, Daten fir déi aus de jsonData a secureJsonData Felder geholl kënne ginn (fir Passwierder oder Tokens a verschlësselte Form ze spÀicheren). An eisem Beispill, Ufroen wéi /__proxy/api/v1/namespaces gëtt op d'URL vum Formulaire proxéiert
/api/v8/namespaces mat der Autorisatioun: Bearer Header.


Natierlech, fir mam k8s API Server ze schaffen, brauche mir e Benotzer mat nëmmen liesen Zougang, Manifestatiounen fir ze kreéieren déi Dir och fannt .
Deel 5: FrÀisetzung

Wann Dir Ăren eegene Grafana Plugin geschriwwen hutt, wĂ«llt Dir se natierlech Ă«ffentlech verfĂŒgbar maachen. Zu Grafana ass dĂ«st eng BibliothĂ©ik vu Plugins dĂ©i hei verfĂŒgbar sinn
Fir datt Ăre Plugin am offiziellen GeschĂ€ft verfĂŒgbar ass, musst Dir e PR maachen andeems Dir Inhalt wĂ©i dĂ«sen an d'repo.json Datei addĂ©iert:

wou Versioun d'Versioun vun Ărem Plugin ass, URL ass e Link op de Repository, an commit ass den Hash vum Engagement fir deen eng spezifesch Versioun vum Plugin verfĂŒgbar ass.
An op der Ausgab gesitt Dir eng wonnerbar Bild wéi:

D'DonnĂ©eĂ«n dofir ginn automatesch vun Ărem Readme.md, Changelog.md an der plugin.json Datei mat der Plugin Beschreiwung gegraff.
Deel 6: amplaz Conclusiounen
Mir hunn net opgehalen eise Plugin no der VerĂ«ffentlechung z'entwĂ©ckelen. An elo schaffe mir un der korrekter Iwwerwaachung vun der Notzung vu Ressourcen vu Clusternoden, nei Fonctiounen afĂ©ieren fir d'UX ze verbesseren, an och eng grouss QuantitĂ©it vu Feedback erakommen, dĂ©i no der Installatioun vum Plugin souwuel vun eise Clienten wĂ©i och vu Leit op GitHub (wann Dir verloosst) Ăr Fro oder Pull Ufro, ech wĂ€ert ganz frou sinn :)
Mir hoffen, datt dĂ«sen Artikel Iech hĂ«lleft esou e wonnerbare Tool wĂ©i Grafana ze verstoen an, vlĂ€icht, Ăren eegene Plugin ze schreiwen.
Merci!)
Source: will.com
