{"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\/cs\/blog\/administrirovanie\/razrabotka-plagina-dlya-grafana-istoriya-nabityh-shishek","title":{"rendered":"V\u00fdvoj pluginu pro Grafanu: p\u0159\u00edb\u011bh o zku\u0161enostech a obt\u00ed\u017e\u00edch","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Ahoj v\u0161ichni! P\u0159ed n\u011bkolika m\u011bs\u00edci jsme uvedli do produkce n\u00e1\u0161 nov\u00fd open-source projekt \u2014 Grafana plugin pro monitoring Kubernetes, kter\u00fd jsme nazvali <b><noindex><a rel=\"nofollow\" href=\"https:\/\/grafana.com\/grafana\/plugins\/devopsprodigy-kubegraf-app\">DevOpsProdigy KubeGraf<\/a><\/noindex><\/b>. Zdrojov\u00fd k\u00f3d pluginu je dostupn\u00fd v <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/devopsprodigy\/kubegraf\">ve\u0159ejn\u00e9m repozit\u00e1\u0159i na GitHubu<\/a><\/noindex>. A v tomto \u010dl\u00e1nku bychom se s v\u00e1mi cht\u011bli pod\u011blit o p\u0159\u00edb\u011bh, jak jsme plugin vytv\u00e1\u0159eli, jak\u00e9 n\u00e1stroje jsme pou\u017e\u00edvali a s jak\u00fdmi p\u0159ek\u00e1\u017ekami jsme se b\u011bhem v\u00fdvoje setkali. Jdeme na to!<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h4>\u010c\u00e1st 0 \u2014 \u00favod: jak jsme se k tomu dostali?<\/h4>\n<p>\nMy\u0161lenka napsat vlastn\u00ed plugin pro Grafanu n\u00e1s napadla zcela n\u00e1hodou. Na\u0161e spole\u010dnost se ji\u017e v\u00edce ne\u017e 10 let zab\u00fdv\u00e1 monitoringem webov\u00fdch projekt\u016f r\u016fzn\u00e9 slo\u017eitosti. B\u011bhem t\u00e9to doby jsme nashrom\u00e1\u017edili bohat\u00e9 zku\u0161enosti, zaj\u00edmav\u00e9 p\u0159\u00edpady a zku\u0161enosti s r\u016fzn\u00fdmi monitorovac\u00edmi syst\u00e9my. A v ur\u010dit\u00e9m okam\u017eiku jsme si polo\u017eili ot\u00e1zku: \u201eExistuje kouzeln\u00fd n\u00e1stroj pro monitoring Kubernetes, kter\u00fd by se dal \u201enainstalovat a zapomenout\u201c?..\u201c Pr\u016fmyslov\u00fdm standardem pro monitoring k8s je samoz\u0159ejm\u011b u\u017e dlouho spojen\u00ed Prometheus + Grafana. A pro tuto technologii existuje \u0161irok\u00e1 \u0161k\u00e1la r\u016fzn\u00fdch hotov\u00fdch n\u00e1stroj\u016f: prometheus-operator, sada dashboard\u016f kubernetes-mixin, grafana-kubernetes-app. <\/p>\n<p>Nejzaj\u00edmav\u011bj\u0161\u00ed mo\u017enost\u00ed pro n\u00e1s se zd\u00e1l plugin grafana-kubernetes-app, ale u\u017e v\u00edce ne\u017e rok nen\u00ed udr\u017eov\u00e1n a nav\u00edc neum\u00ed pracovat s nov\u00fdmi verzemi node-exportera a kube-state-metrics. A v n\u011bjak\u00e9m okam\u017eiku jsme se rozhodli: \u201eA neud\u011blat si vlastn\u00ed \u0159e\u0161en\u00ed?\u201c<\/p>\n<p>Jak\u00e9 n\u00e1pady jsme se rozhodli realizovat ve sv\u00e9m pluginu:<\/p>\n<ul>\n<li>vizualizace \u201emapy aplikace\u201c: p\u0159ehledn\u00e9 zobrazen\u00ed aplikac\u00ed v clusteru, uspo\u0159\u00e1dan\u00fdch podle namespace, deployment\u016f\u2026;<\/li>\n<li>vizualizace vztah\u016f typu \u201edeployment \u2014 service (+ports)\u201c.<\/li>\n<li>vizualizace rozlo\u017een\u00ed aplikac\u00ed clusteru po nodech clusteru.<\/li>\n<li>shroma\u017e\u010fov\u00e1n\u00ed metrik a informac\u00ed z n\u011bkolika zdroj\u016f: Prometheus a k8s API server.<\/li>\n<li>monitoring jak infrastrukturn\u00ed \u010d\u00e1sti (vyu\u017eit\u00ed procesorov\u00e9ho \u010dasu, pam\u011bti, diskov\u00e9ho subsyst\u00e9mu, s\u00edt\u011b), tak logiky aplikac\u00ed \u2014 health-status pod\u016f, po\u010det dostupn\u00fdch replik, informace o prov\u00e1d\u011bn\u00ed liveness\/readiness test\u016f.<\/li>\n<\/ul>\n<p><\/p>\n<h4>\u010c\u00e1st 1: Co je to \u201eplugin pro Grafanu\u201c?<\/h4>\n<p>\nZ technick\u00e9ho hlediska je plugin pro Grafanu angular-ovlada\u010d, kter\u00fd se ukl\u00e1d\u00e1 do data adres\u00e1\u0159e Grafany (<i>\/var\/grafana\/plugins\/&lt;your_plugin_name&gt;\/dist\/module.js<\/i>) a m\u016f\u017ee b\u00fdt na\u010dten jako SystemJS modul. Tak\u00e9 v tomto adres\u00e1\u0159i by m\u011bl b\u00fdt soubor plugin.json, kter\u00fd obsahuje ve\u0161ker\u00e9 meta informace o va\u0161em pluginu: n\u00e1zev, verze, typ pluginu, odkazy na repozit\u00e1\u0159\/web\/license, z\u00e1vislosti a tak d\u00e1le.<\/p>\n<p><img decoding=\"async\" alt=\"V\u00fdvoj pluginu pro Grafanu: p\u0159\u00edb\u011bh o zku\u0161enostech a obt\u00ed\u017e\u00edch\" 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=\"V\u00fdvoj pluginu pro Grafanu: p\u0159\u00edb\u011bh o zku\u0161enostech a obt\u00ed\u017e\u00edch\" src=\"\/wp-content\/uploads\/2019\/11\/1e5b780837e5a9385e5e22a27d83f567.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>plugin.json<\/i><\/p>\n<p>Jak je vid\u011bt na screenshotu, uvedli jsme plugin.type = app. Pluginy pro Grafanu mohou m\u00edt t\u0159i typy:<\/p>\n<p><b>panel<\/b>: nejb\u011b\u017en\u011bj\u0161\u00ed typ plugin\u016f \u2013 p\u0159edstavuje panel pro vizualizaci r\u016fzn\u00fdch metrik, pou\u017e\u00edv\u00e1 se pro vytv\u00e1\u0159en\u00ed r\u016fzn\u00fdch dashboard\u016f.<br \/>\n<b>datasource<\/b>: plugin-konektor k ur\u010dit\u00e9mu zdroji dat (nap\u0159. Prometheus-datasource, ClickHouse-datasource, ElasticSearch-datasource).<br \/>\n<b>app<\/b>: plugin, kter\u00fd v\u00e1m umo\u017e\u0148uje vytvo\u0159it svou vlastn\u00ed frontendovou aplikaci uvnit\u0159 Grafany, vytv\u00e1\u0159et vlastn\u00ed html str\u00e1nky a ru\u010dn\u011b se dotazovat na datasource pro vizualizaci r\u016fzn\u00fdch dat. Tak\u00e9 lze jako z\u00e1vislosti pou\u017e\u00edvat jin\u00e9 typy plugin\u016f (datasource, panel) a r\u016fzn\u00e9 dashboardy.<\/p>\n<p><img decoding=\"async\" alt=\"V\u00fdvoj pluginu pro Grafanu: p\u0159\u00edb\u011bh o zku\u0161enostech a obt\u00ed\u017e\u00edch\" src=\"\/wp-content\/uploads\/2019\/11\/3cd53c7c3a2635f3f20831d52198b5f0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>P\u0159\u00edklad z\u00e1vislost\u00ed pluginu s type = app<\/i>.<\/p>\n<p>Jako programovac\u00ed jazyk je mo\u017en\u00e9 pou\u017e\u00edt jak JavaScript, tak TypeScript (my jsme se rozhodli pro n\u011bj). \u0160ablony pro hello-world pluginy jak\u00e9hokoli typu m\u016f\u017eete <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CorpGlory\">naj\u00edt na odkazu<\/a><\/noindex>: v tomto repozit\u00e1\u0159i je prezentov\u00e1no velk\u00e9 mno\u017estv\u00ed starter-pack\u016f (je zde dokonce experiment\u00e1ln\u00ed p\u0159\u00edklad pluginu na React) s p\u0159edinstalovan\u00fdmi a nastaven\u00fdmi build syst\u00e9my. <\/p>\n<h4>\u010c\u00e1st 2: p\u0159\u00edprava lok\u00e1ln\u00edho prost\u0159ed\u00ed<\/h4>\n<p>\nPro pr\u00e1ci na pluginu budeme samoz\u0159ejm\u011b pot\u0159ebovat Kubernetes klastr se v\u0161emi p\u0159edinstalovan\u00fdmi n\u00e1stroji: Prometheus, Node-exporter, Kube-state-metrics, Grafana. Prost\u0159ed\u00ed by m\u011blo b\u00fdt nastaveno rychle, snadno a bezstarostn\u011b, a pro zaji\u0161t\u011bn\u00ed hot-reload by m\u011bla b\u00fdt data directory Grafany p\u0159ipojena p\u0159\u00edmo z v\u00fdvoj\u00e1\u0159sk\u00e9 stanice.<\/p>\n<p>Nejlep\u0161\u00edm zp\u016fsobem pro lok\u00e1ln\u00ed pr\u00e1ci s Kubernetes, podle na\u0161eho n\u00e1zoru, je <noindex><a rel=\"nofollow\" href=\"https:\/\/kubernetes.io\/docs\/tasks\/tools\/install-minikube\/\">minikube<\/a><\/noindex>. Dal\u0161\u00edm krokem je instalace spojen\u00ed Prometheus + Grafana pomoc\u00ed prometheus-operator. V <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/faun\/trying-prometheus-operator-with-helm-minikube-b617a2dccfa3\">tomto \u010dl\u00e1nku<\/a><\/noindex> je podrobn\u011b pops\u00e1n proces instalace prometheus-operator na minikube. Pro zapnut\u00ed persistentnosti je nutn\u00e9 nastavit parametr <i>persistence: true<\/i> v souboru charts\/grafana\/values.yaml, p\u0159idat sv\u016fj vlastn\u00ed PV a PVC a uv\u00e9st je v parametru persistence.existingClaim<\/p>\n<p>N\u00e1\u0161 fin\u00e1ln\u00ed spou\u0161t\u011bc\u00ed skript pro minikube vypad\u00e1 takto:<\/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>\u010c\u00e1st 3: p\u0159\u00edm\u00fd v\u00fdvoj<\/h4>\n<p>\n<b>Objektov\u00fd model<\/b><\/p>\n<p>Jako p\u0159\u00edpravu na implementaci pluginu jsme se rozhodli popsat v\u0161echny z\u00e1kladn\u00ed entity Kubernetes, se kter\u00fdmi budeme pracovat, ve form\u011b TypeScript t\u0159\u00edd: pod, deployment, daemonset, statefulset, job, cronjob, service, node, namespace. Ka\u017ed\u00e1 z t\u011bchto t\u0159\u00edd d\u011bd\u00ed od obecn\u00e9 t\u0159\u00eddy BaseModel, ve kter\u00e9 jsou pops\u00e1ny konstruktor, destruktor, metody pro aktualizaci a p\u0159ep\u00edn\u00e1n\u00ed viditelnosti. V ka\u017ed\u00e9 z t\u011bchto t\u0159\u00edd jsou pops\u00e1ny vno\u0159en\u00e9 vztahy s jin\u00fdmi entitami, nap\u0159\u00edklad seznam pod\u016f u entity typu 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>\nPomoc\u00ed getter\u016f a setter\u016f m\u016f\u017eeme zobrazit nebo nastavit pot\u0159ebn\u00e9 metriky entit v pohodln\u00e9m a \u010diteln\u00e9m form\u00e1tu. Nap\u0159\u00edklad naform\u00e1tovan\u00fd v\u00fdstup allocatable cpu nodu:<\/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>Str\u00e1nky<\/b><\/p>\n<p>Seznam v\u0161ech str\u00e1nek na\u0161eho pluginu je p\u016fvodn\u011b pops\u00e1n v na\u0161em pluing.json v sekci z\u00e1vislost\u00ed:<\/p>\n<p><img decoding=\"async\" alt=\"V\u00fdvoj pluginu pro Grafanu: p\u0159\u00edb\u011bh o zku\u0161enostech a obt\u00ed\u017e\u00edch\" src=\"\/wp-content\/uploads\/2019\/11\/b86c74839ad0d9c64b97ffc3f2a84bdf.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nV bloku pro ka\u017edou str\u00e1nku mus\u00edme uv\u00e9st N\u00c1ZEV STR\u00c1NKY (ten bude pak p\u0159eveden na slug, podle kter\u00e9ho bude tato str\u00e1nka dostupn\u00e1); n\u00e1zev komponenty, kter\u00e1 zaji\u0161\u0165uje funk\u010dnost t\u00e9to str\u00e1nky (seznam komponent\u016f je exportov\u00e1n v module.ts); specifikaci u\u017eivatelsk\u00e9 role, pro kterou je pr\u00e1ce s touto str\u00e1nkou dostupn\u00e1, a nastaven\u00ed navigace pro postrann\u00ed panel. <\/p>\n<p>V komponent\u011b, kter\u00e1 zaji\u0161\u0165uje funk\u010dnost str\u00e1nky, mus\u00edme nastavit templateUrl, kde p\u0159ed\u00e1me cestu k html souboru s rozlo\u017een\u00edm. Uvnit\u0159 kontroleru, prost\u0159ednictv\u00edm dependency injection, z\u00edsk\u00e1me p\u0159\u00edstup k 2 d\u016fle\u017eit\u00fdm angular slu\u017eb\u00e1m:<\/p>\n<ul>\n<li>backendSrv \u2014 slu\u017eba zaji\u0161\u0165uj\u00edc\u00ed interakci s api serverem Grafany;<\/li>\n<li>datasourceSrv \u2014 slu\u017eba zaji\u0161\u0165uj\u00edc\u00ed lok\u00e1ln\u00ed interakci se v\u0161emi datov\u00fdmi zdroji instalovan\u00fdmi ve va\u0161\u00ed Grafan\u011b (nap\u0159\u00edklad metoda .getAll() \u2014 vr\u00e1t\u00ed seznam v\u0161ech nainstalovan\u00fdch datov\u00fdch zdroj\u016f; .get() \u2014 vr\u00e1t\u00ed objekt-instantci konkr\u00e9tn\u00edho datov\u00e9ho zdroje.<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"V\u00fdvoj pluginu pro Grafanu: p\u0159\u00edb\u011bh o zku\u0161enostech a obt\u00ed\u017e\u00edch\" src=\"\/wp-content\/uploads\/2019\/11\/e616e74c2e31ca3a81b7ed91ca333208.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<img decoding=\"async\" alt=\"V\u00fdvoj pluginu pro Grafanu: p\u0159\u00edb\u011bh o zku\u0161enostech a obt\u00ed\u017e\u00edch\" src=\"\/wp-content\/uploads\/2019\/11\/5e1d45f570dda50774088405abb41c9f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<img decoding=\"async\" alt=\"V\u00fdvoj pluginu pro Grafanu: p\u0159\u00edb\u011bh o zku\u0161enostech a obt\u00ed\u017e\u00edch\" src=\"\/wp-content\/uploads\/2019\/11\/c072867623824e799518984c7b1bee93.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h4>\u010c\u00e1st 4: datov\u00fd zdroj<\/h4>\n<p>\nZ pohledu Grafany je datasource stejn\u00fdm typem pluginu jako v\u0161echny ostatn\u00ed: m\u00e1 sv\u016fj vstupn\u00ed bod module.js a soubor s metainformacemi plugin.json. P\u0159i v\u00fdvoji pluginu s typem = app m\u016f\u017eeme interagovat jak s ji\u017e existuj\u00edc\u00edmi datasource (nap\u0159\u00edklad prometheus-datasource), tak s na\u0161imi vlastn\u00edmi, kter\u00e9 m\u016f\u017eeme ulo\u017eit p\u0159\u00edmo do adres\u00e1\u0159e pluginu (dist\/datasource\/*) nebo je instalovat jako z\u00e1vislost. V na\u0161em p\u0159\u00edpad\u011b je datasource dod\u00e1v\u00e1n spolu s k\u00f3dem pluginu. Tak\u00e9 je nezbytn\u00e9 m\u00edt \u0161ablonu config.html a kontroler ConfigCtrl, kter\u00e9 budou pou\u017eity pro str\u00e1nku konfigurace instance datasource a kontroler Datasource, ve kter\u00e9m je implementov\u00e1na logika fungov\u00e1n\u00ed va\u0161eho datasource.<\/p>\n<p>V pluginu KubeGraf, z pohledu u\u017eivatelsk\u00e9ho rozhran\u00ed, p\u0159edstavuje datasource instanci kubernetes-clusteru, v n\u011bm\u017e jsou implementov\u00e1ny n\u00e1sleduj\u00edc\u00ed funkce (zdrojov\u00fd k\u00f3d je k dispozici <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/devopsprodigy\/kubegraf\/tree\/master\/src\/datasource\">na odkazu<\/a><\/noindex>):<\/p>\n<ul>\n<li>z\u00edsk\u00e1v\u00e1n\u00ed dat z api-serveru k8s (z\u00edsk\u00e1n\u00ed seznamu namespace, deployment...)<\/li>\n<li>proxyov\u00e1n\u00ed po\u017eadavk\u016f na prometheus-datasource (kter\u00fd se vyb\u00edr\u00e1 v nastaven\u00ed pluginu pro ka\u017ed\u00fd konkr\u00e9tn\u00ed cluster) a form\u00e1tov\u00e1n\u00ed odpov\u011bd\u00ed pro pou\u017eit\u00ed dat jak na statick\u00fdch str\u00e1nk\u00e1ch, tak v dashboardech.<\/li>\n<li>aktualizace dat na statick\u00fdch str\u00e1nk\u00e1ch pluginu (s nastaven\u00fdm \u010dasov\u00fdm intervalem obnovov\u00e1n\u00ed).<\/li>\n<li>zpracov\u00e1n\u00ed po\u017eadavk\u016f pro generov\u00e1n\u00ed seznamu \u0161ablon v grafana-dashboards (metoda .metriFindQuery())<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"V\u00fdvoj pluginu pro Grafanu: p\u0159\u00edb\u011bh o zku\u0161enostech a obt\u00ed\u017e\u00edch\" src=\"\/wp-content\/uploads\/2019\/11\/18159bbb41144ebceb457df28b35e7b1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<img decoding=\"async\" alt=\"V\u00fdvoj pluginu pro Grafanu: p\u0159\u00edb\u011bh o zku\u0161enostech a obt\u00ed\u017e\u00edch\" src=\"\/wp-content\/uploads\/2019\/11\/a62665b4409566fbe24f56f88a376d5a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<img decoding=\"async\" alt=\"V\u00fdvoj pluginu pro Grafanu: p\u0159\u00edb\u011bh o zku\u0161enostech a obt\u00ed\u017e\u00edch\" src=\"\/wp-content\/uploads\/2019\/11\/7f2d61fce623ce2a3cf62feb6d0447ac.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<ul>\n<li>testov\u00e1n\u00ed p\u0159ipojen\u00ed k c\u00edlov\u00e9mu k8s clusteru.<\/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: \"Datasource je OK\", title: \"\u00dasp\u011bch\"};\n           }else{\n               return {status: \"error\", message: \"Datasource nen\u00ed OK\", title: \"Chyba\"};\n           }\n       }, error =&gt; {\n           return {status: \"error\", message: \"Datasource nen\u00ed OK\", title: \"Chyba\"};\n       })\n}<\/code><\/pre>\n<p>\nZaj\u00edmav\u00fdm aspektem je realizace mechanismu autentizace a autorizace pro datasource. Obvykle m\u016f\u017eeme pou\u017e\u00edt integrovanou komponentu Grafana \u2014 datasourceHttpSettings pro konfiguraci p\u0159\u00edstupu k c\u00edlov\u00e9mu datov\u00e9mu zdroji. Pomoc\u00ed t\u00e9to komponenty m\u016f\u017eeme nastavit p\u0159\u00edstup k http-datov\u00e9mu zdroji zad\u00e1n\u00edm url a z\u00e1kladn\u00edch autentiza\u010dn\u00edch\/autorizac\u00edch nastaven\u00ed: u\u017eivatelsk\u00e9 jm\u00e9no-heslo nebo client-cert\/client-key. Aby bylo mo\u017en\u00e9 nastavit p\u0159\u00edstup pomoc\u00ed bearer-tokenu (de facto standard pro k8s), muselo se trochu \"pohr\u00e1t\".<\/p>\n<p>K \u0159e\u0161en\u00ed tohoto \u00fakolu lze pou\u017e\u00edt integrovan\u00fd mechanismus Grafana \u201ePlugin Routes\u201c (podrobn\u011bji na <noindex><a rel=\"nofollow\" href=\"https:\/\/grafana.com\/docs\/plugins\/developing\/auth-for-datasources\/\">ofici\u00e1ln\u00ed str\u00e1nce dokumentace<\/a><\/noindex>). V nastaven\u00ed na\u0161eho datasource m\u016f\u017eeme deklarovat sadu pravidel sm\u011brov\u00e1n\u00ed, kter\u00e1 budou zpracov\u00e1v\u00e1na proxy serverem grafana. Nap\u0159\u00edklad pro ka\u017ed\u00fd jednotliv\u00fd endpoint existuje mo\u017enost nastavit hlavi\u010dky nebo url s mo\u017enost\u00ed \u0161ablonov\u00e1n\u00ed, p\u0159i\u010dem\u017e data mohou b\u00fdt \u010derp\u00e1na z pol\u00ed jsonData a secureJsonData (pro uchov\u00e1n\u00ed hesel nebo token\u016f v za\u0161ifrovan\u00e9 podob\u011b). V na\u0161em p\u0159\u00edkladu budou po\u017eadavky ve form\u00e1tu <i>\/__proxy\/api\/v1\/namespaces<\/i> proch\u00e1zet na url ve form\u00e1tu<br \/>\n\/api\/v1\/namespaces s nastaven\u00edm hlavi\u010dky Authorization: Bearer.<\/p>\n<p><img decoding=\"async\" alt=\"V\u00fdvoj pluginu pro Grafanu: p\u0159\u00edb\u011bh o zku\u0161enostech a obt\u00ed\u017e\u00edch\" src=\"\/wp-content\/uploads\/2019\/11\/ca73ff0fef62fba3edab7907c83639b6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<img decoding=\"async\" alt=\"V\u00fdvoj pluginu pro Grafanu: p\u0159\u00edb\u011bh o zku\u0161enostech a obt\u00ed\u017e\u00edch\" src=\"\/wp-content\/uploads\/2019\/11\/9dab7537d7ccba90c9fb62dfa70b9fe2.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSamoz\u0159ejm\u011b, pro pr\u00e1ci s api serverem k8s pot\u0159ebujeme u\u017eivatele s readonly p\u0159\u00edstupem, manifesty pro jeho vytvo\u0159en\u00ed najdete tak\u00e9 v <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/devopsprodigy\/kubegraf\/tree\/master\/kubernetes\/\">zdrojov\u00e9m k\u00f3du pluginu<\/a><\/noindex>.<\/p>\n<h4>\u010c\u00e1st 5: vyd\u00e1n\u00ed<\/h4>\n<p>\n<img decoding=\"async\" alt=\"V\u00fdvoj pluginu pro Grafanu: p\u0159\u00edb\u011bh o zku\u0161enostech a obt\u00ed\u017e\u00edch\" src=\"\/wp-content\/uploads\/2019\/11\/3991a5d412f362770157fc567bb8009c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPo naps\u00e1n\u00ed vlastn\u00edho pluginu pro Grafana se samoz\u0159ejm\u011b budete cht\u00edt o n\u011bj pod\u011blit s ve\u0159ejnost\u00ed. V Grafana je knihovna plugin\u016f dostupn\u00e1 na odkazu <noindex><a rel=\"nofollow\" href=\"https:\/\/grafana.com\/grafana\/plugins\">grafana.com\/grafana\/plugins<\/a><\/noindex> <\/p>\n<p>Aby byl v\u00e1\u0161 plugin dostupn\u00fd v ofici\u00e1ln\u00edm obchod\u011b, mus\u00edte vytvo\u0159it PR v <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/grafana\/grafana-plugin-repository\">tomto repozit\u00e1\u0159i<\/a><\/noindex>, p\u0159id\u00e1n\u00edm obsahu typu do souboru repo.json:<\/p>\n<p><img decoding=\"async\" alt=\"V\u00fdvoj pluginu pro Grafanu: p\u0159\u00edb\u011bh o zku\u0161enostech a obt\u00ed\u017e\u00edch\" src=\"\/wp-content\/uploads\/2019\/11\/160650bf37f8f2f3e12ef7dd291e90eb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nkde version \u2014 verze va\u0161eho pluginu, url \u2014 odkaz na repozit\u00e1\u0159 a commit \u2014 hash commitu, podle kter\u00e9ho bude dostupn\u00e1 konkr\u00e9tn\u00ed verze pluginu. <\/p>\n<p>A na konci uvid\u00edte \u00fa\u017easn\u00fd obr\u00e1zek ve form\u00e1tu:<\/p>\n<p><img decoding=\"async\" alt=\"V\u00fdvoj pluginu pro Grafanu: p\u0159\u00edb\u011bh o zku\u0161enostech a obt\u00ed\u017e\u00edch\" src=\"\/wp-content\/uploads\/2019\/11\/ff906396596e9c4c15c59f8d53555f52.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nData pro n\u011bj budou automaticky extrahov\u00e1na z va\u0161eho Readme.md, Changelog.md a souboru plugin.json s popisem pluginu.<\/p>\n<h4>\u010c\u00e1st 6: m\u00edsto z\u00e1v\u011br\u016f<\/h4>\n<p>\nPo vyd\u00e1n\u00ed jsme nep\u0159estali vyv\u00edjet n\u00e1\u0161 plugin. V sou\u010dasn\u00e9 dob\u011b pracujeme na spr\u00e1vn\u00e9m monitorov\u00e1n\u00ed vyu\u017eit\u00ed zdroj\u016f uzl\u016f clustera, implementaci nov\u00fdch funkc\u00ed pro zlep\u0161en\u00ed UX a \u0159e\u0161\u00edme velk\u00e9 mno\u017estv\u00ed zp\u011btn\u00e9 vazby, kterou jsme obdr\u017eeli po instalaci pluginu, jak od na\u0161ich klient\u016f, tak ze z\u00e1znam\u016f na GitHubu (pokud zanech\u00e1te sv\u016fj issue nebo pull request, budu velmi r\u00e1d \ud83d\ude42 ).<\/p>\n<p>Douf\u00e1me, \u017ee v\u00e1m tento \u010dl\u00e1nek pom\u016f\u017ee pochopit skv\u011bl\u00fd n\u00e1stroj, jak\u00fdm je Grafana, a mo\u017en\u00e1 napsat sv\u016fj vlastn\u00ed plugin. <\/p>\n<p>D\u011bkujeme!)<br \/>\n<br \/>Zdroj: <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.3 - 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\/cs\/blog\/administrirovanie\/razrabotka-plagina-dlya-grafana-istoriya-nabityh-shishek\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"cs_CZ\" \/>\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\/cs\/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\udd47V\u00fdvoj pluginu pro Grafana: historie nabit\u00fdch zku\u0161enost\u00ed | ProHoster","description":"Ahoj v\u0161ichni!","canonical_url":"https:\/\/prohoster.info\/cs\/blog\/administrirovanie\/razrabotka-plagina-dlya-grafana-istoriya-nabityh-shishek","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"cs_CZ","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\/cs\/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\/cs\/wp-json\/wp\/v2\/posts\/52343","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/comments?post=52343"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts\/52343\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/media?parent=52343"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/categories?post=52343"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/tags?post=52343"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}