大家好! 几个月前,我们将新的开源项目投入生产——用于监控 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 这样一个出色的工具,或许还能帮助您编写自己的插件。
谢谢!)
来源: habr.com