大家好! 幾個月前,我們將新的開源專案投入生產——用於監控 kubernetes 的 Grafana 插件,我們稱之為
第 0 部分 - 介紹:我們是如何做到這一點的?
為 Grafan 編寫自己的插件的想法是很偶然的。 我們公司十多年來一直監控各種複雜程度的網路專案。 在這段時間裡,我們累積了大量的專業知識、有趣的案例以及使用各種監控系統的經驗。 在某些時候,我們問自己:「是否有一個神奇的工具來監控 Kubernetes,以便像他們所說的那樣,「設定好然後忘記它」?」..當然,監控 k10s 的行業標準長期以來一直是Prometheus + Grafana 組合。 作為此堆疊的現成解決方案,有大量各種工具:prometheus-operator、一組 kubernetes-mixin 儀表板、grafana-kubernetes-app。
grafana-kubernetes-app 插件似乎是我們最有趣的選擇,但它已經一年多沒有得到支持,而且無法與新版本的 node-exporter 和 kube-state-metrics 一起使用。 在某個時刻,我們決定:“我們不應該自己做決定嗎?”
我們決定在插件中實現哪些想法:
- 「應用程式地圖」的視覺化:方便地呈現叢集中的應用程序,按名稱空間、部署進行分組…;
- 連接的可視化,例如“部署 - 服務(+連接埠)”。
- 叢集應用程式跨叢集節點的分佈的可視化。
- 從多個來源收集指標和資訊:Prometheus 和 k8s api 伺服器。
- 監控基礎設施部分(CPU 時間、記憶體、磁碟子系統、網路的使用)和應用程式邏輯 - 健康狀態 Pod、可用副本數量、有關通過活性/就緒性測試的資訊。
第 1 部分:什麼是「Grafana 插件」?
從技術角度來看,Grafana的插件是一個角度控制器,它儲存在Grafana資料目錄中(/var/grafana/插件/ /dist/module.js)並且可以作為 SystemJS 模組載入。 另外,在此目錄中應該有一個plugin.json 文件,其中包含有關插件的所有元資訊:名稱、版本、插件類型、儲存庫/網站/許可證的連結、依賴項等。
模組.ts
插件.json
正如您在螢幕截圖中看到的,我們指定了plugin.type = app。 因為 Grafana 的插件可以分為三種:
面板:最常見的插件類型 - 它是一個用於視覺化任何指標的面板,用於建立各種儀表板。
數據源:連接到某些資料來源的插件連接器(例如,Prometheus-datasource、ClickHouse-datasource、ElasticSearch-datasource)。
應用:一個插件,允許您在 Grafana 中建立自己的前端應用程序,創建自己的 html 頁面並手動存取資料來源以可視化各種資料。 此外,其他類型的插件(資料來源、面板)和各種儀表板也可以用作依賴項。
type=app 的範例插件依賴項.
您可以使用 JavaScript 和 TypeScript 作為程式語言(我們選擇了它)。 準備任何類型的 hello-world 插件
第2部分:準備本地環境
要使用該插件,我們自然需要一個帶有所有預先安裝工具的 kubernetes 叢集:prometheus、node-exporter、kube-state-metrics、grafana。 環境應該快速、輕鬆、自然地設置,為了確保熱重載,Grafana 資料目錄應該直接從開發人員的機器上掛載。
我們認為,在本地使用 kubernetes 的最方便的方法是
我們最終的 minikube 啟動腳本如下所示:
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
第三部分:實際開發
物件模型
為了準備實作這個插件,我們決定以 TypeScript 類別的形式描述我們將使用的所有基本 Kubernetes 實體:pod、deployment、daemonset、statefulset、job、cronjob、service、node、namespace。 這些類別中的每一個都繼承自公共 BaseModel 類,該類別描述了建構函數、析構函數、更新和切換可見性的方法。 每個類別都描述與其他實體的巢狀關係,例如部署類型實體的 Pod 清單。
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 = [];
}
}
在 getter 和 setter 的幫助下,我們可以以方便且可讀的形式顯示或設定我們需要的實體指標。 例如,可分配 cpu 節點的格式化輸出:
get cpuAllocatableFormatted(){
let cpu = this.data.status.allocatable.cpu;
if(cpu.indexOf('m') > -1){
cpu = parseInt(cpu)/1000;
}
return cpu;
}
網頁
我們所有插件頁面的列表最初在依賴項部分的 pluing.json 中描述:
在每個頁面的區塊中,我們必須指示頁面名稱(然後它將轉換為可存取該頁面的slug); 負責本頁面操作的元件名稱(元件清單匯出到module.ts); 指示可使用此頁面的使用者角色以及側邊欄的導覽設定。
在負責頁面操作的元件中,我們必須設定 templateUrl,將帶有標記的 html 檔案的路徑傳遞到那裡。 在控制器內部,透過依賴注入,我們可以存取最多 2 個重要的 Angular 服務:
- backendSrv - 提供與 Grafana API 伺服器互動的服務;
- datasourceSrv - 提供與 Grafana 中安裝的所有資料來源的本地互動的服務(例如 .getAll() 方法 - 傳回所有已安裝資料來源的清單;.get( ) - 傳回特定資料來源的實例物件。
第四部分:資料來源
從 Grafana 的角度來看,資料來源與其他外掛程式完全相同:它有自己的入口點 module.js,有一個包含元資訊的檔案 plugin.json。 當使用type = app 開發插件時,我們可以與現有的資料來源(例如prometheus-datasource)和我們自己的資料來源進行交互,我們可以將其直接儲存在插件目錄(dist/datasource/*)中或作為依賴項安裝。 在我們的例子中,資料來源附帶插件程式碼。 還需要有一個 config.html 模板和一個 ConfigCtrl 控制器,它將用於資料來源實例配置頁面和資料來源控制器,它實現資料來源的邏輯。
在KubeGraf插件中,從使用者介面的角度來看,資料來源是一個kubernetes叢集的實例,它實現了以下功能(原始碼可取得)
- 從 k8s api 伺服器收集資料(取得命名空間、部署的清單...)
- 代理程式對 prometheus-datasource 的請求(在每個特定叢集的插件設定中選擇)並格式化回應以在靜態頁面和儀表板中使用資料。
- 更新靜態外掛程式頁面上的資料(具有設定的更新率)。
- 處理查詢以在 grafana-dashboards 中產生範本表(metriFindQuery() 方法)
- 與最終 k8s 集群的連接測試。
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"};
})
}
我們認為,一個單獨的有趣點是資料來源的身份驗證和授權機制的實作。 通常,我們可以直接使用內建的 Grafana 元件 datasourceHttpSettings 來配置對最終資料來源的存取。 使用此元件,我們可以透過指定 url 和基本驗證/授權設定(登入密碼或用戶端憑證/用戶端金鑰)來設定對 http 資料來源的存取。 為了實現使用不記名令牌(k8s 的事實上的標準)配置存取的能力,我們必須做一些調整。
為了解決這個問題,您可以使用 Grafana 內建的「Plugin Routes」機制(更多詳細資訊請參見
/api/v8/namespaces 帶有 Authorization: Bearer 標頭。
當然,要使用 k8s api 伺服器,我們需要一個具有唯讀存取權限的用戶,您也可以在中找到用於建立的清單
第 5 部分:發布
一旦您編寫了自己的 Grafana 插件,您自然會希望將其公開。 在 Grafana 中,這是一個可用的插件庫
為了讓您的插件在官方商店上可用,您需要在
其中 version 是插件的版本,url 是存儲庫的鏈接,commit 是可用的特定版本插件的提交的哈希值。
在輸出中你會看到一張精彩的圖片,如下圖:
它的資料將自動從您的 Readme.md、Changelog.md 和帶有插件描述的plugin.json 檔案中取得。
第六部分:代替結論
發布後我們並沒有停止開發插件。 現在,我們正在努力正確監控叢集節點資源的使用情況,引入新功能來改善使用者體驗,並收集我們的客戶和 GitHub 上的人員在安裝插件後收到的大量回饋(如果您離開)您的問題或拉取請求,我會很高興:)
我們希望這篇文章能幫助您了解 Grafana 如此出色的工具,或許還能幫助您撰寫自己的外掛程式。
謝謝!)
來源: www.habr.com