Ahojte všetci! Pred pár mesiacmi sme spustili do produkcie náš nový open-source projekt - plugin Grafana na monitorovanie kubernetes, ktorý sme nazvali
0. časť – úvodná: ako sme sa dostali k tomuto bodu?
Nápad napísať vlastný plugin pre Grafan k nám prišiel celkom náhodou. Naša spoločnosť už viac ako 10 rokov monitoruje webové projekty rôznych úrovní zložitosti. Za tento čas sme nazbierali veľké množstvo odborných znalostí, zaujímavých prípadov a skúseností s používaním rôznych monitorovacích systémov. A v určitom momente sme sa sami seba spýtali: „Existuje magický nástroj na monitorovanie Kubernetes, aby, ako sa hovorí, „nastavil a zabudol“?“.. Priemyselným štandardom pre monitorovanie k8 je, samozrejme, už dlho Kombinácia Prometheus + Grafana. A ako hotové riešenia pre tento zásobník existuje veľká sada rôznych druhov nástrojov: prometheus-operator, sada dashboardov kubernetes-mixin, grafana-kubernetes-app.
Ako najzaujímavejšia možnosť sa nám zdal plugin grafana-kubernetes-app, ktorý však už viac ako rok nie je podporovaný a navyše nevie pracovať s novými verziami node-exporter a kube-state-metrics. A v určitom bode sme sa rozhodli: "Nemali by sme sa rozhodnúť sami?"
Aké nápady sme sa rozhodli implementovať do nášho pluginu:
- vizualizácia „aplikačnej mapy“: pohodlná prezentácia aplikácií v klastri, zoskupených podľa menných priestorov, nasadení...;
- vizualizácia spojení ako „nasadenie – služba (+porty)“.
- vizualizácia distribúcie klastrových aplikácií cez uzly klastra.
- zber metrík a informácií z niekoľkých zdrojov: server Prometheus a k8s api.
- monitorovanie ako časti infraštruktúry (využitie CPU času, pamäte, diskového subsystému, siete), tak aplikačnej logiky - health-status pods, počet dostupných replík, informácie o absolvovaní testov životnosti/pripravenosti.
Časť 1: Čo je to „Grafana plugin“?
Z technického hľadiska je plugin pre Grafana uhlový ovládač, ktorý je uložený v adresári údajov Grafana (/var/grafana/plugins/ /dist/module.js) a možno ho načítať ako modul SystemJS. V tomto adresári by mal byť aj súbor plugin.json obsahujúci všetky meta informácie o vašom plugine: názov, verzia, typ pluginu, odkazy na úložisko/stránku/licenciu, závislosti atď.
modul.ts
plugin.json
Ako môžete vidieť na snímke obrazovky, zadali sme plugin.type = app. Pretože pluginy pre Grafana môžu byť troch typov:
panel: najbežnejší typ pluginu - je to panel na vizualizáciu akýchkoľvek metrík, ktorý sa používa na zostavenie rôznych dashboardov.
Zdroj dát: konektor doplnku k nejakému zdroju údajov (napríklad Prometheus-datasource, ClickHouse-datasource, ElasticSearch-datasource).
aplikácie: Plugin, ktorý vám umožňuje vytvoriť si vlastnú frontendovú aplikáciu v Grafane, vytvoriť si vlastné html stránky a manuálne pristupovať k zdroju údajov na vizualizáciu rôznych údajov. Ako závislosti možno použiť aj pluginy iných typov (zdroj údajov, panel) a rôzne dashboardy.
Príklad závislostí doplnkov s type=app.
Ako programovací jazyk môžete použiť JavaScript aj TypeScript (vybrali sme si ho). Prípravy na hello-world pluginy akéhokoľvek typu
Časť 2: Príprava miestneho prostredia
Na prácu na doplnku prirodzene potrebujeme klaster kubernetes so všetkými predinštalovanými nástrojmi: prometheus, node-exporter, kube-state-metrics, grafana. Prostredie by malo byť nastavené rýchlo, jednoducho a prirodzene a aby sa zabezpečilo rýchle opätovné načítanie, mal by byť dátový adresár Grafana pripojený priamo z vývojárskeho stroja.
Najpohodlnejší spôsob, ako pracovať lokálne s kubernetes, je podľa nášho názoru
Náš posledný spúšťací skript minikube vyzerá 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
Časť 3: skutočný vývoj
Objektový model
V rámci prípravy na implementáciu pluginu sme sa rozhodli popísať všetky základné entity Kubernetes, s ktorými budeme pracovať vo forme tried TypeScript: pod, deployment, daemonset, statefulset, job, cronjob, service, node, namespace. Každá z týchto tried dedí zo spoločnej triedy BaseModel, ktorá popisuje konštruktor, deštruktor, metódy aktualizácie a prepínania viditeľnosti. Každá z tried popisuje vnorené vzťahy s inými entitami, napríklad zoznam modulov pre entitu typu nasadenia.
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 = [];
}
}
Pomocou getterov a nastavovačov vieme zobraziť alebo nastaviť potrebné metriky entity v pohodlnej a čitateľnej forme. Napríklad formátovaný výstup alokovateľných uzlov CPU:
get cpuAllocatableFormatted(){
let cpu = this.data.status.allocatable.cpu;
if(cpu.indexOf('m') > -1){
cpu = parseInt(cpu)/1000;
}
return cpu;
}
stránky
Zoznam všetkých našich stránok doplnkov je na začiatku popísaný v našom súbore pluing.json v sekcii závislostí:
V bloku pre každú stránku musíme uviesť NÁZOV STRÁNKY (ten sa potom skonvertuje na slug, pomocou ktorého bude táto stránka prístupná); názov komponentu zodpovedného za fungovanie tejto stránky (zoznam komponentov je exportovaný do module.ts); označujúce rolu používateľa, pre ktorú je práca s touto stránkou dostupná, a nastavenia navigácie pre bočný panel.
V komponente zodpovednom za fungovanie stránky musíme nastaviť templateUrl a odovzdať tam cestu k súboru html s označením. Vo vnútri ovládača môžeme prostredníctvom vstrekovania závislostí pristupovať až k 2 dôležitým uhlovým službám:
- backendSrv - služba, ktorá poskytuje interakciu so serverom Grafana API;
- datasourceSrv – služba, ktorá poskytuje lokálnu interakciu so všetkými zdrojmi údajov nainštalovanými vo vašej Grafane (napríklad metóda .getAll() – vracia zoznam všetkých nainštalovaných zdrojov údajov; .get( ) - vráti objekt inštancie konkrétneho zdroja údajov.
Časť 4: Zdroj údajov
Z pohľadu Grafany je datasource úplne rovnaký plugin ako všetky ostatné: má svoj vlastný vstupný bod module.js, existuje súbor s meta informáciami plugin.json. Pri vývoji doplnku s type = app môžeme interagovať s existujúcimi zdrojmi údajov (napríklad prometheus-datasource) aj s našimi vlastnými, ktoré môžeme uložiť priamo do adresára pluginu (dist/datasource/*) alebo nainštalovať ako závislosť. V našom prípade sa zdroj údajov dodáva s kódom doplnku. Je tiež potrebné mať šablónu config.html a radič ConfigCtrl, ktorý sa použije na konfiguračnú stránku inštancie zdroja údajov a radič zdroja údajov, ktorý implementuje logiku vášho zdroja údajov.
V doplnku KubeGraf je z pohľadu používateľského rozhrania zdrojom údajov inštancia klastra kubernetes, ktorý implementuje nasledujúce funkcie (zdrojový kód je k dispozícii
- zbieranie údajov z k8s api-serveru (získanie zoznamu menných priestorov, nasadení...)
- proxy požiadavky na prometheus-datasource (ktorý je vybraný v nastaveniach pluginu pre každý konkrétny klaster) a formátovanie odpovedí na použitie údajov na statických stránkach aj v dashboardoch.
- aktualizácia údajov na stránkach statických doplnkov (s nastavenou obnovovacou frekvenciou).
- spracovanie dopytov na generovanie šablóny v grafana-dashboardoch (metóda metriFindQuery())
- test spojenia s finálnym klastrom 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"};
})
}
Samostatným zaujímavým bodom je podľa nášho názoru implementácia autentifikačného a autorizačného mechanizmu pre zdroj údajov. Zvyčajne môžeme použiť vstavaný komponent Grafana datasourceHttpSettings na konfiguráciu prístupu ku konečnému zdroju údajov. Pomocou tohto komponentu môžeme nakonfigurovať prístup k http zdroju údajov zadaním adresy URL a základných nastavení autentifikácie/autorizácie: login-password, alebo client-cert/client-key. Aby sme implementovali možnosť konfigurácie prístupu pomocou nosného tokenu (de facto štandard pre k8), museli sme urobiť malé úpravy.
Na vyriešenie tohto problému môžete použiť vstavaný mechanizmus Grafana „Plugin Routes“ (viac podrobností na
/api/v8/namespaces s hlavičkou Authorization: Bearer.
Na prácu so serverom k8s api samozrejme potrebujeme používateľa s prístupom len na čítanie, manifesty na vytváranie, ktoré nájdete aj v
Časť 5: uvoľnenie
Keď si napíšete svoj vlastný doplnok Grafana, prirodzene ho budete chcieť sprístupniť verejnosti. V Grafane je to knižnica doplnkov dostupných tu
Aby bol váš plugin dostupný v oficiálnom obchode, musíte urobiť PR
kde version je verzia vášho doplnku, url je odkaz na úložisko a commit je hash odovzdania, pre ktorý bude k dispozícii konkrétna verzia doplnku.
A na výstupe uvidíte nádherný obrázok ako:
Údaje preň budú automaticky získané z vášho súboru Readme.md, Changelog.md a súboru plugin.json s popisom pluginu.
Časť 6: namiesto záverov
Po vydaní sme neprestali vyvíjať náš plugin. A teraz pracujeme na správnom monitorovaní využívania zdrojov uzlov klastra, zavádzaní nových funkcií na zlepšenie UX a tiež zbierame veľké množstvo spätnej väzby získanej po inštalácii pluginu od našich klientov aj od ľudí na GitHub (ak odídete váš problém alebo žiadosť o stiahnutie, budem veľmi rád :)
Dúfame, že vám tento článok pomôže pochopiť taký úžasný nástroj, akým je Grafana, a možno si napíšete svoj vlastný doplnok.
Ďakujem!)
Zdroj: hab.com