A Grafana bővítményének fejlesztése: nagy sikerek története

Sziasztok! Néhány hónappal ezelőtt elindítottuk az új nyílt forráskódú projektünket a termelésben - a kubernetes figyelésére szolgáló Grafana bővítményt, amelyet elhívtunk. DevOpsProdigy KubeGraf. Исходный код плагина доступен в nyilvános adattár a GitHubon. Ebben a cikkben pedig szeretnénk megosztani veletek a bővítmény létrehozásának történetét, milyen eszközöket használtunk, és milyen buktatókkal találkoztunk a fejlesztési folyamat során. Gyerünk!

0. rész - bevezető: hogyan jutottunk el idáig?

Egészen véletlenül támadt bennünk az ötlet, hogy írjunk saját bővítményt a Grafan számára. Cégünk több mint 10 éve figyeli a különböző bonyolultságú webprojekteket. Ezalatt az idő alatt nagy mennyiségű szakértelmet, érdekes eseteket, tapasztalatokat halmoztunk fel a különböző monitoring rendszerek használatában. És egy ponton feltettük magunknak a kérdést: „Van valami varázseszköz a Kubernetes figyelésére, hogy – ahogy mondani szokás – „állítsd be és felejtsd el”?”. A k8-ak figyelésének iparági szabványa természetesen régóta a Prometheus + Grafana kombináció. És kész megoldásként ehhez a veremhez számos különféle eszköz található: prometheus-operator, kubernetes-mixin irányítópultok, grafana-kubernetes-app.

Számunkra a grafana-kubernetes-app plugin tűnt a legérdekesebb lehetőségnek, de már több mint egy éve nem támogatott, ráadásul nem működik a node-exporter és a kube-state-metrics új verzióival. És valamikor úgy döntöttünk: „Nem kellene magunk döntenünk?”

Milyen ötleteket határoztunk meg a bővítményünkben:

  • az „alkalmazástérkép” megjelenítése: az alkalmazások kényelmes bemutatása a fürtben, névterek, telepítések szerint csoportosítva...;
  • визуализация связей вида «deployment — service (+ports)».
  • a fürt alkalmazások fürtcsomópontok közötti eloszlásának megjelenítése.
  • metrikák és információk gyűjteménye több forrásból: Prometheus és k8s api szerver.
  • мониторинг как инфраструктурной части (использование процессорного времени, памяти, дисковой подсистемы, сети), так и логики приложений — health-status pod’ов, количество доступных реплик, информация о прохождении liveness/readyness-проб.

1. rész: Mi az a „Grafana plugin”?

Technikai szempontból a Grafana beépülő modulja egy szögvezérlő, amely a Grafana adatkönyvtárában (/var/grafana/plugins/ /dist/module.js), és SystemJS modulként tölthető be. Szintén ebben a könyvtárban kell lennie egy plugin.json fájlnak, amely tartalmazza a beépülő modul összes metainformációját: név, verzió, beépülő modul típusa, hivatkozások a tárhelyre/webhelyre/licencre, függőségek és így tovább.

A Grafana bővítményének fejlesztése: nagy sikerek története
modul.ts

A Grafana bővítményének fejlesztése: nagy sikerek története
plugin.json

Amint a képernyőképen látható, a plugin.type = app-ot adtuk meg. Mivel a Grafana beépülő moduljai háromféleek lehetnek:

panel: a legelterjedtebb beépülő modul - ez egy panel bármilyen mérőszám megjelenítésére, amelyet különféle irányítópultok készítésére használnak.
adatforrás: plugin csatlakozó valamilyen adatforráshoz (például Prometheus-adatforrás, ClickHouse-adatforrás, ElasticSearch-adatforrás).
app: Beépülő modul, amely lehetővé teszi saját frontend alkalmazás létrehozását a Grafana belsejében, saját html-oldalak létrehozását, valamint az adatforrás kézi elérését különféle adatok megjelenítéséhez. Ezenkívül más típusú bővítmények (adatforrás, panel) és különféle irányítópultok is használhatók függőségekként.

A Grafana bővítményének fejlesztése: nagy sikerek története
Példa beépülő modul-függőségekre a type=app paraméterrel.

В качестве языка программирования можно использовать как JavaScript, так и TypeScript (мы свой выбор остановили на нем). Заготовки для hello-world плагинов любого типа вы можете megtalálja a linket: ez a tároló nagyszámú kezdőcsomagot tartalmaz (még a Reactban van egy kísérleti példa is egy bővítményre) előre telepített és konfigurált építőkkel.

2. rész: a helyi környezet előkészítése

A bővítményen való munkához természetesen szükségünk van egy kubernetes-fürtre az összes előre telepített eszközzel: prometheus, node-exporter, kube-state-metrics, grafana. A környezetet gyorsan, egyszerűen és természetesen kell beállítani, és a hot-reload biztosításához a Grafana adatkönyvtárat közvetlenül a fejlesztő gépéről kell felcsatolni.

Самым удобным, на наш взгляд, способом локальной работы с kubernetes является minikube. A következő lépés a Prometheus + Grafana kombináció telepítése a prometheus-operator segítségével. BAN BEN ez a cikk A prometheus-operator minikube-ra történő telepítésének folyamata részletesen le van írva. A perzisztencia engedélyezéséhez be kell állítani a paramétert kitartás: igaz a charts/grafana/values.yaml fájlban adja hozzá saját PV-jét és PVC-jét, és adja meg őket a persistence.existingClaim paraméterben

A végső minikube indító szkriptünk így néz ki:

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

3. rész: tényleges fejlesztés

Objektummodell

В качестве подготовки к реализации плагина мы решили описать все базовые сущности Kubernetes, с которыми мы будем работать в виде TypeScript-классов: pod, deployment, daemonset, statefulset, job, cronjob, service, node, namespace. Каждый из этих классов наследуется от общего класса BaseModel, в котором описаны конструктор, деструктор, методы для обновления и переключения видимости. В каждом из классов описаны вложенные отношения с другими сущностями, например, список pod’ов у сущности типа 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 = [];
   }
}

A getterek és setterek segítségével kényelmes és olvasható formában tudjuk megjeleníteni vagy beállítani a számunkra szükséges entitásmérőket. Például az allokálható CPU-csomópontok formázott kimenete:

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

Oldalak

Az összes beépülő modulunk listája először a pluing.json fájlban található a függőségek szakaszban:

A Grafana bővítményének fejlesztése: nagy sikerek története

Az egyes oldalak blokkjában meg kell jelölnünk az OLDAL NEVÉT (ezt ezután egy slug-vá alakítjuk, amely által ez az oldal elérhető lesz); az oldal működéséért felelős komponens neve (az összetevők listája a module.ts-be kerül exportálásra); jelzi a felhasználói szerepkört, amelyhez ez az oldal elérhető, és az oldalsáv navigációs beállításait.

Az oldal működéséért felelős komponensben be kell állítanunk a templateUrl-t, átadva ott a html fájl elérési útját jelöléssel. A vezérlőn belül a függőségi befecskendezéssel akár 2 fontos szögszolgáltatást is elérhetünk:

  • backendSrv - olyan szolgáltatás, amely interakciót biztosít a Grafana API-kiszolgálóval;
  • datasourceSrv – egy szolgáltatás, amely helyi interakciót biztosít a Grafana-ba telepített összes adatforrással (például a .getAll() metódus) – visszaadja az összes telepített adatforrás listáját; .get( ) - egy adott adatforrás példányobjektumát adja vissza.

A Grafana bővítményének fejlesztése: nagy sikerek története

A Grafana bővítményének fejlesztése: nagy sikerek története

A Grafana bővítményének fejlesztése: nagy sikerek története

4. rész: adatforrás

A Grafana szemszögéből az adatforrás pontosan ugyanaz a plugin, mint az összes többi: saját belépési pontja module.js, van egy fájl metainformációkkal plugin.json. A type = app bővítmény fejlesztésekor a meglévő adatforrásokkal (például prometheus-datasource) és a sajátunkkal is interakcióba léphetünk, amit közvetlenül a plugin könyvtárában (dist/datasource/*) tárolhatunk, vagy függőségként telepíthetünk. Esetünkben az adatforrás a beépülő modul kódjával érkezik. Szükséges továbbá egy config.html sablon és egy ConfigCtrl vezérlő, amely az adatforrás-példány konfigurációs oldalához lesz használva, valamint az adatforrás logikáját megvalósító Datasource vezérlő.

A KubeGraf beépülő modulban a felhasználói felület szempontjából az adatforrás egy kubernetes-fürt példánya, amely a következő képességeket valósítja meg (forráskód elérhető по ссылке):

  • adatok gyűjtése a k8s api-szerverről (névterek, telepítések listájának lekérése...)
  • proxy kérések a prometheus-datasource-hoz (amely az egyes fürtök beépülő modul-beállításaiban van kiválasztva), és a válaszok formázása az adatok statikus oldalakon és irányítópultokon történő használatához.
  • adatok frissítése statikus bővítményoldalakon (beállított frissítési gyakorisággal).
  • lekérdezések feldolgozása sablonlap létrehozásához grafana-dashboardokban (metriFindQuery() metódus)

A Grafana bővítményének fejlesztése: nagy sikerek története

A Grafana bővítményének fejlesztése: nagy sikerek története

A Grafana bővítményének fejlesztése: nagy sikerek története

  • kapcsolati teszt a végső k8s klaszterrel.
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"};
       })
}

Külön érdekesség véleményünk szerint az adatforrás hitelesítési és engedélyezési mechanizmusának megvalósítása. Általában a beépített Grafana komponens datasourceHttpSettings segítségével konfigurálhatjuk a végső adatforráshoz való hozzáférést. Ezzel az összetevővel konfigurálhatjuk a hozzáférést a http adatforráshoz az url és az alapvető hitelesítési/engedélyezési beállítások megadásával: login-password vagy client-cert/client-key. Annak érdekében, hogy megvalósíthassuk a hozzáférést egy vivőjogkivonat (a k8s de facto szabványa) használatával konfigurálhatjuk, egy kis módosítást kellett végrehajtanunk.

A probléma megoldásához használhatja a Grafana beépített „Plugin Routes” mechanizmusát (további részletek: hivatalos dokumentációs oldal). Adatforrásunk beállításaiban deklarálhatunk egy útválasztási szabálykészletet, amelyet a grafana proxyszerver dolgoz fel. Például minden egyes végponthoz lehetőség van sablonozási lehetőséggel fejlécek vagy url-ek beállítására, amelyekhez a jsonData és a secureJsonData mezőkből lehet adatokat venni (jelszavak vagy tokenek titkosított formában tárolásához). Példánkban az olyan lekérdezések, mint a /__proxy/api/v1/namespaces az űrlap url-jéhez kerül proxyként
/api/v8/namespaces az Authorization: Bearer fejléccel.

A Grafana bővítményének fejlesztése: nagy sikerek története

A Grafana bővítményének fejlesztése: nagy sikerek története

Természetesen a k8s api szerverrel való együttműködéshez csak olvasási hozzáféréssel rendelkező felhasználóra van szükségünk, amelynek létrehozásához szintén megtalálható a plugin forráskódja.

5. rész: kiadás

A Grafana bővítményének fejlesztése: nagy sikerek története

Miután megírta saját Grafana beépülő modulját, természetesen nyilvánosan elérhetővé kell tennie azt. A Grafanában ez az itt elérhető bővítmények könyvtára grafana.com/grafana/plugins

Ahhoz, hogy a bővítmény elérhető legyen a hivatalos áruházban, PR-t kell készítenie ezt az adattárat, добавив в файл repo.json содержимое вида:

A Grafana bővítményének fejlesztése: nagy sikerek története

ahol a verzió a beépülő modul verziója, az url a tárolóra mutató hivatkozás, a commit pedig annak a véglegesítésnek a hash-je, amelyhez a beépülő modul egy adott verziója elérhető lesz.

És a kimeneten egy csodálatos képet fog látni, például:

A Grafana bővítményének fejlesztése: nagy sikerek története

Данные для нее будут автоматически сграблены с вашего Readme.md, Changelog.md и файла plugin.json с описанием плагина.

6. rész: következtetések helyett

Мы не прекратили разработку нашего плагина после релиза. И сейчас работаем над корректным мониторингом использования ресурсов нод кластера, внедрением новых фич для повышения UX, а также разгребаем большое количества фидбека, полученного после установок плагина как нашими клиентами, так и из ишшуев на гитхабе (если вы оставите свое issue или pull request, я буду очень счастлив 🙂 ).

Reméljük, hogy ez a cikk segít megérteni egy ilyen csodálatos eszközt, mint a Grafana, és talán megírja saját bővítményét.

Kösz!)

Forrás: will.com

Hozzászólás