Sviluppu di un plugin per Grafana: una storia di big shots

Salut à tutti ! Uni pochi mesi fà, avemu lanciatu u nostru novu prughjettu open-source in pruduzzione - u plugin Grafana per monitorà i kubernetes, chì avemu chjamatu DevOpsProdigy KubeGraf. U codice fonte di u plugin hè dispunibule à repository publicu nantu à GitHub. È in questu articulu vulemu sparte cun voi a storia di cumu avemu creatu u plugin, quale arnesi avemu utilizatu è chì trappule avemu scontru durante u prucessu di sviluppu. Andemu!

Part 0 - introduttu: cumu avemu ghjuntu à questu puntu?

L'idea di scrive u nostru propiu plugin per Grafan hè ghjunta à noi per accidente. A nostra sucietà hà monitoratu prughjetti web di diversi livelli di cumplessità per più di 10 anni. Duranti stu tempu, avemu accumulatu una grande quantità di cumpetenza, casi interessanti è sperienza in l'usu di diversi sistemi di surviglianza. È à un certu puntu avemu dumandatu: "Ci hè un strumentu magicu per u seguimentu di Kubernetes, cusì chì, cum'è dicenu, "imposta è scurdate"? Combinazione Prometheus + Grafana. E cum'è suluzioni pronti per questa pila, ci hè un grande inseme di diversi tipi di strumenti: prometheus-operator, un set di kubernetes-mixin dashboards, grafana-kubernetes-app.

U plugin grafana-kubernetes-app pareva esse l'opzione più interessante per noi, ma ùn hè micca supportatu per più di un annu è, in più, ùn pò micca travaglià cù novi versioni di node-exporter è kube-state-metrics. È à un certu puntu avemu decisu: "Ùn duvemu micca fà a nostra propria decisione?"

Chì idee avemu decisu di implementà in u nostru plugin:

  • visualizazione di a "mappa di l'applicazioni": presentazione conveniente di l'applicazioni in u cluster, raggruppati per spazii di nomi, implementazioni ...;
  • visualizazione di cunnessione cum'è "implementazione - serviziu (+ porti)".
  • visualizazione di a distribuzione di l'applicazioni di cluster in i nodi di cluster.
  • cullizzioni di metriche è infurmazioni da parechje fonti: Prometheus è k8s api server.
  • surviglianza sia di a parte di l'infrastruttura (usu di u tempu di CPU, memoria, sottosistema di discu, rete) è logica di l'applicazione - pods di statu di salute, nùmeru di rèpliche dispunibili, infurmazione nantu à passà e teste di vivacità / prontezza.

Parte 1: Cosa hè un "plugin Grafana"?

Da un puntu di vista tecnicu, u plugin per Grafana hè un controller angular, chì hè guardatu in u cartulare di dati Grafana (/var/grafana/plugins/ /dist/module.js) è pò esse caricatu cum'è un modulu SystemJS. Ancu in questu repertoriu deve esse un schedariu plugin.json chì cuntene tutte e meta infurmazione nantu à u vostru plugin: nome, versione, tipu di plugin, ligami à u repository / situ / licenza, dipendenze, etc.

Sviluppu di un plugin per Grafana: una storia di big shots
modulu.ts

Sviluppu di un plugin per Grafana: una storia di big shots
plugin.json

Comu pudete vede in a screenshot, avemu specificatu plugin.type = app. Perchè i plugins per Grafana ponu esse di trè tipi:

panel francese: u tipu più cumuni di plugin - hè un pannellu per visualizà ogni metrica, utilizatu per custruisce diversi dashboards.
fonte di dati: plugin connector à qualchì fonte di dati (per esempiu, Prometheus-datasource, ClickHouse-datasource, ElasticSearch-datasource).
A app: Un plugin chì permette di custruisce a vostra propria applicazione front-end in Grafana, creà e vostre propie pagine html è accede manualmente à a fonte di dati per visualizà diverse dati. Inoltre, i plugins di altri tipi (datasource, panel) è parechji dashboards ponu esse utilizati cum'è dependenzii.

Sviluppu di un plugin per Grafana: una storia di big shots
Esempiu di dipendenze di plugin cù type=app.

Pudete aduprà JavaScript è TypeScript cum'è lingua di prugrammazione (avemu sceltu). Preparazione per i plugins hello-world di ogni tipu chì pudete truvà u ligame: stu repository cuntene un gran numaru di starter-packs (ci hè ancu un esempiu sperimentale di un plugin in React) cù costruttori preinstallati è cunfigurati.

Parte 2 : priparà l'ambiente lucale

Per travaglià nantu à u plugin, naturalmente avemu bisognu di un cluster kubernetes cù tutti l'arnesi preinstallati: prometheus, node-exporter, kube-state-metrics, grafana. L'ambienti deve esse stallatu rapidamente, facilmente è naturali, è per assicurà a ricarica in calda, u repertoriu di dati Grafana deve esse muntatu direttamente da a macchina di u sviluppatore.

A manera più còmuda, in u nostru parè, di travaglià in u locu cù kubernetes hè minikube. U prossimu passu hè di stallà a cumminazzioni Prometheus + Grafana cù prometheus-operator. IN stu articulu U prucessu di installà prometheus-operator in minikube hè descrittu in detail. Per attivà a persistenza, deve stabilisce u paràmetru persistenza : vera in u schedariu charts/grafana/values.yaml, aghjunghje u vostru propiu PV è PVC è specificate in u paràmetru persistence.existingClaim

U nostru script di lanciamentu finale di minikube pare cusì:

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

Parte 3: sviluppu attuale

Mudellu d'ughjettu

In preparazione per l'implementazione di u plugin, avemu decisu di descriverà tutte l'entità Kubernetes basi chì avemu da travaglià in forma di classi TypeScript: pod, implementazione, daemonset, statefulset, job, cronjob, service, node, namespace. Ognuna di queste classi eredita da a classa BaseModel cumuni, chì descrive u custruttore, u distruttore, i metudi per l'aghjurnamentu è a visibilità di cambià. Ognuna di e classi descrive relazioni nidificate cù altre entità, per esempiu, una lista di pods per una entità di implementazione di tipu.

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 = [];
   }
}

Cù l'aiutu di getters è setters, pudemu vede o stabilisce e metriche di l'entità chì avemu bisognu in una forma cunvene è leghjite. Per esempiu, output formatatu di nodi CPU allocabili:

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

pagine

Una lista di tutte e nostre pagine di plugin hè inizialmente descritta in u nostru pluing.json in a sezione di dipendenze:

Sviluppu di un plugin per Grafana: una storia di big shots

In u bloccu per ogni pagina duvemu indicà u NOME PAGINA (tandu serà cunvertitu in una slug da quale sta pagina serà accessibile); u nome di u cumpunente rispunsevuli di u funziunamentu di sta pagina (a lista di cumpunenti hè esportata à module.ts); indicà u rolu d'utilizatore per quale u travagliu cù sta pagina hè dispunibule è i paràmetri di navigazione per a barra laterale.

In u cumpunente rispunsevuli di u funziunamentu di a pagina, avemu da stabilisce templateUrl, passendu quì u percorsu à u schedariu html cù marcatura. Dentru u controller, attraversu l'iniezione di dependenza, pudemu accede à 2 servizii angulari impurtanti:

  • backendSrv - un serviziu chì furnisce interazzione cù u servitore API Grafana;
  • datasourceSrv - un serviziu chì furnisce interazzione lucale cù tutte e fonti di dati installate in u vostru Grafana (per esempiu, u metudu .getAll() - torna una lista di tutte e fonti di dati installate; .get() ) - restituisce un oggettu di istanza di una fonte di dati specifica.

Sviluppu di un plugin per Grafana: una storia di big shots

Sviluppu di un plugin per Grafana: una storia di big shots

Sviluppu di un plugin per Grafana: una storia di big shots

Parte 4: fonte di dati

Da u puntu di vista di Grafana, datasource hè esattamente u stessu plugin cum'è tutti l'altri: hà u so propiu puntu d'entrata module.js, ci hè un schedariu cù meta informazione plugin.json. Quandu u sviluppu di un plugin cù tipu = app, pudemu interagisce cù i dui fonti di dati esistenti (per esempiu, prometheus-datasource) è u nostru propiu, chì pudemu almacenà direttamente in u repertoriu di plugin (dist/datasource/*) o installà cum'è una dependenza. In u nostru casu, a fonte di dati vene cù u codice plugin. Hè ancu necessariu avè un mudellu config.html è un controller ConfigCtrl, chì serà utilizatu per a pagina di cunfigurazione di l'istanza di datasource è u controller di Datasource, chì implementa a logica di a vostra datasource.

