Pagbuo ng isang plugin para sa Grafana: isang kasaysayan ng malalaking kuha

Hi sa lahat! Ilang buwan na ang nakalipas, inilunsad namin ang aming bagong open-source na proyekto, isang Grafana plugin para sa pagsubaybay sa Kubernetes, sa produksyon. DevOpsProdigy KubeGrafAvailable ang source code ng plugin sa pampublikong imbakan sa GitHubSa artikulong ito, gusto naming ibahagi sa iyo ang kuwento kung paano namin ginawa ang plugin, ang mga tool na ginamit namin, at ang mga pitfalls na naranasan namin sa panahon ng pag-develop. Magsimula na tayo!

Part 0 - Introduction: Paano tayo nakarating dito?

Ang ideya na magsulat ng aming sariling plugin para sa Grafana ay dumating sa amin nang nagkataon. Ang aming kumpanya ay sinusubaybayan ang mga proyekto sa web na may iba't ibang kumplikado sa loob ng higit sa 10 taon. Sa panahong ito, nakaipon kami ng napakaraming kadalubhasaan, mga kawili-wiling pag-aaral ng kaso, at karanasan sa paggamit ng iba't ibang sistema ng pagsubaybay. Sa isang punto, nagtaka kami: "Mayroon bang magic tool para sa pagsubaybay sa Kubernetes na magagawa mo, gaya ng sinasabi nila, 'itakda ito at kalimutan ito,'"? Naturally, ang Prometheus + Grafana combo ay matagal nang naging pamantayan sa industriya para sa pagsubaybay sa K8S. Mayroong malawak na hanay ng mga handa na tool para sa stack na ito, kabilang ang prometheus-operator, ang kubernetes-mixin dashboard suite, at grafana-kubernetes-app.

Ang grafana-kubernetes-app plugin ay tila ang pinakakawili-wiling opsyon para sa amin, ngunit hindi ito suportado nang mahigit isang taon at, higit pa, hindi gumagana sa mga bagong bersyon ng node-exporter at kube-state-metrics. Sa isang punto, nagpasya kami, "Bakit hindi lumikha ng sarili naming solusyon?"

Anong mga ideya ang napagpasyahan naming ipatupad sa aming plugin?

  • Application map visualization: isang maginhawang representasyon ng mga application sa isang cluster, na pinagsama ayon sa mga namespace, deployment, atbp.;
  • visualization ng mga koneksyon ng uri na "deployment - serbisyo (+ports)".
  • visualization ng pamamahagi ng mga cluster application sa mga cluster node.
  • pagkolekta ng mga sukatan at impormasyon mula sa maraming mapagkukunan: Prometheus at k8s api server.
  • Pagsubaybay sa parehong imprastraktura (paggamit ng oras ng CPU, memorya, disk subsystem, network) at lohika ng aplikasyon—ang katayuan ng kalusugan ng mga pod, ang bilang ng mga available na replika, at impormasyon tungkol sa pag-usad ng liveness/readiness test.

Bahagi 1: Ano ang isang Grafana plugin?

Mula sa teknikal na pananaw, ang isang plugin para sa Grafana ay isang angular na controller na nakaimbak sa direktoryo ng data ng Grafana (/var/grafana/plugins/ /dist/module.js) at maaaring i-load bilang isang SystemJS module. Ang direktoryo na ito ay dapat ding maglaman ng plugin.json file, na naglalaman ng lahat ng metadata tungkol sa iyong plugin: pangalan, bersyon, uri ng plugin, repositoryo/website/lisensya link, dependencies, at iba pa.

Pagbuo ng isang plugin para sa Grafana: isang kasaysayan ng malalaking kuha
module.ts

Pagbuo ng isang plugin para sa Grafana: isang kasaysayan ng malalaking kuha
plugin.json

Gaya ng nakikita mo sa screenshot, tinukoy namin ang plugin.type = app. Ito ay dahil mayroong tatlong uri ng mga plugin para sa Grafana:

panel: ang pinakakaraniwang uri ng plugin - ito ay isang panel para sa pagpapakita ng ilang partikular na sukatan at ginagamit upang bumuo ng iba't ibang dashboard.
pinanggalingan ng Datos: isang plugin connector sa anumang data source (halimbawa, Prometheus-datasource, ClickHouse-datasource, ElasticSearch-datasource).
app: Isang plugin na nagbibigay-daan sa iyong bumuo ng sarili mong application sa frontend sa loob ng Grafana, lumikha ng sarili mong HTML na mga pahina, at manu-manong i-access ang datasource upang mailarawan ang iba't ibang data. Ang iba pang mga uri ng plugin (datasource, panel) at iba't ibang mga dashboard ay maaari ding gamitin bilang mga dependency.

Pagbuo ng isang plugin para sa Grafana: isang kasaysayan ng malalaking kuha
Halimbawa ng mga dependency ng plugin na may uri = app.

Maaari mong gamitin ang alinman sa JavaScript o TypeScript bilang programming language (pinili namin ang TypeScript). Maaari kang lumikha ng mga template para sa anumang uri ng hello-world na plugin. hanapin sa pamamagitan ng link: Naglalaman ang repositoryong ito ng malaking bilang ng mga starter pack (mayroong pang-eksperimentong halimbawa ng React plugin) na may mga paunang naka-install at naka-configure na mga tagabuo.

Bahagi 2: Paghahanda sa Lokal na Kapaligiran

Para magtrabaho sa plugin, natural na kakailanganin namin ng Kubernetes cluster kasama ang lahat ng paunang naka-install na tool: prometheus, node-exporter, kube-state-metrics, at grafana. Ang kapaligiran ay dapat na mabilis, madali, at walang problema sa pag-set up, at upang matiyak ang mainit na pag-reload, dapat na direktang i-mount ang direktoryo ng data ng Grafana mula sa makina ng developer.

Sa aming opinyon, ang pinaka-maginhawang paraan upang magtrabaho nang lokal sa Kubernetes ay minikubeAng susunod na hakbang ay i-install ang Prometheus + Grafana bundle gamit ang prometheus-operator. Ang artikulong ito Ang proseso ng pag-install ng prometheus-operator sa minikube ay inilarawan nang detalyado. Upang paganahin ang pagtitiyaga, kailangan mong itakda ang parameter pagpupursige: totoo Sa charts/grafana/values.yaml file, idagdag ang sarili mong PV at PVC at tukuyin ang mga ito sa persistence.existingClaim parameter

Ang aming huling script ng paglulunsad ng minikube ay ganito:

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

Bahagi 3: Direktang pag-unlad

Modelo ng bagay

Bilang paghahanda para sa pagpapatupad ng plugin, nagpasya kaming tukuyin ang lahat ng pangunahing Kubernetes entity na gagawin namin bilang TypeScript classes: pod, deployment, daemonset, statefulset, job, cronjob, service, node, at namespace. Ang bawat isa sa mga klaseng ito ay nagmamana mula sa isang karaniwang klase ng BaseModel, na tumutukoy sa isang constructor, destructor, at mga pamamaraan para sa pag-update at pag-togg ng visibility. Tinutukoy din ng bawat klase ang mga nested na relasyon sa iba pang entity, gaya ng listahan ng mga pod para sa isang deployment entity.

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

Gamit ang mga getter at setter, maaari naming ipakita o itakda ang gustong sukatan ng entity sa isang maginhawa at nababasang format. Halimbawa, ang na-format na output ng mga mailalaang CPU node:

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

Pahina

Ang listahan ng lahat ng pahina ng aming plugin ay unang inilarawan sa aming pluing.json sa seksyong dependencies:

Pagbuo ng isang plugin para sa Grafana: isang kasaysayan ng malalaking kuha

