Ola a todos! Hai uns meses, lanzamos en produción o noso novo proxecto de código aberto: o complemento Grafana para supervisar os kubernetes, que chamamos
Parte 0 - introdución: como chegamos a este punto?
A idea de escribir o noso propio complemento para Grafan xurdiunos por casualidade. A nosa empresa leva máis de 10 anos supervisando proxectos web de varios niveis de complexidade. Durante este tempo, acumulamos unha gran cantidade de experiencia, casos interesantes e experiencia no uso de varios sistemas de vixilancia. E nalgún momento preguntámonos: "Existe unha ferramenta máxica para supervisar Kubernetes, para que, como din, "configúrao e esquéceo"? Combinación Prometheus + Grafana. E como solucións preparadas para esta pila, hai un gran conxunto de varios tipos de ferramentas: prometheus-operator, un conxunto de paneis de control kubernetes-mixin, grafana-kubernetes-app.
O complemento grafana-kubernetes-app pareceu ser a opción máis interesante para nós, pero hai máis dun ano que non se admite e, ademais, non pode funcionar con novas versións de node-exporter e kube-state-metrics. E nalgún momento decidimos: "Non deberíamos tomar a nosa propia decisión?"
Que ideas decidimos implementar no noso complemento:
- visualización do “mapa de aplicacións”: presentación cómoda das aplicacións no clúster, agrupadas por espazos de nomes, despregamentos...;
- visualización de conexións como "despliegue - servizo (+portos)".
- visualización da distribución das aplicacións do clúster entre os nodos do clúster.
- recollida de métricas e información de varias fontes: Prometheus e o servidor api k8s.
- vixilancia tanto da parte da infraestrutura (uso do tempo da CPU, da memoria, do subsistema do disco, da rede) como da lóxica da aplicación: pods de estado de saúde, número de réplicas dispoñibles, información sobre a superación das probas de vida/preparación.
Parte 1: que é un "complemento Grafana"?
Desde un punto de vista técnico, o complemento para Grafana é un controlador angular, que se almacena no directorio de datos de Grafana (/var/grafana/plugins/ /dist/module.js) e pódese cargar como un módulo SystemJS. Tamén neste directorio debería haber un ficheiro plugin.json que conteña toda a metainformación sobre o teu complemento: nome, versión, tipo de complemento, ligazóns ao repositorio/sitio/licenza, dependencias, etc.
módulo.ts
plugin.json
Como podes ver na captura de pantalla, especificamos plugin.type = app. Porque os complementos para Grafana poden ser de tres tipos:
taboleiro: o tipo de complemento máis común: é un panel para visualizar calquera métrica, usado para construír varios paneis.
fonte de datos: conector de complemento a algunha fonte de datos (por exemplo, fonte de datos Prometheus, fonte de datos ClickHouse, fonte de datos ElasticSearch).
app: Un complemento que che permite crear a túa propia aplicación frontend dentro de Grafana, crear as túas propias páxinas html e acceder manualmente á fonte de datos para visualizar varios datos. Ademais, pódense usar complementos doutro tipo (fonte de datos, panel) e varios paneis de mando como dependencias.
Exemplos de dependencias de complementos con type=app.
Podes usar tanto JavaScript como TypeScript como linguaxe de programación (escollimos nós). Preparativos para os complementos hello-world de calquera tipo que poidas
Parte 2: preparación do medio local
Para traballar no complemento, naturalmente necesitamos un clúster de kubernetes con todas as ferramentas preinstaladas: prometheus, node-exporter, kube-state-metrics, grafana. O ambiente debe configurarse de forma rápida, sinxela e natural, e para garantir a recarga en quente, o directorio de datos de Grafana debe montarse directamente desde a máquina do programador.
O xeito máis cómodo, na nosa opinión, de traballar localmente con kubernetes é
O noso guión de lanzamento final de minikube é así:
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
Parte 3: desenvolvemento real
Modelo de obxectos
Como preparación para a implementación do complemento, decidimos describir todas as entidades básicas de Kubernetes coas que traballaremos en forma de clases TypeScript: pod, deployment, daemonset, statefulset, job, cronjob, service, node, namespace. Cada unha destas clases herda da clase BaseModel común, que describe o construtor, o destrutor, os métodos para actualizar e cambiar a visibilidade. Cada unha das clases describe relacións aniñadas con outras entidades, por exemplo, unha lista de pods para unha entidade de tipo despregamento.
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 = [];
}
}
Coa axuda de getters e setters, podemos mostrar ou configurar as métricas de entidades que necesitamos nunha forma cómoda e lexible. Por exemplo, a saída formatada dos nodos de CPU asignables:
get cpuAllocatableFormatted(){
let cpu = this.data.status.allocatable.cpu;
if(cpu.indexOf('m') > -1){
cpu = parseInt(cpu)/1000;
}
return cpu;
}
páxinas
Unha lista de todas as nosas páxinas de complementos descríbese inicialmente no noso pluing.json na sección de dependencias:
No bloque de cada páxina debemos indicar o NOME DA PÁXINA (logo converterase nun slug polo que se poderá acceder a esta páxina); o nome do compoñente responsable do funcionamento desta páxina (a lista de compoñentes expórtase a module.ts); indicando o rol de usuario para o que está dispoñible o traballo con esta páxina e a configuración de navegación para a barra lateral.
No compoñente responsable do funcionamento da páxina, debemos establecer templateUrl, pasando alí o camiño ao ficheiro html con marcado. Dentro do controlador, mediante a inxección de dependencias, podemos acceder a ata 2 servizos angulares importantes:
- backendSrv - un servizo que ofrece interacción co servidor da API de Grafana;
- datasourceSrv: un servizo que proporciona interacción local con todas as fontes de datos instaladas no seu Grafana (por exemplo, o método .getAll()): devolve unha lista de todas as fontes de datos instaladas; .get( ) - devolve un obxecto de instancia dunha fonte de datos específica.
Parte 4: fonte de datos
Desde o punto de vista de Grafana, a fonte de datos é exactamente o mesmo complemento que todos os demais: ten o seu propio punto de entrada module.js, hai un ficheiro con metainformación plugin.json. Ao desenvolver un complemento con type = app, podemos interactuar tanto coas fontes de datos existentes (por exemplo, prometheus-datasource) como coas nosas, que podemos almacenar directamente no directorio de complementos (dist/datasource/*) ou instalar como dependencia. No noso caso, a fonte de datos vén co código do complemento. Tamén é necesario ter un modelo config.html e un controlador ConfigCtrl, que se utilizará para a páxina de configuración da instancia da fonte de datos e o controlador da fonte de datos, que implementa a lóxica da súa fonte de datos.
No complemento KubeGraf, desde o punto de vista da interface de usuario, a fonte de datos é unha instancia dun clúster de kubernetes que implementa as seguintes capacidades (o código fonte está dispoñible
- recollendo datos do servidor api k8s (obtención dunha lista de espazos de nomes, despregamentos...)
- enviar solicitudes de proxy a prometheus-datasource (que se selecciona na configuración do complemento para cada clúster específico) e dar formato ás respostas para usar datos tanto en páxinas estáticas como en paneis.
- actualizar datos en páxinas de complementos estáticas (cunha taxa de actualización establecida).
- procesando consultas para xerar unha folla de modelo en grafana-dashboards (método metriFindQuery())
- proba de conexión co clúster final 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"};
})
}
Un punto interesante aparte, na nosa opinión, é a implementación dun mecanismo de autenticación e autorización para a fonte de datos. Normalmente, fóra da caixa, podemos usar o compoñente Grafana incorporado datasourceHttpSettings para configurar o acceso á fonte de datos final. Usando este compoñente, podemos configurar o acceso á fonte de datos http especificando o URL e a configuración básica de autenticación/autorización: contrasinal de inicio de sesión ou certificado-cliente/clave-cliente. Para implementar a capacidade de configurar o acceso usando un token de portador (o estándar de facto para k8s), tivemos que facer un pequeno axuste.
Para resolver este problema, pode usar o mecanismo integrado de Grafana "Rotas de complementos" (máis detalles en
/api/v8/namespaces coa cabeceira Authorization: Bearer.
Por suposto, para traballar co servidor api k8s necesitamos un usuario con acceso de só lectura, manifestos para crear que tamén podes atopar en
Parte 5: liberación
Unha vez que escribas o teu propio complemento de Grafana, naturalmente quererás facelo dispoñible públicamente. En Grafana esta é unha biblioteca de complementos dispoñible aquí
Para que o teu complemento estea dispoñible na tenda oficial, debes facer un PR
onde versión é a versión do teu complemento, url é unha ligazón ao repositorio e commit é o hash do commit para o que estará dispoñible unha versión específica do complemento.
E na saída verás unha imaxe marabillosa como:
Os datos para iso capturaranse automaticamente do teu Readme.md, Changelog.md e do ficheiro plugin.json coa descrición do complemento.
Parte 6: en vez de conclusións
Non deixamos de desenvolver o noso complemento despois do lanzamento. E agora estamos a traballar para supervisar correctamente o uso dos recursos dos nodos do clúster, introducir novas funcións para mellorar a UX e tamén recoller unha gran cantidade de comentarios recibidos despois de instalar o complemento tanto polos nosos clientes como por parte da xente de GitHub (se deixas o teu problema ou solicitude de extracción, estarei moi feliz :)
Agardamos que este artigo che axude a comprender unha ferramenta tan marabillosa como Grafana e, quizais, a escribir o teu propio complemento.
Grazas!)
Fonte: www.habr.com