Vývoj pluginu pro Grafanu: příběh o zkušenostech a obtížích

Ahoj všichni! Před několika měsíci jsme uvedli do produkce náš nový open-source projekt — Grafana plugin pro monitoring Kubernetes, který jsme nazvali DevOpsProdigy KubeGraf. Zdrojový kód pluginu je dostupný v veřejném repozitáři na GitHubu. A v tomto článku bychom se s vámi chtěli podělit o příběh, jak jsme plugin vytvářeli, jaké nástroje jsme používali a s jakými překážkami jsme se během vývoje setkali. Jdeme na to!

Část 0 — úvod: jak jsme se k tomu dostali?

Myšlenka napsat vlastní plugin pro Grafanu nás napadla zcela náhodou. Naše společnost se již více než 10 let zabývá monitoringem webových projektů různé složitosti. Během této doby jsme nashromáždili bohaté zkušenosti, zajímavé případy a zkušenosti s různými monitorovacími systémy. A v určitém okamžiku jsme si položili otázku: „Existuje kouzelný nástroj pro monitoring Kubernetes, který by se dal „nainstalovat a zapomenout“?..“ Průmyslovým standardem pro monitoring k8s je samozřejmě už dlouho spojení Prometheus + Grafana. A pro tuto technologii existuje široká škála různých hotových nástrojů: prometheus-operator, sada dashboardů kubernetes-mixin, grafana-kubernetes-app.

Nejzajímavější možností pro nás se zdál plugin grafana-kubernetes-app, ale už více než rok není udržován a navíc neumí pracovat s novými verzemi node-exportera a kube-state-metrics. A v nějakém okamžiku jsme se rozhodli: „A neudělat si vlastní řešení?“

Jaké nápady jsme se rozhodli realizovat ve svém pluginu:

  • vizualizace „mapy aplikace“: přehledné zobrazení aplikací v clusteru, uspořádaných podle namespace, deploymentů…;
  • vizualizace vztahů typu „deployment — service (+ports)“.
  • vizualizace rozložení aplikací clusteru po nodech clusteru.
  • shromažďování metrik a informací z několika zdrojů: Prometheus a k8s API server.
  • monitoring jak infrastrukturní části (využití procesorového času, paměti, diskového subsystému, sítě), tak logiky aplikací — health-status podů, počet dostupných replik, informace o provádění liveness/readiness testů.

Část 1: Co je to „plugin pro Grafanu“?

Z technického hlediska je plugin pro Grafanu angular-ovladač, který se ukládá do data adresáře Grafany (/var/grafana/plugins/<your_plugin_name>/dist/module.js) a může být načten jako SystemJS modul. Také v tomto adresáři by měl být soubor plugin.json, který obsahuje veškeré meta informace o vašem pluginu: název, verze, typ pluginu, odkazy na repozitář/web/license, závislosti a tak dále.

Vývoj pluginu pro Grafanu: příběh o zkušenostech a obtížích
module.ts

Vývoj pluginu pro Grafanu: příběh o zkušenostech a obtížích
plugin.json

Jak je vidět na screenshotu, uvedli jsme plugin.type = app. Pluginy pro Grafanu mohou mít tři typy:

panel: nejběžnější typ pluginů – představuje panel pro vizualizaci různých metrik, používá se pro vytváření různých dashboardů.
datasource: plugin-konektor k určitému zdroji dat (např. Prometheus-datasource, ClickHouse-datasource, ElasticSearch-datasource).
app: plugin, který vám umožňuje vytvořit svou vlastní frontendovou aplikaci uvnitř Grafany, vytvářet vlastní html stránky a ručně se dotazovat na datasource pro vizualizaci různých dat. Také lze jako závislosti používat jiné typy pluginů (datasource, panel) a různé dashboardy.

Vývoj pluginu pro Grafanu: příběh o zkušenostech a obtížích
Příklad závislostí pluginu s type = app.

Jako programovací jazyk je možné použít jak JavaScript, tak TypeScript (my jsme se rozhodli pro něj). Šablony pro hello-world pluginy jakéhokoli typu můžete najít na odkazu: v tomto repozitáři je prezentováno velké množství starter-packů (je zde dokonce experimentální příklad pluginu na React) s předinstalovanými a nastavenými build systémy.

