{"id":52343,"date":"2019-11-06T00:00:00","date_gmt":"2019-11-05T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/razrabotka-plagina-dlya-grafana-istoriya-nabityh-shishek"},"modified":"2020-02-18T14:00:02","modified_gmt":"2020-02-18T11:00:02","slug":"razrabotka-plagina-dlya-grafana-istoriya-nabityh-shishek","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/razrabotka-plagina-dlya-grafana-istoriya-nabityh-shishek","title":{"rendered":"Razvoj plugina za Grafana: povijest nau\u010denih lekcija","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Pozdrav svima! Prije nekoliko mjeseci pokrenuli smo na\u0161 novi open-source projekt u produkciji \u2014 Grafana plugin za pra\u0107enje kubernetes, kojeg smo nazvali <b><noindex><a rel=\"nofollow\" href=\"https:\/\/grafana.com\/grafana\/plugins\/devopsprodigy-kubegraf-app\">DevOpsProdigy KubeGraf<\/a><\/noindex><\/b>. Izvorni kod plugina dostupan je u <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/devopsprodigy\/kubegraf\">javnom repozitoriju na GitHubu<\/a><\/noindex>. U ovom \u010dlanku \u017eelimo podijeliti s vama pri\u010du o tome kako smo razvijali plugin, koje alate smo koristili i s kakvim smo se izazovima susreli tijekom razvoja. Krenimo!<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h4>Dio 0 \u2014 uvod: kako smo do\u0161li do ovoga?<\/h4>\n<p>\nIdeja da napisemo vlastiti plugin za Grafanu pojavila se sasvim slu\u010dajno. Na\u0161a kompanija vi\u0161e od 10 godina se bavi pra\u0107enjem web projekata razli\u010ditih slo\u017eenosti. Tijekom tog vremena stekli smo bogato iskustvo, zanimljive slu\u010dajeve i iskustva kori\u0161tenja raznih sustava za pra\u0107enje. I u jednom trenutku postavili smo si pitanje: \u201ePostoji li \u010darobni alat za pra\u0107enje Kubernetes-a, da, kako se ka\u017ee, 'instalira\u0161 i zaboravi\u0161'?\u201d? Normativ za pra\u0107enje k8s ve\u0107 dugo je kombinacija Prometheus + Grafana. Kao gotova rje\u0161enja za ovaj stack postoji veliki broj razli\u010ditih alata: prometheus-operator, set nadzornika kubernetes-mixin, grafana-kubernetes-app. <\/p>\n<p>Najzanimljivija opcija za nas \u010dinila se plugin grafana-kubernetes-app, no nije podr\u017eana ve\u0107 vi\u0161e od godinu dana i, osim toga, ne mo\u017ee raditi s novim verzijama node-exportera i kube-state-metricsa. I u jednom trenutku odlu\u010dili smo: \u201eZa\u0161to ne bismo napravili svoje vlastito rje\u0161enje?\u201d<\/p>\n<p>Koje ideje smo odlu\u010dili realizirati u svom pluginu:<\/p>\n<ul>\n<li>vizualizacija 'mape aplikacije': prikladno predstavljanje aplikacija u klasteru, grupiranih po namespace-ima, deployment-ima...;<\/li>\n<li>vizualizacija odnosa tipa 'deployment \u2014 service (+ports)'.<\/li>\n<li>vizualizacija raspodjele aplikacija klastera po nodovima klastera.<\/li>\n<li>prikupljanje metrika i informacija iz vi\u0161e izvora: Prometheus i k8s API server.<\/li>\n<li>pra\u0107enje kako infrastrukturnih dijelova (kori\u0161tenje procesorskog vremena, memorije, diska, mre\u017ee), tako i logike aplikacija \u2014 health-status pod-ova, broj dostupnih replika, informacije o prolasku liveness\/readyness provjera.<\/li>\n<\/ul>\n<p><\/p>\n<h4>Dio 1: \u0160to je 'plugin za Grafana'?<\/h4>\n<p>\nS tehni\u010dke to\u010dke gledi\u0161ta, plugin za Grafanu \u2014 to je angular-kontroler, koji se \u010duva u data-direktoriju Grafane (<i>\/var\/grafana\/plugins\/&lt;your_plugin_name&gt;\/dist\/module.js<\/i>) lahko nalo\u017eite tudi kot SystemJS modul. V tej mapi mora biti tudi datoteka plugin.json, ki vsebuje vse metapodatke o va\u0161em vti\u010dniku: ime, razli\u010dica, tip vti\u010dnika, povezave na repozitorij\/spletno stran\/licenco, odvisnosti in tako naprej.<\/p>\n<p><img decoding=\"async\" alt=\"Razvoj plugina za Grafana: povijest nau\u010denih lekcija\" src=\"\/wp-content\/uploads\/2019\/11\/5993fec77a3904ed8b9e19a5addbb6ea.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>module.ts<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Razvoj plugina za Grafana: povijest nau\u010denih lekcija\" src=\"\/wp-content\/uploads\/2019\/11\/1e5b780837e5a9385e5e22a27d83f567.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>plugin.json<\/i><\/p>\n<p>Kot je razvidno na zaslonu, smo navedli plugin.type = app. Vti\u010dniki za Grafano so lahko treh vrst:<\/p>\n<p><b>panel<\/b>: najpogostej\u0161a vrsta vti\u010dnikov \u2014 predstavlja panel za vizualizacijo razli\u010dnih metrik, uporablja se za izdelavo razli\u010dnih nadzornih plo\u0161\u010d.<br \/>\n<b>datasource<\/b>: vti\u010dnik-connector za katerikoli vir podatkov (na primer, Prometheus-datasource, ClickHouse-datasource, ElasticSearch-datasource).<br \/>\n<b>app<\/b>: vti\u010dnik, ki vam omogo\u010da, da zgradite svojo lastno aplikacijo za frontend znotraj Grafane, ustvarite svoje HTML strani in ro\u010dno dostopate do datasource za vizualizacijo razli\u010dnih podatkov. Tudi vti\u010dniki drugih vrst (datasource, panel) in razli\u010dne nadzorne plo\u0161\u010de se lahko uporabljajo kot odvisnosti.<\/p>\n<p><img decoding=\"async\" alt=\"Razvoj plugina za Grafana: povijest nau\u010denih lekcija\" src=\"\/wp-content\/uploads\/2019\/11\/3cd53c7c3a2635f3f20831d52198b5f0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Primer odvisnosti vti\u010dnika tipa app<\/i>.<\/p>\n<p>Kot programski jezik lahko uporabite tako JavaScript kot TypeScript (mi smo se odlo\u010dili za slednjega). Predloge za hello-world vti\u010dnike katerega koli tipa lahko <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CorpGlory\">najdete na povezavi<\/a><\/noindex>: v tem repozitoriju je predstavljen velik \u0161tevil od starter-packov (tudi eksperimentalni primer vti\u010dnika v React) s prednastavljenimi in konfiguriranimi gradbeniki. <\/p>\n<h4>Del 2: priprava lokalnega okolja<\/h4>\n<p>\nZa delo na vti\u010dniku bomo seveda potrebovali kubernetes grozd z vsemi prednastavljenimi orodji: prometheus, node-exporter, kube-state-metrics, grafana. Okolje bi se moralo hitro, enostavno in nekonfliktno nastaviti, za zagotavljanje hot-reload pa mora biti data-map Grafane monta\u017ena neposredno z razvojne naprave.<\/p>\n<p>Najbolj priro\u010den na\u010din lokalnega dela z kubernetes se nam zdi <noindex><a rel=\"nofollow\" href=\"https:\/\/kubernetes.io\/docs\/tasks\/tools\/install-minikube\/\">minikube<\/a><\/noindex>. Naslednji korak je namestitev povezave Prometheus + Grafana z uporabo prometheus-operator. V <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/faun\/trying-prometheus-operator-with-helm-minikube-b617a2dccfa3\">tem \u010dlanku<\/a><\/noindex> je podrobno opisan postopek namestitve prometheus-operator na minikube. Za omogo\u010danje obstojnosti je potrebno nastaviti parameter <i>persistence: true<\/i> v datoteki charts\/grafana\/values.yaml, dodajte svoj lasten PV in PVC ter jih navedite v parametru persistence.existingClaim<\/p>\n<p>Kon\u010dni skript za zagon minikube je videti takole:<\/p>\n<pre><code class=\"plaintext\">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\nminikube mount \n\/home\/sergeisporyshev\/Projects\/Grafana:\/var\/grafana --gid=472 --uid=472 --9p-version=9p2000.L<\/code><\/pre>\n<p><\/p>\n<h4>Dio 3: neposredno razvoj<\/h4>\n<p>\n<b>Objektni model<\/b><\/p>\n<p>Kao pripremu za implementaciju plugina, odlu\u010dili smo opisati sve osnovne entitete Kubernetes-a koje \u0107emo koristiti u obliku TypeScript klasa: pod, deployment, daemonset, statefulset, job, cronjob, service, node, namespace. Svaka od ovih klasa nasle\u0111uje zajedni\u010dku klasu BaseModel, u kojoj su opisani konstruktor, destruktor, metode za a\u017euriranje i prebacivanje vidljivosti. U svakoj od klasa su opisani ugnije\u017edeni odnosi s drugim entitetima, na primer, lista podova za entitet tipa deployment.<\/p>\n<pre><code class=\"plaintext\">import {Pod} from \".\/pod\";\nimport {Service} from \".\/service\";\nimport {BaseModel} from '.\/traits\/baseModel';\n\nexport class Deployment extends BaseModel{\n   pods: Array;\n   services: Array;\n\n   constructor(data: any){\n       super(data);\n       this.pods = [];\n       this.services = [];\n   }\n}<\/code><\/pre>\n<p>\nPomo\u0107u getter-a i setter-a mo\u017eemo prikazati ili postaviti potrebne metrik\u0435 entiteta na zgodan i \u010ditljiv na\u010din. Na primer, formatirani prikaz allocatable cpu nod-a:<\/p>\n<pre><code class=\"plaintext\">get cpuAllocatableFormatted(){\n   let cpu = this.data.status.allocatable.cpu;\n   if(cpu.indexOf('m') &gt; -1){\n       cpu = parseInt(cpu)\/1000;\n   }\n   return cpu;\n}<\/code><\/pre>\n<p>\n<b>Stranice<\/b><\/p>\n<p>Lista svih stranica na\u0161eg plugina prvobitno se opisuje u na\u0161em pluing.json u odeljku zavisnosti:<\/p>\n<p><img decoding=\"async\" alt=\"Razvoj plugina za Grafana: povijest nau\u010denih lekcija\" src=\"\/wp-content\/uploads\/2019\/11\/b86c74839ad0d9c64b97ffc3f2a84bdf.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nU bloku za svaku stranicu moramo navesti NAZIV STRANICE (koji \u0107e potom biti konvertovan u slug, pod kojim \u0107e ova stranica biti dostupna); naziv komponente koja je odgovorna za rad na ovoj stranici (lista komponenti se eksportuje u module.ts); navo\u0111enje uloge korisnika za koju je dostupno kori\u0161\u0107enje ove stranice i pode\u0161avanja navigacije za bo\u010dnu traku. <\/p>\n<p>U komponenti koja je odgovorna za rad na stranici, moramo postaviti templateUrl, predaju\u0107i putanju do html datoteke sa markup-om. Unutar kontrolera, putem dependency injection-a, mo\u017eemo dobiti pristup do 2 va\u017ena angular servisa:<\/p>\n<ul>\n<li>backendSrv \u2014 servis koji omogu\u0107ava interakciju s api-serverom Grafane;<\/li>\n<li>datasourceSrv \u2014 servis koji omogu\u0107ava lokalnu interakciju sa svim datasource-ima instaliranim u va\u0161oj Grafani (na primer, metoda .getAll() \u2014 vra\u0107a listu svih instaliranih datasource-a; .get() \u2014 vra\u0107a objekat-instanac konkretnog datasource-a.<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Razvoj plugina za Grafana: povijest nau\u010denih lekcija\" src=\"\/wp-content\/uploads\/2019\/11\/e616e74c2e31ca3a81b7ed91ca333208.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<img decoding=\"async\" alt=\"Razvoj plugina za Grafana: povijest nau\u010denih lekcija\" src=\"\/wp-content\/uploads\/2019\/11\/5e1d45f570dda50774088405abb41c9f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<img decoding=\"async\" alt=\"Razvoj plugina za Grafana: povijest nau\u010denih lekcija\" src=\"\/wp-content\/uploads\/2019\/11\/c072867623824e799518984c7b1bee93.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h4>Dio 4: datasource<\/h4>\n<p>\nZ vidika Grafane, podatkovni vir je prav tako vti\u010dnik kot kateri koli drugi: ima svoj vstopni modul module.js in datoteko z metainformacijami plugin.json. Pri razvoju vti\u010dnika s tipom = app lahko komuniciramo tako z obstoje\u010dimi podatkovnimi viri (na primer prometheus-datasource) kot z lastnimi, ki jih lahko shranimo neposredno v direktorij vti\u010dnika (dist\/datasource\/*) ali jih namestimo kot odvisnost. V na\u0161em primeru se podatkovni vir dostavi skupaj s kodo vti\u010dnika. Prav tako je obvezna prisotnost predloge config.html in kontrolerja ConfigCtrl, ki se bosta uporabljala za konfiguracijsko stran instan\u010dnega podatkovnega vira ter kontrolerja Datasource, v katerem je implementirana logika delovanja va\u0161ega podatkovnega vira.<\/p>\n<p>V vti\u010dniku KubeGraf, z vidika uporabni\u0161kega vmesnika, podatkovni vir predstavlja instanco kubernetes grozda, v katerem so implementirane naslednje funkcionalnosti (izvorna koda je na voljo <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/devopsprodigy\/kubegraf\/tree\/master\/src\/datasource\">na povezavi<\/a><\/noindex>):<\/p>\n<ul>\n<li>pridobivanje podatkov iz api-serverja k8s (pridobitev seznama namespace-ov, deployment-ov\u2026)<\/li>\n<li>proksiranje zahtevkov v prometheus-datasource (ki se izbere v nastavitvah vti\u010dnika za vsak konkretni grozd) in formatiranje odgovorov za uporabo podatkov tako na stati\u010dnih straneh kot na nadzornih plo\u0161\u010dah.<\/li>\n<li>posodabljanje podatkov na stati\u010dnih straneh vti\u010dnika (z nastavljenim \u010dasom osve\u017eevanja).<\/li>\n<li>obdelava zahtevkov za oblikovanje seznama predlog v grafana-nadzornih plo\u0161\u010dah (metoda .metriFindQuery())<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Razvoj plugina za Grafana: povijest nau\u010denih lekcija\" src=\"\/wp-content\/uploads\/2019\/11\/18159bbb41144ebceb457df28b35e7b1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<img decoding=\"async\" alt=\"Razvoj plugina za Grafana: povijest nau\u010denih lekcija\" src=\"\/wp-content\/uploads\/2019\/11\/a62665b4409566fbe24f56f88a376d5a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<img decoding=\"async\" alt=\"Razvoj plugina za Grafana: povijest nau\u010denih lekcija\" src=\"\/wp-content\/uploads\/2019\/11\/7f2d61fce623ce2a3cf62feb6d0447ac.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<ul>\n<li>test povezave s kon\u010dnim k8s grozdom.<\/li>\n<\/ul>\n<pre><code class=\"plaintext\">testDatasource(){\n   let url = '\/api\/v1\/namespaces';\n   let _url = this.url;\n   if(this.accessViaToken)\n       _url += '\/__proxy';\n   _url += url;\n   return this.backendSrv.datasourceRequest({\n       url: _url,\n       method: \"GET\",\n       headers:{\"Content-Type\": 'application\/json'}\n   })\n       .then(response =&gt; {\n           if (response.status === 200) {\n               return {status: \"success\", message: \"Z virom podatkov je vse v redu\", title: \"Uspeh\"};\n           } else {\n               return {status: \"error\", message: \"Vir podatkov ni v redu\", title: \"Napaka\"};\n           }\n       }, error =&gt; {\n           return {status: \"error\", message: \"Vir podatkov ni v redu\", title: \"Napaka\"};\n       })\n}<\/code><\/pre>\n<p>\nZanimljiv aspekt, s na\u0161eg gledi\u0161ta, je implementacija mehanizma autentifikacije i autorizacije za datasource. Obi\u010dno, out-of-the-box, za postavljanje pristupa krajnjem izvoru podataka mo\u017eemo koristiti ugra\u0111enu komponentu Grafana \u2014 datasourceHttpSettings. Pomo\u0107u ove komponente mo\u017eemo konfigurisati pristup http-izvoru podataka, navode\u0107i url i osnovne postavke autentifikacije\/autorization: korisni\u010dko ime-lozinka, ili client-cert\/client-key. Da bismo omogu\u0107ili pode\u0161avanje pristupa preko bearer tokena (de facto standard za k8s), morali smo malo \u201ehemijati\u201c.<\/p>\n<p>Za re\u0161avanje ovog zadatka mo\u017ee se iskoristiti ugra\u0111eni mehanizam Grafana \u201ePlugin Routes\u201c (vi\u0161e o tome na <noindex><a rel=\"nofollow\" href=\"https:\/\/grafana.com\/docs\/plugins\/developing\/auth-for-datasources\/\">slu\u017ebenoj stranici dokumentacije<\/a><\/noindex>). U postavkama na\u0161eg datasource-a mo\u017eemo deklarisati skup pravila usmeravanja, koja \u0107e se obra\u0111ivati proxy-serverom grafana. Na primer, za svaki pojedina\u010dni endpoint postoji mogu\u0107nost postavljanja zaglavlja ili url-a sa mogu\u0107no\u0161\u0107u \u0161ablonizacije, podaci za koje mogu biti uzeti iz polja jsonData i secureJsonData (za \u010duvanje lozinki ili tokena u \u0161ifrovanom obliku). U na\u0161em primeru zahtevi ovog tipa <i>\/__proxy\/api\/v1\/namespaces<\/i> bi\u0107e proxirani na url ovog tipa<br \/>\n\/api\/v1\/namespaces uz postavljanje zaglavlja Authorization: Bearer.<\/p>\n<p><img decoding=\"async\" alt=\"Razvoj plugina za Grafana: povijest nau\u010denih lekcija\" src=\"\/wp-content\/uploads\/2019\/11\/ca73ff0fef62fba3edab7907c83639b6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<img decoding=\"async\" alt=\"Razvoj plugina za Grafana: povijest nau\u010denih lekcija\" src=\"\/wp-content\/uploads\/2019\/11\/9dab7537d7ccba90c9fb62dfa70b9fe2.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNaravno, za rad sa api-serverom k8s nam je potreban korisnik sa readonly pristupima, manifesti za kreiranje kojeg mo\u017eete prona\u0107i i u <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/devopsprodigy\/kubegraf\/tree\/master\/kubernetes\/\">izvornom kodu plugina<\/a><\/noindex>.<\/p>\n<h4>Deo 5: izdanje<\/h4>\n<p>\n<img decoding=\"async\" alt=\"Razvoj plugina za Grafana: povijest nau\u010denih lekcija\" src=\"\/wp-content\/uploads\/2019\/11\/3991a5d412f362770157fc567bb8009c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNakon \u0161to napi\u0161ete svoj vlastiti plugin za Grafana, naravno, po\u017eele\u0107ete da ga objavite javno. U Grafani postoji biblioteka plugina, dostupna na linku <noindex><a rel=\"nofollow\" href=\"https:\/\/grafana.com\/grafana\/plugins\">grafana.com\/grafana\/plugins<\/a><\/noindex> <\/p>\n<p>Da bi va\u0161 plugin bio dostupan u zvani\u010dnom prodavcu, potrebno je da napravite PR u <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/grafana\/grafana-plugin-repository\">ovu \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0458\u0443<\/a><\/noindex>, dodaju\u0107i u fajl repo.json sadr\u017eaj ovakvog tipa:<\/p>\n<p><img decoding=\"async\" alt=\"Razvoj plugina za Grafana: povijest nau\u010denih lekcija\" src=\"\/wp-content\/uploads\/2019\/11\/160650bf37f8f2f3e12ef7dd291e90eb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\ngde version \u2014 verzija va\u0161eg plugina, url \u2014 link ka \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0458\u0438, a commit \u2014 hash commit-a, prema kojem \u0107e biti dostupna konkretna verzija plugina. <\/p>\n<p>I na izlazu \u0107ete videti sjajan prikaz ovog tipa:<\/p>\n<p><img decoding=\"async\" alt=\"Razvoj plugina za Grafana: povijest nau\u010denih lekcija\" src=\"\/wp-content\/uploads\/2019\/11\/ff906396596e9c4c15c59f8d53555f52.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPodaci za njega bi\u0107e automatski prikupljeni iz va\u0161eg Readme.md, Changelog.md i fajla plugin.json sa opisom plugina.<\/p>\n<h4>Deo 6: umesto zaklju\u010daka<\/h4>\n<p>\nNismo prekinuli razvoj na\u0161eg dodatka nakon objave. Sada radimo na pravilnom pra\u0107enju kori\u0161\u0107enja resursa \u010dvorova klastera, implementaciji novih funkcija za pobolj\u0161anje UX-a, kao i na re\u0161avanju velike koli\u010dine povratnih informacija dobijenih nakon instalacija dodatka, kako od na\u0161ih klijenata, tako i iz izve\u0161taja na GitHub-u (ako ostavite svoje pitanje ili zahtev za povla\u010denje, bi\u0107u veoma sre\u0107an \ud83d\ude42 ).<\/p>\n<p>Nadamo se da \u0107e vam ovaj \u010dlanak pomo\u0107i da razumete ovaj divan alat kao \u0161to je Grafana i, mo\u017eda, da napi\u0161ete svoj vlastiti dodatak. <\/p>\n<p>Hvala!)<br \/>\n<br \/>Izvor: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/itsumma\/blog\/474500\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0441\u044f\u0446\u0435\u0432 \u043d\u0430\u0437\u0430\u0434 \u043c\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u0438 \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d \u043d\u0430\u0448 \u043d\u043e\u0432\u044b\u0439 open-source \u043f\u0440\u043e\u0435\u043a\u0442 \u2014 Grafana-\u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430 kubernetes, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0437\u0432\u0430\u043b\u0438 DevOpsProdigy KubeGraf. \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043d\u0430 GitHub. \u0410 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u0430\u043c\u0438 \u0438\u0441\u0442\u043e\u0440\u0438\u0435\u0439 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0438 \u043f\u043b\u0430\u0433\u0438\u043d, \u043a\u0430\u043a\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0438 \u0441 \u043a\u0430\u043a\u0438\u043c\u0438 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u043c\u0438 \u043a\u0430\u043c\u043d\u044f\u043c\u0438 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-52343","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.4 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442!\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/razrabotka-plagina-dlya-grafana-istoriya-nabityh-shishek\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"sl_SI\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0434\u043b\u044f Grafana: \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u043d\u0430\u0431\u0438\u0442\u044b\u0445 \u0448\u0438\u0448\u0435\u043a | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442!\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/razrabotka-plagina-dlya-grafana-istoriya-nabityh-shishek\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-11-05T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:00:02+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Razvoj dodatka za Grafana: istorija ste\u010denih iskustava | ProHoster","description":"Zdravo svima!","canonical_url":"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/razrabotka-plagina-dlya-grafana-istoriya-nabityh-shishek","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sl_SI","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0434\u043b\u044f Grafana: \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u043d\u0430\u0431\u0438\u0442\u044b\u0445 \u0448\u0438\u0448\u0435\u043a | ProHoster","og:description":"\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442!","og:url":"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/razrabotka-plagina-dlya-grafana-istoriya-nabityh-shishek","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-11-05T21:00:00+00:00","article:modified_time":"2020-02-18T11:00:02+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"52343","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-24 03:18:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:45:28","updated":"2026-01-24 03:18:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/posts\/52343","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/comments?post=52343"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/posts\/52343\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/media?parent=52343"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/categories?post=52343"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/tags?post=52343"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}