In u plugin KubeGraf, da u puntu di vista di l'interfaccia d'utilizatore, a fonte di dati hè una istanza di un cluster kubernetes chì implementa e seguenti capacità (u codice fonte hè dispunibule Member):

  • cullezzione di dati da u k8s api-server (ottene una lista di spazii di nomi, implementazioni ...)
  • richieste di proxy à prometheus-datasource (chì hè sceltu in i paràmetri di u plugin per ogni cluster specificu) è e risposti di furmatu per utilizà e dati sia in pagine statiche sia in dashboards.
  • aghjurnà e dati nantu à e pagine di plugin statiche (cù una freccia di rinfrescante stabilita).
  • processà e dumande per generà un fogliu di mudellu in grafana-dashboards (metudu metriFindQuery())

Sviluppu di un plugin per Grafana: una storia di big shots

Sviluppu di un plugin per Grafana: una storia di big shots

Sviluppu di un plugin per Grafana: una storia di big shots

  • prova di cunnessione cù u 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"};
       })
}

Un puntu interessante separatu, in u nostru parè, hè l'implementazione di un mecanismu d'autentificazione è d'autorizazione per a datasource. Di genere, fora di a scatula, pudemu usà u cumpunente Grafana integratu datasourceHttpSettings per cunfigurà l'accessu à a fonte di dati finali. Utilizendu stu cumpunente, pudemu cunfigurà l'accessu à a fonti di dati http specificendu l'url è i paràmetri di autentificazione / auturizazione di basa: login-password, o client-cert/client-key. Per implementà a capacità di cunfigurà l'accessu cù un token di portatore (u standard di facto per k8s), avemu avutu à fà un pocu tweaking.

Per risolve stu prublema, pudete aduprà u mecanismu integratu di Grafana "Plugin Routes" (più ditaglii à pagina di documentazione ufficiale). In i paràmetri di a nostra fonti di dati, pudemu dichjarà un settore di reguli di routing chì serà trattatu da u servitore proxy grafana. Per esempiu, per ogni puntu finale individuale hè pussibule stabilisce headers o urls cù a pussibilità di mudelli, dati per quale pò esse pigliatu da i campi jsonData è secureJsonData (per almacenà password o tokens in forma criptata). In u nostru esempiu, dumande cum'è /__proxy/api/v1/namespaces serà proxy à l'url di a forma
/api/v8/namespaces cù l'Authorization: Bearer header.

Sviluppu di un plugin per Grafana: una storia di big shots

Sviluppu di un plugin per Grafana: una storia di big shots

Naturalmente, per travaglià cù u servitore api k8s avemu bisognu di un utilizatore cù accessu solu in lettura, manifesti per creà chì pudete truvà ancu in codice fonte plugin.

Parte 5: liberazione

Sviluppu di un plugin per Grafana: una storia di big shots

Una volta chì avete scrittu u vostru propiu plugin Grafana, naturalmente vulete rende dispunibule publicamente. In Grafana questa hè una biblioteca di plugins dispunibili quì grafana.com/grafana/plugins

Per chì u vostru plugin sia dispunibule nantu à a tenda ufficiale, avete bisognu di fà un PR in stu repositoryaghjustendu cuntenutu cum'è questu à u schedariu repo.json:

Sviluppu di un plugin per Grafana: una storia di big shots

induve a versione hè a versione di u vostru plugin, url hè un ligame à u repository, è commit hè l'hash di u commit per quale una versione specifica di u plugin serà dispunibule.

È à l'output vi vede una maravigliosa stampa cum'è:

Sviluppu di un plugin per Grafana: una storia di big shots

I dati per questu seranu automaticamente pigliati da u vostru Readme.md, Changelog.md è u schedariu plugin.json cù a descrizzione di u plugin.

Parte 6: invece di cunclusioni

Ùn avemu micca cessatu di sviluppà u nostru plugin dopu a liberazione. È avà travagliammu per monitorà currettamente l'usu di risorse di i nodi di cluster, introducendu novi funzioni per migliurà UX, è ancu raking in una grande quantità di feedback ricevuti dopu a stallazione di u plugin sia da i nostri clienti sia da e persone in GitHub (se lasciate). u vostru prublema o pull request, seraghju assai felice :)

Speremu chì questu articulu vi aiuterà à capisce un strumentu cusì maravigliu cum'è Grafana è, forsi, scrive u vostru propiu plugin.

Grazie!)

Source: www.habr.com

Cumprate un hosting affidabile per i siti cù prutezzione DDoS, servitori VPS VDS 🔥 Cumprate un hosting di siti web affidabile cù prutezzione DDoS, servitori VPS VDS | ProHoster