Část 2: příprava lokálního prostředí

Pro práci na pluginu budeme samozřejmě potřebovat Kubernetes klastr se všemi předinstalovanými nástroji: Prometheus, Node-exporter, Kube-state-metrics, Grafana. Prostředí by mělo být nastaveno rychle, snadno a bezstarostně, a pro zajištění hot-reload by měla být data directory Grafany připojena přímo z vývojářské stanice.

Nejlepším způsobem pro lokální práci s Kubernetes, podle našeho názoru, je minikube. Dalším krokem je instalace spojení Prometheus + Grafana pomocí prometheus-operator. V tomto článku je podrobně popsán proces instalace prometheus-operator na minikube. Pro zapnutí persistentnosti je nutné nastavit parametr persistence: true v souboru charts/grafana/values.yaml, přidat svůj vlastní PV a PVC a uvést je v parametru persistence.existingClaim

Náš finální spouštěcí skript pro minikube vypadá takto:

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

Část 3: přímý vývoj

Objektový model

Jako přípravu na implementaci pluginu jsme se rozhodli popsat všechny základní entity Kubernetes, se kterými budeme pracovat, ve formě TypeScript tříd: pod, deployment, daemonset, statefulset, job, cronjob, service, node, namespace. Každá z těchto tříd dědí od obecné třídy BaseModel, ve které jsou popsány konstruktor, destruktor, metody pro aktualizaci a přepínání viditelnosti. V každé z těchto tříd jsou popsány vnořené vztahy s jinými entitami, například seznam podů u entity typu deployment.

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

export class Deployment extends BaseModel{
   pods: Array;
   services: Array;

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

Pomocí getterů a setterů můžeme zobrazit nebo nastavit potřebné metriky entit v pohodlném a čitelném formátu. Například naformátovaný výstup allocatable cpu nodu:

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

Stránky

Seznam všech stránek našeho pluginu je původně popsán v našem pluing.json v sekci závislostí:

Vývoj pluginu pro Grafanu: příběh o zkušenostech a obtížích

V bloku pro každou stránku musíme uvést NÁZEV STRÁNKY (ten bude pak převeden na slug, podle kterého bude tato stránka dostupná); název komponenty, která zajišťuje funkčnost této stránky (seznam komponentů je exportován v module.ts); specifikaci uživatelské role, pro kterou je práce s touto stránkou dostupná, a nastavení navigace pro postranní panel.

V komponentě, která zajišťuje funkčnost stránky, musíme nastavit templateUrl, kde předáme cestu k html souboru s rozložením. Uvnitř kontroleru, prostřednictvím dependency injection, získáme přístup k 2 důležitým angular službám:

  • backendSrv — služba zajišťující interakci s api serverem Grafany;
  • datasourceSrv — služba zajišťující lokální interakci se všemi datovými zdroji instalovanými ve vaší Grafaně (například metoda .getAll() — vrátí seznam všech nainstalovaných datových zdrojů; .get() — vrátí objekt-instantci konkrétního datového zdroje.

Vývoj pluginu pro Grafanu: příběh o zkušenostech a obtížích

Vývoj pluginu pro Grafanu: příběh o zkušenostech a obtížích

Vývoj pluginu pro Grafanu: příběh o zkušenostech a obtížích

Část 4: datový zdroj

Z pohledu Grafany je datasource stejným typem pluginu jako všechny ostatní: má svůj vstupní bod module.js a soubor s metainformacemi plugin.json. Při vývoji pluginu s typem = app můžeme interagovat jak s již existujícími datasource (například prometheus-datasource), tak s našimi vlastními, které můžeme uložit přímo do adresáře pluginu (dist/datasource/*) nebo je instalovat jako závislost. V našem případě je datasource dodáván spolu s kódem pluginu. Také je nezbytné mít šablonu config.html a kontroler ConfigCtrl, které budou použity pro stránku konfigurace instance datasource a kontroler Datasource, ve kterém je implementována logika fungování vašeho datasource.

V pluginu KubeGraf, z pohledu uživatelského rozhraní, představuje datasource instanci kubernetes-clusteru, v němž jsou implementovány následující funkce (zdrojový kód je k dispozici na odkazu):

  • získávání dat z api-serveru k8s (získání seznamu namespace, deployment...)
  • proxyování požadavků na prometheus-datasource (který se vybírá v nastavení pluginu pro každý konkrétní cluster) a formátování odpovědí pro použití dat jak na statických stránkách, tak v dashboardech.
  • aktualizace dat na statických stránkách pluginu (s nastaveným časovým intervalem obnovování).
  • zpracování požadavků pro generování seznamu šablon v grafana-dashboards (metoda .metriFindQuery())

Vývoj pluginu pro Grafanu: příběh o zkušenostech a obtížích

Vývoj pluginu pro Grafanu: příběh o zkušenostech a obtížích

Vývoj pluginu pro Grafanu: příběh o zkušenostech a obtížích

  • testování připojení k cílovému k8s clusteru.
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: "Datasource je OK", title: "Úspěch"};
           }else{
               return {status: "error", message: "Datasource není OK", title: "Chyba"};
           }
       }, error => {
           return {status: "error", message: "Datasource není OK", title: "Chyba"};
       })
}

Zajímavým aspektem je realizace mechanismu autentizace a autorizace pro datasource. Obvykle můžeme použít integrovanou komponentu Grafana — datasourceHttpSettings pro konfiguraci přístupu k cílovému datovému zdroji. Pomocí této komponenty můžeme nastavit přístup k http-datovému zdroji zadáním url a základních autentizačních/autorizacích nastavení: uživatelské jméno-heslo nebo client-cert/client-key. Aby bylo možné nastavit přístup pomocí bearer-tokenu (de facto standard pro k8s), muselo se trochu "pohrát".

K řešení tohoto úkolu lze použít integrovaný mechanismus Grafana „Plugin Routes“ (podrobněji na oficiální stránce dokumentace). V nastavení našeho datasource můžeme deklarovat sadu pravidel směrování, která budou zpracovávána proxy serverem grafana. Například pro každý jednotlivý endpoint existuje možnost nastavit hlavičky nebo url s možností šablonování, přičemž data mohou být čerpána z polí jsonData a secureJsonData (pro uchování hesel nebo tokenů v zašifrované podobě). V našem příkladu budou požadavky ve formátu /__proxy/api/v1/namespaces procházet na url ve formátu
/api/v1/namespaces s nastavením hlavičky Authorization: Bearer.

Vývoj pluginu pro Grafanu: příběh o zkušenostech a obtížích

Vývoj pluginu pro Grafanu: příběh o zkušenostech a obtížích

Samozřejmě, pro práci s api serverem k8s potřebujeme uživatele s readonly přístupem, manifesty pro jeho vytvoření najdete také v zdrojovém kódu pluginu.

Část 5: vydání

Vývoj pluginu pro Grafanu: příběh o zkušenostech a obtížích

Po napsání vlastního pluginu pro Grafana se samozřejmě budete chtít o něj podělit s veřejností. V Grafana je knihovna pluginů dostupná na odkazu grafana.com/grafana/plugins

Aby byl váš plugin dostupný v oficiálním obchodě, musíte vytvořit PR v tomto repozitáři, přidáním obsahu typu do souboru repo.json:

Vývoj pluginu pro Grafanu: příběh o zkušenostech a obtížích

kde version — verze vašeho pluginu, url — odkaz na repozitář a commit — hash commitu, podle kterého bude dostupná konkrétní verze pluginu.

A na konci uvidíte úžasný obrázek ve formátu:

Vývoj pluginu pro Grafanu: příběh o zkušenostech a obtížích

Data pro něj budou automaticky extrahována z vašeho Readme.md, Changelog.md a souboru plugin.json s popisem pluginu.

Část 6: místo závěrů

Po vydání jsme nepřestali vyvíjet náš plugin. V současné době pracujeme na správném monitorování využití zdrojů uzlů clustera, implementaci nových funkcí pro zlepšení UX a řešíme velké množství zpětné vazby, kterou jsme obdrželi po instalaci pluginu, jak od našich klientů, tak ze záznamů na GitHubu (pokud zanecháte svůj issue nebo pull request, budu velmi rád 🙂 ).

Doufáme, že vám tento článek pomůže pochopit skvělý nástroj, jakým je Grafana, a možná napsat svůj vlastní plugin.

Děkujeme!)

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster