Herkese selam! Birkaç ay önce yeni açık kaynak projemizi üretime soktuk; kubernet'leri izlemek için Grafana eklentisi adını verdik. . Eklenti kaynak kodu şu adreste mevcuttur: . Ve bu yazımızda eklentiyi nasıl oluşturduğumuzun, hangi araçları kullandığımızın ve geliştirme sürecinde karşılaştığımız tuzakların hikayesini sizlerle paylaşmak istiyoruz. Hadi gidelim!
Bölüm 0 - giriş: Bu noktaya nasıl geldik?
Grafan için kendi eklentimizi yazma fikri aklımıza tamamen tesadüfen geldi. Şirketimiz 10 yılı aşkın bir süredir çeşitli karmaşıklık seviyelerindeki web projelerini izlemektedir. Bu süre zarfında, çeşitli izleme sistemlerini kullanma konusunda büyük miktarda uzmanlık, ilginç vakalar ve deneyim biriktirdik. Ve bir noktada kendimize şunu sorduk: "Kubernetes'i izlemek için, dedikleri gibi, "ayarla ve unut" diyen sihirli bir araç var mı?". K8'leri izlemeye yönelik endüstri standardı elbette uzun zamandır Prometheus + Grafana kombinasyonu. Ve bu yığın için hazır çözümler olarak çok çeşitli araçlar vardır: prometheus-operatör, bir dizi kubernetes-mixin kontrol paneli, grafana-kubernetes-app.
Grafana-kubernetes-app eklentisi bizim için en ilginç seçenek gibi göründü, ancak bir yıldan fazla bir süredir desteklenmiyor ve dahası, node-exporter ve kube-state-metrics'in yeni sürümleriyle çalışamıyor. Ve bir noktada şuna karar verdik: "Kendi kararımızı vermemiz gerekmez mi?"
Eklentimizde hangi fikirleri uygulamaya karar verdik:
- “uygulama haritasının” görselleştirilmesi: kümedeki uygulamaların ad alanlarına, dağıtımlara göre gruplandırılmış şekilde uygun şekilde sunulması...;
- “dağıtım – hizmet (+bağlantı noktaları)” gibi bağlantıların görselleştirilmesi.
- küme uygulamalarının küme düğümleri arasındaki dağıtımının görselleştirilmesi.
- Çeşitli kaynaklardan ölçüm ve bilgilerin toplanması: Prometheus ve k8s API sunucusu.
- hem altyapı kısmının (CPU zamanı, bellek, disk alt sistemi, ağ kullanımı) hem de uygulama mantığının (sağlık durumu bölmeleri, mevcut kopya sayısı, canlılık/hazırlık testlerini geçmeyle ilgili bilgiler) izlenmesi.
Bölüm 1: “Grafana eklentisi” nedir?
Teknik açıdan bakıldığında Grafana eklentisi, Grafana veri dizininde saklanan açısal bir denetleyicidir (/var/grafana/eklentiler/ /dist/module.js) ve SystemJS modülü olarak yüklenebilir. Ayrıca bu dizinde eklentinizle ilgili tüm meta bilgileri içeren bir eklenti.json dosyası bulunmalıdır: ad, sürüm, eklenti türü, depo/site/lisans bağlantıları, bağımlılıklar vb.

modül.ts

eklenti.json
Ekran görüntüsünde görebileceğiniz gibi, eklenti.tipi = app olarak belirttik. Çünkü Grafana eklentileri üç türden olabilir:
panel: En yaygın eklenti türü - çeşitli gösterge tabloları oluşturmak için kullanılan ölçümleri görselleştirmeye yönelik bir paneldir.
veri kaynağı: bazı veri kaynaklarına eklenti bağlayıcı (örneğin, Prometheus-datasource, ClickHouse-datasource, ElasticSearch-datasource).
uygulamayı yükleyeceğiz: Grafana içinde kendi ön uç uygulamanızı oluşturmanıza, kendi html sayfalarınızı oluşturmanıza ve çeşitli verileri görselleştirmek için veri kaynağına manuel olarak erişmenize olanak tanıyan bir eklenti. Ayrıca diğer türlerdeki eklentiler (veri kaynağı, panel) ve çeşitli gösterge tabloları bağımlılık olarak kullanılabilir.

type=app ile örnek eklenti bağımlılıkları.
Programlama dili olarak hem JavaScript'i hem de TypeScript'i kullanabilirsiniz (biz bunu seçtik). Yapabileceğiniz her türden merhaba dünya eklentisi için hazırlıklar : Bu depo, önceden yüklenmiş ve yapılandırılmış geliştiricilere sahip çok sayıda başlangıç paketi içerir (React'te deneysel bir eklenti örneği bile vardır).
Bölüm 2: Yerel ortamın hazırlanması
Eklenti üzerinde çalışmak için doğal olarak önceden yüklenmiş tüm araçları içeren bir kubernetes kümesine ihtiyacımız var: prometheus, node-exporter, kube-state-metrics, grafana. Ortam hızlı, kolay ve doğal bir şekilde kurulmalı ve çalışırken yeniden yüklemeyi sağlamak için Grafana veri dizini doğrudan geliştiricinin makinesinden kurulmalıdır.
Bize göre kubernetes ile yerel olarak çalışmanın en uygun yolu . Bir sonraki adım, prometheus operatörünü kullanarak Prometheus + Grafana kombinasyonunu kurmaktır. İÇİNDE Prometheus operatörünün minikube üzerine kurulma süreci detaylı olarak anlatılmıştır. Kalıcılığı etkinleştirmek için parametreyi ayarlamanız gerekir. kalıcılık: doğru charts/grafana/values.yaml dosyasına kendi PV'nizi ve PVC'nizi ekleyin ve bunları persistence.existingClaim parametresinde belirtin
Son minikube başlatma betiğimiz şuna benzer:
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.LBölüm 3: Gerçek Gelişim
Nesne Modeli
Eklentiyi uygulamaya hazırlanırken birlikte çalışacağımız tüm temel Kubernetes varlıklarını TypeScript sınıfları biçiminde tanımlamaya karar verdik: pod, dağıtım, daemonset, durum bilgisi kümesi, iş, cronjob, hizmet, düğüm, ad alanı. Bu sınıfların her biri, yapıcıyı, yıkıcıyı, görünürlüğü güncelleme ve değiştirme yöntemlerini tanımlayan ortak BaseModel sınıfından miras alır. Sınıfların her biri, diğer varlıklarla iç içe geçmiş ilişkileri açıklar; örneğin, tür dağıtımındaki bir varlık için bölmelerin listesi.
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 = [];
}
}Alıcılar ve ayarlayıcıların yardımıyla ihtiyacımız olan varlık metriklerini kullanışlı ve okunabilir bir biçimde görüntüleyebilir veya ayarlayabiliriz. Örneğin, tahsis edilebilir CPU düğümlerinin biçimlendirilmiş çıktısı:
get cpuAllocatableFormatted(){
let cpu = this.data.status.allocatable.cpu;
if(cpu.indexOf('m') > -1){
cpu = parseInt(cpu)/1000;
}
return cpu;
}Sayfalar
Tüm eklenti sayfalarımızın bir listesi başlangıçta eklentimiz.json'da bağımlılıklar bölümünde açıklanmıştır:

Her sayfanın bloğunda SAYFA ADI'nı belirtmeliyiz (daha sonra bu sayfaya erişilebilecek bir bilgi notuna dönüştürülecektir); bu sayfanın işleyişinden sorumlu bileşenin adı (bileşenlerin listesi module.ts'ye aktarılır); bu sayfayla çalışmanın mümkün olduğu kullanıcı rolünü ve kenar çubuğuna ilişkin gezinme ayarlarını belirtir.
Sayfanın işleyişinden sorumlu bileşende, şablonUrl'yi ayarlamalı ve oraya işaretlemeli html dosyasının yolunu iletmeliyiz. Denetleyicinin içinde bağımlılık enjeksiyonu yoluyla 2'ye kadar önemli açısal hizmete erişebiliriz:
- backendSrv - Grafana API sunucusuyla etkileşim sağlayan bir hizmet;
- datasourceSrv - Grafana'nızda kurulu tüm veri kaynaklarıyla yerel etkileşim sağlayan bir hizmet (örneğin, .getAll() yöntemi - yüklü tüm veri kaynaklarının bir listesini döndürür; .get( ) - belirli bir veri kaynağının örnek nesnesini döndürür.



Bölüm 4: veri kaynağı
Grafana'nın bakış açısından, veri kaynağı diğerleriyle tamamen aynı eklentidir: kendi giriş noktası module.js'ye sahiptir ve meta bilgi eklentisi.json'u içeren bir dosya vardır. type = app ile bir eklenti geliştirirken, hem mevcut veri kaynaklarıyla (örneğin, prometheus-datasource) hem de doğrudan eklenti dizininde saklayabileceğimiz (dist/datasource/*) veya bağımlılık olarak kurabileceğimiz kendi veri kaynaklarımızla etkileşime girebiliriz. Bizim durumumuzda veri kaynağı eklenti koduyla birlikte gelir. Ayrıca, veri kaynağı örneğini yapılandırmak için sayfa için kullanılacak bir config.html şablonuna ve bir ConfigCtrl denetleyicisine ve veri kaynağınızın mantığını uygulayan Veri kaynağı denetleyicisine sahip olmak da gereklidir.
KubeGraf eklentisinde, kullanıcı arayüzü açısından veri kaynağı, aşağıdaki yetenekleri uygulayan bir kubernetes kümesinin örneğidir (kaynak kodu mevcuttur) ):
- k8s api sunucusundan veri toplama (ad alanlarının, dağıtımların bir listesini alma...)
- prometheus-datasource isteklerine proxy oluşturma (bu, her belirli küme için eklenti ayarlarında seçilir) ve yanıtları hem statik sayfalarda hem de kontrol panellerinde verileri kullanacak şekilde biçimlendirme.
- Statik eklenti sayfalarındaki verilerin güncellenmesi (belirlenmiş bir yenileme hızıyla).
- grafana-dashboard'larda bir şablon sayfası oluşturmak için sorguları işleme (metriFindQuery() yöntemi)



- son k8s kümesiyle bağlantı testi.
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"};
})
}Bizim görüşümüze göre ayrı bir ilginç nokta, veri kaynağı için bir kimlik doğrulama ve yetkilendirme mekanizmasının uygulanmasıdır. Genellikle, son veri kaynağına erişimi yapılandırmak için yerleşik Grafana bileşeni datasourceHttpSettings'i kullanabiliriz. Bu bileşeni kullanarak, URL'yi ve temel kimlik doğrulama/yetkilendirme ayarlarını belirterek http veri kaynağına erişimi yapılandırabiliriz: oturum açma parolası veya istemci sertifikası/istemci anahtarı. Taşıyıcı jeton (k8'ler için fiili standart) kullanarak erişimi yapılandırma yeteneğini uygulamak için küçük bir değişiklik yapmamız gerekti.
Bu sorunu çözmek için yerleşik Grafana “Eklenti Yolları” mekanizmasını kullanabilirsiniz (daha fazla ayrıntı için bkz. ). Veri kaynağımızın ayarlarında grafana proxy sunucusu tarafından işlenecek bir dizi yönlendirme kuralı bildirebiliriz. Örneğin, her bir uç nokta için, verileri jsonData ve secureJsonData alanlarından alınabilen (şifreleri veya belirteçleri şifrelenmiş biçimde saklamak için) şablon oluşturma olanağına sahip başlıklar veya URL'ler ayarlamak mümkündür. Örneğimizde aşağıdaki gibi sorgular /__proxy/api/v1/ad alanları formun URL'sine proxy verilecek
Yetkilendirme: Taşıyıcı başlığıyla /api/v8/namespaces.


Doğal olarak, k8s API sunucusuyla çalışmak için salt okunur erişime sahip bir kullanıcıya ihtiyacımız var; oluşturma bildirimlerini şurada da bulabilirsiniz: .
Bölüm 5: yayın

Kendi Grafana eklentinizi yazdığınızda, doğal olarak onu herkesin kullanımına sunmak isteyeceksiniz. Grafana'da bu, burada bulunan bir eklenti kütüphanesidir
Eklentinizin resmi mağazada satışa sunulması için PR yapmanız gerekir. repo.json dosyasına buna benzer içerik ekleyerek:

version, eklentinizin sürümüdür, url, depoya bir bağlantıdır ve taahhüt, eklentinin belirli bir sürümünün mevcut olacağı taahhüdün karmasıdır.
Ve çıktıda şöyle harika bir resim göreceksiniz:

Bunun verileri otomatik olarak Readme.md, Changelog.md ve eklenti açıklamasıyla birlikte eklenti.json dosyasından alınacaktır.
Bölüm 6: sonuçlar yerine
Eklentimizi yayınladıktan sonra geliştirmeyi bırakmadık. Ve şimdi, küme düğümlerinin kaynaklarının kullanımını doğru bir şekilde izlemek, UX'i geliştirmek için yeni özellikler sunmak ve ayrıca eklentiyi yükledikten sonra hem müşterilerimizden hem de GitHub'daki kişilerden (eğer ayrılırsanız) alınan büyük miktarda geri bildirimi toplamak için çalışıyoruz. sorun veya çekme isteğiniz olursa çok mutlu olurum :)
Bu makalenin Grafana gibi harika bir aracı anlamanıza ve belki de kendi eklentinizi yazmanıza yardımcı olacağını umuyoruz.
Teşekkür ederim!)
Kaynak: habr.com