Sa block para sa bawat pahina, dapat naming tukuyin ang PAGE NAME (ito ay mako-convert sa isang slug kung saan ang pahinang ito ay maa-access); ang pangalan ng sangkap na responsable para sa pagpapatakbo ng pahinang ito (ang listahan ng mga bahagi ay na-export sa module.ts); isang indikasyon ng tungkulin ng user kung saan magagamit ang page na ito at mga setting ng navigation para sa sidebar.

Sa bahaging responsable para sa pagpapatakbo ng pahina, dapat nating itakda ang templateUrl sa pamamagitan ng pagpasa nito ng landas patungo sa HTML file na naglalaman ng markup. Sa loob ng controller, sa pamamagitan ng dependency injection, maa-access namin ang dalawang mahalagang serbisyong Angular:

  • Ang backendSrv ay isang serbisyong nagbibigay ng pakikipag-ugnayan sa server ng Grafana API;
  • Ang datasourceSrv ay isang serbisyong nagbibigay ng lokal na pakikipag-ugnayan sa lahat ng datasources na naka-install sa iyong Grafana (halimbawa, ang .getAll() method ay nagbabalik ng listahan ng lahat ng naka-install na datasources; .get( ) — nagbabalik ng instance object ng isang partikular na datasource.

Pagbuo ng isang plugin para sa Grafana: isang kasaysayan ng malalaking kuha

Pagbuo ng isang plugin para sa Grafana: isang kasaysayan ng malalaking kuha

Pagbuo ng isang plugin para sa Grafana: isang kasaysayan ng malalaking kuha

Bahagi 4: Datasource

Mula sa pananaw ni Grafana, ang datasource ay isang plugin tulad ng iba: mayroon itong sariling entry point, module.js, at plugin.json file na may metadata. Kapag nagde-develop ng plugin na may type = app, maaari kaming makipag-ugnayan sa mga kasalukuyang datasource (halimbawa, prometheus-datasource) o sa amin, na maaari naming i-store nang direkta sa direktoryo ng plugin (dist/datasource/*) o i-install bilang dependency. Sa aming kaso, ang datasource ay kasama ng plugin code. Kinakailangan din ang isang config.html template at isang ConfigCtrl controller, na gagamitin para sa datasource instance configuration page at ang Datasource controller, na nagpapatupad ng logic para sa iyong datasource.

Sa KubeGraf plugin, mula sa pananaw ng user interface, ang datasource ay isang instance ng isang Kubernetes cluster na nagpapatupad ng mga sumusunod na kakayahan (available ang source code по ссылке):

  • pagkuha ng data mula sa k8s api server (pagkuha ng listahan ng mga namespace, deployment, atbp.)
  • Mga kahilingan sa pag-proxy sa prometheus-datasource (na pinipili sa mga setting ng plugin para sa bawat partikular na cluster) at pag-format ng mga tugon para sa paggamit ng data sa parehong mga static na page at dashboard.
  • pag-update ng data sa mga static na page ng plugin (na may nakatakdang refresh rate).
  • Pagproseso ng mga query para makabuo ng template sheet sa mga grafana-dashboard (paraan .metriFindQuery())

Pagbuo ng isang plugin para sa Grafana: isang kasaysayan ng malalaking kuha

Pagbuo ng isang plugin para sa Grafana: isang kasaysayan ng malalaking kuha

Pagbuo ng isang plugin para sa Grafana: isang kasaysayan ng malalaking kuha

  • pagsubok ng koneksyon sa huling k8s cluster.
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"};
       })
}

Ang isang partikular na kawili-wiling aspeto, sa aming opinyon, ay ang pagpapatupad ng mekanismo ng pagpapatunay at awtorisasyon para sa datasource. Karaniwan, sa labas ng kahon, maaari naming gamitin ang built-in na datasourceHttpSettings component ng Grafana upang i-configure ang access sa huling data source. Gamit ang bahaging ito, maaari naming i-configure ang access sa HTTP data source sa pamamagitan ng pagtukoy sa URL at mga pangunahing setting ng pagpapatunay/awtorisasyon: login/password, o client-cert/client-key. Ang pagpapatupad ng kakayahang i-configure ang pag-access gamit ang isang bearer token (ang de facto na pamantayan para sa mga k8) ay nangangailangan ng ilang tinkering.

Upang malutas ang problemang ito, maaari mong gamitin ang built-in na "Mga Ruta ng Plugin" ng Grafana (higit pang mga detalye sa opisyal na pahina ng dokumentasyon). Sa aming mga setting ng datasource, maaari kaming magdeklara ng isang hanay ng mga panuntunan sa pagruruta na ipoproseso ng grafana proxy server. Halimbawa, para sa bawat indibidwal na endpoint, mayroong opsyon na magtakda ng mga header o URL na may suporta sa template, ang data na maaaring kunin mula sa jsonData at secureJsonData na mga field (para sa pag-imbak ng mga password o token sa naka-encrypt na form). Sa aming halimbawa, ang mga kahilingan ng form /__proxy/api/v1/namespaces ay i-proxy sa mga URL ng sumusunod na uri
/api/v1/namespaces na may Authorization: Bearer header set.

Pagbuo ng isang plugin para sa Grafana: isang kasaysayan ng malalaking kuha

Pagbuo ng isang plugin para sa Grafana: isang kasaysayan ng malalaking kuha

Naturally, upang gumana sa k8s api server, kailangan namin ng isang user na may read-only na access, ang mga manifest para sa paglikha na maaari mo ring mahanap sa source code ng plugin.

Bahagi 5: Paglabas

Pagbuo ng isang plugin para sa Grafana: isang kasaysayan ng malalaking kuha

Kapag naisulat mo na ang sarili mong Grafana plugin, natural na gusto mong gawin itong open source. Sa Grafana, ito ay isang library ng plugin, na magagamit sa grafana.com/grafana/plugins

Upang maging available ang iyong plugin sa opisyal na tindahan, kailangan mong gumawa ng PR imbakan na ito, pagdaragdag ng nilalamang tulad nito sa repo.json file:

Pagbuo ng isang plugin para sa Grafana: isang kasaysayan ng malalaking kuha

kung saan ang bersyon ay ang bersyon ng iyong plugin, ang url ay ang link sa repositoryo, at ang commit ay ang hash ng commit na gagawing available ang partikular na bersyon ng plugin.

At sa output makikita mo ang isang kahanga-hangang larawan tulad nito:

Pagbuo ng isang plugin para sa Grafana: isang kasaysayan ng malalaking kuha

Ang data para dito ay awtomatikong kukunin mula sa iyong Readme.md, Changelog.md, at ang plugin.json file na may paglalarawan ng plugin.

Bahagi 6: Sa halip na mga konklusyon

Hindi kami tumigil sa pagbuo ng aming plugin mula nang ilabas ito. Kasalukuyan kaming nagsusumikap sa maayos na pagsubaybay sa paggamit ng mapagkukunan ng cluster node, pagpapatupad ng mga bagong feature para mapahusay ang karanasan ng user, at pag-uuri-uri sa malaking halaga ng feedback na natanggap namin mula sa aming mga customer at mula sa mga user sa GitHub pagkatapos i-install ang plugin (kung mag-iiwan ka ng isyu o humiling ng pull, lubos akong magiging masaya :)).

Umaasa kami na ang artikulong ito ay makakatulong sa iyo na maunawaan ang napakagandang tool tulad ng Grafana at, marahil, isulat ang iyong sariling plugin.

salamat!)

Pinagmulan: www.habr.com

Bumili ng maaasahang pagho-host para sa mga site na may proteksyon ng DDoS, mga server ng VPS VDS 🔥 Bumili ng maaasahang website hosting na may proteksyon ng DDoS, VPS VDS servers | ProHoster